Usermode/AxWin4 - Working in shared memory usage
[tpg/acess2.git] / Usermode / Applications / axwin4_src / Server / ipc.cpp
1 /*
2  */
3 #define __STDC_LIMIT_MACROS
4 #include <ipc.hpp>
5 #include <list>
6 #include <IIPCChannel.hpp>
7 #include <algorithm>
8 #include <CClient.hpp>
9 #include <serialisation.hpp>
10 #include <ipc_proto.hpp>
11 #include <CCompositor.hpp>
12 extern "C" {
13 #include <assert.h>
14 };
15 #include <CIPCChannel_AcessIPCPipe.hpp>
16
17 namespace AxWin {
18 namespace IPC {
19
20 CCompositor*    gpCompositor;
21 ::std::list<IIPCChannel*>       glChannels;
22 //::std::map<uint16_t,CClient*> glClients;
23
24 void Initialise(const CConfigIPC& config, CCompositor& compositor)
25 {
26         gpCompositor = &compositor;
27         
28         ::std::string pipe_basepath = "axwin4";
29         glChannels.push_back( new CIPCChannel_AcessIPCPipe( pipe_basepath ) );
30
31         //glChannels.push_back( new CIPCChannel_TCP("0.0.0.0:2100") );
32         
33         //for( auto channel : config.m_channels )
34         //{
35         //      channels.push_back(  );
36         //}
37 }
38
39 int FillSelect(fd_set& rfds)
40 {
41         int ret = 0;
42         for( const auto channel : glChannels )
43         {
44                 assert(channel);
45                 ret = ::std::max(ret, channel->FillSelect(rfds));
46         }
47         return ret;
48 }
49
50 void HandleSelect(const fd_set& rfds)
51 {
52         for( const auto channel : glChannels )
53         {
54                 assert(channel);
55                 channel->HandleSelect(rfds);
56         }
57 }
58
59 void RegisterClient(CClient& client)
60 {
61         // allocate a client ID, and save
62         //client.m_id = 123;
63         //glClients[client.m_id] = &client;
64 }
65
66 void DeregisterClient(CClient& client)
67 {
68         //glClients.erase( client.m_id );
69 }
70
71
72 void SendNotify_Dims(CClient& client, unsigned int NewW, unsigned int NewH)
73 {
74         _SysDebug("TODO: CClient::SendNotify_Dims");
75 }
76
77
78 void HandleMessage_Nop(CClient& client, CDeserialiser& message)
79 {
80 }
81 void HandleMessage_Reply(CClient& client, CDeserialiser& message)
82 {
83         // Reply to a sent message
84         // - Not many messages need server-bound replies
85         int orig_command = message.ReadU8();
86         switch(orig_command)
87         {
88         case IPCMSG_PING:
89                 // Ping reply, mark client as still responding
90                 break;
91         default:
92                 // Unexpected reply
93                 break;
94         }
95 }
96
97 void HandleMessage_Ping(CClient& client, CDeserialiser& message)
98 {
99         // A client has asked for a ping, we pong them back
100         CSerialiser     reply;
101         reply.WriteU8(IPCMSG_REPLY);
102         reply.WriteU8(IPCMSG_PING);
103         client.SendMessage(reply);
104 }
105
106 void HandleMessage_GetGlobalAttr(CClient& client, CDeserialiser& message)
107 {
108         uint16_t        attr_id = message.ReadU16();
109         
110         CSerialiser     reply;
111         reply.WriteU8(IPCMSG_REPLY);
112         reply.WriteU8(IPCMSG_GETGLOBAL);
113         reply.WriteU16(attr_id);
114         
115         switch(attr_id)
116         {
117         case IPC_GLOBATTR_SCREENDIMS: {
118                 uint8_t screen_id = message.ReadU8();
119                 unsigned int w, h;
120                 gpCompositor->GetScreenDims(screen_id, &w, &h);
121                 reply.WriteU16( (w <= UINT16_MAX ? w : UINT16_MAX) );
122                 reply.WriteU16( (h <= UINT16_MAX ? h : UINT16_MAX) );
123                 break; }
124         case IPC_GLOBATTR_MAXAREA:
125                 assert(!"TODO: IPC_GLOBATTR_MAXAREA");
126                 break;
127         default:
128                 throw IPC::CClientFailure("Bad global attribute ID");
129         }
130         
131         client.SendMessage(reply);
132 }
133
134 void HandleMessage_SetGlobalAttr(CClient& client, CDeserialiser& message)
135 {
136         uint16_t        attr_id = message.ReadU16();
137         
138         switch(attr_id)
139         {
140         case IPC_GLOBATTR_SCREENDIMS:
141                 // Setting readonly
142                 break;
143         case IPC_GLOBATTR_MAXAREA:
144                 assert(!"TODO: IPC_GLOBATTR_MAXAREA");
145                 break;
146         default:
147                 throw IPC::CClientFailure("Bad global attribute ID");
148         }
149 }
150
151 void HandleMessage_CreateWindow(CClient& client, CDeserialiser& message)
152 {
153         uint16_t        new_id = message.ReadU16();
154         //uint16_t      parent_id = message.ReadU16();
155         //CWindow* parent = client.GetWindow( parent_id );
156         ::std::string   name = message.ReadString();
157         
158         ::_SysDebug("_CreateWindow: (%i, '%s')", new_id, name.c_str());
159         client.SetWindow( new_id, gpCompositor->CreateWindow(client, name) );
160 }
161
162 void HandleMessage_DestroyWindow(CClient& client, CDeserialiser& message)
163 {
164         uint16_t        win_id = message.ReadU16();
165         _SysDebug("_DestroyWindow: (%i)", win_id);
166         
167         CWindow*        win = client.GetWindow(win_id);
168         if(!win) {
169                 throw IPC::CClientFailure("_DestroyWindow: Bad window");
170         }
171         client.SetWindow(win_id, 0);    
172         
173         // TODO: Directly inform compositor?
174         delete win;
175 }
176
177 void HandleMessage_SetWindowAttr(CClient& client, CDeserialiser& message)
178 {
179         uint16_t        win_id = message.ReadU16();
180         uint16_t        attr_id = message.ReadU16();
181         _SysDebug("_SetWindowAttr: (%i, %i)", win_id, attr_id);
182         
183         CWindow*        win = client.GetWindow(win_id);
184         if(!win) {
185                 throw IPC::CClientFailure("_SetWindowAttr - Bad window");
186         }
187         
188         switch(attr_id)
189         {
190         case IPC_WINATTR_DIMENSIONS: {
191                 uint16_t new_w = message.ReadU16();
192                 uint16_t new_h = message.ReadU16();
193                 win->Resize(new_w, new_h);
194                 break; }
195         case IPC_WINATTR_POSITION: {
196                 int16_t new_x = message.ReadS16();
197                 int16_t new_y = message.ReadS16();
198                 win->Move(new_x, new_y);
199                 break; }
200         case IPC_WINATTR_SHOW:
201                 win->Show( message.ReadU8() != 0 );
202                 break;
203         case IPC_WINATTR_FLAGS:
204                 _SysDebug("TODO: IPC_WINATTR_FLAGS");
205                 break;
206         case IPC_WINATTR_TITLE:
207                 assert(!"TODO: IPC_WINATTR_TITLE");
208                 break;
209         default:
210                 _SysDebug("HandleMessage_SetWindowAttr - Bad attr %u", attr_id);
211                 throw IPC::CClientFailure("Bad window attr");
212         }
213 }
214
215 void HandleMessage_GetWindowAttr(CClient& client, CDeserialiser& message)
216 {
217         assert(!"TODO HandleMessage_GetWindowAttr");
218 }
219
220 void HandleMessage_SendIPC(CClient& client, CDeserialiser& message)
221 {
222         assert(!"TODO HandleMessage_SendIPC");
223 }
224
225 void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message)
226 {
227         uint16_t        win_id = message.ReadU16();
228         _SysDebug("_SetWindowAttr: (%i)", win_id);
229         
230         CWindow*        win = client.GetWindow(win_id);
231         if(!win) {
232                 throw IPC::CClientFailure("_PushData: Bad window");
233         }
234         
235         uint64_t handle = win->m_surface.GetSHMHandle();
236         
237         CSerialiser     reply;
238         reply.WriteU8(IPCMSG_REPLY);
239         reply.WriteU16(win_id);
240         reply.WriteU64(handle);
241         client.SendMessage(reply);
242 }
243
244 void HandleMessage_PushData(CClient& client, CDeserialiser& message)
245 {
246         uint16_t        win_id = message.ReadU16();
247         uint16_t        x = message.ReadU16();
248         uint16_t        y = message.ReadU16();
249         uint16_t        w = message.ReadU16();
250         uint16_t        h = message.ReadU16();
251         //_SysDebug("_PushData: (%i, (%i,%i) %ix%i)", win_id, x, y, w, h);
252         
253         CWindow*        win = client.GetWindow(win_id);
254         if(!win) {
255                 throw IPC::CClientFailure("_PushData: Bad window");
256         }
257         
258         for( unsigned int row = 0; row < h; row ++ )
259         {
260                 const ::std::vector<uint8_t> scanline_data = message.ReadBuffer();
261                 if( scanline_data.size() != w * 4 ) {
262                         _SysDebug("ERROR _PushData: Scanline buffer size mismatch (%i,%i)",
263                                 scanline_data.size(), w*4);
264                         continue ;
265                 }
266                 win->DrawScanline(y+row, x, w, scanline_data.data());
267         }
268 }
269 void HandleMessage_Blit(CClient& client, CDeserialiser& message)
270 {
271         assert(!"TODO HandleMessage_Blit");
272 }
273 void HandleMessage_DrawCtl(CClient& client, CDeserialiser& message)
274 {
275         assert(!"TODO HandleMessage_DrawCtl");
276 }
277 void HandleMessage_DrawText(CClient& client, CDeserialiser& message)
278 {
279         assert(!"TODO HandleMessage_DrawText");
280 }
281
282 typedef void    MessageHandler_op_t(CClient& client, CDeserialiser& message);
283
284 MessageHandler_op_t     *message_handlers[] = {
285         [IPCMSG_NULL]       = &HandleMessage_Nop,
286         [IPCMSG_REPLY]      = &HandleMessage_Reply,
287         [IPCMSG_PING]       = &HandleMessage_Ping,
288         [IPCMSG_GETGLOBAL]  = &HandleMessage_GetGlobalAttr,
289         [IPCMSG_SETGLOBAL]  = &HandleMessage_SetGlobalAttr,
290         
291         [IPCMSG_CREATEWIN]  = &HandleMessage_CreateWindow,
292         [IPCMSG_CLOSEWIN]   = &HandleMessage_DestroyWindow,
293         [IPCMSG_SETWINATTR] = &HandleMessage_SetWindowAttr,
294         [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr,
295         [IPCMSG_SENDIPC]    = &HandleMessage_SendIPC,   // Use the GUI server for low-bandwith IPC
296         [IPCMSG_GETWINBUF]  = &HandleMessage_GetWindowBuffer,
297         [IPCMSG_DAMAGERECT] = nullptr,
298         [IPCMSG_PUSHDATA]   = &HandleMessage_PushData,  // to a window's buffer
299         [IPCMSG_BLIT]       = &HandleMessage_Blit,      // Copy data from one part of the window to another
300         [IPCMSG_DRAWCTL]    = &HandleMessage_DrawCtl,   // Draw a control
301         [IPCMSG_DRAWTEXT]   = &HandleMessage_DrawText,  // Draw text
302 };
303
304 void HandleMessage(CClient& client, CDeserialiser& message)
305 {
306         unsigned int command = message.ReadU8();
307         if( command >= sizeof(message_handlers)/sizeof(IPC::MessageHandler_op_t*) ) {
308                 // Drop, invalid command
309                 return ;
310         }
311         
312         (message_handlers[command])(client, message);
313 }
314
315 CClientFailure::CClientFailure(std::string&& what):
316         m_what(what)
317 {
318 }
319 const char *CClientFailure::what() const throw()
320 {
321         return m_what.c_str();
322 }
323 CClientFailure::~CClientFailure() throw()
324 {
325 }
326
327 };      // namespace IPC
328
329 IIPCChannel::~IIPCChannel()
330 {
331 }
332
333 };      // namespace AxWin
334

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