]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/sckipc.cpp
bug fixes for '\r' handling in wxTextFile::Translate()
[wxWidgets.git] / src / common / sckipc.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: sckipc.cpp
3// Purpose: Interprocess communication implementation (wxSocket version)
4// Author: Julian Smart
5// Modified by: Guilhem Lavaux (big rewrite) May 1997, 1998
6// Guillermo Rodriguez (updated for wxSocket v2) Jan 2000
7// Created: 1993
8// RCS-ID: $Id$
9// Copyright: (c) Julian Smart 1993
10// (c) Guilhem Lavaux 1997, 1998
11// (c) 2000 Guillermo Rodriguez <guille@iies.es>
12// Licence: wxWindows license
13/////////////////////////////////////////////////////////////////////////////
14
15#ifdef __GNUG__
16#pragma implementation "sckipc.h"
17#endif
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23#pragma hdrstop
24#endif
25
26#if wxUSE_SOCKETS
27
28#ifndef WX_PRECOMP
29#endif
30
31#include <stdlib.h>
32#include <stdio.h>
33
34#include "wx/socket.h"
35#include "wx/sckipc.h"
36#include "wx/log.h"
37
38#ifdef __BORLANDC__
39#pragma hdrstop
40#endif
41
42IMPLEMENT_DYNAMIC_CLASS(wxTCPServer, wxServerBase)
43IMPLEMENT_DYNAMIC_CLASS(wxTCPClient, wxClientBase)
44IMPLEMENT_DYNAMIC_CLASS(wxTCPConnection, wxConnectionBase)
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,
65 wxSocketNotify evt,
66 char *cdata);
67void Client_OnRequest(wxSocketBase& sock,
68 wxSocketNotify evt,
69 char *cdata);
70
71// ---------------------------------------------------------------------------
72// wxTCPClient
73// ---------------------------------------------------------------------------
74
75wxTCPClient::wxTCPClient ()
76 : wxClientBase()
77{
78}
79
80wxTCPClient::~wxTCPClient ()
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{
95 wxSocketClient *client = new wxSocketClient();
96 wxSocketStream *stream = new wxSocketStream(*client);
97 wxDataInputStream *data_is = new wxDataInputStream(*stream);
98 wxDataOutputStream *data_os = new wxDataOutputStream(*stream);
99
100 wxIPV4address addr;
101 addr.Service(server_name);
102 addr.Hostname(host);
103
104 if (client->Connect(addr))
105 {
106 unsigned char msg;
107
108 // Send topic name, and enquire whether this has succeeded
109 data_os->Write8(IPC_CONNECT);
110 data_os->WriteString(topic);
111
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 }
139 }
140 }
141 }
142
143 // something went wrong
144 delete data_is;
145 delete data_os;
146 delete stream;
147 delete client;
148 return NULL;
149}
150
151wxConnectionBase *wxTCPClient::OnMakeConnection()
152{
153 return new wxTCPConnection;
154}
155
156// ---------------------------------------------------------------------------
157// wxTCPServer
158// ---------------------------------------------------------------------------
159
160wxTCPServer::wxTCPServer ()
161 : wxServerBase()
162{
163}
164
165bool wxTCPServer::Create(const wxString& server_name)
166{
167 wxIPV4address addr;
168 wxSocketServer *server;
169
170 addr.LocalHost(); // GRG
171 addr.Service(server_name);
172
173 // Create a socket listening on specified port
174 server = new wxSocketServer(addr);
175 server->Callback((wxSocketBase::wxSockCbk)Server_OnRequest);
176 server->CallbackData((char *)this);
177 server->SetNotify(wxSOCKET_CONNECTION_FLAG);
178 server->Notify(TRUE); // GRG
179
180 return TRUE;
181}
182
183wxTCPServer::~wxTCPServer()
184{
185}
186
187wxConnectionBase *wxTCPServer::OnAcceptConnection( const wxString& WXUNUSED(topic) )
188{
189 return new wxTCPConnection();
190}
191
192// ---------------------------------------------------------------------------
193// wxTCPConnection
194// ---------------------------------------------------------------------------
195
196wxTCPConnection::wxTCPConnection ()
197 : wxConnectionBase(),
198 m_sock(NULL), m_sockstrm(NULL), m_codeci(NULL), m_codeco(NULL)
199{
200}
201
202wxTCPConnection::wxTCPConnection(char * WXUNUSED(buffer), int WXUNUSED(size))
203{
204}
205
206wxTCPConnection::~wxTCPConnection ()
207{
208 wxDELETE(m_sock);
209 wxDELETE(m_codeci);
210 wxDELETE(m_codeco);
211 wxDELETE(m_sockstrm);
212}
213
214void wxTCPConnection::Compress(bool WXUNUSED(on))
215{
216 // Use wxLZWStream
217}
218
219// Calls that CLIENT can make.
220bool wxTCPConnection::Disconnect ()
221{
222 // Send the the disconnect message to the peer.
223 m_codeco->Write8(IPC_DISCONNECT);
224 m_sock->Close();
225
226 return TRUE;
227}
228
229bool wxTCPConnection::Execute(const wxChar *data, int size, wxIPCFormat format)
230{
231 if (!m_sock->IsConnected())
232 return FALSE;
233
234 // Prepare EXECUTE message
235 m_codeco->Write8(IPC_EXECUTE);
236 m_codeco->Write8(format);
237
238 if (size < 0)
239 size = strlen(data) + 1; // includes final NUL
240
241 m_codeco->Write32(size);
242 m_sockstrm->Write(data, size);
243
244 return TRUE;
245}
246
247char *wxTCPConnection::Request (const wxString& item, int *size, wxIPCFormat format)
248{
249 if (!m_sock->IsConnected())
250 return NULL;
251
252 m_codeco->Write8(IPC_REQUEST);
253 m_codeco->WriteString(item);
254 m_codeco->Write8(format);
255
256 // If Unpack doesn't initialize it.
257 int ret;
258
259 ret = m_codeci->Read8();
260 if (ret == IPC_FAIL)
261 return NULL;
262 else
263 {
264 size_t s;
265 char *data = NULL;
266
267 s = m_codeci->Read32();
268 data = new char[s];
269 m_sockstrm->Read(data, s);
270
271 if (size)
272 *size = s;
273 return data;
274 }
275}
276
277bool wxTCPConnection::Poke (const wxString& item, wxChar *data, int size, wxIPCFormat format)
278{
279 if (!m_sock->IsConnected())
280 return FALSE;
281
282 m_codeco->Write8(IPC_POKE);
283 m_codeco->WriteString(item);
284 m_codeco->Write8(format);
285
286 if (size < 0)
287 size = strlen(data) + 1; // includes final NUL
288
289 m_codeco->Write32(size);
290 m_sockstrm->Write(data, size);
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
302 m_codeco->Write8(IPC_ADVISE_START);
303 m_codeco->WriteString(item);
304
305 ret = m_codeci->Read8();
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
320 m_codeco->Write8(IPC_ADVISE_STOP);
321 m_codeco->WriteString(item);
322
323 msg = m_codeci->Read8();
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,
333 wxChar *data, int size, wxIPCFormat format)
334{
335 if (!m_sock->IsConnected())
336 return FALSE;
337
338 m_codeco->Write8(IPC_ADVISE);
339 m_codeco->WriteString(item);
340 m_codeco->Write8(format);
341
342 if (size < 0)
343 size = strlen(data) + 1; // includes final NUL
344
345 m_codeco->Write32(size);
346 m_sockstrm->Write(data, size);
347
348 return TRUE;
349}
350
351void Client_OnRequest(wxSocketBase& sock, wxSocketNotify evt,
352 char *cdata)
353{
354 int msg = 0;
355 wxTCPConnection *connection = (wxTCPConnection *)cdata;
356 wxDataInputStream *codeci;
357 wxDataOutputStream *codeco;
358 wxSocketStream *sockstrm;
359 wxString topic_name = connection->m_topic;
360 wxString item;
361
362 // The socket handler signals us that we lost the connection: destroy all.
363 if (evt == wxSOCKET_LOST)
364 {
365 sock.Close();
366 connection->OnDisconnect();
367 return;
368 }
369
370 // Receive message number.
371 codeci = connection->m_codeci;
372 codeco = connection->m_codeco;
373 sockstrm = connection->m_sockstrm;
374 msg = codeci->Read8();
375
376 switch (msg)
377 {
378 case IPC_EXECUTE:
379 {
380 char *data;
381 size_t size;
382 wxIPCFormat format;
383
384 format = (wxIPCFormat)codeci->Read8();
385 size = codeci->Read32();
386 data = new char[size];
387 sockstrm->Read(data, size);
388
389 connection->OnExecute (topic_name, data, size, format);
390
391 delete [] data;
392 break;
393 }
394 case IPC_ADVISE:
395 {
396 char *data;
397 size_t size;
398 wxIPCFormat format;
399
400 item = codeci->ReadString();
401 format = (wxIPCFormat)codeci->Read8();
402 size = codeci->Read32();
403 data = new char[size];
404 sockstrm->Read(data, size);
405
406 connection->OnAdvise (topic_name, item, data, size, format);
407
408 delete [] data;
409 break;
410 }
411 case IPC_ADVISE_START:
412 {
413 item = codeci->ReadString();
414
415 bool ok = connection->OnStartAdvise (topic_name, item);
416 if (ok)
417 codeco->Write8(IPC_ADVISE_START);
418 else
419 codeco->Write8(IPC_FAIL);
420
421 break;
422 }
423 case IPC_ADVISE_STOP:
424 {
425 item = codeci->ReadString();
426
427 bool ok = connection->OnStopAdvise (topic_name, item);
428 if (ok)
429 codeco->Write8(IPC_ADVISE_STOP);
430 else
431 codeco->Write8(IPC_FAIL);
432
433 break;
434 }
435 case IPC_POKE:
436 {
437 wxIPCFormat format;
438 size_t size;
439 wxChar *data;
440
441 item = codeci->ReadString();
442 format = (wxIPCFormat)codeci->Read8();
443 size = codeci->Read32();
444 data = new wxChar[size];
445 sockstrm->Read(data, size);
446
447 connection->OnPoke (topic_name, item, data, size, format);
448
449 delete [] data;
450
451 break;
452 }
453 case IPC_REQUEST:
454 {
455 wxIPCFormat format;
456
457 item = codeci->ReadString();
458 format = (wxIPCFormat)codeci->Read8();
459
460 int user_size = -1;
461 char *user_data = connection->OnRequest (topic_name, item, &user_size, format);
462
463 if (user_data)
464 {
465 codeco->Write8(IPC_REQUEST_REPLY);
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
474 codeco->Write8(IPC_FAIL);
475
476 break;
477 }
478 case IPC_DISCONNECT:
479 {
480 sock.Close();
481 connection->OnDisconnect();
482 break;
483 }
484 default:
485 codeco->Write8(IPC_FAIL);
486 break;
487 }
488}
489
490void Server_OnRequest(wxSocketServer& server,
491 wxSocketNotify evt, char *cdata)
492{
493 wxTCPServer *ipcserv = (wxTCPServer *)cdata;
494 wxSocketStream *stream;
495 wxDataInputStream *codeci;
496 wxDataOutputStream *codeco;
497
498 if (evt != wxSOCKET_CONNECTION)
499 return;
500
501 /* Accept the connection, getting a new socket */
502 wxSocketBase *sock = server.Accept();
503 if (!sock->Ok())
504 return;
505
506 stream = new wxSocketStream(*sock);
507 codeci = new wxDataInputStream(*stream);
508 codeco = new wxDataOutputStream(*stream);
509
510 int msg;
511 msg = codeci->Read8();
512
513 if (msg == IPC_CONNECT)
514 {
515 wxString topic_name;
516 topic_name = codeci->ReadString();
517
518 /* Register new socket with the notifier */
519 wxTCPConnection *new_connection =
520 (wxTCPConnection *)ipcserv->OnAcceptConnection (topic_name);
521 if (new_connection)
522 {
523 if (!new_connection->IsKindOf(CLASSINFO(wxTCPConnection)))
524 {
525 delete new_connection;
526 codeco->Write8(IPC_FAIL);
527 return;
528 }
529 // Acknowledge success
530 codeco->Write8(IPC_CONNECT);
531 new_connection->m_topic = topic_name;
532 new_connection->m_sock = sock;
533 new_connection->m_sockstrm = stream;
534 new_connection->m_codeci = codeci;
535 new_connection->m_codeco = codeco;
536 sock->Callback(Client_OnRequest);
537 sock->CallbackData((char *)new_connection);
538 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
539 sock->Notify(TRUE);
540 }
541 else
542 {
543 // Send failure message
544 codeco->Write8(IPC_FAIL);
545 }
546 }
547}
548
549#endif
550 // wxUSE_SOCKETS