a9e416470f7b18c0ffc6b43e378bd01b22c55770
[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                 assert( strncmp(ServerDesc, "udp:", 4) == 0 );
63                 ServerDesc += 4;
64                 _SysDebug("TODO: UDP connection to '%s'", ServerDesc);
65                 // TODO: Open socket and create UDP header
66                 break;
67         case 't':
68                 assert( strncmp(ServerDesc, "tcp:", 4) == 0 );
69                 ServerDesc += 4;
70                 _SysDebug("TODO: TCP connection to '%s'", ServerDesc);
71                 // TODO: Open socket
72                 break;
73         case 'p':
74                 assert( strncmp(ServerDesc, "pipe:", 5) == 0 );
75                 ServerDesc += 5;
76                 giConnectionType = CONNTYPE_IPCPIPE;
77                 giConnectionNum = _SysOpen(ServerDesc, OPENFLAG_READ|OPENFLAG_WRITE);
78                 if( giConnectionNum == -1 ) {
79                         _SysDebug("Cannot open IPC Pipe '%s'", ServerDesc);
80                         exit(-1);
81                 }
82                 break;
83         default:
84                 _SysDebug("Unknown server desc format '%s'", ServerDesc);
85                 exit(-1);
86                 break;
87         }
88 }
89
90 tAxWin3_MessageCallback AxWin3_SetMessageCallback(tAxWin3_MessageCallback Callback)
91 {
92         tAxWin3_MessageCallback old = gAxWin3_MessageCallback;
93         gAxWin3_MessageCallback = Callback;
94         return old;
95 }
96
97 uint32_t AxWin3_int_GetWindowID(tHWND Window)
98 {
99         if(Window)
100                 return Window->ServerID;
101         else
102                 return -1;
103 }
104
105 tAxWin_IPCMessage *AxWin3_int_AllocateIPCMessage(tHWND Window, int Message, int Flags, int ExtraBytes)
106 {
107         tAxWin_IPCMessage       *ret;
108
109         ret = malloc( sizeof(tAxWin_IPCMessage) + ExtraBytes );
110         ret->Flags = Flags;
111         ret->ID = Message;
112         ret->Window = AxWin3_int_GetWindowID(Window);
113         ret->Size = ExtraBytes;
114         return ret;
115 }
116
117 void AxWin3_int_SendIPCMessage(tAxWin_IPCMessage *Msg)
118 {
119          int    size = sizeof(tAxWin_IPCMessage) + Msg->Size;
120         switch(giConnectionType)
121         {
122         case CONNTYPE_SENDMESSAGE:
123                 _SysSendMessage(giConnectionNum, size, Msg);
124                 break;
125         case CONNTYPE_UDP: {
126                 // Create UDP header
127                 char    tmpbuf[giAxWin3_int_UDPHeaderLen + size];
128                 memcpy(tmpbuf, gaAxWin3_int_UDPHeader, giAxWin3_int_UDPHeaderLen);
129                 memcpy(tmpbuf + giAxWin3_int_UDPHeaderLen, Msg, size);
130                 _SysWrite(giConnectionNum, tmpbuf, sizeof(tmpbuf));
131                 }
132                 break;
133         case CONNTYPE_IPCPIPE:
134         case CONNTYPE_TCP:
135                 _SysWrite(giConnectionNum, Msg, size);
136                 break;
137         default:
138                 break;
139         }
140 }
141
142 tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(int nFD, fd_set *fds)
143 {
144          int    len;
145         tAxWin_IPCMessage       *ret = NULL;
146          int    tid;
147         fd_set  local_set;
148         
149         if(!fds)
150                 fds = &local_set;
151
152         if( giConnectionType != CONNTYPE_SENDMESSAGE )
153         {
154                 if(nFD <= giConnectionNum)
155                         nFD = giConnectionNum+1;
156                 FD_SET(giConnectionNum, fds);
157         }
158
159         _SysSelect(nFD, fds, NULL, NULL, NULL, THREAD_EVENT_IPCMSG);
160         
161         // Clear out IPC messages
162         while( (len = _SysGetMessage(&tid, 0, NULL)) )
163         {
164                 if( giConnectionType != CONNTYPE_SENDMESSAGE || tid != giConnectionNum )
165                 {
166                         _SysDebug("%i byte message from %i", len, tid);
167                         // If not, pass the buck (or ignore)
168                         if( gAxWin3_MessageCallback )
169                                 gAxWin3_MessageCallback(tid, len);
170                         else
171                                 _SysGetMessage(NULL, 0, GETMSG_IGNORE);
172                         continue ;
173                 }
174                 
175                 // Using CONNTYPE_SENDMESSAGE and server message has arrived
176                 ret = malloc(len);
177                 if(ret == NULL) {
178                         _SysDebug("malloc() failed, ignoring message");
179                         _SysGetMessage(NULL, 0, GETMSG_IGNORE);
180                         return NULL;
181                 }
182                 _SysGetMessage(NULL, len, ret);
183                 break;
184         }
185
186         if( giConnectionType != CONNTYPE_SENDMESSAGE )
187         {
188                 if( FD_ISSET(giConnectionNum, fds) )
189                 {
190                         char    tmpbuf[STATICBUF_SIZE];
191                         char    *data = tmpbuf;
192                         size_t len = _SysRead(giConnectionNum, tmpbuf, sizeof(tmpbuf));
193                         
194                         if( giConnectionType == CONNTYPE_UDP )
195                         {
196                                 assert(len > giAxWin3_int_UDPHeaderLen);
197                                 len -= giAxWin3_int_UDPHeaderLen;
198                                 data += giAxWin3_int_UDPHeaderLen;
199                         }
200                         assert(len >= sizeof(tAxWin_IPCMessage));
201                         ret = malloc(len);
202                         memcpy(ret, data, len);
203                 }
204         }
205
206         return ret;
207 }
208
209 tAxWin_IPCMessage *AxWin3_int_WaitIPCMessage(int WantedID)
210 {
211         tAxWin_IPCMessage       *msg;
212         for(;;)
213         {
214                 msg = AxWin3_int_GetIPCMessage(0, NULL);
215                 if(msg->ID == WantedID) return msg;
216                 AxWin3_int_HandleMessage( msg );
217         }
218 }
219

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