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