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