b222cea8c3a27dbb26f103863c636373fa1ddd46
[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          int    maxfd = m_fd;
34         FD_SET(m_fd, &rfds);
35         
36         for( auto& clientref : m_clients )
37         {
38                 maxfd = ::std::max(maxfd, clientref.m_fd);
39                 FD_SET(clientref.m_fd, &rfds);
40         }
41         
42         return maxfd+1;
43 }
44
45 void CIPCChannel_AcessIPCPipe::HandleSelect(const fd_set& rfds)
46 {
47         if( FD_ISSET(m_fd, &rfds) )
48         {
49                 int newfd = _SysOpenChild(m_fd, "newclient", OPENFLAG_READ|OPENFLAG_WRITE);
50                 if( newfd == -1 ) {
51                         _SysDebug("ERROR - Failure to open new client on FD%i", m_fd);
52                 }
53                 else {
54                         _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect - New client on FD %i with FD%i", m_fd, 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
62         for( auto it = m_clients.begin(); it != m_clients.end();  )
63         {
64                 CClient_AcessIPCPipe& clientref = *it;
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', removing",
74                                         clientref.m_fd, e.what()
75                                         );
76                                 it = m_clients.erase(--it);
77                         }
78                 }
79         }
80 }
81
82
83 CClient_AcessIPCPipe::CClient_AcessIPCPipe(::AxWin::IIPCChannel& channel, int fd):
84         CClient(channel),
85         m_fd(fd),
86         m_rxbuf(0x1000)
87 {
88 }
89
90 CClient_AcessIPCPipe::~CClient_AcessIPCPipe()
91 {
92         _SysClose(m_fd);
93         _SysDebug("Closed client FD%i", m_fd);
94 }
95
96 void CClient_AcessIPCPipe::SendMessage(CSerialiser& message)
97 {
98         const ::std::vector<uint8_t>&   data = message.Compact();
99         
100         _SysDebug("CClient_AcessIPCPipe::SendMessage - %i bytes to %i", data.size(), m_fd);
101         _SysWrite(m_fd, data.data(), data.size());
102 }
103
104 void CClient_AcessIPCPipe::HandleReceive()
105 {
106         size_t len = _SysRead(m_fd, &m_rxbuf[0], m_rxbuf.capacity());
107         if( len == (size_t)-1 )
108                 throw ::std::system_error(errno, ::std::system_category());
109         
110         CDeserialiser   message(len, &m_rxbuf[0]);
111         CClient::HandleMessage(message);
112 }
113
114 };
115

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