#include <ipcmessages.h> // AxWin3 common
#include "include/internal.h"
#include "include/ipc.h"
+#include <errno.h>
+
+#define assert(cnd) do{if(!(cnd)){_SysDebug("Assertion failed: %s", #cnd);}}while(0)
+
+#define STATICBUF_SIZE 0x1000
// === CONSTANTS ===
enum eConnectionType
{
CONNTYPE_NONE,
CONNTYPE_SENDMESSAGE,
+ CONNTYPE_IPCPIPE,
CONNTYPE_UDP,
CONNTYPE_TCP
};
// === CODE ===
void AxWin3_Connect(const char *ServerDesc)
{
- _SysDebug("ServerDesc = %s", ServerDesc);
- if( !ServerDesc )
- {
+ if( !ServerDesc ) {
ServerDesc = gsAxWin3_int_ServerDesc;
}
_SysDebug("ServerDesc = %s", ServerDesc);
case '6': case '7': case '8': case '9': case '0':
giConnectionType = CONNTYPE_SENDMESSAGE;
giConnectionNum = atoi(ServerDesc);
+ if( giConnectionNum == 0 ) {
+ _SysDebug("Invalid server PID");
+ exit(-1);
+ }
break;
case 'u':
- while(*ServerDesc && *ServerDesc != ':') ServerDesc ++;
- ServerDesc ++;
+ assert( strncmp(ServerDesc, "udp:", 4) == 0 );
+ ServerDesc += 4;
+ _SysDebug("TODO: UDP connection to '%s'", ServerDesc);
// TODO: Open socket and create UDP header
break;
case 't':
- while(*ServerDesc && *ServerDesc != ':') ServerDesc ++;
- ServerDesc ++;
+ assert( strncmp(ServerDesc, "tcp:", 4) == 0 );
+ ServerDesc += 4;
+ _SysDebug("TODO: TCP connection to '%s'", ServerDesc);
// TODO: Open socket
break;
+ case 'p':
+ assert( strncmp(ServerDesc, "pipe:", 5) == 0 );
+ ServerDesc += 5;
+ giConnectionType = CONNTYPE_IPCPIPE;
+ giConnectionNum = _SysOpen(ServerDesc, OPENFLAG_READ|OPENFLAG_WRITE);
+ if( giConnectionNum == -1 ) {
+ _SysDebug("Cannot open IPC Pipe '%s'", ServerDesc);
+ exit(-1);
+ }
+ break;
+ default:
+ _SysDebug("Unknown server desc format '%s'", ServerDesc);
+ exit(-1);
+ break;
}
}
switch(giConnectionType)
{
case CONNTYPE_SENDMESSAGE:
- SysSendMessage(giConnectionNum, size, Msg);
+ _SysSendMessage(giConnectionNum, size, Msg);
break;
case CONNTYPE_UDP: {
// Create UDP header
char tmpbuf[giAxWin3_int_UDPHeaderLen + size];
memcpy(tmpbuf, gaAxWin3_int_UDPHeader, giAxWin3_int_UDPHeaderLen);
memcpy(tmpbuf + giAxWin3_int_UDPHeaderLen, Msg, size);
- write(giConnectionNum, tmpbuf, sizeof(tmpbuf));
+ size_t rv = _SysWrite(giConnectionNum, tmpbuf, sizeof(tmpbuf));
+ if( rv == -1 ) {
+ _SysDebug("AxWin3 SendIPCMessage: UDP Write Failed %s", strerror(errno));
+ exit(1);
+ }
}
break;
- case CONNTYPE_TCP:
- write(giConnectionNum, Msg, size);
+ case CONNTYPE_IPCPIPE:
+ case CONNTYPE_TCP: {
+ size_t rv = _SysWrite(giConnectionNum, Msg, size);
+ if( rv != size ) {
+ _SysDebug("AxWin3 SendIPCMessage: Write Failed %s - sent %i want %i",
+ strerror(errno), rv, size);
+ exit(1);
+ }
+ }
break;
default:
break;
}
}
-tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(void)
+tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(int nFD, fd_set *fds)
{
int len;
tAxWin_IPCMessage *ret = NULL;
- switch(giConnectionType)
+ int tid;
+ fd_set local_set;
+
+ if(!fds)
+ fds = &local_set;
+
+ if( giConnectionType != CONNTYPE_SENDMESSAGE )
{
- case CONNTYPE_SENDMESSAGE:
- for( ;; )
+ if(nFD <= giConnectionNum)
+ nFD = giConnectionNum+1;
+ FD_SET(giConnectionNum, fds);
+ }
+
+ _SysSelect(nFD, fds, NULL, NULL, NULL, THREAD_EVENT_IPCMSG);
+
+ // Clear out IPC messages
+ while( (len = _SysGetMessage(&tid, 0, NULL)) )
+ {
+ if( giConnectionType != CONNTYPE_SENDMESSAGE || tid != giConnectionNum )
{
- pid_t tid;
+ _SysDebug("%i byte message from %i", len, tid);
+ // If not, pass the buck (or ignore)
+ if( gAxWin3_MessageCallback )
+ gAxWin3_MessageCallback(tid, len);
+ else
+ _SysGetMessage(NULL, 0, GETMSG_IGNORE);
+ continue ;
+ }
- // Wait for a message to arrive
- while( !(len = SysGetMessage(&tid, NULL)) )
- {
- _SysWaitEvent(THREAD_EVENT_IPCMSG);
- }
+ // Using CONNTYPE_SENDMESSAGE and server message has arrived
+ ret = malloc(len);
+ if(ret == NULL) {
+ _SysDebug("malloc() failed, ignoring message");
+ _SysGetMessage(NULL, 0, GETMSG_IGNORE);
+ return NULL;
+ }
+ _SysGetMessage(NULL, len, ret);
+ break;
+ }
+
+ if( giConnectionType != CONNTYPE_SENDMESSAGE )
+ {
+ if( FD_ISSET(giConnectionNum, fds) )
+ {
+ char tmpbuf[STATICBUF_SIZE];
+ char *data = tmpbuf;
+ size_t len = _SysRead(giConnectionNum, tmpbuf, sizeof(tmpbuf));
- // Check if the message came from the server
- if(tid != giConnectionNum)
+ if( giConnectionType == CONNTYPE_UDP )
{
- _SysDebug("%i byte message from %i", len, tid);
- // If not, pass the buck (or ignore)
- if( gAxWin3_MessageCallback )
- gAxWin3_MessageCallback(tid, len);
- else
- SysGetMessage(NULL, GETMSG_IGNORE);
- continue ;
+ assert(len > giAxWin3_int_UDPHeaderLen);
+ len -= giAxWin3_int_UDPHeaderLen;
+ data += giAxWin3_int_UDPHeaderLen;
}
-
- // If it's from the server, allocate a buffer and return it
+ assert(len >= sizeof(tAxWin_IPCMessage));
ret = malloc(len);
- if(ret == NULL) {
- _SysDebug("malloc() failed, ignoring message");
- SysGetMessage(NULL, GETMSG_IGNORE);
- return NULL;
- }
- SysGetMessage(NULL, ret);
- break;
+ memcpy(ret, data, len);
}
- break;
- default:
- // TODO: Implement
- _SysDebug("TODO: Implement AxWin3_int_GetIPCMessage for TCP/UDP");
- break;
}
- // No message?
- if( ret == NULL )
- return NULL;
-
- // TODO: Sanity checks, so a stupid server can't crash us
-
return ret;
}
tAxWin_IPCMessage *msg;
for(;;)
{
- msg = AxWin3_int_GetIPCMessage();
+ msg = AxWin3_int_GetIPCMessage(0, NULL);
if(msg->ID == WantedID) return msg;
AxWin3_int_HandleMessage( msg );
- free(msg);
}
}