X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;ds=sidebyside;f=Usermode%2FApplications%2Faxwin2_src%2FWM%2Fmessages.c;h=f25e1c4b1cefd377b779ab3a9289925a21b0270e;hb=70e01c27ee4c2f92000e0857262bec59db59efda;hp=bf2d2b89f7eeb531278ae6ff5f6b7707ecb84b42;hpb=3c85c92afe3f506a921447ef07963525d796137b;p=tpg%2Facess2.git diff --git a/Usermode/Applications/axwin2_src/WM/messages.c b/Usermode/Applications/axwin2_src/WM/messages.c index bf2d2b89..f25e1c4b 100644 --- a/Usermode/Applications/axwin2_src/WM/messages.c +++ b/Usermode/Applications/axwin2_src/WM/messages.c @@ -4,70 +4,224 @@ */ #include "common.h" #include -#include +#include +#include +#include + +#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; - int 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, staticBuf, sizeof(staticBuf)); + + identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] ); + msg = staticBuf + identlen; + + IPC_Handle(&gIPC_Type_Datagram, staticBuf, readlen - identlen, (void*)msg); + _SysDebug("IPC_HandleSelect: UDP handled"); + } + + 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); + _SysDebug("IPC_HandleSelect: Message handled"); + } +} + +void IPC_Handle(tIPC_Type *IPCType, void *Ident, size_t MsgLen, tAxWin_Message *Msg) +{ + tApplication *app; + tElement *ele; + + _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)", + IPCType, Ident, MsgLen, Msg); - // Wait for a message - while( (len = SysGetMessage(&tid, NULL)) ) - yield(); + if( MsgLen < sizeof(tAxWin_Message) ) + return ; + if( MsgLen < sizeof(tAxWin_Message) + Msg->Size ) + return ; + + app = AxWin_GetClient(IPCType, Ident); + + switch((enum eAxWin_Messages) Msg->ID) + { + // --- Ping message (reset timeout and get server version) + case MSG_SREQ_PING: + _SysDebug(" IPC_Handle: 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: + _SysDebug(" IPC_Handle: MSG_SREQ_REGISTER"); + if( Msg->Data[Msg->Size-1] != '\0' ) { + // Invalid message + _SysDebug("IPC_Handle: RETURN - Not NULL terminated"); + 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; - // 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); + // --- Create a window + case MSG_SREQ_ADDWIN: + _SysDebug(" IPC_Handle: 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: + _SysDebug(" IPC_Handle: MSG_SREQ_SETICON"); + // TODO: Find a good way of implementing this + break; + + // --- Create an element + case MSG_SREQ_INSERT: { + _SysDebug(" IPC_Handle: 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; - Respond(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, tmpbuf, sizeof(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 ); +}