]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/sckipc.cpp
1. wxWizard supports setting images for each page, sample updated to show it
[wxWidgets.git] / src / common / sckipc.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: sckipc.cpp
3// Purpose: Interprocess communication implementation (wxSocket version)
4// Author: Julian Smart
5// Modified by: Guilhem Lavaux (big rewrite) May 1997, 1998
6// Guillermo Rodriguez (updated for wxSocket v2) Jan 2000
7// Created: 1993
8// RCS-ID: $Id$
9// Copyright: (c) Julian Smart 1993
10// (c) Guilhem Lavaux 1997, 1998
11// (c) 2000 Guillermo Rodriguez <guille@iies.es>
12// Licence: wxWindows license
13/////////////////////////////////////////////////////////////////////////////
14
15#ifdef __GNUG__
16#pragma implementation "sckipc.h"
17#endif
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23#pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
27#include "wx/defs.h"
28#endif
29
30#if wxUSE_SOCKETS
31
32#include <stdlib.h>
33#include <stdio.h>
34
35#include "wx/socket.h"
36#include "wx/sckipc.h"
37#include "wx/log.h"
38
39#ifdef __BORLANDC__
40#pragma hdrstop
41#endif
42
43IMPLEMENT_DYNAMIC_CLASS(wxTCPServer, wxServerBase)
44IMPLEMENT_DYNAMIC_CLASS(wxTCPClient, wxClientBase)
45IMPLEMENT_CLASS(wxTCPConnection, wxConnectionBase)
46
47// It seems to be already defined somewhere in the Xt includes.
48#ifndef __XT__
49// Message codes
50enum {
51 IPC_EXECUTE = 1,
52 IPC_REQUEST,
53 IPC_POKE,
54 IPC_ADVISE_START,
55 IPC_ADVISE_REQUEST,
56 IPC_ADVISE,
57 IPC_ADVISE_STOP,
58 IPC_REQUEST_REPLY,
59 IPC_FAIL,
60 IPC_CONNECT,
61 IPC_DISCONNECT
62};
63#endif
64
65void Server_OnRequest(wxSocketServer& server,
66 wxSocketNotify evt,
67 char *cdata);
68void Client_OnRequest(wxSocketBase& sock,
69 wxSocketNotify evt,
70 char *cdata);
71
72// ---------------------------------------------------------------------------
73// wxTCPClient
74// ---------------------------------------------------------------------------
75
76wxTCPClient::wxTCPClient ()
77 : wxClientBase()
78{
79}
80
81wxTCPClient::~wxTCPClient ()
82{
83}
84
85bool wxTCPClient::ValidHost(const wxString& host)
86{
87 wxIPV4address addr;
88
89 return addr.Hostname(host);
90}
91
92wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host,
93 const wxString& server_name,
94 const wxString& topic)
95{
96 wxSocketClient *client = new wxSocketClient();
97 wxSocketStream *stream = new wxSocketStream(*client);
98 wxDataInputStream *data_is = new wxDataInputStream(*stream);
99 wxDataOutputStream *data_os = new wxDataOutputStream(*stream);
100
101 wxIPV4address addr;
102 addr.Service(server_name);
103 addr.Hostname(host);
104
105 if (client->Connect(addr))
106 {
107 unsigned char msg;
108
109 // Send topic name, and enquire whether this has succeeded
110 data_os->Write8(IPC_CONNECT);
111 data_os->WriteString(topic);
112
113 msg = data_is->Read8();
114
115 // OK! Confirmation.
116 if (msg == IPC_CONNECT)
117 {
118 wxTCPConnection *connection = (wxTCPConnection *)OnMakeConnection ();
119
120 if (connection)
121 {
122 if (!connection->IsKindOf(CLASSINFO(wxTCPConnection)))
123 {
124 delete connection;
125 // and fall through to delete everything else
126 }
127 else
128 {
129 connection->m_topic = topic;
130 connection->m_sock = client;
131 connection->m_sockstrm = stream;
132 connection->m_codeci = data_is;
133 connection->m_codeco = data_os;
134 client->Callback(Client_OnRequest);
135 client->CallbackData((char *)connection);
136 client->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
137 client->Notify(TRUE);
138 return connection;
139 }
140 }
141 }
142 }
143
144 // something went wrong
145 delete data_is;
146 delete data_os;
147 delete stream;
148 delete client;
149 return NULL;
150}
151
152wxConnectionBase *wxTCPClient::OnMakeConnection()
153{
154 return new wxTCPConnection;
155}
156
157// ---------------------------------------------------------------------------
158// wxTCPServer
159// ---------------------------------------------------------------------------
160
161wxTCPServer::wxTCPServer ()
162 : wxServerBase()
163{
164}
165
166bool wxTCPServer::Create(const wxString& server_name)
167{
168 wxIPV4address addr;
169 wxSocketServer *server;
170
171 addr.LocalHost(); // GRG
172 addr.Service(server_name);
173
174 // Create a socket listening on specified port
175 server = new wxSocketServer(addr);
176 server->Callback((wxSocketBase::wxSockCbk)Server_OnRequest);
177 server->CallbackData((char *)this);
178 server->SetNotify(wxSOCKET_CONNECTION_FLAG);
179 server->Notify(TRUE); // GRG
180
181 return TRUE;
182}
183
184wxTCPServer::~wxTCPServer()
185{
186}
187
188wxConnectionBase *wxTCPServer::OnAcceptConnection( const wxString& WXUNUSED(topic) )
189{
190 return new wxTCPConnection();
191}
192
193// ---------------------------------------------------------------------------
194// wxTCPConnection
195// ---------------------------------------------------------------------------
196
197wxTCPConnection::wxTCPConnection ()
198 : wxConnectionBase(),
199 m_sock(NULL), m_sockstrm(NULL), m_codeci(NULL), m_codeco(NULL)
200{
201}
202
203wxTCPConnection::wxTCPConnection(char * WXUNUSED(buffer), int WXUNUSED(size))
204{
205}
206
207wxTCPConnection::~wxTCPConnection ()
208{
209 wxDELETE(m_sock);
210 wxDELETE(m_codeci);
211 wxDELETE(m_codeco);
212 wxDELETE(m_sockstrm);
213}
214
215void wxTCPConnection::Compress(bool WXUNUSED(on))
216{
217 // Use wxLZWStream
218}
219
220// Calls that CLIENT can make.
221bool wxTCPConnection::Disconnect ()
222{
223 // Send the the disconnect message to the peer.
224 m_codeco->Write8(IPC_DISCONNECT);
225 m_sock->Close();
226
227 return TRUE;
228}
229
230bool wxTCPConnection::Execute(const wxChar *data, int size, wxIPCFormat format)
231{
232 if (!m_sock->IsConnected())
233 return FALSE;
234
235 // Prepare EXECUTE message
236 m_codeco->Write8(IPC_EXECUTE);
237 m_codeco->Write8(format);
238
239 if (size < 0)
240 size = strlen(data) + 1; // includes final NUL
241
242 m_codeco->Write32(size);
243 m_sockstrm->Write(data, size);
244
245 return TRUE;
246}
247
248char *wxTCPConnection::Request (const wxString& item, int *size, wxIPCFormat format)
249{
250 if (!m_sock->IsConnected())
251 return NULL;
252
253 m_codeco->Write8(IPC_REQUEST);
254 m_codeco->WriteString(item);
255 m_codeco->Write8(format);
256
257 // If Unpack doesn't initialize it.
258 int ret;
259
260 ret = m_codeci->Read8();
261 if (ret == IPC_FAIL)
262 return NULL;
263 else
264 {
265 size_t s;
266 char *data = NULL;
267
268 s = m_codeci->Read32();
269 data = new char[s];
270 m_sockstrm->Read(data, s);
271
272 if (size)
273 *size = s;
274 return data;
275 }
276}
277
278bool wxTCPConnection::Poke (const wxString& item, wxChar *data, int size, wxIPCFormat format)
279{
280 if (!m_sock->IsConnected())
281 return FALSE;
282
283 m_codeco->Write8(IPC_POKE);
284 m_codeco->WriteString(item);
285 m_codeco->Write8(format);
286
287 if (size < 0)
288 size = strlen(data) + 1; // includes final NUL
289
290 m_codeco->Write32(size);
291 m_sockstrm->Write(data, size);
292
293 return TRUE;
294}
295
296bool wxTCPConnection::StartAdvise (const wxString& item)
297{
298 int ret;
299
300 if (!m_sock->IsConnected())
301 return FALSE;
302
303 m_codeco->Write8(IPC_ADVISE_START);
304 m_codeco->WriteString(item);
305
306 ret = m_codeci->Read8();
307
308 if (ret != IPC_FAIL)
309 return TRUE;
310 else
311 return FALSE;
312}
313
314bool wxTCPConnection::StopAdvise (const wxString& item)
315{
316 int msg;
317
318 if (!m_sock->IsConnected())
319 return FALSE;
320
321 m_codeco->Write8(IPC_ADVISE_STOP);
322 m_codeco->WriteString(item);
323
324 msg = m_codeci->Read8();
325
326 if (msg != IPC_FAIL)
327 return TRUE;
328 else
329 return FALSE;
330}
331
332// Calls that SERVER can make
333bool wxTCPConnection::Advise (const wxString& item,
334 wxChar *data, int size, wxIPCFormat format)
335{
336 if (!m_sock->IsConnected())
337 return FALSE;
338
339 m_codeco->Write8(IPC_ADVISE);
340 m_codeco->WriteString(item);
341 m_codeco->Write8(format);
342
343 if (size < 0)
344 size = strlen(data) + 1; // includes final NUL
345
346 m_codeco->Write32(size);
347 m_sockstrm->Write(data, size);
348
349 return TRUE;
350}
351
352void Client_OnRequest(wxSocketBase& sock, wxSocketNotify evt,
353 char *cdata)
354{
355 int msg = 0;
356 wxTCPConnection *connection = (wxTCPConnection *)cdata;
357 wxDataInputStream *codeci;
358 wxDataOutputStream *codeco;
359 wxSocketStream *sockstrm;
360 wxString topic_name = connection->m_topic;
361 wxString item;
362
363 // The socket handler signals us that we lost the connection: destroy all.
364 if (evt == wxSOCKET_LOST)
365 {
366 sock.Close();
367 connection->OnDisconnect();
368 return;
369 }
370
371 // Receive message number.
372 codeci = connection->m_codeci;
373 codeco = connection->m_codeco;
374 sockstrm = connection->m_sockstrm;
375 msg = codeci->Read8();
376
377 switch (msg)
378 {
379 case IPC_EXECUTE:
380 {
381 char *data;
382 size_t size;
383 wxIPCFormat format;
384
385 format = (wxIPCFormat)codeci->Read8();
386 size = codeci->Read32();
387 data = new char[size];
388 sockstrm->Read(data, size);
389
390 connection->OnExecute (topic_name, data, size, format);
391
392 delete [] data;
393 break;
394 }
395 case IPC_ADVISE:
396 {
397 char *data;
398 size_t size;
399 wxIPCFormat format;
400
401 item = codeci->ReadString();
402 format = (wxIPCFormat)codeci->Read8();
403 size = codeci->Read32();
404 data = new char[size];
405 sockstrm->Read(data, size);
406
407 connection->OnAdvise (topic_name, item, data, size, format);
408
409 delete [] data;
410 break;
411 }
412 case IPC_ADVISE_START:
413 {
414 item = codeci->ReadString();
415
416 bool ok = connection->OnStartAdvise (topic_name, item);
417 if (ok)
418 codeco->Write8(IPC_ADVISE_START);
419 else
420 codeco->Write8(IPC_FAIL);
421
422 break;
423 }
424 case IPC_ADVISE_STOP:
425 {
426 item = codeci->ReadString();
427
428 bool ok = connection->OnStopAdvise (topic_name, item);
429 if (ok)
430 codeco->Write8(IPC_ADVISE_STOP);
431 else
432 codeco->Write8(IPC_FAIL);
433
434 break;
435 }
436 case IPC_POKE:
437 {
438 wxIPCFormat format;
439 size_t size;
440 wxChar *data;
441
442 item = codeci->ReadString();
443 format = (wxIPCFormat)codeci->Read8();
444 size = codeci->Read32();
445 data = new wxChar[size];
446 sockstrm->Read(data, size);
447
448 connection->OnPoke (topic_name, item, data, size, format);
449
450 delete [] data;
451
452 break;
453 }
454 case IPC_REQUEST:
455 {
456 wxIPCFormat format;
457
458 item = codeci->ReadString();
459 format = (wxIPCFormat)codeci->Read8();
460
461 int user_size = -1;
462 char *user_data = connection->OnRequest (topic_name, item, &user_size, format);
463
464 if (user_data)
465 {
466 codeco->Write8(IPC_REQUEST_REPLY);
467
468 if (user_size == -1)
469 user_size = strlen(user_data) + 1; // includes final NUL
470
471 codeco->Write32(user_size);
472 sockstrm->Write(user_data, user_size);
473 }
474 else
475 codeco->Write8(IPC_FAIL);
476
477 break;
478 }
479 case IPC_DISCONNECT:
480 {
481 sock.Close();
482 connection->OnDisconnect();
483 break;
484 }
485 default:
486 codeco->Write8(IPC_FAIL);
487 break;
488 }
489}
490
491void Server_OnRequest(wxSocketServer& server,
492 wxSocketNotify evt, char *cdata)
493{
494 wxTCPServer *ipcserv = (wxTCPServer *)cdata;
495 wxSocketStream *stream;
496 wxDataInputStream *codeci;
497 wxDataOutputStream *codeco;
498
499 if (evt != wxSOCKET_CONNECTION)
500 return;
501
502 /* Accept the connection, getting a new socket */
503 wxSocketBase *sock = server.Accept();
504 if (!sock->Ok())
505 return;
506
507 stream = new wxSocketStream(*sock);
508 codeci = new wxDataInputStream(*stream);
509 codeco = new wxDataOutputStream(*stream);
510
511 int msg;
512 msg = codeci->Read8();
513
514 if (msg == IPC_CONNECT)
515 {
516 wxString topic_name;
517 topic_name = codeci->ReadString();
518
519 /* Register new socket with the notifier */
520 wxTCPConnection *new_connection =
521 (wxTCPConnection *)ipcserv->OnAcceptConnection (topic_name);
522 if (new_connection)
523 {
524 if (!new_connection->IsKindOf(CLASSINFO(wxTCPConnection)))
525 {
526 delete new_connection;
527 codeco->Write8(IPC_FAIL);
528 return;
529 }
530 // Acknowledge success
531 codeco->Write8(IPC_CONNECT);
532 new_connection->m_topic = topic_name;
533 new_connection->m_sock = sock;
534 new_connection->m_sockstrm = stream;
535 new_connection->m_codeci = codeci;
536 new_connection->m_codeco = codeco;
537 sock->Callback(Client_OnRequest);
538 sock->CallbackData((char *)new_connection);
539 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
540 sock->Notify(TRUE);
541 }
542 else
543 {
544 // Send failure message
545 codeco->Write8(IPC_FAIL);
546 }
547 }
548}
549
550#endif
551 // wxUSE_SOCKETS