Merge branch 'master' of ssh.ucc.asn.au:tpg/acess2
[tpg/acess2.git] / Usermode / Applications / axwin3_src / libaxwin3.so_src / msg.c
1 /*
2  * AxWin3 Interface Library
3  * - By John Hodge (thePowersGang)
4  *
5  * msg.c
6  * - Message handling / IPC
7  */
8 #include <axwin3/axwin.h>
9 #include <acess/sys.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <ipcmessages.h>        // AxWin3 common
13 #include "include/internal.h"
14 #include "include/ipc.h"
15
16 #define assert(cnd)     do{if(!(cnd)){_SysDebug("Assertion failed: %s", #cnd);}}while(0)
17
18 #define STATICBUF_SIZE  0x1000
19
20 // === CONSTANTS ===
21 enum eConnectionType
22 {
23         CONNTYPE_NONE,
24         CONNTYPE_SENDMESSAGE,
25         CONNTYPE_IPCPIPE,
26         CONNTYPE_UDP,
27         CONNTYPE_TCP
28 };
29
30 // === GLOBALS ===
31 enum eConnectionType    giConnectionType;
32 int     giConnectionNum;        // FD or PID
33 char    gaAxWin3_int_UDPHeader[] = {5,16,0,0};  // Port 4101
34  int    giAxWin3_int_UDPHeaderLen = sizeof(gaAxWin3_int_UDPHeader);
35 const char      *gsAxWin3_int_ServerDesc;
36 tAxWin3_MessageCallback gAxWin3_MessageCallback;
37
38 // === CODE ===
39 void AxWin3_Connect(const char *ServerDesc)
40 {
41         if( !ServerDesc ) {
42                 ServerDesc = gsAxWin3_int_ServerDesc;
43         }
44         _SysDebug("ServerDesc = %s", ServerDesc);
45         if( !ServerDesc )
46         {
47                 // TODO: Error out
48                 return ;
49         }
50         switch(ServerDesc[0])
51         {
52         case '1': case '2': case '3': case '4': case '5':
53         case '6': case '7': case '8': case '9': case '0':
54                 giConnectionType = CONNTYPE_SENDMESSAGE;
55                 giConnectionNum = atoi(ServerDesc);
56                 if( giConnectionNum == 0 ) {
57                         _SysDebug("Invalid server PID");
58                         exit(-1);
59                 }
60                 break;
61         case 'u':
62                 while(*ServerDesc && *ServerDesc != ':')        ServerDesc ++;
63                 ServerDesc ++;
64                 // TODO: Open socket and create UDP header
65                 break;
66         case 't':
67                 while(*ServerDesc && *ServerDesc != ':')        ServerDesc ++;
68                 ServerDesc ++;
69                 // TODO: Open socket
70                 break;
71         case 'p':
72                 assert( strncmp(ServerDesc, "pipe:", 5) == 0 );
73                 ServerDesc += 5;
74                 giConnectionType = CONNTYPE_IPCPIPE;
75                 giConnectionNum = _SysOpen(ServerDesc, OPENFLAG_READ|OPENFLAG_WRITE);
76                 if( giConnectionNum == -1 ) {
77                         _SysDebug("Cannot open IPC Pipe '%s'", ServerDesc);
78                         exit(-1);
79                 }
80                 break;
81         default:
82                 _SysDebug("Unknown server desc format '%s'", ServerDesc);
83                 exit(-1);
84                 break;
85         }
86 }
87
88 tAxWin3_MessageCallback AxWin3_SetMessageCallback(tAxWin3_MessageCallback Callback)
89 {
90         tAxWin3_MessageCallback old = gAxWin3_MessageCallback;
91         gAxWin3_MessageCallback = Callback;
92         return old;
93 }
94
95 uint32_t AxWin3_int_GetWindowID(tHWND Window)
96 {
97         if(Window)
98                 return Window->ServerID;
99         else
100                 return -1;
101 }
102
103 tAxWin_IPCMessage *AxWin3_int_AllocateIPCMessage(tHWND Window, int Message, int Flags, int ExtraBytes)
104 {
105         tAxWin_IPCMessage       *ret;
106
107         ret = malloc( sizeof(tAxWin_IPCMessage) + ExtraBytes );
108         ret->Flags = Flags;
109         ret->ID = Message;
110         ret->Window = AxWin3_int_GetWindowID(Window);
111         ret->Size = ExtraBytes;
112         return ret;
113 }
114
115 void AxWin3_int_SendIPCMessage(tAxWin_IPCMessage *Msg)
116 {
117          int    size = sizeof(tAxWin_IPCMessage) + Msg->Size;
118         switch(giConnectionType)
119         {
120         case CONNTYPE_SENDMESSAGE:
121                 _SysSendMessage(giConnectionNum, size, Msg);
122                 break;
123         case CONNTYPE_UDP: {
124                 // Create UDP header
125                 char    tmpbuf[giAxWin3_int_UDPHeaderLen + size];
126                 memcpy(tmpbuf, gaAxWin3_int_UDPHeader, giAxWin3_int_UDPHeaderLen);
127                 memcpy(tmpbuf + giAxWin3_int_UDPHeaderLen, Msg, size);
128                 _SysWrite(giConnectionNum, tmpbuf, sizeof(tmpbuf));
129                 }
130                 break;
131         case CONNTYPE_IPCPIPE:
132         case CONNTYPE_TCP:
133                 _SysWrite(giConnectionNum, Msg, size);
134                 break;
135         default:
136                 break;
137         }
138 }
139
140 tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(int nFD, fd_set *fds)
141 {
142          int    len;
143         tAxWin_IPCMessage       *ret = NULL;
144          int    tid;
145         fd_set  local_set;
146         
147         if(!fds)
148                 fds = &local_set;
149
150         if( giConnectionType != CONNTYPE_SENDMESSAGE )
151         {
152                 if(nFD <= giConnectionNum)
153                         nFD = giConnectionNum+1;
154                 FD_SET(giConnectionNum, fds);
155         }
156
157         _SysSelect(nFD, fds, NULL, NULL, NULL, THREAD_EVENT_IPCMSG);
158         
159         // Clear out IPC messages
160         while( (len = _SysGetMessage(&tid, 0, NULL)) )
161         {
162                 if( giConnectionType != CONNTYPE_SENDMESSAGE || tid != giConnectionNum )
163                 {
164                         _SysDebug("%i byte message from %i", len, tid);
165                         // If not, pass the buck (or ignore)
166                         if( gAxWin3_MessageCallback )
167                                 gAxWin3_MessageCallback(tid, len);
168                         else
169                                 _SysGetMessage(NULL, 0, GETMSG_IGNORE);
170                         continue ;
171                 }
172                 
173                 // Using CONNTYPE_SENDMESSAGE and server message has arrived
174                 ret = malloc(len);
175                 if(ret == NULL) {
176                         _SysDebug("malloc() failed, ignoring message");
177                         _SysGetMessage(NULL, 0, GETMSG_IGNORE);
178                         return NULL;
179                 }
180                 _SysGetMessage(NULL, len, ret);
181                 break;
182         }
183
184         if( giConnectionType != CONNTYPE_SENDMESSAGE )
185         {
186                 if( FD_ISSET(giConnectionNum, fds) )
187                 {
188                         char    tmpbuf[STATICBUF_SIZE];
189                         char    *data = tmpbuf;
190                         size_t len = _SysRead(giConnectionNum, tmpbuf, sizeof(tmpbuf));
191                         
192                         if( giConnectionType == CONNTYPE_UDP )
193                         {
194                                 assert(len > giAxWin3_int_UDPHeaderLen);
195                                 len -= giAxWin3_int_UDPHeaderLen;
196                                 data += giAxWin3_int_UDPHeaderLen;
197                         }
198                         assert(len >= sizeof(tAxWin_IPCMessage));
199                         ret = malloc(len);
200                         memcpy(ret, data, len);
201                 }
202         }
203
204         return ret;
205 }
206
207 tAxWin_IPCMessage *AxWin3_int_WaitIPCMessage(int WantedID)
208 {
209         tAxWin_IPCMessage       *msg;
210         for(;;)
211         {
212                 msg = AxWin3_int_GetIPCMessage(0, NULL);
213                 if(msg->ID == WantedID) return msg;
214                 AxWin3_int_HandleMessage( msg );
215         }
216 }
217

UCC git Repository :: git.ucc.asn.au