AxWin2 - More fiddling, almost ready now :)
[tpg/acess2.git] / Usermode / Applications / axwin2_src / WM / messages.c
1 /*
2  * Acess GUI (AxWin) Version 2
3  * By John Hodge (thePowersGang)
4  */
5 #include "common.h"
6 #include <acess/sys.h>
7 #include <net.h>
8 #include <axwin2/messages.h>
9 #include <string.h>
10
11 #define AXWIN_PORT      4101
12
13 #define STATICBUF_SIZE  64
14
15 // === TYPES ===
16
17 // === PROTOTYPES ===
18 void    IPC_Init(void);
19 void    IPC_FillSelect(int *nfds, fd_set *set);
20 void    IPC_HandleSelect(fd_set *set);
21 void    IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg);
22 void    IPC_ReturnValue(tIPC_Type *IPCType, void *Ident, int MessageID, uint32_t Value);
23  int    IPC_Type_Datagram_GetSize(void *Ident);
24  int    IPC_Type_Datagram_Compare(void *Ident1, void *Ident2);
25 void    IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data);
26  int    IPC_Type_Sys_GetSize(void *Ident);
27  int    IPC_Type_Sys_Compare(void *Ident1, void *Ident2);
28 void    IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data);
29
30 // === GLOBALS ===
31  int    giNetworkFileHandle = -1;
32  int    giMessagesFileHandle = -1;
33 tIPC_Type       gIPC_Type_Datagram = {
34         IPC_Type_Datagram_GetSize,
35         IPC_Type_Datagram_Compare, 
36         IPC_Type_Datagram_Send
37 };
38 tIPC_Type       gIPC_Type_SysMessage = {
39         IPC_Type_Sys_GetSize,
40         IPC_Type_Sys_Compare,
41         IPC_Type_Sys_Send
42 };
43
44 // === CODE ===
45 void IPC_Init(void)
46 {
47          int    tmp;
48         // TODO: Check this
49         giNetworkFileHandle = open("/Devices/ip/loop/udp", OPENFLAG_READ);
50         tmp = AXWIN_PORT;       ioctl(giNetworkFileHandle, 4, &tmp);    // TODO: Don't hard-code IOCtl number
51 }
52
53 void IPC_FillSelect(int *nfds, fd_set *set)
54 {
55         if( giNetworkFileHandle > *nfds )       *nfds = giNetworkFileHandle;
56         FD_SET(giNetworkFileHandle, set);
57 }
58
59 void IPC_HandleSelect(fd_set *set)
60 {
61         if( FD_ISSET(giNetworkFileHandle, set) )
62         {
63                 char    staticBuf[STATICBUF_SIZE];
64                  int    readlen, identlen;
65                 char    *msg;
66
67                 readlen = read(giNetworkFileHandle, sizeof(staticBuf), staticBuf);
68                 
69                 // Assume that all connections are from localhost
70                 identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
71                 msg = staticBuf + identlen;
72
73                 IPC_Handle(&gIPC_Type_Datagram, staticBuf, readlen - identlen, (void*)msg);
74         }
75
76         while(SysGetMessage(NULL, NULL))
77         {
78                 pid_t   tid;
79                  int    len = SysGetMessage(&tid, NULL);
80                 char    data[len];
81                 SysGetMessage(NULL, data);
82
83                 IPC_Handle(&gIPC_Type_SysMessage, &tid, len, (void*)data);
84         }
85 }
86
87 void IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg)
88 {
89         tApplication    *app;
90         tElement        *ele;
91         
92         if( MsgLen < sizeof(tAxWin_Message) )
93                 return ;
94         if( MsgLen < sizeof(tAxWin_Message) + Msg->Size )
95                 return ;
96         
97         app = AxWin_GetClient(IPCType, Ident);
98
99         switch((enum eAxWin_Messages) Msg->ID)
100         {
101         // --- Ping message (reset timeout and get server version)
102         case MSG_SREQ_PING:
103                 if( MsgLen < sizeof(tAxWin_Message) + 4 )       return;
104                 Msg->ID = MSG_SRSP_VERSION;
105                 Msg->Size = 4;
106                 Msg->Data[0] = 0;
107                 Msg->Data[1] = 1;
108                 *(uint16_t*)&Msg->Data[2] = -1;
109                 IPCType->SendMessage(Ident, sizeof(Msg->ID), Msg);
110                 break;
111
112
113         // --- Register an application
114         case MSG_SREQ_REGISTER:
115                 if( Msg->Data[Msg->Size-1] != '\0' ) {
116                         // Invalid message
117                         return ;
118                 }
119                 
120                 if( app != NULL ) {
121                         _SysDebug("Notice: Duplicate registration (%s)\n", Msg->Data);
122                         return ;
123                 }
124                 
125                 // TODO: Should this function be implemented here?
126                 AxWin_RegisterClient(IPCType, Ident, Msg->Data);
127                 break;
128         
129         // --- Create a window
130         case MSG_SREQ_ADDWIN:
131                 if( Msg->Data[Msg->Size-1] != '\0' ) {
132                         // Invalid message
133                         return ;
134                 }
135                 
136                 ele = AxWin_CreateAppWindow(app, Msg->Data);
137                 IPC_ReturnValue(IPCType, Ident, MSG_SREQ_ADDWIN, ele->ApplicationID);
138                 break;
139         
140         // --- Set a window's icon
141         case MSG_SREQ_SETICON:
142                 // TODO: Find a good way of implementing this
143                 break;
144         
145         // --- Create an element
146         case MSG_SREQ_INSERT: {
147                 struct sAxWin_SReq_NewElement   *info = (void *)Msg->Data;
148                 
149                 if( Msg->Size != sizeof(*info) )        return;
150                 
151                 if( !app || info->Parent > app->MaxElementIndex )       return ;
152                 
153                 ele = AxWin_CreateElement( app->EleIndex[info->Parent], info->Type, info->Flags, NULL );
154                 IPC_ReturnValue(IPCType, Ident, MSG_SREQ_ADDWIN, ele->ApplicationID);
155                 break; }
156         
157         // --- Unknown message
158         default:
159                 fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
160                 _SysDebug("WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
161                 break;
162         }
163 }
164
165 void IPC_ReturnValue(tIPC_Type *IPCType, void *Ident, int MessageID, uint32_t Value)
166 {
167         char    data[sizeof(tAxWin_Message) + sizeof(tAxWin_RetMsg)];
168         tAxWin_Message  *msg = (void *)data;
169         tAxWin_RetMsg   *ret_msg = (void *)msg->Data;
170         
171         msg->Source = 0;        // 0 = Server
172         msg->ID = MSG_SRSP_RETURN;
173         msg->Size = sizeof(tAxWin_RetMsg);
174         ret_msg->ReqID = MessageID;
175         ret_msg->Rsvd = 0;
176         ret_msg->Value = Value;
177         
178         IPCType->SendMessage(Ident, sizeof(data), data);
179 }
180
181 int IPC_Type_Datagram_GetSize(void *Ident)
182 {
183         return 4 + Net_GetAddressSize( ((uint16_t*)Ident)[1] );
184 }
185
186 int IPC_Type_Datagram_Compare(void *Ident1, void *Ident2)
187 {
188         // Pass the buck :)
189         // - No need to worry about mis-matching sizes, as the size is computed
190         //   from the 3rd/4th bytes, hence it will differ before the size is hit.
191         return memcmp(Ident1, Ident2, IPC_Type_Datagram_GetSize(Ident1));
192 }
193
194 void IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data)
195 {
196          int    identlen = IPC_Type_Datagram_GetSize(Ident);
197         char    tmpbuf[ identlen + Length ];
198         memcpy(tmpbuf, Ident, identlen);        // Header
199         memcpy(tmpbuf + identlen, Data, Length);        // Data
200         // TODO: Handle fragmented packets
201         write(giNetworkFileHandle, sizeof(tmpbuf), tmpbuf);
202 }
203
204 int IPC_Type_Sys_GetSize(void *Ident)
205 {
206         return sizeof(pid_t);
207 }
208
209 int IPC_Type_Sys_Compare(void *Ident1, void *Ident2)
210 {
211         return *(int*)Ident1 - *(int*)Ident2;
212 }
213
214 void IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data)
215 {
216         SysSendMessage( *(tid_t*)Ident, Length, Data );
217 }

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