Usermode/AxWin4 - Server implementation runnable
authorJohn Hodge <[email protected]>
Mon, 26 May 2014 09:41:30 +0000 (17:41 +0800)
committerJohn Hodge <[email protected]>
Mon, 26 May 2014 09:41:30 +0000 (17:41 +0800)
12 files changed:
Usermode/Applications/axwin4_src/Common/include/serialisation.hpp
Usermode/Applications/axwin4_src/Common/serialisation.cpp
Usermode/Applications/axwin4_src/Server/CClient.cpp
Usermode/Applications/axwin4_src/Server/CIPCChannel_AcessIPCPipe.cpp
Usermode/Applications/axwin4_src/Server/Makefile
Usermode/Applications/axwin4_src/Server/include/CClient.hpp
Usermode/Applications/axwin4_src/Server/include/CIPCChannel_AcessIPCPipe.hpp
Usermode/Applications/axwin4_src/Server/include/ipc.hpp
Usermode/Applications/axwin4_src/Server/input.cpp
Usermode/Applications/axwin4_src/Server/ipc.cpp
Usermode/Applications/axwin4_src/Server/main.cpp
Usermode/Applications/axwin4_src/Server/timing.cpp

index 32ba465..d680043 100644 (file)
@@ -28,10 +28,11 @@ class CDeserialiser
        size_t  m_offset;
 public:
        CDeserialiser(size_t Length, const uint8_t *Buffer);
+       bool    IsConsumed() const;
        ::uint8_t       ReadU8();
        ::uint16_t      ReadU16();
        ::int16_t       ReadS16();
-       ::std::string   ReadString();
+       const ::std::string     ReadString();
 };
 
 class CSerialiser
@@ -42,6 +43,7 @@ public:
        void WriteU8(::uint8_t val);
        void WriteU16(::uint16_t val);
        void WriteS16(::int16_t val);
+       void WriteBuffer(size_t n, const void* val);
        void WriteString(const char* val, size_t n);
        void WriteString(const char* val) {
                WriteString(val, ::std::char_traits<char>::length(val));
@@ -50,6 +52,8 @@ public:
                WriteString(val.data(), val.size());
        }
        void WriteSub(const CSerialiser& val);
+       
+       const ::std::vector<uint8_t>& Compact();
 };
 
 };
index 4388eab..8dad5d3 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <serialisation.hpp>
 #include <cstddef>
+#include <stdexcept>
 
 namespace AxWin {
 
@@ -17,24 +18,52 @@ CDeserialiser::CDeserialiser(size_t Length, const uint8_t *Buffer):
 {
 }
 
+bool CDeserialiser::IsConsumed() const
+{
+       return m_offset == m_length;
+}
+
 ::uint8_t CDeserialiser::ReadU8()
 {
-       return 0;
+       if( m_offset + 1 >= m_length )
+               throw ::std::out_of_range("CDeserialiser::ReadU8");
+       uint8_t rv = m_data[m_offset];
+       m_offset ++;
+       return rv;
 }
 
 ::uint16_t CDeserialiser::ReadU16()
 {
-       return 0;
+       if( m_offset + 2 >= m_length )
+               throw ::std::out_of_range("CDeserialiser::ReadU16");
+       
+       uint16_t rv = m_data[m_offset] | ((uint16_t)m_data[m_offset+1] << 8);
+       m_offset += 2;
+       return rv;
 }
 
 ::int16_t CDeserialiser::ReadS16()
 {
-       return 0;
+       uint16_t rv_u = ReadU16();
+       if( rv_u < 0x8000 )
+               return rv_u;
+       else
+               return ~rv_u + 1;
 }
 
-::std::string CDeserialiser::ReadString()
+const ::std::string CDeserialiser::ReadString()
 {
-       return "";
+       if( m_offset + 1 >= m_length )
+               throw ::std::out_of_range("CDeserialiser::ReadString");
+       uint8_t len = m_data[m_offset];
+       m_offset ++;
+       
+       if( m_offset + len >= m_length )
+               throw ::std::out_of_range("CDeserialiser::ReadString");
+       
+       ::std::string ret( reinterpret_cast<const char*>(m_data+m_offset), len );
+       m_offset += len;
+       return ret;
 }
 
 CSerialiser::CSerialiser()
@@ -65,21 +94,39 @@ void CSerialiser::WriteS16(::int16_t Value)
        }
 }
 
+void CSerialiser::WriteBuffer(size_t n, const void* val)
+{
+       const uint8_t*  val8 = static_cast<const uint8_t*>(val);
+       if( n > 0xFFFF )
+               throw ::std::length_error("CSerialiser::WriteBuffer");
+       m_data.reserve( m_data.size() + 2 + n );
+       WriteU16(n);
+       for( size_t i = 0; i < n; i ++ )
+               m_data.push_back(val8[i]);
+}
+
 void CSerialiser::WriteString(const char* val, size_t n)
 {
-       //if( n >= 256 )
-       //      throw ::std::out_of_range("CSerialiser::WriteString");
+       if( n > 0xFF )
+               throw ::std::length_error("CSerialiser::WriteString");
+       m_data.reserve( m_data.size() + 1 + n );
        WriteU8(n);
        for( size_t i = 0; i < n; i ++ )
-               WriteU8(val[i]);
+               m_data.push_back(val[i]);
 }
 
 void CSerialiser::WriteSub(const CSerialiser& val)
 {
+       // TODO: Append reference to sub-buffer contents
        m_data.reserve( m_data.size() + val.m_data.size() );
        for( auto byte : val.m_data )
                m_data.push_back( byte );
 }
 
+const ::std::vector<uint8_t>& CSerialiser::Compact()
+{
+       return m_data;
+}
+
 };     // namespace AxWin
 
index 6f1f256..f61ca31 100644 (file)
@@ -6,15 +6,22 @@
  * - IPC Client
  */
 #include <CClient.hpp>
+#include <IIPCChannel.hpp>
+#include <ipc.hpp>
 
 namespace AxWin {
 
-CClient::CClient(IIPCChannel& channel):
+CClient::CClient(::AxWin::IIPCChannel& channel):
        m_channel(channel)
 {
        
 }
 
+CClient::~CClient()
+{
+       ::AxWin::IPC::DeregisterClient(*this);
+}
+
 CWindow* CClient::GetWindow(int ID)
 {
        if( ID == 0 )
@@ -31,8 +38,23 @@ void CClient::SetWindow(int ID, CWindow* window)
        m_windows[ID] = window;
 }
 
-void CClient::SendMessage(CSerialiser& reply)
+void CClient::HandleMessage(CDeserialiser& message)
 {
+       try {
+               IPC::HandleMessage(*this, message);
+               if( !message.IsConsumed() )
+               {
+                       _SysDebug("NOTICE - CClient::HandleMessage - Trailing data in message");
+               }
+       }
+       catch( const ::std::exception& e )
+       {
+               _SysDebug("ERROR - Exception while processing message from client: %s", e.what());
+       }
+       catch( ... )
+       {
+               _SysDebug("ERROR - Unknown exception while processing message from client");
+       }
 }
 
 };     // namespace AxWin
index 1686349..183253b 100644 (file)
  * CIPCChannel_AcessIPCPipe.cpp
  * - IPC Channel :: Acess' IPC Pipe /Devices/ipcpipe/<name>
  */
+#include <ipc.hpp>
 #include <CIPCChannel_AcessIPCPipe.hpp>
+#include <cerrno>
+#include <system_error>
+#include <acess/sys.h>
+#include <algorithm>
 
 namespace AxWin {
 
 CIPCChannel_AcessIPCPipe::CIPCChannel_AcessIPCPipe(const ::std::string& suffix)
 {
-       
+       ::std::string   path = "/Devices/ipcpipe/" + suffix;
+       m_fd = _SysOpen(path.c_str(), OPENFLAG_CREATE);
+       if(m_fd == -1) {
+               _SysDebug("Failed to open %s: %s", path.c_str(), strerror(errno));
+               throw ::std::system_error(errno, ::std::system_category());
+       }
 }
 CIPCChannel_AcessIPCPipe::~CIPCChannel_AcessIPCPipe()
 {
+       _SysClose(m_fd);
 }
 
 int CIPCChannel_AcessIPCPipe::FillSelect(fd_set& rfds)
 {
-       return 0;
+       _SysDebug("CIPCChannel_AcessIPCPipe::FillSelect");
+        int    maxfd = m_fd;
+       FD_SET(m_fd, &rfds);
+       
+       for( auto& clientref : m_clients )
+       {
+               _SysDebug("CIPCChannel_AcessIPCPipe::FillSelect - FD%i", clientref.m_fd);
+               maxfd = ::std::max(maxfd, clientref.m_fd);
+               FD_SET(clientref.m_fd, &rfds);
+       }
+       
+       return maxfd+1;
 }
 
 void CIPCChannel_AcessIPCPipe::HandleSelect(const fd_set& rfds)
 {
+       _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect");
+       if( FD_ISSET(m_fd, &rfds) )
+       {
+               _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect - New client on FD %i", m_fd);
+               int newfd = _SysOpenChild(m_fd, "newclient", OPENFLAG_READ|OPENFLAG_WRITE);
+               _SysDebug("newfd = %i", newfd);
+               
+               // emplace creates a new object within the list
+               m_clients.emplace( m_clients.end(), *this, newfd );
+               IPC::RegisterClient( m_clients.back() );
+       }
+
+       for( auto it = m_clients.begin(); it != m_clients.end();  )
+       {
+               CClient_AcessIPCPipe& clientref = *it;
+               _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect - Trying FD%i", clientref.m_fd);
+               ++ it;
+               
+               if( FD_ISSET(clientref.m_fd, &rfds) )
+               {
+                       try {
+                               clientref.HandleReceive();
+                       }
+                       catch( const ::std::exception& e ) {
+                               _SysDebug("ERROR - Exception processing IPCPipe FD%i: %s",
+                                       clientref.m_fd, e.what()
+                                       );
+                               it = m_clients.erase(--it);
+                       }
+               }
+       }
+       _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect - END");
+}
+
+
+CClient_AcessIPCPipe::CClient_AcessIPCPipe(::AxWin::IIPCChannel& channel, int fd):
+       CClient(channel),
+       m_fd(fd),
+       m_rxbuf(0x1000)
+{
+}
+
+CClient_AcessIPCPipe::~CClient_AcessIPCPipe()
+{
+       _SysClose(m_fd);
+       _SysDebug("Closed client FD%i", m_fd);
+}
+
+void CClient_AcessIPCPipe::SendMessage(CSerialiser& message)
+{
+       const ::std::vector<uint8_t>&   data = message.Compact();
+       
+       _SysDebug("CClient_AcessIPCPipe::SendMessage - %i bytes to %i", data.size(), m_fd);
+       _SysWrite(m_fd, data.data(), data.size());
+}
+
+void CClient_AcessIPCPipe::HandleReceive()
+{
+       size_t len = _SysRead(m_fd, &m_rxbuf[0], m_rxbuf.capacity());
+       if( len == (size_t)-1 )
+               throw ::std::system_error(errno, ::std::system_category());
+       
+       CDeserialiser   message(len, &m_rxbuf[0]);
+       CClient::HandleMessage(message);
 }
 
 };
index 6f88f14..18b7d37 100644 (file)
@@ -1,6 +1,8 @@
 
 include ../../Makefile.cfg
 
+DIR := Apps/AxWin/4.0
+
 CPPFLAGS += -Iinclude/ -I../Common/include/
 OBJ := main.o ipc.o CConfig.o video.o input.o timing.o
 OBJ += compositor.o CWindow.o
index 44961da..6e8a09b 100644 (file)
 #include "CWindow.hpp"
 #include "serialisation.hpp"
 
-class IIPCChannel;
-
 namespace AxWin {
 
+class IIPCChannel;
+
 class CClient
 {
        IIPCChannel&    m_channel;
@@ -22,13 +22,14 @@ class CClient
        //::std::map<unsigned int,CWindow*>     m_windows;
        CWindow*        m_windows[1];
 public:
-       CClient(IIPCChannel& channel);
-       ~CClient();
+       CClient(::AxWin::IIPCChannel& channel);
+       virtual ~CClient();
        
        CWindow*        GetWindow(int ID);
        void    SetWindow(int ID, CWindow* window);
        
-       void    SendMessage(CSerialiser& reply);
+       virtual void    SendMessage(CSerialiser& reply) = 0;
+       void    HandleMessage(CDeserialiser& message);
 };
 
 
index 1e24b0e..4a717d4 100644 (file)
@@ -9,20 +9,31 @@
 #define _CIPCCHANNEL_ACESSIPCPIPE_HPP_
 
 #include <IIPCChannel.hpp>
+#include <CClient.hpp>
 #include <string>
 #include <list>
 
 namespace AxWin {
 
-class CClient_AcessIPCPipe
+class CClient_AcessIPCPipe:
+       public CClient
 {
+       friend class CIPCChannel_AcessIPCPipe;
+        int    m_fd;
+       ::std::vector<uint8_t>  m_rxbuf;
 public:
+       CClient_AcessIPCPipe(IIPCChannel& channel, int fd);
+       ~CClient_AcessIPCPipe();
+       
+       void SendMessage(CSerialiser& message);
+       
+       void HandleReceive();
 };
 
 class CIPCChannel_AcessIPCPipe:
        public IIPCChannel
 {
-        int    m_mainFD;
+        int    m_fd;
        ::std::list<CClient_AcessIPCPipe>       m_clients;
 public:
        CIPCChannel_AcessIPCPipe(const ::std::string& suffix);
index d801953..cb06f67 100644 (file)
@@ -14,16 +14,22 @@ extern "C" {
 #include <acess/sys.h>
 };
 
+#include <serialisation.hpp>
 #include <CConfigIPC.hpp>
 
 namespace AxWin {
+
 class CCompositor;
+class CClient;
 
 namespace IPC {
 
 extern void    Initialise(const CConfigIPC& config, CCompositor& compositor);
 extern int     FillSelect(::fd_set& rfds);
-extern void    HandleSelect(::fd_set& rfds);
+extern void    HandleSelect(const ::fd_set& rfds);
+extern void    RegisterClient(CClient& client);
+extern void    DeregisterClient(CClient& client);
+extern void    HandleMessage(CClient& client, CDeserialiser& message);
 
 class CClientFailure:
        public ::std::exception
index 7519b87..c120ed4 100644 (file)
@@ -23,7 +23,8 @@ CInput::CInput(const ::AxWin::CConfigInput& config, CCompositor& compositor):
 int CInput::FillSelect(::fd_set& rfds)
 {
        FD_SET(m_keyboardFD, &rfds);
-       FD_SET(m_mouseFD, &rfds);
+       if( m_mouseFD != -1 )
+               FD_SET(m_mouseFD, &rfds);
        return ::std::max(m_keyboardFD, m_mouseFD)+1;
 }
 
@@ -31,10 +32,38 @@ void CInput::HandleSelect(::fd_set& rfds)
 {
        if( FD_ISSET(m_keyboardFD, &rfds) )
        {
-               // TODO: Read keystroke and handle
+               uint32_t        codepoint;
+               static uint32_t scancode;
+               #define KEY_CODEPOINT_MASK      0x3FFFFFFF
+               
+               size_t readlen = _SysRead(m_keyboardFD, &codepoint, sizeof(codepoint));
+               if( readlen != sizeof(codepoint) )
+               {
+                       // oops, error
+                       _SysDebug("Terminal read failed? (%i != %i)", readlen, sizeof(codepoint));
+               }
+       
+//             _SysDebug("Keypress 0x%x", codepoint);
+       
+               switch(codepoint & 0xC0000000)
+               {
+               case 0x00000000:        // Key pressed
+                       //WM_Input_KeyDown(codepoint & KEY_CODEPOINT_MASK, scancode);
+               case 0x80000000:        // Key release
+                       //WM_Input_KeyFire(codepoint & KEY_CODEPOINT_MASK, scancode);
+                       scancode = 0;
+                       break;
+               case 0x40000000:        // Key refire
+                       //WM_Input_KeyUp(codepoint & KEY_CODEPOINT_MASK, scancode);
+                       scancode = 0;
+                       break;
+               case 0xC0000000:        // Raw scancode
+                       scancode = codepoint & KEY_CODEPOINT_MASK;
+                       break;
+               }
        }
        
-       if( FD_ISSET(m_mouseFD, &rfds) )
+       if( m_mouseFD != -1 && FD_ISSET(m_mouseFD, &rfds) )
        {
                // TODO: Read mouse event and handle
        }
index f842578..46ba551 100644 (file)
@@ -39,17 +39,21 @@ void Initialise(const CConfigIPC& config, CCompositor& compositor)
 int FillSelect(fd_set& rfds)
 {
        int ret = 0;
+       _SysDebug("IPC::FillSelect");
        for( auto channel : glChannels )
        {
+               _SysDebug("IPC::FillSelect - channel=%p", channel);
                ret = ::std::max(ret, channel->FillSelect(rfds));
        }
        return ret;
 }
 
-void HandleSelect(fd_set& rfds)
+void HandleSelect(const fd_set& rfds)
 {
+       _SysDebug("IPC::HandleSelect");
        for( auto channel : glChannels )
        {
+               _SysDebug("IPC::HandleSelect - channel=%p", channel);
                channel->HandleSelect(rfds);
        }
 }
index acea927..0cd048f 100644 (file)
@@ -15,6 +15,9 @@
 #include <algorithm>
 #include <common.hpp>
 
+#include <system_error>
+#include <cerrno>
+
 extern "C" {
 #include <stdio.h>
 #include <stdint.h>
@@ -32,32 +35,91 @@ int main(int argc, char *argv[])
        }
        catch(const std::exception& e) {
                fprintf(stderr, "Exception: %s\n", e.what());
+               _SysDebug("Config threw exception: %s", e.what());
+               return 1;
+       }
+       
+       CVideo* vid = 0;
+       CCompositor*    compositor = 0;
+       CInput* input = 0;
+       
+       try {
+               // - Open graphics
+               vid = new CVideo(config.m_video);
+               ::_SysDebug("vid = %p", vid);
+               // - Initialise compositor structures
+               compositor = new CCompositor(/*config.m_compositor,*/ *vid);
+               ::_SysDebug("compositor = %p", compositor);
+               // - Open input
+               input = new CInput(config.m_input, *compositor);
+               ::_SysDebug("input = %p", input);
+               //  > Handles hotkeys?
+               // - Bind IPC channels
+               IPC::Initialise(config.m_ipc, *compositor);
+               ::_SysDebug("IPC up");
+               // - Start root child process (from config)
+               // TODO: Spin up child process
+               
+               {
+                       const char *interface_app = "/Acess/Apps/AxWin/4.0/AxWinUI";
+                       const char *argv[] = {interface_app, NULL};
+                        int    rv = _SysSpawn(interface_app, argv, NULL, 0, NULL, NULL);
+                       if( rv < 0 ) {
+                               _SysDebug("_SysSpawn chucked a sad, rv=%i, errno=%i", rv, _errno);
+                               throw ::std::system_error(errno, ::std::system_category());
+                       }
+               }
+       }
+       catch(const ::std::exception& e) {
+               fprintf(stderr, "Startup threw exception: %s\n", e.what());
+               _SysDebug("Startup threw exception: %s", e.what());
+               delete input;
+               delete compositor;
+               delete vid;
                return 1;
        }
-       // - Open graphics
-       CVideo* vid = new CVideo(config.m_video);
-       // - Initialise compositor structures
-       CCompositor* compositor = new CCompositor(/*config.m_compositor,*/ *vid);
-       // - Open input
-       CInput* input = new CInput(config.m_input, *compositor);
-       //  > Handles hotkeys?
-       // - Bind IPC channels
-       IPC::Initialise(config.m_ipc, *compositor);
-       // - Start root child process (from config)
-       // TODO: Spin up child process
        
        // - Event loop
        for( ;; )
        {
                 int    nfd = 0;
-               fd_set  rfds;
+               fd_set  rfds, efds;
                
+               FD_ZERO(&rfds);
+               FD_ZERO(&efds);
+       
                nfd = ::std::max(nfd, input->FillSelect(rfds));
                nfd = ::std::max(nfd, IPC::FillSelect(rfds));
                
+               for( int i = 0; i < nfd; i ++ )
+                       if( FD_ISSET(i, &rfds) )
+                               FD_SET(i, &efds);
+
+               for( int i = 0; i < nfd; i ++ ) {
+                       if( FD_ISSET(i, &rfds) ) {
+                               _SysDebug("FD%i", i);
+                       }
+               }
+               
                // TODO: Support _SysSendMessage IPC?
                int64_t timeout = Timing::GetTimeToNextEvent();
-               int rv = ::_SysSelect(nfd, &rfds, NULL, &rfds, &timeout, 0);
+               int64_t *timeoutp;
+               if( timeout >= 0 ) {
+                       ::_SysDebug("Calling select with timeout %lli", timeout);
+                       timeoutp = &timeout;
+               }
+               else {
+                       ::_SysDebug("Calling select with no timeout");
+                       timeoutp = 0;
+               }
+               int rv = ::_SysSelect(nfd, &rfds, NULL, NULL/*&efds*/, timeoutp, 0);
+               
+               for( int i = 0; i < nfd; i ++ ) {
+                       if( FD_ISSET(i, &rfds) ) {
+                               _SysDebug("FD%i", i);
+                       }
+               }
+               _SysDebug("rv=%i, timeout=%lli", rv, timeout);
                
                Timing::CheckEvents();
                
index 1874009..e61c8e2 100644 (file)
@@ -12,7 +12,7 @@ namespace Timing {
 
 int64_t GetTimeToNextEvent()
 {
-       return 10*1000;
+       return -1;
 }
 
 void CheckEvents()

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