Usermode/AxWin3 - Working on IPC
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / ipc.c
1 /*
2  * Acess2 GUI (AxWin) Version 3
3  * - By John Hodge (thePowersGang)
4  * 
5  * ipc.c
6  * - Interprocess communication
7  */
8 #include <common.h>
9 #include <acess/sys.h>
10 #include <net.h>
11 #include <string.h>
12 #include <ipcmessages.h>
13
14 #define AXWIN_PORT      4101
15
16 #define STATICBUF_SIZE  64
17
18 // === TYPES ===
19 typedef struct sIPC_Type        tIPC_Type;
20 struct sIPC_Type
21 {
22          int    (*GetIdentSize)(void *Ident);
23          int    (*CompareIdent)(void *Ident1, void *Ident2);
24         void    (*SendMessage)(void *Ident, size_t, void *Data);
25 };
26
27 // === PROTOTYPES ===
28 void    IPC_Init(void);
29 void    IPC_FillSelect(int *nfds, fd_set *set);
30 void    IPC_HandleSelect(fd_set *set);
31 void    IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg);
32 void    IPC_ReturnValue(tIPC_Type *IPCType, void *Ident, int MessageID, uint32_t Value);
33  int    IPC_Type_Datagram_GetSize(void *Ident);
34  int    IPC_Type_Datagram_Compare(void *Ident1, void *Ident2);
35 void    IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data);
36  int    IPC_Type_Sys_GetSize(void *Ident);
37  int    IPC_Type_Sys_Compare(void *Ident1, void *Ident2);
38 void    IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data);
39
40 // === GLOBALS ===
41  int    giNetworkFileHandle = -1;
42  int    giMessagesFileHandle = -1;
43 tIPC_Type       gIPC_Type_Datagram = {
44         IPC_Type_Datagram_GetSize,
45         IPC_Type_Datagram_Compare, 
46         IPC_Type_Datagram_Send
47 };
48 tIPC_Type       gIPC_Type_SysMessage = {
49         IPC_Type_Sys_GetSize,
50         IPC_Type_Sys_Compare,
51         IPC_Type_Sys_Send
52 };
53
54 // === CODE ===
55 void IPC_Init(void)
56 {
57          int    tmp;
58         // TODO: Check this
59         giNetworkFileHandle = open("/Devices/ip/loop/udp", OPENFLAG_READ);
60         tmp = AXWIN_PORT;       ioctl(giNetworkFileHandle, 4, &tmp);    // TODO: Don't hard-code IOCtl number
61 }
62
63 void IPC_FillSelect(int *nfds, fd_set *set)
64 {
65         if( giNetworkFileHandle > *nfds )       *nfds = giNetworkFileHandle;
66         FD_SET(giNetworkFileHandle, set);
67 }
68
69 void IPC_HandleSelect(fd_set *set)
70 {
71         if( FD_ISSET(giNetworkFileHandle, set) )
72         {
73                 char    staticBuf[STATICBUF_SIZE];
74                  int    readlen, identlen;
75                 char    *msg;
76
77                 readlen = read(giNetworkFileHandle, staticBuf, sizeof(staticBuf));
78                 
79                 identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
80                 msg = staticBuf + identlen;
81
82                 IPC_Handle(&gIPC_Type_Datagram, staticBuf, readlen - identlen, (void*)msg);
83                 _SysDebug("IPC_HandleSelect: UDP handled");
84         }
85
86         while(SysGetMessage(NULL, NULL))
87         {
88                 pid_t   tid;
89                  int    len = SysGetMessage(&tid, NULL);
90                 char    data[len];
91                 SysGetMessage(NULL, data);
92
93                 IPC_Handle(&gIPC_Type_SysMessage, &tid, len, (void*)data);
94                 _SysDebug("IPC_HandleSelect: Message handled");
95         }
96 }
97
98 void IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_IPCMessage *Msg)
99 {
100         tApplication    *app;
101         tElement        *ele;
102         
103         _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)",
104                 IPCType, Ident, MsgLen, Msg);
105         
106         if( MsgLen < sizeof(tAxWin_Message) )
107                 return ;
108         if( MsgLen < sizeof(tAxWin_Message) + Msg->Size )
109                 return ;
110         
111         app = AxWin_GetClient(IPCType, Ident);
112
113         switch((enum eAxWin_IPCMessageTypes) Msg->ID)
114         {
115         // --- Ping message (reset timeout and get server version)
116         case IPCMSG_PING:
117                 _SysDebug(" IPC_Handle: IPCMSG_PING");
118                 if( MsgLen < sizeof(tAxWin_Message) + 4 )       return;
119                 if( Msg->Flags & IPCMSG_FLAG_RETURN )
120                 {
121                         Msg->ID = IPCMSG_PING;
122                         Msg->Size = sizeof(tIPCMsg_Return);
123                         ((tIPCMsg_Return*)Msg->Data)->Value = AXWIN_VERSION;
124                         IPCType->SendMessage(Ident, sizeof(tIPCMsg_Return), Msg);
125                 }
126                 break;
127
128         // --- 
129
130         // --- Unknown message
131         default:
132                 fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
133                 _SysDebug("WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
134                 break;
135         }
136 }
137
138 void IPC_ReturnValue(tIPC_Type *IPCType, void *Ident, int MessageID, uint32_t Value)
139 {
140         char    data[sizeof(tAxWin_Message) + sizeof(tAxWin_RetMsg)];
141         tAxWin_Message  *msg = (void *)data;
142         tAxWin_RetMsg   *ret_msg = (void *)msg->Data;
143         
144         msg->Source = 0;        // 0 = Server
145         msg->ID = MSG_SRSP_RETURN;
146         msg->Size = sizeof(tAxWin_RetMsg);
147         ret_msg->ReqID = MessageID;
148         ret_msg->Rsvd = 0;
149         ret_msg->Value = Value;
150         
151         IPCType->SendMessage(Ident, sizeof(data), data);
152 }
153
154 int IPC_Type_Datagram_GetSize(void *Ident)
155 {
156         return 4 + Net_GetAddressSize( ((uint16_t*)Ident)[1] );
157 }
158
159 int IPC_Type_Datagram_Compare(void *Ident1, void *Ident2)
160 {
161         // Pass the buck :)
162         // - No need to worry about mis-matching sizes, as the size is computed
163         //   from the 3rd/4th bytes, hence it will differ before the size is hit.
164         return memcmp(Ident1, Ident2, IPC_Type_Datagram_GetSize(Ident1));
165 }
166
167 void IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data)
168 {
169          int    identlen = IPC_Type_Datagram_GetSize(Ident);
170         char    tmpbuf[ identlen + Length ];
171         memcpy(tmpbuf, Ident, identlen);        // Header
172         memcpy(tmpbuf + identlen, Data, Length);        // Data
173         // TODO: Handle fragmented packets
174         write(giNetworkFileHandle, tmpbuf, sizeof(tmpbuf));
175 }
176
177 int IPC_Type_Sys_GetSize(void *Ident)
178 {
179         return sizeof(pid_t);
180 }
181
182 int IPC_Type_Sys_Compare(void *Ident1, void *Ident2)
183 {
184         return *(int*)Ident1 - *(int*)Ident2;
185 }
186
187 void IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data)
188 {
189         SysSendMessage( *(tid_t*)Ident, Length, Data );
190 }

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