Usermode/AxWin4 - Mouse input in progress
[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",
55                                 m_fd, newfd);
56                         
57                         // emplace creates a new object within the list
58                         m_clients.emplace( m_clients.end(), *this, newfd );
59                         IPC::RegisterClient( m_clients.back() );
60                 }
61         }
62
63         for( auto it = m_clients.begin(); it != m_clients.end();  )
64         {
65                 CClient_AcessIPCPipe& clientref = *it;
66                 ++ it;
67                 
68                 if( FD_ISSET(clientref.m_fd, &rfds) )
69                 {
70                         try {
71                                 clientref.HandleReceive();
72                         }
73                         catch( const ::std::exception& e ) {
74                                 _SysDebug("ERROR - Exception processing IPCPipe FD%i: '%s', removing",
75                                         clientref.m_fd, e.what()
76                                         );
77                                 it = m_clients.erase(--it);
78                         }
79                 }
80         }
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