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