MySVC
an open source UNIX framework for shell script based web services provider
»Home
»Tools
»Man Page
»User Guide
»ChangeLog
»Installation
»Source Code
»Downloads
»FAQ
»Support
»License

»My Apps

protocol.hh

// $Id$

//  myspl - My Service Protocol Library - Version 1.0 (www.mysvc.it)
//  Copyright (C) 2009 Davide Cucciniello <davide6169@gmail.com>
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

/* **********************************************************************
 *
 *  ***   **        *** **  **  ****
 *   **  **        *  *  *  ** **  *
 *   *** **  **  * ***   *  *  *
 *   * ** *   * **   **   * *  *
 *   * *  *   * *  *  *   **   **
 *  ***  ***   **  ***     *    ****
 *             *
 *            *
 *
 *  My Service
 *
 * ***********************************************************************
 *
 *  ***   **        *** ****  ***
 *   **  **        *  *  *  *  *
 *   *** **  **  * ***   *  *  *
 *   * ** *   * **   **  ***   *
 *   * *  *   * *  *  *  *     *  *
 *  ***  ***   **  ***  ***   *****
 *             *
 *            *
 *
 *  My Service Protocol Library
 *
 *  File: protocol.hh
 *
 *  Description:
 *    C++ library to implement any TCP/IP socket client/server
 *    for binary or ascii protocols
 *
 * ***********************************************************************
 *
 *  History:
 *    1.0               first version
 *
 * *********************************************************************** */

#ifndef _PROTOCOL_HH_
#define _PROTOCOL_HH_

#include <iostream>
#include <string>
#include <map>
#include <cstring>
#include <cctype>
#include <exception>

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/utsname.h>
#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

using namespace std;

/*
 *  class Exception
 */

class Exception
{
  public:
    Exception(string message__ = "",
              int code__ = 0,
              string file__ = "",
              int line__ = 0);

    string& file();
    int& line();

    string& message();
    int& code();

    virtual void write(ostream& os);

  private:
    int code_;
    string message_;
    string file_;
    int line_;
};

/*
 *  class SocketException
 */

class SocketException: public Exception
{
  public:
    enum
    {
      gethostbynameError = -1,
      socketError = -2,
      setsockoptError = -3,
      connectError = -4,
      closeError = -5,
      bindError = -6,
      listenError = -7,
      acceptError = -8
    };

    SocketException(string message__ = "",
                    int code__ = 0,
                    string file__ = "",
                    int line__ = 0);
};

ostream& operator<<(ostream& os,Exception& e);

/*
 *  class Reader
 */

class Reader
{
  public:
    virtual int read(char* buffer,int n,bool peek = false,bool line = false) = 0;
};

/*
 *  class Writer
 */

class Writer
{
  public:
    virtual int write(char* buffer,int n,bool line = false) = 0;
};

/*
 *  class SocketReader:
 */

class SocketReader: public Reader
{
  public:
    SocketReader(int fd);

    int read(char* buffer,int n,bool peek = false,bool line = false);

  private:
    int fd;
};

/*
 *  class SocketWriter
 */

class SocketWriter: public Writer
{
  public:
    SocketWriter(int fd);

    int write(char* buffer,int n,bool line = false);

  private:
    int fd;
};

/*
 *  class FileReader
 */

class FileReader: public Reader
{
  public:
    FileReader(int fd);

    int read(char* buffer,int n,bool peek = false,bool line = false);

  private:
    int fd;
};

/*
 *  class FileWriter
 */

class FileWriter: public Writer
{
  public:
    FileWriter(int fd);

    int write(char* buffer,int n,bool line = false);

  private:
    int fd;
};

/*
 *  class Field
 */

class Field
{
  public:
    Field();
    Field(int size, string name__ = "Field");
    Field(const Field& f);

    int size();

    char* data();

    void init(int size_);

    operator char*();

    char& operator[](int i);

    Field& operator=(string value);

    Field& operator=(Field& f);

    bool operator==(Field& f);
    bool operator!=(Field& f);

    virtual bool equal(Field& f);

    virtual Field* clone();

    void empty();

    string name();

    virtual bool isAscii();

    virtual void write(ostream& os);

    virtual void read(Reader& r,bool peek = false,bool line = false);
    virtual void write(Writer& w,bool line = false);

    Field& operator<<(Reader& r);
    Field& operator>>(Writer& w);

    virtual void read(Field& f,int from = 0);
    virtual void write(Field& f,int from = 0);

    virtual void assign(char* buffer,int n);

    virtual ~Field();

  protected:
    virtual void assign(string value);

    virtual void copy(const Field& f);

    virtual void writeValue(ostream& os);
  private:
    string name_;

    int size_;
    char* data_;
};

ostream& operator<<(ostream& os,Field& f);

/*
 *  class Message
 */

class Message
{
  public:
    Message();
    Message(int size_,string name__ = "Message");
    Message(const Message& m);

    int size();

    unsigned long bytes();

    Field** data();
    Field*& data(int i);

    Field& operator[](int i);

    Message& operator=(Message& m);

    bool operator==(Message& f);
    bool operator!=(Message& f);

    virtual bool equal(Message& f);

    virtual string name();

    void empty();

    virtual void write(ostream& os);

    virtual void read(Reader& r,bool peek = false,bool line = false);
    virtual void write(Writer& w,bool line = false);

    Message& operator<<(Reader& r);
    Message& operator>>(Writer& w);

    virtual Message* clone();

    virtual ~Message();

  protected:
    void assign(int i,Field* f);
    void assign(Message* m);

    void copy(const Message& m);
  private:
    int size_;
    Field** data_;

    string name_;
    int nextfield;
};

ostream& operator<<(ostream& os,Message& m);

/*
 * TreeMessage
 */

class TreeMessage
{
  public:
    TreeMessage();
    TreeMessage(const TreeMessage& m);
    TreeMessage(Message* info_);
    TreeMessage(int size_,string name__ = "TreeMessage");

    void init(Message* info_);
    void init(int size_);

    bool isEmpty();
    bool isTree();
    bool isLeaf();

    Message*& info();

    TreeMessage& operator[](int i);
    TreeMessage*& operator()(int i);
    Message& operator()();

    TreeMessage& operator=(TreeMessage& m);

    bool operator==(TreeMessage& f);
    bool operator!=(TreeMessage& f);

    virtual bool equal(TreeMessage& f);

    TreeMessage** data();
    TreeMessage*& data(int i);

    virtual string name();

    void empty();

    int size();

    unsigned long bytes();

    virtual void write(ostream& os);

    void read(Reader& r,bool peek = false,bool line = false);
    void write(Writer& w,bool line = false);

    TreeMessage& operator<<(Reader& r);
    TreeMessage& operator>>(Writer& w);

    virtual void update();
    virtual void updateTree();

    virtual TreeMessage* clone();

    virtual ~TreeMessage();
  protected:
    void assign(Message* m);
    void assign(int i,TreeMessage* m);

    virtual bool isReadable(int pos);
    virtual int update(int size_);
    virtual TreeMessage* child(int pos);
  private:
    int size_;
    Message* info_;
    TreeMessage** data_;

    string name_;
};

ostream& operator<<(ostream& os,TreeMessage& m);

/*
 * FieldMessage
 */

class FieldMessage: public Message
{
  public:
    FieldMessage(Field* f,string name = "FieldMessage"):
      Message(1,name)
    {
      assign(0,f);
    }
};

//  Basic Fields

/*
 *  class Int2Field
 */

class Int2Field: public Field
{
  public:
    Int2Field(string name_ = "Int2Field",
              int value_ = 0);

    virtual bool isAscii();

    int value();

    Field& operator=(int value);

    operator int();

    void write(ostream& os);

    virtual Field* clone();

  protected:
    void assign(string value_);

    void writeValue(ostream& os);

  private:
    void assign(int value_);
};

/*
 *  class Int4Field
 */

class Int4Field: public Field
{
  public:
    Int4Field(string name_ = "Int4Field",
              int value_ = 0);

    virtual bool isAscii();

    int value();

    Field& operator=(int value);

    operator int();

    void write(ostream& os);

    virtual Field* clone();

  protected:
    void assign(string value_);

    void writeValue(ostream& os);
  private:
    void assign(int value_);
};

/*
 *  class BoolField
 */

class BoolField: public Field
{
  public:
    BoolField(string name_ = "BoolField",
              bool value_ = false,
              char truevalue = 'T',
              char falsevalue = 'F');

    virtual bool isAscii();

    bool value();

    Field& operator=(bool value_);

    operator bool();

    void write(ostream& os);

    virtual Field* clone();

  protected:
    void assign(string value_);

    void writeValue(ostream& os);

  private:
    char truevalue;
    char falsevalue;

    void assign(bool value_);
};

/*
 *  class OctetField
 */

class OctetField: public Field
{
  public:
    OctetField(string name_ = "OctetField",
               char value_ = '\0');

    virtual bool isAscii();

    char value();

    Field& operator=(char value_);

    operator char();

    void write(ostream& os);

    virtual Field* clone();

  protected:
    void assign(string value_);

    void writeValue(ostream& os);
  private:
    void assign(char value_);
};

/*
 *  class StringField
 */

class StringField: public Field
{
  public:
    StringField(int size_,
                string name_ = "StringField",
                string value_ = "");

    StringField(string name_ = "StringField",
                string value_ = "");

    virtual bool isAscii();

    string value();

    operator string();

    Field& operator=(string value_);

    void write(ostream& os);

    virtual Field* clone();

  protected:
    void assign(string value_);

    void writeValue(ostream& os);
  private:
    bool isVariable;
};

/*
 *  class Client
 */

class Client
{
  public:
    Client(bool binary);

    virtual void connect() = 0;
    virtual void close() = 0;

    void peek(TreeMessage& m);
    void peek(Message& m);
    void peek(Field& f);

    Client& operator>>(TreeMessage& m);
    Client& operator>>(Message& m);
    Client& operator>>(Field& f);

    Client& operator<<(TreeMessage& m);
    Client& operator<<(Message& m);
    Client& operator<<(Field& f);

    virtual ~Client();

  protected:
    virtual Reader* getReader() = 0;
    virtual Writer* getWriter() = 0;

  private:
    bool binary;
};

/*
 *  Server
 */

class Server
{
  public:
    Server(bool binary);

    virtual Client* accept() = 0;
    virtual void close() = 0;

    virtual ~Server();

  protected:
    bool binary;
};

/*
 *  class SocketClient
 */

class SocketClient: public Client
{
  public:
    SocketClient(string ipaddress,int port,bool binary = true);
    SocketClient(int clientfd,bool binary = true);

    void connect();
    void close();

  protected:
    virtual Reader* getReader();
    virtual Writer* getWriter();

  private:
    string ipaddress;
    int port;

    struct sockaddr_in sSockaddrin;
    int clientfd;

    bool isConnected;

    Reader* reader;
    Writer* writer;

    int init(string ipaddress,int port,
             struct sockaddr_in& sSockaddrin);
};

/*
 *  class SocketServer
 */

class SocketServer: public Server
{
  public:
    SocketServer(int port,bool binary = true);

    Client* accept();
    void close();

  private:
    int port;

    struct sockaddr_in sSockaddrin;
    int serverfd;

    int init(int port,struct sockaddr_in& sSockaddrin);
};

/*
 *  class FileClient
 */

class FileClient: public Client
{
  public:
    FileClient(string infilename_ = "",
               string outfilename_ = "",
               bool binary = true);

    void connect();
    void close();

  protected:
    virtual Reader* getReader();
    virtual Writer* getWriter();

  private:
    string infilename;
    string outfilename;

    int infd;
    int outfd;

    bool isOpened;

    Reader* reader;
    Writer* writer;
};

/*
 *  Helper functions
 */

void daemon();

unsigned long getLocalIPAddress();

#endif

/* end of file */