70605fc0bad9b52413d434b9505ac3bae272228f
[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                 _SysDebug("IPC::FillSelect - channel=%p", channel);
45                 assert(channel);
46                 ret = ::std::max(ret, channel->FillSelect(rfds));
47         }
48         return ret;
49 }
50
51 void HandleSelect(const fd_set& rfds)
52 {
53         for( const auto channel : glChannels )
54         {
55                 assert(channel);
56                 channel->HandleSelect(rfds);
57         }
58 }
59
60 void RegisterClient(CClient& client)
61 {
62         // allocate a client ID, and save
63         //client.m_id = 123;
64         //glClients[client.m_id] = &client;
65 }
66
67 void DeregisterClient(CClient& client)
68 {
69         //glClients.erase( client.m_id );
70 }
71
72
73 void SendNotify_Dims(CClient& client, unsigned int NewW, unsigned int NewH)
74 {
75         _SysDebug("TODO: CClient::SendNotify_Dims");
76 }
77
78
79 void HandleMessage_Nop(CClient& client, CDeserialiser& message)
80 {
81 }
82 void HandleMessage_Reply(CClient& client, CDeserialiser& message)
83 {
84         // Reply to a sent message
85         // - Not many messages need server-bound replies
86         int orig_command = message.ReadU8();
87         switch(orig_command)
88         {
89         case IPCMSG_PING:
90                 // Ping reply, mark client as still responding
91                 break;
92         default:
93                 // Unexpected reply
94                 break;
95         }
96 }
97
98 void HandleMessage_Ping(CClient& client, CDeserialiser& message)
99 {
100         // A client has asked for a ping, we pong them back
101         CSerialiser     reply;
102         reply.WriteU8(IPCMSG_REPLY);
103         reply.WriteU8(IPCMSG_PING);
104         client.SendMessage(reply);
105 }
106
107 void HandleMessage_GetGlobalAttr(CClient& client, CDeserialiser& message)
108 {
109         uint16_t        attr_id = message.ReadU16();
110         
111         CSerialiser     reply;
112         reply.WriteU8(IPCMSG_REPLY);
113         reply.WriteU8(IPCMSG_GETGLOBAL);
114         reply.WriteU16(attr_id);
115         
116         switch(attr_id)
117         {
118         case IPC_GLOBATTR_SCREENDIMS: {
119                 uint8_t screen_id = message.ReadU8();
120                 unsigned int w, h;
121                 gpCompositor->GetScreenDims(screen_id, &w, &h);
122                 reply.WriteU16( (w <= UINT16_MAX ? w : UINT16_MAX) );
123                 reply.WriteU16( (h <= UINT16_MAX ? h : UINT16_MAX) );
124                 break; }
125         default:
126                 throw IPC::CClientFailure("Bad global attribute ID");
127         }
128         
129         client.SendMessage(reply);
130 }
131
132 void HandleMessage_SetGlobalAttr(CClient& client, CDeserialiser& message)
133 {
134         uint16_t        attr_id = message.ReadU16();
135         
136         switch(attr_id)
137         {
138         case IPC_GLOBATTR_SCREENDIMS:
139                 // Setting readonly
140                 break;
141         case IPC_GLOBATTR_MAXAREA:
142                 assert(!"TODO: IPC_GLOBATTR_MAXAREA");
143                 break;
144         default:
145                 throw IPC::CClientFailure("Bad global attribute ID");
146         }
147 }
148
149 void HandleMessage_CreateWindow(CClient& client, CDeserialiser& message)
150 {
151         uint16_t        new_id = message.ReadU16();
152         //uint16_t      parent_id = message.ReadU16();
153         //CWindow* parent = client.GetWindow( parent_id );
154         ::std::string   name = message.ReadString();
155         
156         ::_SysDebug("_CreateWindow: (%i, '%s')", new_id, name.c_str());
157         client.SetWindow( new_id, gpCompositor->CreateWindow(client, name) );
158 }
159
160 void HandleMessage_DestroyWindow(CClient& client, CDeserialiser& message)
161 {
162         uint16_t        win_id = message.ReadU16();
163         _SysDebug("_DestroyWindow: (%i)", win_id);
164         
165         CWindow*        win = client.GetWindow(win_id);
166         if(!win) {
167                 throw IPC::CClientFailure("_DestroyWindow: Bad window");
168         }
169         client.SetWindow(win_id, 0);    
170         
171         // TODO: Directly inform compositor?
172         delete win;
173 }
174
175 void HandleMessage_SetWindowAttr(CClient& client, CDeserialiser& message)
176 {
177         uint16_t        win_id = message.ReadU16();
178         uint16_t        attr_id = message.ReadU16();
179         _SysDebug("_SetWindowAttr: (%i, %i)", win_id, attr_id);
180         
181         CWindow*        win = client.GetWindow(win_id);
182         if(!win) {
183                 throw IPC::CClientFailure("_SetWindowAttr - Bad window");
184         }
185         
186         switch(attr_id)
187         {
188         case IPC_WINATTR_DIMENSIONS: {
189                 uint16_t new_w = message.ReadU16();
190                 uint16_t new_h = message.ReadU16();
191                 win->Resize(new_w, new_h);
192                 break; }
193         case IPC_WINATTR_POSITION: {
194                 int16_t new_x = message.ReadS16();
195                 int16_t new_y = message.ReadS16();
196                 win->Move(new_x, new_y);
197                 break; }
198         default:
199                 _SysDebug("HandleMessage_SetWindowAttr - Bad attr %u", attr_id);
200                 throw IPC::CClientFailure("Bad window attr");
201         }
202 }
203
204 void HandleMessage_GetWindowAttr(CClient& client, CDeserialiser& message)
205 {
206         assert(!"TODO HandleMessage_GetWindowAttr");
207 }
208
209 void HandleMessage_SendIPC(CClient& client, CDeserialiser& message)
210 {
211         assert(!"TODO HandleMessage_SendIPC");
212 }
213
214 void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message)
215 {
216         assert(!"TODO HandleMessage_GetWindowBuffer");
217 }
218
219 void HandleMessage_PushData(CClient& client, CDeserialiser& message)
220 {
221         uint16_t        win_id = message.ReadU16();
222         uint16_t        x = message.ReadU16();
223         uint16_t        y = message.ReadU16();
224         uint16_t        w = message.ReadU16();
225         uint16_t        h = message.ReadU16();
226         _SysDebug("_PushData: (%i, (%i,%i) %ix%i)", win_id, x, y, w, h);
227         
228         CWindow*        win = client.GetWindow(win_id);
229         if(!win) {
230                 throw IPC::CClientFailure("_PushData: Bad window");
231         }
232         
233         for( unsigned int row = 0; row < h; row ++ )
234         {
235                 const ::std::vector<uint8_t> scanline_data = message.ReadBuffer();
236                 _SysDebug("_PushData: Scanline %i: %i bytes", row, scanline_data.size());
237                 if( scanline_data.size() != w * 4 ) {
238                         _SysDebug("ERROR _PushData: Scanline buffer size mismatch (%i,%i)",
239                                 scanline_data.size(), w*4);
240                         continue ;
241                 }
242                 win->m_surface.DrawScanline(y+row, x, w, scanline_data.data());
243         }
244 }
245 void HandleMessage_Blit(CClient& client, CDeserialiser& message)
246 {
247         assert(!"TODO HandleMessage_Blit");
248 }
249 void HandleMessage_DrawCtl(CClient& client, CDeserialiser& message)
250 {
251         assert(!"TODO HandleMessage_DrawCtl");
252 }
253 void HandleMessage_DrawText(CClient& client, CDeserialiser& message)
254 {
255         assert(!"TODO HandleMessage_DrawText");
256 }
257
258 typedef void    MessageHandler_op_t(CClient& client, CDeserialiser& message);
259
260 MessageHandler_op_t     *message_handlers[] = {
261         [IPCMSG_NULL]       = &HandleMessage_Nop,
262         [IPCMSG_REPLY]      = &HandleMessage_Reply,
263         [IPCMSG_PING]       = &HandleMessage_Ping,
264         [IPCMSG_GETGLOBAL]  = &HandleMessage_GetGlobalAttr,
265         [IPCMSG_SETGLOBAL]  = &HandleMessage_SetGlobalAttr,
266         
267         [IPCMSG_CREATEWIN]  = &HandleMessage_CreateWindow,
268         [IPCMSG_CLOSEWIN]   = &HandleMessage_DestroyWindow,
269         [IPCMSG_SETWINATTR] = &HandleMessage_SetWindowAttr,
270         [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr,
271         [IPCMSG_SENDIPC]    = &HandleMessage_SendIPC,   // Use the GUI server for low-bandwith IPC
272         [IPCMSG_GETWINBUF]  = &HandleMessage_GetWindowBuffer,
273         [IPCMSG_PUSHDATA]   = &HandleMessage_PushData,  // to a window's buffer
274         [IPCMSG_BLIT]       = &HandleMessage_Blit,      // Copy data from one part of the window to another
275         [IPCMSG_DRAWCTL]    = &HandleMessage_DrawCtl,   // Draw a control
276         [IPCMSG_DRAWTEXT]   = &HandleMessage_DrawText,  // Draw text
277 };
278
279 void HandleMessage(CClient& client, CDeserialiser& message)
280 {
281         unsigned int command = message.ReadU8();
282         if( command >= sizeof(message_handlers)/sizeof(IPC::MessageHandler_op_t*) ) {
283                 // Drop, invalid command
284                 return ;
285         }
286         
287         _SysDebug("IPC::HandleMessage - command=%i", command);
288         (message_handlers[command])(client, message);
289         _SysDebug("IPC::HandleMessage - Completed");
290 }
291
292 CClientFailure::CClientFailure(std::string&& what):
293         m_what(what)
294 {
295 }
296 const char *CClientFailure::what() const throw()
297 {
298         return m_what.c_str();
299 }
300 CClientFailure::~CClientFailure() throw()
301 {
302 }
303
304 };      // namespace IPC
305
306 IIPCChannel::~IIPCChannel()
307 {
308 }
309
310 };      // namespace AxWin
311

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