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