/* ************************************************************************** */
/* ***************************** definitions ******************************** */
/* ************************************************************************** */

#if !defined(_MPSSERVER_DEFS_H_INCLUDED_)
#define _MPSSERVER_DEFS_H_INCLUDED_

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <inttypes.h>
#include <sys/time.h>
#include "MPS_consts.h"

#if defined(__MINGW32__)
	#include <winsock2.h>
	#include <ws2tcpip.h>
	#include <windef.h>
	#include <sys/timeb.h>

	#define SHUT_RD   SD_RECEIVE
	#define SHUT_WR   SD_SEND
	#define SHUT_RDWR SD_BOTH

	int get_time(struct timeval *tp);
#else
	#include <sys/socket.h>
	#include <sys/select.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>

	#define get_time(x) gettimeofday(x, NULL)
	#define closesocket(x) close(x)
#endif

#define MIN(x,y) ( ( (x) <= (y) )?(x):(y) )

/* maximum number of connections per thread */
#define MAX_CLIENTS_PER_THREAD 10

#undef WAIT_FOR_WRITE

#define CREATE_LOG 1
#undef LOG_OPERATION_FFLUSH

typedef int (*filter_function) (char *, u_long, u_long);

typedef struct _td_buffer_struct_ {
	unsigned int pos, size;
	void *buf;
} td_buffer_struct;


/* operation data */
typedef struct _operation_data_ {
	u_long operation_id;				/* operation id */
	u_long process_id;					/* process id */
	u_char operation_type;				/* operation type (enum OperationTypes) */
	u_long message_id;					/* message id */
	u_long mlength;						/* message length */
	char *mtext;						/* message text */
	u_long num_process_ids;				/* number of process ids */
	u_long *process_ids;				/* pointer to list of process ids */
	filter_function filter;				/* pointer to filter function */
	char *fname2;						/* function name */
	int ftype;							/* function type */
	int ftag;							/* function tag parameter */
	int fsender;						/* function sender parameter */
	struct timeval operation_time;		/* receive time of operation */
	struct _process_data_ *process;		/* pointer to process data */
	u_long process_id2;					/* process id of matching operation */

	/* client information */
	u_long SignalPtr;					/* pointer value of semaphor to signal */
	u_long MessagePtr;					/* pointer value of memory place to store the pointer to message text */
	u_long MLengthPtr;					/* pointer value of memory place to store the message length */
	u_long MIDPtr;						/* pointer value of memory place to store the message id */
	u_long PIDPtr;						/* pointer value of memory place to store the process id */
} operation_data;

/* connection data */
typedef struct _connection_data_ {
	struct sockaddr_in conn_name;		/* connection name */
	int conn_socket;					/* connection socket */
	u_long process_id;					/* process id */
	struct _process_data_ *process;		/* pointer to process data */
	td_buffer_struct td_buffer;			/* buffer for sending */
} connection_data;

/* thread data */
typedef struct _thread_data_
{
	connection_data conn_sockets[MAX_CLIENTS_PER_THREAD];		/* array of connections the thread is attending */
	int num_conn_sockets;										/* number of connections */
	pthread_t thread_ptr;										/* pointer to thread */
	int exit_thread;											/* non-zero if thread is supposed to exit */

	struct _thread_data_ *prev, *next;							/* pointer to next/prev thread data */
} thread_data;

/* process data */
typedef struct _process_data_ {
	u_long process_id;									/* process id */
	connection_data *cdata;								/* pointer to connection data */
	thread_data *tdata;									/* pointer to thread data */
	struct _message_list_Block_List_ *message_list;		/* pointer to list of messages */
} process_data;

/* process search data */
typedef struct _process_search_data_ {
	u_long process_id;			/* process id */
	process_data *process;		/* pointer to process data */
} process_search_data;

/* message data */
typedef struct _message_data_ {
	u_long message_id;		/* message id */
	u_long mlength;			/* message length */
	char *mtext;			/* message text */
} message_data;

/* function data */
typedef struct _function_data_ {
	char *fname;				/* function name */
	filter_function fptr;		/* pointer to function */
	int ftype;					/* function type */
} function_data;

extern void *conn_thread(thread_data *data);

/* functions for reading data from socket */
extern int td_read_char_array(int socket, char *data, u_long length);
extern int td_read_string(int socket, char *data, u_long length);
extern int td_read_u_char(int socket, u_char *data);
extern int td_read_u_long(int socket, u_long *data);

/* functions for writing data to socket */
extern int td_write_char_array(int socket, char *data, u_long length, td_buffer_struct *buffer);
extern int td_write_u_char(int socket, u_char *data, td_buffer_struct *buffer);
extern int td_write_u_long(int socket, u_long *data, td_buffer_struct *buffer);

extern int td_flush(int socket, td_buffer_struct *buffer);
#endif
