]> git.saurik.com Git - wxWidgets.git/blame - src/common/sckipc.cpp
wxTextStream now interprets 1,1 as 1.1 (European formating).
[wxWidgets.git] / src / common / sckipc.cpp
CommitLineData
f4ada568
GL
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
fcc6dddd
JS
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
f4ada568 18
fcc6dddd
JS
19#ifdef __BORLANDC__
20#pragma hdrstop
f4ada568
GL
21#endif
22
35a4dab7
GL
23#if wxUSE_SOCKETS
24
fcc6dddd
JS
25#ifndef WX_PRECOMP
26#endif
27
28#include <stdlib.h>
29#include <stdio.h>
30
f4ada568
GL
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,
aa8fb7a0 63 wxSocketNotify evt,
f4ada568
GL
64 char *cdata);
65void Client_OnRequest(wxSocketBase& sock,
aa8fb7a0 66 wxSocketNotify evt,
f4ada568
GL
67 char *cdata);
68
69// ---------------------------------------------------------------------------
70// wxTCPClient
71// ---------------------------------------------------------------------------
72
6e31e940 73wxTCPClient::wxTCPClient ()
f4ada568
GL
74 : wxClientBase()
75{
76}
77
6e31e940 78wxTCPClient::~wxTCPClient ()
f4ada568
GL
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;
a324a7bc 94 wxSocketClient *client = new wxSocketClient();
f4ada568 95 wxSocketStream *stream = new wxSocketStream(*client);
75ed1d15
GL
96 wxDataInputStream data_is(*stream);
97 wxDataOutputStream data_os(*stream);
f4ada568 98
aa8fb7a0 99 client->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
f4ada568
GL
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
75ed1d15
GL
112 data_os.Write8(IPC_CONNECT);
113 data_os.WriteString(topic);
f4ada568 114
75ed1d15 115 msg = data_is.Read8();
f4ada568
GL
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 }
f4ada568
GL
138}
139
140wxConnectionBase *wxTCPClient::OnMakeConnection()
141{
142 return new wxTCPConnection;
143}
144
145// ---------------------------------------------------------------------------
146// wxTCPServer
147// ---------------------------------------------------------------------------
148
6e31e940 149wxTCPServer::wxTCPServer ()
f4ada568
GL
150 : wxServerBase()
151{
152}
153
154bool wxTCPServer::Create(const wxString& server_name)
155{
156 wxIPV4address addr;
f4ada568
GL
157 wxSocketServer *server;
158
159 addr.Service(server_name);
160
161 // Create a socket listening on specified port
a324a7bc 162 server = new wxSocketServer(addr);
f4ada568 163 server->Callback((wxSocketBase::wxSockCbk)Server_OnRequest);
aa8fb7a0 164 server->SetNotify(wxSOCKET_CONNECTION_FLAG);
f4ada568
GL
165
166 server->CallbackData((char *)this);
167
168 return TRUE;
169}
170
6e31e940 171wxTCPServer::~wxTCPServer()
f4ada568
GL
172{
173}
174
e22036dc 175wxConnectionBase *wxTCPServer::OnAcceptConnection( const wxString& WXUNUSED(topic) )
f4ada568
GL
176{
177 return new wxTCPConnection();
178}
179
180// ---------------------------------------------------------------------------
181// wxTCPConnection
182// ---------------------------------------------------------------------------
183
6e31e940 184wxTCPConnection::wxTCPConnection ()
f4ada568 185 : wxConnectionBase(),
75ed1d15 186 m_sock(NULL), m_sockstrm(NULL), m_codeci(NULL), m_codeco(NULL)
f4ada568
GL
187{
188}
189
6e31e940 190wxTCPConnection::wxTCPConnection(char * WXUNUSED(buffer), int WXUNUSED(size))
7921cf2b
JS
191{
192}
193
6e31e940 194wxTCPConnection::~wxTCPConnection ()
f4ada568
GL
195{
196 wxDELETE(m_sock);
75ed1d15
GL
197 wxDELETE(m_codeci);
198 wxDELETE(m_codeco);
f4ada568
GL
199 wxDELETE(m_sockstrm);
200}
201
cb43b372 202void wxTCPConnection::Compress(bool WXUNUSED(on))
f4ada568
GL
203{
204 // Use wxLZWStream
205}
206
207// Calls that CLIENT can make.
6e31e940 208bool wxTCPConnection::Disconnect ()
f4ada568
GL
209{
210 // Send the the disconnect message to the peer.
75ed1d15 211 m_codeco->Write8(IPC_DISCONNECT);
f4ada568
GL
212 m_sock->Close();
213
214 return TRUE;
215}
216
e90c1d2a 217bool wxTCPConnection::Execute (const wxChar *data, int size, wxIPCFormat format)
f4ada568
GL
218{
219 if (!m_sock->IsConnected())
220 return FALSE;
221
222 // Prepare EXECUTE message
75ed1d15
GL
223 m_codeco->Write8(IPC_EXECUTE);
224 m_codeco->Write8(format);
f4ada568 225 if (size < 0)
75ed1d15 226 m_codeco->WriteString(data);
f4ada568 227 else {
75ed1d15 228 m_codeco->Write32(size);
fae05df5 229 m_sockstrm->Write(data, size);
f4ada568
GL
230 }
231
232 return TRUE;
233}
234
0d2a2b60 235char *wxTCPConnection::Request (const wxString& item, int *size, wxIPCFormat format)
f4ada568
GL
236{
237 if (!m_sock->IsConnected())
238 return NULL;
239
75ed1d15
GL
240 m_codeco->Write8(IPC_REQUEST);
241 m_codeco->WriteString(item);
242 m_codeco->Write8(format);
f4ada568
GL
243
244 // If Unpack doesn't initialize it.
245 int ret;
246
75ed1d15 247 ret = m_codeci->Read8();
f4ada568
GL
248 if (ret == IPC_FAIL)
249 return NULL;
250 else {
251 size_t s;
252 char *data = NULL;
253
75ed1d15 254 s = m_codeci->Read32();
f4ada568 255 data = new char[s];
fae05df5 256 m_sockstrm->Read(data, s);
f4ada568
GL
257
258 if (size)
259 *size = s;
260 return data;
261 }
262}
263
783b6cfd 264bool wxTCPConnection::Poke (const wxString& item, wxChar *data, int size, wxIPCFormat format)
f4ada568
GL
265{
266 if (!m_sock->IsConnected())
267 return FALSE;
268
75ed1d15
GL
269 m_codeco->Write8(IPC_POKE);
270 m_codeco->WriteString(item);
271 m_codeco->Write8(format);
f4ada568 272 if (size < 0)
75ed1d15 273 m_codeco->WriteString(data);
f4ada568 274 else {
75ed1d15 275 m_codeco->Write32(size);
fae05df5 276 m_sockstrm->Write(data, size);
f4ada568
GL
277 }
278
279 return TRUE;
280}
281
282bool wxTCPConnection::StartAdvise (const wxString& item)
283{
284 int ret;
285
286 if (!m_sock->IsConnected())
287 return FALSE;
288
75ed1d15
GL
289 m_codeco->Write8(IPC_ADVISE_START);
290 m_codeco->WriteString(item);
f4ada568 291
75ed1d15 292 ret = m_codeci->Read8();
f4ada568
GL
293
294 if (ret != IPC_FAIL)
295 return TRUE;
296 else
297 return FALSE;
298}
299
300bool wxTCPConnection::StopAdvise (const wxString& item)
301{
302 int msg;
303
304 if (!m_sock->IsConnected())
305 return FALSE;
306
75ed1d15
GL
307 m_codeco->Write8(IPC_ADVISE_STOP);
308 m_codeco->WriteString(item);
f4ada568 309
75ed1d15 310 msg = m_codeci->Read8();
f4ada568
GL
311
312 if (msg != IPC_FAIL)
313 return TRUE;
314 else
315 return FALSE;
316}
317
318// Calls that SERVER can make
319bool wxTCPConnection::Advise (const wxString& item,
783b6cfd 320 wxChar *data, int size, wxIPCFormat format)
f4ada568
GL
321{
322 if (!m_sock->IsConnected())
323 return FALSE;
324
75ed1d15
GL
325 m_codeco->Write8(IPC_ADVISE);
326 m_codeco->WriteString(item);
327 m_codeco->Write8(format);
f4ada568 328 if (size < 0)
75ed1d15 329 m_codeco->WriteString(data);
f4ada568 330 else {
75ed1d15 331 m_codeco->Write32(size);
fae05df5 332 m_sockstrm->Write(data, size);
f4ada568
GL
333 }
334
335 return TRUE;
336}
337
aa8fb7a0 338void Client_OnRequest(wxSocketBase& sock, wxSocketNotify evt,
f4ada568
GL
339 char *cdata)
340{
341 int msg = 0;
342 wxTCPConnection *connection = (wxTCPConnection *)cdata;
75ed1d15
GL
343 wxDataInputStream *codeci;
344 wxDataOutputStream *codeco;
fae05df5 345 wxSocketStream *sockstrm;
f4ada568
GL
346 wxString topic_name = connection->m_topic;
347 wxString item;
348
349 // The socket handler signals us that we lost the connection: destroy all.
aa8fb7a0 350 if (evt == wxSOCKET_LOST) {
f4ada568
GL
351 sock.Close();
352 connection->OnDisconnect();
353 return;
354 }
355
356 // Receive message number.
75ed1d15
GL
357 codeci = connection->m_codeci;
358 codeco = connection->m_codeco;
fae05df5 359 sockstrm = connection->m_sockstrm;
75ed1d15 360 msg = codeci->Read8();
f4ada568
GL
361
362 switch (msg) {
363 case IPC_EXECUTE: {
364 char *data;
365 size_t size;
0d2a2b60 366 wxIPCFormat format;
f4ada568 367
0d2a2b60 368 format = (wxIPCFormat)codeci->Read8();
75ed1d15 369 size = codeci->Read32();
f4ada568 370 data = new char[size];
fae05df5 371 sockstrm->Read(data, size);
f4ada568
GL
372
373 connection->OnExecute (topic_name, data, size, format);
374
375 delete [] data;
376 break;
377 }
378 case IPC_ADVISE: {
379 char *data;
380 size_t size;
0d2a2b60 381 wxIPCFormat format;
f4ada568 382
75ed1d15 383 item = codeci->ReadString();
0d2a2b60 384 format = (wxIPCFormat)codeci->Read8();
75ed1d15 385 size = codeci->Read32();
f4ada568 386 data = new char[size];
fae05df5 387 sockstrm->Read(data, size);
f4ada568
GL
388
389 connection->OnAdvise (topic_name, item, data, size, format);
390
391 delete [] data;
392 break;
393 }
394 case IPC_ADVISE_START: {
75ed1d15 395 item = codeci->ReadString();
f4ada568
GL
396
397 bool ok = connection->OnStartAdvise (topic_name, item);
398 if (ok)
75ed1d15 399 codeco->Write8(IPC_ADVISE_START);
f4ada568 400 else
75ed1d15 401 codeco->Write8(IPC_FAIL);
f4ada568
GL
402
403 break;
404 }
405 case IPC_ADVISE_STOP: {
75ed1d15 406 item = codeci->ReadString();
f4ada568
GL
407
408 bool ok = connection->OnStopAdvise (topic_name, item);
409 if (ok)
75ed1d15 410 codeco->Write8(IPC_ADVISE_STOP);
f4ada568 411 else
75ed1d15 412 codeco->Write8(IPC_FAIL);
f4ada568
GL
413
414 break;
415 }
416 case IPC_POKE: {
0d2a2b60 417 wxIPCFormat format;
f4ada568 418 size_t size;
783b6cfd 419 wxChar *data;
f4ada568 420
75ed1d15 421 item = codeci->ReadString();
0d2a2b60 422 format = (wxIPCFormat)codeci->Read8();
75ed1d15 423 size = codeci->Read32();
783b6cfd 424 data = new wxChar[size];
fae05df5 425 sockstrm->Read(data, size);
f4ada568
GL
426
427 connection->OnPoke (topic_name, item, data, size, format);
428
429 delete [] data;
430
431 break;
432 }
433 case IPC_REQUEST: {
0d2a2b60 434 wxIPCFormat format;
f4ada568 435
75ed1d15 436 item = codeci->ReadString();
0d2a2b60 437 format = (wxIPCFormat)codeci->Read8();
f4ada568
GL
438
439 int user_size = -1;
440 char *user_data = connection->OnRequest (topic_name, item, &user_size, format);
441
442 if (user_data) {
75ed1d15 443 codeco->Write8(IPC_REQUEST_REPLY);
f4ada568 444 if (user_size != -1) {
75ed1d15 445 codeco->Write32(user_size);
fae05df5 446 sockstrm->Write(user_data, user_size);
f4ada568 447 } else
75ed1d15 448 codeco->WriteString(user_data);
f4ada568 449 } else
75ed1d15 450 codeco->Write8(IPC_FAIL);
f4ada568
GL
451
452 break;
453 }
454 case IPC_DISCONNECT: {
455 sock.Close();
456 connection->OnDisconnect();
457 break;
458 }
459 default:
75ed1d15 460 codeco->Write8(IPC_FAIL);
f4ada568
GL
461 break;
462 }
463}
464
465void Server_OnRequest(wxSocketServer& server,
aa8fb7a0 466 wxSocketNotify evt, char *cdata)
f4ada568
GL
467{
468 wxTCPServer *ipcserv = (wxTCPServer *)cdata;
469 wxSocketStream *stream;
75ed1d15
GL
470 wxDataInputStream *codeci;
471 wxDataOutputStream *codeco;
f4ada568 472
aa8fb7a0 473 if (evt != wxSOCKET_CONNECTION)
f4ada568
GL
474 return;
475
476 /* Accept the connection, getting a new socket */
477 wxSocketBase *sock = server.Accept();
478 sock->Notify(FALSE);
aa8fb7a0 479 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
f4ada568
GL
480
481 stream = new wxSocketStream(*sock);
75ed1d15
GL
482 codeci = new wxDataInputStream(*stream);
483 codeco = new wxDataOutputStream(*stream);
f4ada568
GL
484
485 if (!sock->Ok())
486 return;
487
488 int msg;
75ed1d15 489 msg = codeci->Read8();
f4ada568
GL
490
491 if (msg == IPC_CONNECT) {
492 wxString topic_name;
75ed1d15 493 topic_name = codeci->ReadString();
f4ada568
GL
494
495 /* Register new socket with the notifier */
496 wxTCPConnection *new_connection =
497 (wxTCPConnection *)ipcserv->OnAcceptConnection (topic_name);
498 if (new_connection) {
499 if (!new_connection->IsKindOf(CLASSINFO(wxTCPConnection))) {
500 delete new_connection;
75ed1d15 501 codeco->Write8(IPC_FAIL);
f4ada568
GL
502 return;
503 }
504 // Acknowledge success
75ed1d15 505 codeco->Write8(IPC_CONNECT);
f4ada568
GL
506
507 new_connection->m_topic = topic_name;
508 new_connection->m_sockstrm = stream;
75ed1d15
GL
509 new_connection->m_codeci = codeci;
510 new_connection->m_codeco = codeco;
f4ada568
GL
511 sock->Callback(Client_OnRequest);
512 sock->CallbackData((char *)new_connection);
513 sock->Notify(TRUE);
514 } else {
515 // Send failure message
75ed1d15 516 codeco->Write8(IPC_FAIL);
f4ada568
GL
517 }
518 }
519}
35a4dab7
GL
520
521#endif
522 // wxUSE_SOCKETS