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