Usermode/AxWin4 - Server implementation runnable
[tpg/acess2.git] / Usermode / Applications / axwin4_src / Server / CIPCChannel_AcessIPCPipe.cpp
1 /*
2  * Acess2 GUI v4
3  * - By John Hodge (thePowersGang)
4  *
5  * CIPCChannel_AcessIPCPipe.cpp
6  * - IPC Channel :: Acess' IPC Pipe /Devices/ipcpipe/<name>
7  */
8 #include <ipc.hpp>
9 #include <CIPCChannel_AcessIPCPipe.hpp>
10 #include <cerrno>
11 #include <system_error>
12 #include <acess/sys.h>
13 #include <algorithm>
14
15 namespace AxWin {
16
17 CIPCChannel_AcessIPCPipe::CIPCChannel_AcessIPCPipe(const ::std::string& suffix)
18 {
19         ::std::string   path = "/Devices/ipcpipe/" + suffix;
20         m_fd = _SysOpen(path.c_str(), OPENFLAG_CREATE);
21         if(m_fd == -1) {
22                 _SysDebug("Failed to open %s: %s", path.c_str(), strerror(errno));
23                 throw ::std::system_error(errno, ::std::system_category());
24         }
25 }
26 CIPCChannel_AcessIPCPipe::~CIPCChannel_AcessIPCPipe()
27 {
28         _SysClose(m_fd);
29 }
30
31 int CIPCChannel_AcessIPCPipe::FillSelect(fd_set& rfds)
32 {
33         _SysDebug("CIPCChannel_AcessIPCPipe::FillSelect");
34          int    maxfd = m_fd;
35         FD_SET(m_fd, &rfds);
36         
37         for( auto& clientref : m_clients )
38         {
39                 _SysDebug("CIPCChannel_AcessIPCPipe::FillSelect - FD%i", clientref.m_fd);
40                 maxfd = ::std::max(maxfd, clientref.m_fd);
41                 FD_SET(clientref.m_fd, &rfds);
42         }
43         
44         return maxfd+1;
45 }
46
47 void CIPCChannel_AcessIPCPipe::HandleSelect(const fd_set& rfds)
48 {
49         _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect");
50         if( FD_ISSET(m_fd, &rfds) )
51         {
52                 _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect - New client on FD %i", m_fd);
53                 int newfd = _SysOpenChild(m_fd, "newclient", OPENFLAG_READ|OPENFLAG_WRITE);
54                 _SysDebug("newfd = %i", newfd);
55                 
56                 // emplace creates a new object within the list
57                 m_clients.emplace( m_clients.end(), *this, newfd );
58                 IPC::RegisterClient( m_clients.back() );
59         }
60
61         for( auto it = m_clients.begin(); it != m_clients.end();  )
62         {
63                 CClient_AcessIPCPipe& clientref = *it;
64                 _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect - Trying FD%i", clientref.m_fd);
65                 ++ it;
66                 
67                 if( FD_ISSET(clientref.m_fd, &rfds) )
68                 {
69                         try {
70                                 clientref.HandleReceive();
71                         }
72                         catch( const ::std::exception& e ) {
73                                 _SysDebug("ERROR - Exception processing IPCPipe FD%i: %s",
74                                         clientref.m_fd, e.what()
75                                         );
76                                 it = m_clients.erase(--it);
77                         }
78                 }
79         }
80         _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect - END");
81 }
82
83
84 CClient_AcessIPCPipe::CClient_AcessIPCPipe(::AxWin::IIPCChannel& channel, int fd):
85         CClient(channel),
86         m_fd(fd),
87         m_rxbuf(0x1000)
88 {
89 }
90
91 CClient_AcessIPCPipe::~CClient_AcessIPCPipe()
92 {
93         _SysClose(m_fd);
94         _SysDebug("Closed client FD%i", m_fd);
95 }
96
97 void CClient_AcessIPCPipe::SendMessage(CSerialiser& message)
98 {
99         const ::std::vector<uint8_t>&   data = message.Compact();
100         
101         _SysDebug("CClient_AcessIPCPipe::SendMessage - %i bytes to %i", data.size(), m_fd);
102         _SysWrite(m_fd, data.data(), data.size());
103 }
104
105 void CClient_AcessIPCPipe::HandleReceive()
106 {
107         size_t len = _SysRead(m_fd, &m_rxbuf[0], m_rxbuf.capacity());
108         if( len == (size_t)-1 )
109                 throw ::std::system_error(errno, ::std::system_category());
110         
111         CDeserialiser   message(len, &m_rxbuf[0]);
112         CClient::HandleMessage(message);
113 }
114
115 };
116

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