/*
 * (C) Copyright Cogent Real-Time Systems Inc., 1997-2000.
 *     All rights reserved.
 *
 * This file constitutes a part of the Cascade (TM) C-Language
 * application programming interface.  It is not to be modified.  This
 * file is licensed for the purpose of creating programs that will
 * communicate with Cogent's products, and for no other purpose.
 * Cogent claims no rights in any program created by a party other than
 * Cogent by compiling this file, and accepts no responsibility or
 * liability in such a program.
 *
 * It is illegal for any party other than Cogent to sell the contents of
 * this file, or any part thereof, or to attempt to gain in any way from
 * the transmission of this file.  It is illegal to remove this notice
 * from this file.
 */

/*
 * Global structures and definitions for generalized IPC library
 */

#define IPC_H

#if defined(__QNX__) || defined(__LINUX__)
#include	<sys/kernel.h>
#endif

#ifdef __QNXNTO__
#include	<sys/neutrino.h>
#include	<process.h>
#include	<fcntl.h>
#endif

#ifdef HAVE_TIME_H
#include <time.h>
#endif

#ifdef __MS_WINDOWS__
#define timer_t		int
#endif

#include	<stdarg.h>

#ifndef __QNXNTO__
#define ND_NODE_CMP(n1,n2)	((n1) - (n2))
#endif

typedef struct IP_Task
{
	int			nid;		/* Node ID or Node Descriptor */
	pid_t		pid;		/* Process ID */
	int			chid;		/* QNXNTO only */
	char		*nidname;	/* string representation of node */

	/* Network connection */
	int			vcoid;		/* VC or COID, -1 for none*/

	/* Queue */
	char		*qname;		/* NULL for none */
	int			qid;		/* 0 for none */
	int			qpulse;		/* 0 for none */
	int			qsize;		/* max number of messages in input queue */
	int			qflags;		/* for example, open mode */

	/* Cascade IPC */
	char		*domain;	/* Must not be NULL */
	int			security;	/* 0 for minimum */

	/* Cascade name server */
	char		*name;		/* Must not be NULL */

	/* Extra stuff */
	void		*userdata;

	/* Networking */
	int			mynid;		/* My node ID according to this task */
} IP_Task;

typedef struct IP_MsgBuffer
{
	int16_t		type;
	int16_t		subtype;
	int32_t		nbytes;
	nid_t		nid;
	int32_t		pid;
	int32_t		chid;
	int16_t		status;
	char		data[1];
} GCC_PACKED IP_MsgBuffer;

#define IP_MSG_COGENT		0x1701
#define IP_SUB_RAW			0x4077
#define IP_SUB_LISP			0x4078
#define IP_SUB_PULSE		0x4079
#define IP_MSG_NO_TYPE		0x5a5a
#define IP_MSG_NO_SUBTYPE	0x7b7b

typedef struct IP_Msg
{
	IP_MsgBuffer	*msg;
	size_t			alloclen;	/* Size of total allocation for IP_MsgBuffer */
	size_t			datalen;	/* Size of data portion of IP_MsgBuffer */
	int8_t			dynamic:1;
	int8_t			resizeable:1;
} IP_Msg;

	
#ifndef __QNXNTO__
struct _msg_info {
	uint32_t			nd;			/* node of client, as seen by server */
	uint32_t			srcnd;		/* node of server as seen by client  */
	pid_t				pid;		/* pid of sending thread */
	int32_t				tid;		/* thread id of sending thread */
	int32_t				chid;		/* channel id message was received on */
	int32_t				scoid;		/* server connection ID */
	int32_t				coid;		/* client connection ID */
	int32_t				msglen;		/* number of bytes received */
	int32_t				srcmsglen;	/* number of bytes sent */
	int32_t				dstmsglen;	/* maximum number of bytes receivable? */
	int16_t				priority;	/* priority of sending thread */
	int16_t				flags;		/* _NTO_MI_UNBLOCK_REQ */
	uint32_t			reserved;
};
#endif	

typedef struct IP_MsgInfo
{
	enum 
	{
		IP_ERROR = -1,	/* Error during receive */
		IP_NONE,		/* Receive had no data, no error */
		IP_ASYNC,		/* Asynchronous via the Cogent qserve */
		IP_SYNC,		/* Synchronous vis the IP library */
		IP_PULSE,		/* Pulse or proxy */
		IP_FD,			/* Activity on a file descriptor */
		IP_SIGNAL,		/* Signal caused receive to exit */
		IP_SYSTEM,		/* System death message (QNX4/Linux) */
		IP_RAW,			/* Message with unknown header */
		IP_GUI,			/* Message from GUI (Photon or X) */
	} type;
	short subtype;		/* From incoming message */

//	int	special;		/* proxy, pulse code, file descriptor, signal, errno */
	int	rcvid;			/* rcvid, pid_t, proxy, fd, signal, pulse code */
	struct _msg_info msginfo;
} IP_MsgInfo;

typedef int (*IP_pfMessageHandler)(int type, void* msg, IP_MsgInfo* msginfo);
typedef int (*IP_pfGUIFilter)(int rcvid, void* msg, int length);
typedef int (*IP_pfGUIHandler)(void* msg, int length);

/* ============================== Macros ================================ */

enum IP_NOTIFY_TYPE
{
	IP_NOTIFY_MSG = 0x0001,
	IP_NOTIFY_EVERY_MSG = 0x0002,
	IP_NOTIFY_SPACE = 0x0004,
	IP_NOTIFY_ANY_SPACE = 0x0008,
	IP_NOTIFY_HALF_SPACE = 0x0010,
	IP_NOTIFY_ANY_HALF_SPACE = 0x0020
};

enum NS_NOTIFY_TYPE
{
	NS_NOTIFY_STARTED = 0x0040,
	NS_NOTIFY_CHANGED = 0x0080,
	NS_NOTIFY_DIED = 0x0100
};

#define IP_DCMD_QUEUE	122
#define IP_DCMD_NSERVE	123

#define IP_QUEUE_OPEN	0x1000

#define IP_MsgRawData(m)	((void*)((m)->msg))

/* ============================ Temporary =============================== */

#if 0
#define IP_FillMsg(_hmsg,_command,_status,_data,_length,_elist) \
				( IP_MsgRaw (_hmsg,_data,_length), \
					_hmsg->msg->subtype = _command, \
					_hmsg->msg->status = _status )
#endif
#define IP_MsgMaxLength(_hmsg)	(((IP_Msg*)(_hmsg))->datalen)
#define IP_MsgSubtype(_hmsg)	(((IP_Msg*)(_hmsg))->msg->subtype)
#define IP_MsgStatus(_hmsg)		(((IP_Msg*)(_hmsg))->msg->status)
#define IP_MsgLength(_hmsg)		(((IP_Msg*)(_hmsg))->msg->nbytes)
#define IP_MsgData(_hmsg)		(((IP_Msg*)(_hmsg))->msg->data)
#define IP_TaskID(_task)		(((IP_Task*)(_task))->pid)
#define IP_TaskName(_task)		(((IP_Task*)(_task))->name)
#define IP_TaskDomain(_task)	(((IP_Task*)(_task))->domain)
#define IP_TaskQueueName(_task)	(((IP_Task*)(_task))->qname)
#define IP_TaskSecurity(_task)	(((IP_Task*)(_task))->security)
#define IP_TaskSetSecurity(_task,_s)	(((IP_Task*)(_task))->security = _s)

#if 0
#define IP_CreateMsg(cmd,status,data,len,elist) IP_MsgCreate(data,len,0)
#define IP_DefaultDomain	IP_TaskDefaultDomain

typedef IP_Task	*IP_hTASK;
typedef IP_Msg	*IP_hMSG;

#define IP_FillMsg(_hmsg,_command,_status,_data,_length,_elist) \
				( IP_MsgRaw (_hmsg,_data,_length), \
					_hmsg->msg->subtype = _command, \
					_hmsg->msg->status = _status )
#define IP_MaxWriteLength(hmsg) (hmsg->datalen)
#define IP_MsgCommand(hmsg)	(hmsg->msg->subtype)
#define IP_MsgStatus(hmsg)	(hmsg->msg->status)
#define IP_MsgLength(hmsg)	(hmsg->msg->nbytes)
#define IP_ReadMsgBuffer(hmsg)	(hmsg->msg->data)
#define IP_TaskID(htask)	(htask->pid)
#define IP_TaskName(htask)	(htask->name)
#define IP_TaskQueueName(htask)	(htask->qname)
#define IP_TaskReceive(receiver,sender,message,type,elist) \
		(*(type) = IP_Receive(receiver,message,NULL))
#define IP_WriteMsgBuffer(hmsg)	(hmsg->msg->data)
#define IP_InitIPC(n,q,f)	IP_NserveInit(n,NULL,q,f)

#define IP_MAX_MESSAGE	IP_MsgDefaultSize()
#endif

/* =========================== Functions =============================== */

/* --------------------------- ip_conn.c ------------------------------- */

DllSym void IP_SetConnectionID (int coid);
DllSym void IP_SetChannelID (int chid);
DllSym int IP_GetChannelID (void);
DllSym int IP_GetConnectionID (void);

/* --------------------------- ip_find.c ------------------------------- */

DllSym IP_Task* IP_TaskFindName (char* name);
DllSym IP_Task* IP_TaskFindID (int nid, int pid, int chid);
DllSym IP_Task* IP_TaskCopy (IP_Task* task);
DllSym IP_Task* IP_TaskIntern (IP_Task* task);
DllSym IP_Task* IP_TaskUnintern (IP_Task* task);

/* ---------------------------- ip_msg.c ------------------------------- */

DllSym int IP_MsgDefaultSize (void);
DllSym IP_Msg *IP_MsgCreate (void* data, int datalen, int noresize);
DllSym void IP_MsgDestroy (IP_Msg* mb);
DllSym int IP_MsgResize (IP_Msg* mb, int datalen);
DllSym int IP_MsgRaw (IP_Msg* mb, void* data, int len);
DllSym int IP_MsgCascade (IP_Msg* mb, void* data, int len,
						  int subtype, int status);
DllSym int IP_MsgLisp (IP_Msg* mb, int status, char* format, ...);
DllSym int IP_VMsgLisp (IP_Msg* mb, int status, char* format, va_list params);

/* --------------------------- ip_nserve.c ----------------------------- */

DllSym int IP_NserveInitMyself (IP_Task* myself, int flags);
DllSym IP_Task* IP_NserveInit (char* name, char* domain, char* qname,
							   int qsize, int flags);
DllSym int IP_NservePackTaskInfo (char* buffer, int maxlen, char* prefix,
								  char* name, char* domain, char* qname,
								  int nid, int pid, int chid);
DllSym int IP_NserveLookup (char* name, IP_Task* task);
DllSym int IP_NserveLookupId (int nid, int pid, int chid, IP_Task* task);
DllSym IP_Task* IP_NserveLookupName (char* name);

DllSym int IP_NserveAdd (char* name, char* domain, char* qname,
						 int nid, int pid, int chid);
DllSym int IP_NserveRemove (char* name);
DllSym int IP_NserveReattach (IP_Task* task);
DllSym int IP_NserveClose (IP_Task* tsk);
DllSym int IP_NserveSetDomain (IP_Task* task, char* domain);
DllSym int IP_NserveQueryNameCount (void);
DllSym int IP_NserveQueryNames (char** names, int maxnames);
#ifdef NO_QNX_IPC
DllSym IP_Task* IP_NserveConnect (char* nodename);
#else
DllSym IP_Task* IP_NserveConnect (int node);
#endif
DllSym int IP_NserveVSendTask (IP_Task* nserve, int sync, char* reply,
							   int replysize, char* format, va_list params);
DllSym IP_Task* IP_NserveQueryNserve (void);
DllSym int IP_NserveInform (IP_Task* myself);

/* --------------------------- ip_photon.c ----------------------------- */

DllSym int IP_DetachPhotonMainloop (void);
DllSym int IP_AttachPhotonMainloop (IP_pfMessageHandler handler);
DllSym int IP_AttachPhoton (void);
DllSym int IP_PhotonGUIFilter (int rcvid, void* msg, int length);
DllSym int IP_PhotonGUIHandler (void* msg, int length);

/* --------------------------- ip_pulse.c ------------------------------ */

DllSym int IP_PulseNew (void);
DllSym int IP_PulseDestroy (int pulse);
DllSym timer_t IP_PulseTimed (int pulse, time_t init_sec, time_t init_nsec,
							  time_t interval_sec, time_t interval_nsec);
DllSym int IP_IsPulse (int pulse, int rcvid, void* msg);
DllSym int IP_TimerTime (timer_t timer, int absolute,
						 time_t init_sec, time_t init_nsec,
						 time_t interval_sec, time_t interval_nsec);
DllSym int IP_PulseTrigger (IP_Task* task, int pulse);

/* ---------------------------- ip_queue.c ------------------------------ */

DllSym int IP_QueueOpen (char* name, int node, int max_msgs, int mode);
DllSym int IP_QueueClose (int qid);
DllSym int IP_QueueWrite (int qid, void* msg, int length, int priority);
DllSym int IP_QueueRead (int qid, void* msg, int maxlength);
DllSym int IP_QueueWait (int qid, int proxy, int eventmask);
DllSym char* IP_QueueStrerror (int status);

/* ---------------------------- ip_recv.c ------------------------------- */

DllSym int IP_SetGUIHandler (IP_pfGUIFilter filter, IP_pfGUIHandler handler);
DllSym int IP_Receive (IP_Task* myself, IP_Msg* rmsg,
					   IP_MsgInfo* msginfo);
DllSym int IP_ReceiveNonblock (IP_Task* myself, IP_Msg* rmsg,
							   IP_MsgInfo* msginfo);
DllSym int IP_AddFDHandler (int fd);
DllSym int IP_RemoveFDHandler (int fd);
DllSym int IP_HaveFDHandler (int fd);
DllSym int IP_SelectFD (void);
DllSym int IP_UnselectFD (int fd);
DllSym int IP_ProcessMessage (IP_Task* myself, int rcvid, void* msgbuffer,
							  int length, IP_MsgInfo* msginfo);

/* ---------------------------- ip_reply.c ------------------------------ */

DllSym int IP_Reply (int rcvid, IP_Msg* rmsg);
DllSym int IP_MsgInfoReply (IP_MsgInfo *orig, IP_Msg* rmsg);
DllSym int IP_ReplyRaw (int rcvid, char* msg, int len);
DllSym int IP_MsgInfoReplyRaw (IP_MsgInfo *orig, char* msg, int len);

/* ---------------------------- ip_send.c ------------------------------- */

DllSym int IP_TaskConnect (IP_Task* receiver);
DllSym int IP_TaskSendSync (IP_Task* myself, IP_Task* receiver, IP_Msg* smsg,
							IP_Msg* rmsg);
DllSym int IP_TaskSendAsync (IP_Task* myself, IP_Task* receiver, IP_Msg* smsg,
							 int priority);
DllSym int IP_TaskSendRaw (IP_Task* receiver, char* outbuf, int lout,
						   char* inbuf, int lin);

/* ---------------------------- ip_task.c ------------------------------- */

DllSym int IP_TaskCloseAsync (IP_Task* task);
DllSym int IP_TaskCloseSync (IP_Task* task);

DllSym IP_Task *IP_TaskSetInfo (IP_Task* ptask, int nid, int pid,
								int chid, char* name, char* domain,
								char* qname, int security, void* userdata);
DllSym IP_Task *IP_TaskCreate (int nid, int pid, int chid, char* name,
							   char* domain, char* qname, int security,
							   void* userdata);
DllSym IP_Task* IP_TaskCreateMe (int chid, char* name, char* domain,
								 char* qname, int qsize);
DllSym char* IP_TaskDefaultDomain (void);
DllSym void IP_TaskDestroy (IP_Task* ptask);
DllSym int IP_TaskInitAsync (IP_Task* myself, char* qname, int qsize);
DllSym int IP_TaskInitAsyncWrites (IP_Task* receiver);
DllSym int IP_pfTaskComp (const void* t1, const void* t2);
DllSym int IP_TaskWaitAsync (IP_Task* task, int flags);
DllSym IP_Task *IP_TaskZero (IP_Task* task);
DllSym IP_Task *IP_TaskNew (void);
DllSym void IP_TaskSetDomain (IP_Task* task, char* domain);
DllSym void IP_TaskSetQname (IP_Task* task, char* qname);

/* ----------------------------- ip_tcp.c ------------------------------- */

DllSym int IP_ListenToPort (int port, int backlog);
DllSym int IP_ListenToService (char* service, int backlog);
DllSym int IP_ConnectToPort (char* host, int port);
DllSym int IP_ConnectToService (char* host, char* service);
