Usermode/AxWin3 - Updated for PTY support
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / ipc.c
index 2917bc9..dcb43a9 100644 (file)
@@ -53,7 +53,12 @@ void IPC_Type_Datagram_Send(const void *Ident, size_t Length, const void *Data);
  int   IPC_Type_Sys_GetSize(const void *Ident);
  int   IPC_Type_Sys_Compare(const void *Ident1, const void *Ident2);
 void   IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data);
-void   IPC_Handle(const tIPC_Type *IPCType, const void *Ident, size_t MsgLen, tAxWin_IPCMessage *Msg);
+ int   IPC_Type_IPCPipe_GetSize(const void *Ident);
+ int   IPC_Type_IPCPipe_Compare(const void *Ident1, const void *Ident2);
+void   IPC_Type_IPCPipe_Send(const void *Ident, size_t Length, const void *Data);
+tIPC_Client    *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident);
+void   IPC_int_DropClient(tIPC_Client *Client);
+void   IPC_Handle(tIPC_Client *Client, size_t MsgLen, tAxWin_IPCMessage *Msg);
 
 // === GLOBALS ===
 const tIPC_Type        gIPC_Type_Datagram = {
@@ -65,9 +70,14 @@ const tIPC_Type      gIPC_Type_SysMessage = {
        IPC_Type_Sys_GetSize,
        IPC_Type_Sys_Compare,
        IPC_Type_Sys_Send
+};
+const tIPC_Type        gIPC_Type_IPCPipe = {
+       IPC_Type_IPCPipe_GetSize,
+       IPC_Type_IPCPipe_Compare,
+       IPC_Type_IPCPipe_Send
 };
  int   giNetworkFileHandle = -1;
- int   giMessagesFileHandle = -1;
+ int   giIPCPipeHandle = -1;
  int   giIPC_ClientCount;
 tIPC_Client    **gIPC_Clients;
 
@@ -76,51 +86,91 @@ void IPC_Init(void)
 {
         int    tmp;
        // TODO: Check this
-       giNetworkFileHandle = open("/Devices/ip/loop/udp", OPENFLAG_READ);
+       giNetworkFileHandle = _SysOpen("/Devices/ip/loop/udp", OPENFLAG_READ);
        if( giNetworkFileHandle != -1 )
        {
                tmp = AXWIN_PORT;
-               ioctl(giNetworkFileHandle, 4, &tmp);    // TODO: Don't hard-code IOCtl number
+               _SysIOCtl(giNetworkFileHandle, 4, &tmp);        // TODO: Don't hard-code IOCtl number
+       }
+       
+       giIPCPipeHandle = _SysOpen("/Devices/ipcpipe/axwin"/*-$USER*/, OPENFLAG_CREATE);
+       _SysDebug("giIPCPipeHandle = %i", giIPCPipeHandle);
+       if( giIPCPipeHandle == -1 )
+               _SysDebug("ERROR: Can't create IPCPipe handle");
+}
+
+void _setfd(int fd, int *nfds, fd_set *set)
+{
+       if( fd >= 0 )
+       {
+               if( fd >= *nfds )       *nfds = fd+1;
+               FD_SET(fd, set);
        }
 }
 
 void IPC_FillSelect(int *nfds, fd_set *set)
 {
-       if( giNetworkFileHandle != -1 )
+       _setfd(giNetworkFileHandle, nfds, set);
+       _setfd(giIPCPipeHandle, nfds, set);
+       for( int i = 0; i < giIPC_ClientCount; i ++ )
        {
-               if( giNetworkFileHandle > *nfds )       *nfds = giNetworkFileHandle;
-               FD_SET(giNetworkFileHandle, set);
+               if( gIPC_Clients[i] && gIPC_Clients[i]->IPCType == &gIPC_Type_IPCPipe )
+                       _setfd( *(int*)(gIPC_Clients[i]->Ident), nfds, set );
        }
 }
 
 void IPC_HandleSelect(fd_set *set)
 {
-       if( giNetworkFileHandle != -1 )
+       if( giNetworkFileHandle != -1 && FD_ISSET(giNetworkFileHandle, set) )
        {
-               if( FD_ISSET(giNetworkFileHandle, set) )
-               {
-                       char    staticBuf[STATICBUF_SIZE];
-                        int    readlen, identlen;
-                       char    *msg;
+               char    staticBuf[STATICBUF_SIZE];
+                int    readlen, identlen;
+               char    *msg;
+
+               readlen = _SysRead(giNetworkFileHandle, staticBuf, sizeof(staticBuf));
+               
+               identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
+               msg = staticBuf + identlen;
+
+               IPC_Handle( IPC_int_GetClient(&gIPC_Type_Datagram, staticBuf), readlen - identlen, (void*)msg);
+               //_SysDebug("IPC_HandleSelect: UDP handled");
+       }
        
-                       readlen = read(giNetworkFileHandle, staticBuf, sizeof(staticBuf));
-                       
-                       identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
-                       msg = staticBuf + identlen;
+       if( giIPCPipeHandle != -1 && FD_ISSET(giIPCPipeHandle, set) )
+       {
+               int newfd = _SysOpenChild(giIPCPipeHandle, "newclient", OPENFLAG_READ|OPENFLAG_WRITE);
+               _SysDebug("newfd = %i", newfd);
+               IPC_int_GetClient(&gIPC_Type_IPCPipe, &newfd);
+       }
        
-                       IPC_Handle(&gIPC_Type_Datagram, staticBuf, readlen - identlen, (void*)msg);
-//                     _SysDebug("IPC_HandleSelect: UDP handled");
+       for( int i = 0; i < giIPC_ClientCount; i ++ )
+       {
+               if( gIPC_Clients[i] && gIPC_Clients[i]->IPCType == &gIPC_Type_IPCPipe )
+               {
+                        int fd = *(const int*)gIPC_Clients[i]->Ident;
+                       if( FD_ISSET(fd, set) )
+                       {
+                               char    staticBuf[STATICBUF_SIZE];
+                               size_t  len;
+                               len = _SysRead(fd, staticBuf, sizeof(staticBuf));
+                               if( len == (size_t)-1 ) {
+                                       // TODO: Check errno for EINTR
+                                       IPC_int_DropClient(gIPC_Clients[i]);
+                                       break;
+                               }
+                               IPC_Handle( gIPC_Clients[i], len, (void*)staticBuf );
+                       }
                }
        }
 
        size_t  len;
-       pid_t   tid;
-       while( (len = SysGetMessage(&tid, 0, NULL)) )
+       int     tid;
+       while( (len = _SysGetMessage(&tid, 0, NULL)) )
        {
                char    data[len];
-               SysGetMessage(NULL, len, data);
+               _SysGetMessage(NULL, len, data);
 
-               IPC_Handle(&gIPC_Type_SysMessage, &tid, len, (void*)data);
+               IPC_Handle( IPC_int_GetClient(&gIPC_Type_SysMessage, &tid), len, (void*)data );
 //             _SysDebug("IPC_HandleSelect: Message handled");
        }
 }
@@ -145,7 +195,7 @@ void IPC_Type_Datagram_Send(const void *Ident, size_t Length, const void *Data)
        memcpy(tmpbuf, Ident, identlen);        // Header
        memcpy(tmpbuf + identlen, Data, Length);        // Data
        // TODO: Handle fragmented packets
-       write(giNetworkFileHandle, tmpbuf, sizeof(tmpbuf));
+       _SysWrite(giNetworkFileHandle, tmpbuf, sizeof(tmpbuf));
 }
 
 int IPC_Type_Sys_GetSize(const void *Ident)
@@ -160,7 +210,23 @@ int IPC_Type_Sys_Compare(const void *Ident1, const void *Ident2)
 
 void IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data)
 {
-       SysSendMessage( *(const tid_t*)Ident, Length, Data );
+       _SysSendMessage( *(const tid_t*)Ident, Length, Data );
+}
+
+int IPC_Type_IPCPipe_GetSize(const void *Ident)
+{
+       return sizeof(int);
+}
+int IPC_Type_IPCPipe_Compare(const void *Ident1, const void *Ident2)
+{
+       return *(const int*)Ident1 - *(const int*)Ident2;
+}
+void IPC_Type_IPCPipe_Send(const void *Ident, size_t Length, const void *Data)
+{
+       size_t rv = _SysWrite( *(const int*)Ident, Data, Length );
+       if(rv != Length) {
+               _SysDebug("Sent message oversize %x", Length);
+       }
 }
 
 // --- Client -> Window Mappings
@@ -168,13 +234,49 @@ int _CompareClientPtrs(const void *_a, const void *_b)
 {
        tIPC_Client     *a = *(tIPC_Client**)_a;
        tIPC_Client     *b = *(tIPC_Client**)_b;
-       
+
+       ASSERT(a);
+       if(!b)  return -1;
+
        if(a->IPCType < b->IPCType)     return -1;
        if(a->IPCType > b->IPCType)     return 1;
        
        return a->IPCType->CompareIdent(a->Ident, b->Ident);
 }
 
+int IPC_int_BSearchClients(const tIPC_Client *TargetClient, int *Pos)
+{
+        int    div;
+        int    cmp = -1;
+        int    pos = 0;
+
+       div = giIPC_ClientCount;
+       pos = div/2;
+       while(div > 0)
+       {
+               div /= 2;
+               _SysDebug("Cmp with %i [%i] (%p)", pos, div, gIPC_Clients[pos]);
+               cmp = _CompareClientPtrs(&TargetClient, &gIPC_Clients[pos]);
+//             _SysDebug("Checking against %i gives %i", pos, cmp);
+               if(cmp == 0)    break;
+               if(cmp < 0)
+                       pos -= div;
+               else
+                       pos += div;
+       }
+       
+       // - Return if found    
+       if(cmp == 0) {
+               *Pos = pos;
+               return 1;
+       }
+
+       // Adjust pos to be the index where the new client will be placed
+       if(cmp > 0)     pos ++;
+       *Pos = pos;
+       return 0;
+}
+
 tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident)
 {
         int    pos = 0;        // Position where the new client will be inserted
@@ -185,33 +287,10 @@ tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident)
        if(giIPC_ClientCount > 0)
        {
                tIPC_Client     target;
-                int    div;
-                int    cmp = -1;
-       
                target.IPCType = IPCType;
                target.Ident = Ident;
-               ret = &target;  // Abuse ret to get a pointer
-               
-               div = giIPC_ClientCount;
-               pos = div/2;
-               while(div > 0)
-               {
-                       div /= 2;
-                       cmp = _CompareClientPtrs(&ret, &gIPC_Clients[pos]);
-//                     _SysDebug("Checking against %i gives %i", pos, cmp);
-                       if(cmp == 0)    break;
-                       if(cmp < 0)
-                               pos -= div;
-                       else
-                               pos += div;
-               }
-               
-               // - Return if found    
-               if(cmp == 0)
+               if( IPC_int_BSearchClients(&target, &pos) )
                        return gIPC_Clients[pos];
-       
-               // Adjust pos to be the index where the new client will be placed
-               if(cmp > 0)     pos ++;
        }
 
 
@@ -239,6 +318,40 @@ tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident)
        return ret;
 }
 
+void IPC_int_DropClient(tIPC_Client *Client)
+{
+       // Remove from client list
+        int    pos;
+       if( !IPC_int_BSearchClients(Client, &pos) ) {
+               _SysDebug("IPC_int_DropClient: Can't find client %p", Client);
+               return ;
+       }
+
+       giIPC_ClientCount --;
+       memmove(&gIPC_Clients[pos], &gIPC_Clients[pos+1], (giIPC_ClientCount-pos)*sizeof(tIPC_Client*));
+
+       // Terminate client's windows
+       // - If there were active windows, show an error?
+        int    nWindowsDestroyed = 0;
+       for(int i = 0; i < Client->nWindows; i ++)
+       {
+               if( Client->Windows[i] )
+               {
+                       _SysDebug("Window %p:%i %p still exists", Client, i, Client->Windows[i]);
+                       WM_DestroyWindow(Client->Windows[i]);
+                       nWindowsDestroyed ++;
+               }
+       }
+       if( nWindowsDestroyed )
+       {
+               _SysDebug("TODO: Show notice that application exited without destroying windows");
+       }
+       
+       // Free client structure
+       free(Client);
+       _SysDebug("Dropped client %p", Client);
+}
+
 tWindow *IPC_int_GetWindow(tIPC_Client *Client, uint32_t WindowID)
 {
        if( WindowID == -1 )
@@ -406,6 +519,21 @@ int IPC_Msg_CreateWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
        return 0;
 }
 
+int IPC_Msg_DestroyWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
+{
+       tWindow *win;
+       
+       ASSERT(Msg->ID == IPCMSG_DESTROYWIN);
+
+       win = IPC_int_GetWindow(Client, Msg->Window);
+       if( !win )
+               return 0;
+       
+       WM_DestroyWindow(win);
+       IPC_int_SetWindow(Client, Msg->Window, NULL);
+       return 0;
+}
+
 int IPC_Msg_SetWindowTitle(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
 {
        tWindow *win;
@@ -461,8 +589,8 @@ int IPC_Msg_FocusWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
        ASSERT(Msg->ID == IPCMSG_FOCUSWINDOW);
        
        // Don't allow the focus to be changed unless the client has the focus
-       if(!gpWM_FocusedWindow) return 1;
-       if(gpWM_FocusedWindow->Client != Client)        return 1;
+//     if(!gpWM_FocusedWindow) return 1;
+//     if(gpWM_FocusedWindow->Client != Client)        return 1;
 
        win = IPC_int_GetWindow(Client, Msg->Window);
        if(!win)        return 1;
@@ -525,7 +653,7 @@ int (*gIPC_MessageHandlers[])(tIPC_Client *Client, tAxWin_IPCMessage *Msg) = {
        IPC_Msg_GetDisplayDims,
        IPC_Msg_SendMsg,
        IPC_Msg_CreateWin,
-       NULL,   // Destroy window
+       IPC_Msg_DestroyWin,     // Destroy window
        IPC_Msg_SetWindowTitle,
        IPC_Msg_ShowWindow,
        IPC_Msg_DecorateWindow,
@@ -535,9 +663,8 @@ int (*gIPC_MessageHandlers[])(tIPC_Client *Client, tAxWin_IPCMessage *Msg) = {
 };
 const int giIPC_NumMessageHandlers = sizeof(gIPC_MessageHandlers)/sizeof(gIPC_MessageHandlers[0]);
 
-void IPC_Handle(const tIPC_Type *IPCType, const void *Ident, size_t MsgLen, tAxWin_IPCMessage *Msg)
+void IPC_Handle(tIPC_Client *Client, size_t MsgLen, tAxWin_IPCMessage *Msg)
 {
-       tIPC_Client     *client;
         int    rv = 0;
        
 //     _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)",
@@ -548,16 +675,11 @@ void IPC_Handle(const tIPC_Type *IPCType, const void *Ident, size_t MsgLen, tAxW
        if( MsgLen < sizeof(tAxWin_IPCMessage) + Msg->Size )
                return ;
        
-       client = IPC_int_GetClient(IPCType, Ident);
-       if( !client ) {
-               // Oops?
-       }
-       
        if( Msg->Flags & IPCMSG_FLAG_RENDERER )
        {
-               tWindow *win = IPC_int_GetWindow(client, Msg->Window);
+               tWindow *win = IPC_int_GetWindow(Client, Msg->Window);
                if( !win ) {
-                       _SysDebug("WARNING: NULL window in message %i", Msg->ID);
+                       _SysDebug("WARNING: NULL window in message %i (%x)", Msg->ID, Msg->Window);
                        return ;
                }
                tWMRenderer     *renderer = win->Renderer;
@@ -577,8 +699,8 @@ void IPC_Handle(const tIPC_Type *IPCType, const void *Ident, size_t MsgLen, tAxW
        else
        {
                if( Msg->ID >= giIPC_NumMessageHandlers ) {
-                       fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
-                       _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, IPCType);
+                       fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, Client);
+                       _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, Client);
                        return ;
                }
                
@@ -589,7 +711,7 @@ void IPC_Handle(const tIPC_Type *IPCType, const void *Ident, size_t MsgLen, tAxW
                }
        
                _SysDebug("IPC_Handle: Call WM-%i", Msg->ID);
-               rv = gIPC_MessageHandlers[Msg->ID](client, Msg);
+               rv = gIPC_MessageHandlers[Msg->ID](Client, Msg);
                if( rv )
                        _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
        }

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