*/
#include "common.h"
#include <acess/sys.h>
-#include <axwin/messages.h>
+#include <net.h>
+#include <axwin2/messages.h>
+#include <string.h>
+
+#define AXWIN_PORT 4101
#define STATICBUF_SIZE 64
// === TYPES ===
-typedef void tMessages_Handle_Callback(int, size_t,void*);
// === PROTOTYPES ===
-void Messages_PollIPC();
-void Messages_RespondIPC(int ID, size_t Length, void *Data);
-void Messages_Handle(tAxWin_Message *Msg, tMessages_Handle_Callback *Respond, int ID);
+void IPC_Init(void);
+void IPC_FillSelect(int *nfds, fd_set *set);
+void IPC_HandleSelect(fd_set *set);
+void IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg);
+void IPC_ReturnValue(tIPC_Type *IPCType, void *Ident, int MessageID, uint32_t Value);
+ int IPC_Type_Datagram_GetSize(void *Ident);
+ int IPC_Type_Datagram_Compare(void *Ident1, void *Ident2);
+void IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data);
+ int IPC_Type_Sys_GetSize(void *Ident);
+ int IPC_Type_Sys_Compare(void *Ident1, void *Ident2);
+void IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data);
// === GLOBALS ===
+ int giNetworkFileHandle = -1;
+ int giMessagesFileHandle = -1;
+tIPC_Type gIPC_Type_Datagram = {
+ IPC_Type_Datagram_GetSize,
+ IPC_Type_Datagram_Compare,
+ IPC_Type_Datagram_Send
+};
+tIPC_Type gIPC_Type_SysMessage = {
+ IPC_Type_Sys_GetSize,
+ IPC_Type_Sys_Compare,
+ IPC_Type_Sys_Send
+};
// === CODE ===
-void Messages_PollIPC()
+void IPC_Init(void)
+{
+ int tmp;
+ // TODO: Check this
+ giNetworkFileHandle = open("/Devices/ip/loop/udp", OPENFLAG_READ);
+ tmp = AXWIN_PORT; ioctl(giNetworkFileHandle, 4, &tmp); // TODO: Don't hard-code IOCtl number
+}
+
+void IPC_FillSelect(int *nfds, fd_set *set)
{
- int len;
- pid_t tid = 0;
- char staticBuf[STATICBUF_SIZE];
- tAxWin_Message *msg;
+ if( giNetworkFileHandle > *nfds ) *nfds = giNetworkFileHandle;
+ FD_SET(giNetworkFileHandle, set);
+}
+
+void IPC_HandleSelect(fd_set *set)
+{
+ if( FD_ISSET(giNetworkFileHandle, set) )
+ {
+ char staticBuf[STATICBUF_SIZE];
+ int readlen, identlen;
+ char *msg;
+
+ readlen = read(giNetworkFileHandle, sizeof(staticBuf), staticBuf);
+
+ // Assume that all connections are from localhost
+ identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
+ msg = staticBuf + identlen;
+
+ IPC_Handle(&gIPC_Type_Datagram, staticBuf, readlen - identlen, (void*)msg);
+ }
+
+ while(SysGetMessage(NULL, NULL))
+ {
+ pid_t tid;
+ int len = SysGetMessage(&tid, NULL);
+ char data[len];
+ SysGetMessage(NULL, data);
+
+ IPC_Handle(&gIPC_Type_SysMessage, &tid, len, (void*)data);
+ }
+}
+
+void IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg)
+{
+ tApplication *app;
+ tElement *ele;
- // Wait for a message
- while( (len = SysGetMessage(&tid, NULL)) == 0 )
- sleep();
+ if( MsgLen < sizeof(tAxWin_Message) )
+ return ;
+ if( MsgLen < sizeof(tAxWin_Message) + Msg->Size )
+ return ;
- // Allocate the space for it
- if( len <= STATICBUF_SIZE )
- msg = (void*)staticBuf;
- else {
- msg = malloc( len );
- if(!msg) {
- fprintf(
- stderr,
- "ERROR - Unable to allocate message buffer, ignoring message from %i\n",
- tid);
- SysGetMessage(NULL, GETMSG_IGNORE);
+ app = AxWin_GetClient(IPCType, Ident);
+
+ switch((enum eAxWin_Messages) Msg->ID)
+ {
+ // --- Ping message (reset timeout and get server version)
+ case MSG_SREQ_PING:
+ if( MsgLen < sizeof(tAxWin_Message) + 4 ) return;
+ Msg->ID = MSG_SRSP_VERSION;
+ Msg->Size = 4;
+ Msg->Data[0] = 0;
+ Msg->Data[1] = 1;
+ *(uint16_t*)&Msg->Data[2] = -1;
+ IPCType->SendMessage(Ident, sizeof(Msg->ID), Msg);
+ break;
+
+
+ // --- Register an application
+ case MSG_SREQ_REGISTER:
+ if( Msg->Data[Msg->Size-1] != '\0' ) {
+ // Invalid message
+ return ;
+ }
+
+ if( app != NULL ) {
+ _SysDebug("Notice: Duplicate registration (%s)\n", Msg->Data);
return ;
}
+
+ // TODO: Should this function be implemented here?
+ AxWin_RegisterClient(IPCType, Ident, Msg->Data);
+ break;
+
+ // --- Create a window
+ case MSG_SREQ_ADDWIN:
+ if( Msg->Data[Msg->Size-1] != '\0' ) {
+ // Invalid message
+ return ;
+ }
+
+ ele = AxWin_CreateAppWindow(app, Msg->Data);
+ IPC_ReturnValue(IPCType, Ident, MSG_SREQ_ADDWIN, ele->ApplicationID);
+ break;
+
+ // --- Set a window's icon
+ case MSG_SREQ_SETICON:
+ // TODO: Find a good way of implementing this
+ break;
+
+ // --- Create an element
+ case MSG_SREQ_INSERT: {
+ struct sAxWin_SReq_NewElement *info = (void *)Msg->Data;
+
+ if( Msg->Size != sizeof(*info) ) return;
+
+ if( !app || info->Parent > app->MaxElementIndex ) return ;
+
+ ele = AxWin_CreateElement( app->EleIndex[info->Parent], info->Type, info->Flags, NULL );
+ IPC_ReturnValue(IPCType, Ident, MSG_SREQ_ADDWIN, ele->ApplicationID);
+ break; }
+
+ // --- Unknown message
+ default:
+ fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
+ _SysDebug("WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
+ break;
}
+}
+
+void IPC_ReturnValue(tIPC_Type *IPCType, void *Ident, int MessageID, uint32_t Value)
+{
+ char data[sizeof(tAxWin_Message) + sizeof(tAxWin_RetMsg)];
+ tAxWin_Message *msg = (void *)data;
+ tAxWin_RetMsg *ret_msg = (void *)msg->Data;
- // Get message data
- SysGetMessage(NULL, msg);
+ msg->Source = 0; // 0 = Server
+ msg->ID = MSG_SRSP_RETURN;
+ msg->Size = sizeof(tAxWin_RetMsg);
+ ret_msg->ReqID = MessageID;
+ ret_msg->Rsvd = 0;
+ ret_msg->Value = Value;
- Messages_Handle(msg, Messages_RespondIPC, tid);
+ IPCType->SendMessage(Ident, sizeof(data), data);
}
-void Messages_RespondIPC(int ID, size_t Length, void *Data)
+int IPC_Type_Datagram_GetSize(void *Ident)
{
- SysSendMessage(ID, Length, Data);
+ return 4 + Net_GetAddressSize( ((uint16_t*)Ident)[1] );
}
-void Messages_Handle(tAxWin_Message *Msg, tMessages_Handle_Callback *Respond, int ID)
+int IPC_Type_Datagram_Compare(void *Ident1, void *Ident2)
{
- switch(Msg->ID)
- {
- case MSG_SREQ_PING:
- Msg->ID = MSG_SRSP_PONG;
- Msg->Size = 2;
- Msg->SRsp_Pong.Major = 0;
- Msg->SRsp_Pong.Minor = 1;
- Msg->SRsp_Pong.Build = -1;
- Messages_RespondIPC(ID, sizeof(Msg->ID), Msg);
- break;
- default:
- fprintf(stderr, "WARNING: Unknown message %i from %i (%p)\n", Msg->ID, ID, Respond);
- _SysDebug("WARNING: Unknown message %i from %i (%p)\n", Msg->ID, ID, Respond);
- break;
- }
+ // Pass the buck :)
+ // - No need to worry about mis-matching sizes, as the size is computed
+ // from the 3rd/4th bytes, hence it will differ before the size is hit.
+ return memcmp(Ident1, Ident2, IPC_Type_Datagram_GetSize(Ident1));
+}
+
+void IPC_Type_Datagram_Send(void *Ident, size_t Length, void *Data)
+{
+ int identlen = IPC_Type_Datagram_GetSize(Ident);
+ char tmpbuf[ identlen + Length ];
+ memcpy(tmpbuf, Ident, identlen); // Header
+ memcpy(tmpbuf + identlen, Data, Length); // Data
+ // TODO: Handle fragmented packets
+ write(giNetworkFileHandle, sizeof(tmpbuf), tmpbuf);
+}
+
+int IPC_Type_Sys_GetSize(void *Ident)
+{
+ return sizeof(pid_t);
}
+int IPC_Type_Sys_Compare(void *Ident1, void *Ident2)
+{
+ return *(int*)Ident1 - *(int*)Ident2;
+}
+
+void IPC_Type_Sys_Send(void *Ident, size_t Length, void *Data)
+{
+ SysSendMessage( *(tid_t*)Ident, Length, Data );
+}