/******************************************************************************
Copyright (C) 2005 Matteo Lucarelli
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 2
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
******************************************************************************/
// WIN NEED: libpthreadGC.a , libws2_32.a
// LIN NEED: lpthread
#if !defined(_ULM_H_INCLUDED_)
#define _ULM_H_INCLUDED_
#ifdef WIN32
#include <Winsock2.h>
#else
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#define ULM_MAX_MSG 32768 // max message dim
#define ULM_HEAD_DIM 13 // header dim
// ulmSocket utility class - win/lin compatibility layer ///////////////////////
class ulmSocket
{
public:
ulmSocket(unsigned short port);
virtual ~ulmSocket();
// host can be name or addr
// use addr to avoid time-consuming resolution
int Send(const void* buff, // buffer to send
long size, // size of buffer
const char* host, // destination host
unsigned short port); // destination port
// wait (without timeout) incoming data
// sender address and port are returned in fromHost:fromPort
// return value is the size of packet (could be higher then size!)
int Recv(void *buff, // buffer where put incoming msg
long size, // size (must be allocated)
char* fromHost, // sender address - char[16] or NULL
unsigned short* fromPort, // sender port - NULL if don't care
long msTimeout=500); // Timeout (-1 infinite)
private:
#ifdef WIN32
SOCKET m_hSocket;
bool m_WsaInit;
#else
int m_hSocket;
#endif
struct sockaddr_in m_BindAddr;
};
// ulmMessage - to send messages ///////////////////////////////////////////////
class ulmMessage
{
public:
// header chars are configurable
// message with different header are discarded from the receiver
ulmMessage(char ch1=0, // first configurable header char
char ch2=0, // second configurable header char
char ch3=0); // third configurable header char
virtual ~ulmMessage();
char msg_buf[ULM_MAX_MSG+ULM_HEAD_DIM]; // the message
unsigned short msg_dim; // message dim (without header)
// add a text field to current message
// text value must be null terminate string of printable chars
int FieldAdd( const char* label, // string label
const char* value); // string value
// extract a text fiels from message
int FieldGet( const char* label, // label to search (string)
char* value, // returned value (string)
long valueDimBytes); // buffer dim - must be allocated
// add a binary field to message - no more text field are admitted
int BinaryFieldAdd( const char* label, // string label
const void* data, // binary value
unsigned short size); // value dim in bytes
// extract a binary field from message
// if size>sizeof(data) then data war too small
int BinaryFieldGet( const char* label, // label to search
void* data, // buffer to return data
unsigned short maxsize, // max byte to return
unsigned short* size); // found field size
// send current message to host:port using local port lport
// Return 0: ok
// -1: generic error
// -2: unresolved name
int Send( unsigned short lport, // local port used to send
const char* host, // destination host
unsigned short port); // destination port
// empty current message
void Clear();
private:
char computeXOR(char* buf,long dim);
char m_ch1,m_ch2,m_ch3;
bool m_binFlag; // true if message contains binary fields
};
// ulmReceiver - ///////////////////////////////////////////////////////////////
// to receive message put a global function defined friend in handler class
//
// friend ulmCallback ulmCb;
//
// the function body for windows will be something like:
//
// void __stdcall ulmCb(ulmMessage msg, void* pClient){
// ((YourHandlerClass*)pClient)->YourHandlerFunction(msg);
// }
//
// and for linux:
//
// void ulmCb(ulmMessage msg, void* pClient){
// ((YourHandlerClass*)pClient)->YourHandlerFunction(msg);
// }
//
////////////////////////////////////////////////////////////////////////////////
typedef void ulmCallback(ulmMessage msg,const void* pClient);
class ulmReceiver
{
public:
// note: the receiver start immediatly
// header chars are configurable
// use 0 means 'don't care', else message with
// different header are discarded
ulmReceiver( void* pClient, // pointer to the handler object
ulmCallback* Cb, // pointer to the callback
unsigned short ListenOnPort, // port to listen to
char ch1=0, // first header char
char ch2=0, // second header char
char ch3=0); // third header char
virtual ~ulmReceiver();
private:
struct RecvThreadParms{
ulmCallback* ClientCb;
void* pClient;
ulmSocket* Socket;
char ch1,ch2,ch3;
};
struct RecvThreadParms m_RTparms;
pthread_t m_pRecvThread;
static void* RecvThread(void* pParms);
};
#endif // !defined(_ULM_H_INCLUDED_)