]> git.saurik.com Git - wxWidgets.git/blame - src/common/sckipc.cpp
OS/2 Updates
[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{
e5b502f3 194 return new wxTCPConnection();
f4ada568
GL
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 253
e5b502f3
GRG
254 if (m_sock)
255 {
256 m_sock->SetClientData(NULL);
257 m_sock->Destroy();
258 }
f4ada568
GL
259}
260
cb43b372 261void wxTCPConnection::Compress(bool WXUNUSED(on))
f4ada568
GL
262{
263 // Use wxLZWStream
264}
265
266// Calls that CLIENT can make.
6e31e940 267bool wxTCPConnection::Disconnect ()
f4ada568
GL
268{
269 // Send the the disconnect message to the peer.
75ed1d15 270 m_codeco->Write8(IPC_DISCONNECT);
cdc59bb6 271 m_sock->Notify(FALSE);
f4ada568
GL
272 m_sock->Close();
273
274 return TRUE;
275}
276
0834112f 277bool wxTCPConnection::Execute(const wxChar *data, int size, wxIPCFormat format)
f4ada568
GL
278{
279 if (!m_sock->IsConnected())
280 return FALSE;
281
282 // Prepare EXECUTE message
75ed1d15
GL
283 m_codeco->Write8(IPC_EXECUTE);
284 m_codeco->Write8(format);
0834112f 285
f4ada568 286 if (size < 0)
0834112f
GRG
287 size = strlen(data) + 1; // includes final NUL
288
289 m_codeco->Write32(size);
290 m_sockstrm->Write(data, size);
f4ada568
GL
291
292 return TRUE;
293}
294
0d2a2b60 295char *wxTCPConnection::Request (const wxString& item, int *size, wxIPCFormat format)
f4ada568
GL
296{
297 if (!m_sock->IsConnected())
298 return NULL;
299
75ed1d15
GL
300 m_codeco->Write8(IPC_REQUEST);
301 m_codeco->WriteString(item);
302 m_codeco->Write8(format);
f4ada568
GL
303
304 // If Unpack doesn't initialize it.
305 int ret;
306
75ed1d15 307 ret = m_codeci->Read8();
f4ada568
GL
308 if (ret == IPC_FAIL)
309 return NULL;
0834112f
GRG
310 else
311 {
f4ada568
GL
312 size_t s;
313 char *data = NULL;
314
75ed1d15 315 s = m_codeci->Read32();
f4ada568 316 data = new char[s];
fae05df5 317 m_sockstrm->Read(data, s);
f4ada568
GL
318
319 if (size)
320 *size = s;
321 return data;
322 }
323}
324
783b6cfd 325bool wxTCPConnection::Poke (const wxString& item, wxChar *data, int size, wxIPCFormat format)
f4ada568
GL
326{
327 if (!m_sock->IsConnected())
328 return FALSE;
329
75ed1d15
GL
330 m_codeco->Write8(IPC_POKE);
331 m_codeco->WriteString(item);
332 m_codeco->Write8(format);
0834112f 333
f4ada568 334 if (size < 0)
0834112f
GRG
335 size = strlen(data) + 1; // includes final NUL
336
337 m_codeco->Write32(size);
338 m_sockstrm->Write(data, size);
f4ada568
GL
339
340 return TRUE;
341}
342
343bool wxTCPConnection::StartAdvise (const wxString& item)
344{
345 int ret;
346
347 if (!m_sock->IsConnected())
348 return FALSE;
349
75ed1d15
GL
350 m_codeco->Write8(IPC_ADVISE_START);
351 m_codeco->WriteString(item);
f4ada568 352
75ed1d15 353 ret = m_codeci->Read8();
f4ada568
GL
354
355 if (ret != IPC_FAIL)
356 return TRUE;
357 else
358 return FALSE;
359}
360
361bool wxTCPConnection::StopAdvise (const wxString& item)
362{
363 int msg;
364
365 if (!m_sock->IsConnected())
366 return FALSE;
367
75ed1d15
GL
368 m_codeco->Write8(IPC_ADVISE_STOP);
369 m_codeco->WriteString(item);
f4ada568 370
75ed1d15 371 msg = m_codeci->Read8();
f4ada568
GL
372
373 if (msg != IPC_FAIL)
374 return TRUE;
375 else
376 return FALSE;
377}
378
379// Calls that SERVER can make
380bool wxTCPConnection::Advise (const wxString& item,
783b6cfd 381 wxChar *data, int size, wxIPCFormat format)
f4ada568
GL
382{
383 if (!m_sock->IsConnected())
384 return FALSE;
385
75ed1d15
GL
386 m_codeco->Write8(IPC_ADVISE);
387 m_codeco->WriteString(item);
388 m_codeco->Write8(format);
0834112f 389
f4ada568 390 if (size < 0)
0834112f
GRG
391 size = strlen(data) + 1; // includes final NUL
392
393 m_codeco->Write32(size);
394 m_sockstrm->Write(data, size);
f4ada568
GL
395
396 return TRUE;
397}
398
cdc59bb6
GRG
399// --------------------------------------------------------------------------
400// wxTCPEventHandler (private class)
401// --------------------------------------------------------------------------
402
403BEGIN_EVENT_TABLE(wxTCPEventHandler, wxEvtHandler)
404 EVT_SOCKET(_CLIENT_ONREQUEST_ID, wxTCPEventHandler::Client_OnRequest)
405 EVT_SOCKET(_SERVER_ONREQUEST_ID, wxTCPEventHandler::Server_OnRequest)
406END_EVENT_TABLE()
407
408void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event)
f4ada568 409{
cdc59bb6
GRG
410 wxSocketBase *sock = event.GetSocket();
411 wxSocketNotify evt = event.GetSocketEvent();
1f0500b3 412 wxTCPConnection *connection = (wxTCPConnection *)(sock->GetClientData());
cdc59bb6 413
e5b502f3
GRG
414 // This socket is being deleted; skip this event
415 if (!connection)
416 return;
417
f4ada568 418 int msg = 0;
75ed1d15
GL
419 wxDataInputStream *codeci;
420 wxDataOutputStream *codeco;
fae05df5 421 wxSocketStream *sockstrm;
f4ada568
GL
422 wxString topic_name = connection->m_topic;
423 wxString item;
424
e5b502f3 425 // We lost the connection: destroy everything
0834112f
GRG
426 if (evt == wxSOCKET_LOST)
427 {
cdc59bb6
GRG
428 sock->Notify(FALSE);
429 sock->Close();
f4ada568
GL
430 connection->OnDisconnect();
431 return;
432 }
433
434 // Receive message number.
75ed1d15
GL
435 codeci = connection->m_codeci;
436 codeco = connection->m_codeco;
fae05df5 437 sockstrm = connection->m_sockstrm;
75ed1d15 438 msg = codeci->Read8();
f4ada568 439
0834112f
GRG
440 switch (msg)
441 {
442 case IPC_EXECUTE:
443 {
f4ada568
GL
444 char *data;
445 size_t size;
0d2a2b60 446 wxIPCFormat format;
f4ada568 447
0d2a2b60 448 format = (wxIPCFormat)codeci->Read8();
75ed1d15 449 size = codeci->Read32();
f4ada568 450 data = new char[size];
fae05df5 451 sockstrm->Read(data, size);
f4ada568
GL
452
453 connection->OnExecute (topic_name, data, size, format);
454
455 delete [] data;
456 break;
457 }
0834112f
GRG
458 case IPC_ADVISE:
459 {
f4ada568
GL
460 char *data;
461 size_t size;
0d2a2b60 462 wxIPCFormat format;
f4ada568 463
75ed1d15 464 item = codeci->ReadString();
0d2a2b60 465 format = (wxIPCFormat)codeci->Read8();
75ed1d15 466 size = codeci->Read32();
f4ada568 467 data = new char[size];
fae05df5 468 sockstrm->Read(data, size);
f4ada568
GL
469
470 connection->OnAdvise (topic_name, item, data, size, format);
471
472 delete [] data;
473 break;
474 }
0834112f
GRG
475 case IPC_ADVISE_START:
476 {
75ed1d15 477 item = codeci->ReadString();
f4ada568
GL
478
479 bool ok = connection->OnStartAdvise (topic_name, item);
480 if (ok)
75ed1d15 481 codeco->Write8(IPC_ADVISE_START);
f4ada568 482 else
75ed1d15 483 codeco->Write8(IPC_FAIL);
f4ada568
GL
484
485 break;
486 }
0834112f
GRG
487 case IPC_ADVISE_STOP:
488 {
75ed1d15 489 item = codeci->ReadString();
f4ada568
GL
490
491 bool ok = connection->OnStopAdvise (topic_name, item);
492 if (ok)
75ed1d15 493 codeco->Write8(IPC_ADVISE_STOP);
f4ada568 494 else
75ed1d15 495 codeco->Write8(IPC_FAIL);
f4ada568
GL
496
497 break;
498 }
0834112f
GRG
499 case IPC_POKE:
500 {
0d2a2b60 501 wxIPCFormat format;
f4ada568 502 size_t size;
783b6cfd 503 wxChar *data;
f4ada568 504
75ed1d15 505 item = codeci->ReadString();
0d2a2b60 506 format = (wxIPCFormat)codeci->Read8();
75ed1d15 507 size = codeci->Read32();
783b6cfd 508 data = new wxChar[size];
fae05df5 509 sockstrm->Read(data, size);
f4ada568
GL
510
511 connection->OnPoke (topic_name, item, data, size, format);
512
513 delete [] data;
514
515 break;
516 }
0834112f
GRG
517 case IPC_REQUEST:
518 {
0d2a2b60 519 wxIPCFormat format;
f4ada568 520
75ed1d15 521 item = codeci->ReadString();
0d2a2b60 522 format = (wxIPCFormat)codeci->Read8();
f4ada568
GL
523
524 int user_size = -1;
525 char *user_data = connection->OnRequest (topic_name, item, &user_size, format);
526
0834112f
GRG
527 if (user_data)
528 {
75ed1d15 529 codeco->Write8(IPC_REQUEST_REPLY);
0834112f
GRG
530
531 if (user_size == -1)
532 user_size = strlen(user_data) + 1; // includes final NUL
533
534 codeco->Write32(user_size);
535 sockstrm->Write(user_data, user_size);
536 }
537 else
75ed1d15 538 codeco->Write8(IPC_FAIL);
f4ada568
GL
539
540 break;
541 }
0834112f
GRG
542 case IPC_DISCONNECT:
543 {
cdc59bb6
GRG
544 sock->Notify(FALSE);
545 sock->Close();
f4ada568
GL
546 connection->OnDisconnect();
547 break;
548 }
549 default:
75ed1d15 550 codeco->Write8(IPC_FAIL);
f4ada568
GL
551 break;
552 }
553}
554
cdc59bb6 555void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event)
f4ada568 556{
cdc59bb6
GRG
557 wxSocketServer *server = (wxSocketServer *) event.GetSocket();
558 wxTCPServer *ipcserv = (wxTCPServer *) event.GetClientData();
f4ada568 559
e5b502f3
GRG
560 // This socket is being deleted; skip this event
561 if (!ipcserv)
562 return;
563
cdc59bb6 564 if (event.GetSocketEvent() != wxSOCKET_CONNECTION)
f4ada568
GL
565 return;
566
3adb47a9 567 // Accept the connection, getting a new socket
cdc59bb6 568 wxSocketBase *sock = server->Accept();
0834112f 569 if (!sock->Ok())
3adb47a9
GRG
570 {
571 sock->Destroy();
0834112f 572 return;
3adb47a9 573 }
f4ada568 574
cdc59bb6
GRG
575 wxSocketStream *stream = new wxSocketStream(*sock);
576 wxDataInputStream *codeci = new wxDataInputStream(*stream);
577 wxDataOutputStream *codeco = new wxDataOutputStream(*stream);
f4ada568 578
f4ada568 579 int msg;
75ed1d15 580 msg = codeci->Read8();
f4ada568 581
0834112f
GRG
582 if (msg == IPC_CONNECT)
583 {
f4ada568 584 wxString topic_name;
75ed1d15 585 topic_name = codeci->ReadString();
f4ada568 586
f4ada568
GL
587 wxTCPConnection *new_connection =
588 (wxTCPConnection *)ipcserv->OnAcceptConnection (topic_name);
3adb47a9 589
0834112f
GRG
590 if (new_connection)
591 {
3adb47a9 592 if (new_connection->IsKindOf(CLASSINFO(wxTCPConnection)))
0834112f 593 {
3adb47a9
GRG
594 // Acknowledge success
595 codeco->Write8(IPC_CONNECT);
596 new_connection->m_topic = topic_name;
597 new_connection->m_sock = sock;
598 new_connection->m_sockstrm = stream;
599 new_connection->m_codeci = codeci;
600 new_connection->m_codeco = codeco;
cdc59bb6
GRG
601 sock->SetEventHandler(*gs_handler, _CLIENT_ONREQUEST_ID);
602 sock->SetClientData(new_connection);
3adb47a9
GRG
603 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
604 sock->Notify(TRUE);
f4ada568
GL
605 return;
606 }
3adb47a9
GRG
607 else
608 {
609 delete new_connection;
610 // and fall through to delete everything else
611 }
f4ada568
GL
612 }
613 }
3adb47a9
GRG
614
615 // Something went wrong, send failure message and delete everything
616 codeco->Write8(IPC_FAIL);
617
618 delete codeco;
619 delete codeci;
620 delete stream;
621 sock->Destroy();
f4ada568 622}
35a4dab7 623
cdc59bb6
GRG
624// --------------------------------------------------------------------------
625// wxTCPEventHandlerModule (private class)
626// --------------------------------------------------------------------------
627
628class WXDLLEXPORT wxTCPEventHandlerModule: public wxModule
629{
630 DECLARE_DYNAMIC_CLASS(wxTCPEventHandlerModule)
631
632public:
633 bool OnInit() { gs_handler = new wxTCPEventHandler(); return TRUE; }
634 void OnExit() { wxDELETE(gs_handler); }
635};
636
637IMPLEMENT_DYNAMIC_CLASS(wxTCPEventHandlerModule, wxModule)
638
639
35a4dab7 640#endif
3adb47a9 641 // wxUSE_SOCKETS && wxUSE_IPC