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