]> git.saurik.com Git - wxWidgets.git/blame - src/common/sckipc.cpp
added compression ratio argument to wxZlibOutputStream ctor
[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 71
d3ea6527
GRG
72
73// All sockets will be created with the following flags
74
75#define SCKIPC_FLAGS wxSOCKET_NONE
76
f4ada568
GL
77// ---------------------------------------------------------------------------
78// wxTCPClient
79// ---------------------------------------------------------------------------
80
6e31e940 81wxTCPClient::wxTCPClient ()
f4ada568
GL
82 : wxClientBase()
83{
84}
85
6e31e940 86wxTCPClient::~wxTCPClient ()
f4ada568
GL
87{
88}
89
90bool wxTCPClient::ValidHost(const wxString& host)
91{
92 wxIPV4address addr;
93
94 return addr.Hostname(host);
95}
96
97wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host,
98 const wxString& server_name,
99 const wxString& topic)
100{
d3ea6527 101 wxSocketClient *client = new wxSocketClient(SCKIPC_FLAGS);
f4ada568 102 wxSocketStream *stream = new wxSocketStream(*client);
0834112f
GRG
103 wxDataInputStream *data_is = new wxDataInputStream(*stream);
104 wxDataOutputStream *data_os = new wxDataOutputStream(*stream);
105
106 wxIPV4address addr;
f4ada568
GL
107 addr.Service(server_name);
108 addr.Hostname(host);
109
0834112f
GRG
110 if (client->Connect(addr))
111 {
112 unsigned char msg;
f4ada568 113
0834112f
GRG
114 // Send topic name, and enquire whether this has succeeded
115 data_os->Write8(IPC_CONNECT);
116 data_os->WriteString(topic);
f4ada568 117
0834112f
GRG
118 msg = data_is->Read8();
119
120 // OK! Confirmation.
121 if (msg == IPC_CONNECT)
122 {
123 wxTCPConnection *connection = (wxTCPConnection *)OnMakeConnection ();
124
125 if (connection)
126 {
127 if (!connection->IsKindOf(CLASSINFO(wxTCPConnection)))
128 {
129 delete connection;
130 // and fall through to delete everything else
131 }
132 else
133 {
134 connection->m_topic = topic;
135 connection->m_sock = client;
136 connection->m_sockstrm = stream;
137 connection->m_codeci = data_is;
138 connection->m_codeco = data_os;
139 client->Callback(Client_OnRequest);
140 client->CallbackData((char *)connection);
141 client->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
142 client->Notify(TRUE);
143 return connection;
144 }
f4ada568 145 }
f4ada568 146 }
f4ada568 147 }
0834112f
GRG
148
149 // something went wrong
150 delete data_is;
151 delete data_os;
152 delete stream;
153 delete client;
154 return NULL;
f4ada568
GL
155}
156
157wxConnectionBase *wxTCPClient::OnMakeConnection()
158{
159 return new wxTCPConnection;
160}
161
162// ---------------------------------------------------------------------------
163// wxTCPServer
164// ---------------------------------------------------------------------------
165
6e31e940 166wxTCPServer::wxTCPServer ()
f4ada568
GL
167 : wxServerBase()
168{
169}
170
171bool wxTCPServer::Create(const wxString& server_name)
172{
f4ada568
GL
173 wxSocketServer *server;
174
d3ea6527
GRG
175 // wxIPV4address defaults to INADDR_ANY:0
176 wxIPV4address addr;
f4ada568
GL
177 addr.Service(server_name);
178
179 // Create a socket listening on specified port
d3ea6527 180 server = new wxSocketServer(addr, SCKIPC_FLAGS);
f4ada568 181 server->Callback((wxSocketBase::wxSockCbk)Server_OnRequest);
f4ada568 182 server->CallbackData((char *)this);
0834112f 183 server->SetNotify(wxSOCKET_CONNECTION_FLAG);
d3ea6527 184 server->Notify(TRUE);
f4ada568
GL
185
186 return TRUE;
187}
188
6e31e940 189wxTCPServer::~wxTCPServer()
f4ada568
GL
190{
191}
192
e22036dc 193wxConnectionBase *wxTCPServer::OnAcceptConnection( const wxString& WXUNUSED(topic) )
f4ada568
GL
194{
195 return new wxTCPConnection();
196}
197
198// ---------------------------------------------------------------------------
199// wxTCPConnection
200// ---------------------------------------------------------------------------
201
6e31e940 202wxTCPConnection::wxTCPConnection ()
f4ada568 203 : wxConnectionBase(),
75ed1d15 204 m_sock(NULL), m_sockstrm(NULL), m_codeci(NULL), m_codeco(NULL)
f4ada568
GL
205{
206}
207
6e31e940 208wxTCPConnection::wxTCPConnection(char * WXUNUSED(buffer), int WXUNUSED(size))
7921cf2b
JS
209{
210}
211
6e31e940 212wxTCPConnection::~wxTCPConnection ()
f4ada568
GL
213{
214 wxDELETE(m_sock);
75ed1d15
GL
215 wxDELETE(m_codeci);
216 wxDELETE(m_codeco);
f4ada568
GL
217 wxDELETE(m_sockstrm);
218}
219
cb43b372 220void wxTCPConnection::Compress(bool WXUNUSED(on))
f4ada568
GL
221{
222 // Use wxLZWStream
223}
224
225// Calls that CLIENT can make.
6e31e940 226bool wxTCPConnection::Disconnect ()
f4ada568
GL
227{
228 // Send the the disconnect message to the peer.
75ed1d15 229 m_codeco->Write8(IPC_DISCONNECT);
f4ada568
GL
230 m_sock->Close();
231
232 return TRUE;
233}
234
0834112f 235bool wxTCPConnection::Execute(const wxChar *data, int size, wxIPCFormat format)
f4ada568
GL
236{
237 if (!m_sock->IsConnected())
238 return FALSE;
239
240 // Prepare EXECUTE message
75ed1d15
GL
241 m_codeco->Write8(IPC_EXECUTE);
242 m_codeco->Write8(format);
0834112f 243
f4ada568 244 if (size < 0)
0834112f
GRG
245 size = strlen(data) + 1; // includes final NUL
246
247 m_codeco->Write32(size);
248 m_sockstrm->Write(data, size);
f4ada568
GL
249
250 return TRUE;
251}
252
0d2a2b60 253char *wxTCPConnection::Request (const wxString& item, int *size, wxIPCFormat format)
f4ada568
GL
254{
255 if (!m_sock->IsConnected())
256 return NULL;
257
75ed1d15
GL
258 m_codeco->Write8(IPC_REQUEST);
259 m_codeco->WriteString(item);
260 m_codeco->Write8(format);
f4ada568
GL
261
262 // If Unpack doesn't initialize it.
263 int ret;
264
75ed1d15 265 ret = m_codeci->Read8();
f4ada568
GL
266 if (ret == IPC_FAIL)
267 return NULL;
0834112f
GRG
268 else
269 {
f4ada568
GL
270 size_t s;
271 char *data = NULL;
272
75ed1d15 273 s = m_codeci->Read32();
f4ada568 274 data = new char[s];
fae05df5 275 m_sockstrm->Read(data, s);
f4ada568
GL
276
277 if (size)
278 *size = s;
279 return data;
280 }
281}
282
783b6cfd 283bool wxTCPConnection::Poke (const wxString& item, wxChar *data, int size, wxIPCFormat format)
f4ada568
GL
284{
285 if (!m_sock->IsConnected())
286 return FALSE;
287
75ed1d15
GL
288 m_codeco->Write8(IPC_POKE);
289 m_codeco->WriteString(item);
290 m_codeco->Write8(format);
0834112f 291
f4ada568 292 if (size < 0)
0834112f
GRG
293 size = strlen(data) + 1; // includes final NUL
294
295 m_codeco->Write32(size);
296 m_sockstrm->Write(data, size);
f4ada568
GL
297
298 return TRUE;
299}
300
301bool wxTCPConnection::StartAdvise (const wxString& item)
302{
303 int ret;
304
305 if (!m_sock->IsConnected())
306 return FALSE;
307
75ed1d15
GL
308 m_codeco->Write8(IPC_ADVISE_START);
309 m_codeco->WriteString(item);
f4ada568 310
75ed1d15 311 ret = m_codeci->Read8();
f4ada568
GL
312
313 if (ret != IPC_FAIL)
314 return TRUE;
315 else
316 return FALSE;
317}
318
319bool wxTCPConnection::StopAdvise (const wxString& item)
320{
321 int msg;
322
323 if (!m_sock->IsConnected())
324 return FALSE;
325
75ed1d15
GL
326 m_codeco->Write8(IPC_ADVISE_STOP);
327 m_codeco->WriteString(item);
f4ada568 328
75ed1d15 329 msg = m_codeci->Read8();
f4ada568
GL
330
331 if (msg != IPC_FAIL)
332 return TRUE;
333 else
334 return FALSE;
335}
336
337// Calls that SERVER can make
338bool wxTCPConnection::Advise (const wxString& item,
783b6cfd 339 wxChar *data, int size, wxIPCFormat format)
f4ada568
GL
340{
341 if (!m_sock->IsConnected())
342 return FALSE;
343
75ed1d15
GL
344 m_codeco->Write8(IPC_ADVISE);
345 m_codeco->WriteString(item);
346 m_codeco->Write8(format);
0834112f 347
f4ada568 348 if (size < 0)
0834112f
GRG
349 size = strlen(data) + 1; // includes final NUL
350
351 m_codeco->Write32(size);
352 m_sockstrm->Write(data, size);
f4ada568
GL
353
354 return TRUE;
355}
356
aa8fb7a0 357void Client_OnRequest(wxSocketBase& sock, wxSocketNotify evt,
f4ada568
GL
358 char *cdata)
359{
360 int msg = 0;
361 wxTCPConnection *connection = (wxTCPConnection *)cdata;
75ed1d15
GL
362 wxDataInputStream *codeci;
363 wxDataOutputStream *codeco;
fae05df5 364 wxSocketStream *sockstrm;
f4ada568
GL
365 wxString topic_name = connection->m_topic;
366 wxString item;
367
368 // The socket handler signals us that we lost the connection: destroy all.
0834112f
GRG
369 if (evt == wxSOCKET_LOST)
370 {
f4ada568
GL
371 sock.Close();
372 connection->OnDisconnect();
373 return;
374 }
375
376 // Receive message number.
75ed1d15
GL
377 codeci = connection->m_codeci;
378 codeco = connection->m_codeco;
fae05df5 379 sockstrm = connection->m_sockstrm;
75ed1d15 380 msg = codeci->Read8();
f4ada568 381
0834112f
GRG
382 switch (msg)
383 {
384 case IPC_EXECUTE:
385 {
f4ada568
GL
386 char *data;
387 size_t size;
0d2a2b60 388 wxIPCFormat format;
f4ada568 389
0d2a2b60 390 format = (wxIPCFormat)codeci->Read8();
75ed1d15 391 size = codeci->Read32();
f4ada568 392 data = new char[size];
fae05df5 393 sockstrm->Read(data, size);
f4ada568
GL
394
395 connection->OnExecute (topic_name, data, size, format);
396
397 delete [] data;
398 break;
399 }
0834112f
GRG
400 case IPC_ADVISE:
401 {
f4ada568
GL
402 char *data;
403 size_t size;
0d2a2b60 404 wxIPCFormat format;
f4ada568 405
75ed1d15 406 item = codeci->ReadString();
0d2a2b60 407 format = (wxIPCFormat)codeci->Read8();
75ed1d15 408 size = codeci->Read32();
f4ada568 409 data = new char[size];
fae05df5 410 sockstrm->Read(data, size);
f4ada568
GL
411
412 connection->OnAdvise (topic_name, item, data, size, format);
413
414 delete [] data;
415 break;
416 }
0834112f
GRG
417 case IPC_ADVISE_START:
418 {
75ed1d15 419 item = codeci->ReadString();
f4ada568
GL
420
421 bool ok = connection->OnStartAdvise (topic_name, item);
422 if (ok)
75ed1d15 423 codeco->Write8(IPC_ADVISE_START);
f4ada568 424 else
75ed1d15 425 codeco->Write8(IPC_FAIL);
f4ada568
GL
426
427 break;
428 }
0834112f
GRG
429 case IPC_ADVISE_STOP:
430 {
75ed1d15 431 item = codeci->ReadString();
f4ada568
GL
432
433 bool ok = connection->OnStopAdvise (topic_name, item);
434 if (ok)
75ed1d15 435 codeco->Write8(IPC_ADVISE_STOP);
f4ada568 436 else
75ed1d15 437 codeco->Write8(IPC_FAIL);
f4ada568
GL
438
439 break;
440 }
0834112f
GRG
441 case IPC_POKE:
442 {
0d2a2b60 443 wxIPCFormat format;
f4ada568 444 size_t size;
783b6cfd 445 wxChar *data;
f4ada568 446
75ed1d15 447 item = codeci->ReadString();
0d2a2b60 448 format = (wxIPCFormat)codeci->Read8();
75ed1d15 449 size = codeci->Read32();
783b6cfd 450 data = new wxChar[size];
fae05df5 451 sockstrm->Read(data, size);
f4ada568
GL
452
453 connection->OnPoke (topic_name, item, data, size, format);
454
455 delete [] data;
456
457 break;
458 }
0834112f
GRG
459 case IPC_REQUEST:
460 {
0d2a2b60 461 wxIPCFormat format;
f4ada568 462
75ed1d15 463 item = codeci->ReadString();
0d2a2b60 464 format = (wxIPCFormat)codeci->Read8();
f4ada568
GL
465
466 int user_size = -1;
467 char *user_data = connection->OnRequest (topic_name, item, &user_size, format);
468
0834112f
GRG
469 if (user_data)
470 {
75ed1d15 471 codeco->Write8(IPC_REQUEST_REPLY);
0834112f
GRG
472
473 if (user_size == -1)
474 user_size = strlen(user_data) + 1; // includes final NUL
475
476 codeco->Write32(user_size);
477 sockstrm->Write(user_data, user_size);
478 }
479 else
75ed1d15 480 codeco->Write8(IPC_FAIL);
f4ada568
GL
481
482 break;
483 }
0834112f
GRG
484 case IPC_DISCONNECT:
485 {
f4ada568
GL
486 sock.Close();
487 connection->OnDisconnect();
488 break;
489 }
490 default:
75ed1d15 491 codeco->Write8(IPC_FAIL);
f4ada568
GL
492 break;
493 }
494}
495
496void Server_OnRequest(wxSocketServer& server,
aa8fb7a0 497 wxSocketNotify evt, char *cdata)
f4ada568
GL
498{
499 wxTCPServer *ipcserv = (wxTCPServer *)cdata;
500 wxSocketStream *stream;
75ed1d15
GL
501 wxDataInputStream *codeci;
502 wxDataOutputStream *codeco;
f4ada568 503
aa8fb7a0 504 if (evt != wxSOCKET_CONNECTION)
f4ada568
GL
505 return;
506
507 /* Accept the connection, getting a new socket */
508 wxSocketBase *sock = server.Accept();
0834112f
GRG
509 if (!sock->Ok())
510 return;
f4ada568
GL
511
512 stream = new wxSocketStream(*sock);
75ed1d15
GL
513 codeci = new wxDataInputStream(*stream);
514 codeco = new wxDataOutputStream(*stream);
f4ada568 515
f4ada568 516 int msg;
75ed1d15 517 msg = codeci->Read8();
f4ada568 518
0834112f
GRG
519 if (msg == IPC_CONNECT)
520 {
f4ada568 521 wxString topic_name;
75ed1d15 522 topic_name = codeci->ReadString();
f4ada568
GL
523
524 /* Register new socket with the notifier */
525 wxTCPConnection *new_connection =
526 (wxTCPConnection *)ipcserv->OnAcceptConnection (topic_name);
0834112f
GRG
527 if (new_connection)
528 {
529 if (!new_connection->IsKindOf(CLASSINFO(wxTCPConnection)))
530 {
f4ada568 531 delete new_connection;
75ed1d15 532 codeco->Write8(IPC_FAIL);
f4ada568
GL
533 return;
534 }
535 // Acknowledge success
75ed1d15 536 codeco->Write8(IPC_CONNECT);
f4ada568 537 new_connection->m_topic = topic_name;
0834112f 538 new_connection->m_sock = sock;
f4ada568 539 new_connection->m_sockstrm = stream;
75ed1d15
GL
540 new_connection->m_codeci = codeci;
541 new_connection->m_codeco = codeco;
f4ada568
GL
542 sock->Callback(Client_OnRequest);
543 sock->CallbackData((char *)new_connection);
0834112f 544 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
f4ada568 545 sock->Notify(TRUE);
0834112f
GRG
546 }
547 else
548 {
f4ada568 549 // Send failure message
75ed1d15 550 codeco->Write8(IPC_FAIL);
f4ada568
GL
551 }
552 }
553}
35a4dab7
GL
554
555#endif
556 // wxUSE_SOCKETS