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