/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/common/sckipc.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/common/sckipc.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations) (download)
Mon Sep 6 11:40:06 2010 UTC (9 years, 11 months ago) by william
File size: 19409 byte(s)
exported r3113 from ./upstream/trunk
1 william 10 /////////////////////////////////////////////////////////////////////////////
2     // Name: src/common/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     // (callbacks deprecated) Mar 2000
8     // Vadim Zeitlin (added support for Unix sockets) Apr 2002
9     // Created: 1993
10     // RCS-ID: $Id: sckipc.cpp 41982 2006-10-13 09:00:06Z RR $
11     // Copyright: (c) Julian Smart 1993
12     // (c) Guilhem Lavaux 1997, 1998
13     // (c) 2000 Guillermo Rodriguez <guille@iies.es>
14     // Licence: wxWindows licence
15     /////////////////////////////////////////////////////////////////////////////
16    
17     // ==========================================================================
18     // declarations
19     // ==========================================================================
20    
21     // --------------------------------------------------------------------------
22     // headers
23     // --------------------------------------------------------------------------
24    
25     // For compilers that support precompilation, includes "wx.h".
26     #include "wx/wxprec.h"
27    
28     #ifdef __BORLANDC__
29     #pragma hdrstop
30     #endif
31    
32     #if wxUSE_SOCKETS && wxUSE_IPC && wxUSE_STREAMS
33    
34     #include "wx/sckipc.h"
35    
36     #ifndef WX_PRECOMP
37     #include "wx/log.h"
38     #include "wx/event.h"
39     #include "wx/module.h"
40     #endif
41    
42     #include <stdlib.h>
43     #include <stdio.h>
44     #include <errno.h>
45    
46     #include "wx/socket.h"
47    
48     // --------------------------------------------------------------------------
49     // macros and constants
50     // --------------------------------------------------------------------------
51    
52     // It seems to be already defined somewhere in the Xt includes.
53     #ifndef __XT__
54     // Message codes
55     enum
56     {
57     IPC_EXECUTE = 1,
58     IPC_REQUEST,
59     IPC_POKE,
60     IPC_ADVISE_START,
61     IPC_ADVISE_REQUEST,
62     IPC_ADVISE,
63     IPC_ADVISE_STOP,
64     IPC_REQUEST_REPLY,
65     IPC_FAIL,
66     IPC_CONNECT,
67     IPC_DISCONNECT
68     };
69     #endif
70    
71     // All sockets will be created with the following flags
72     #define SCKIPC_FLAGS (wxSOCKET_WAITALL)
73    
74     // headers needed for umask()
75     #ifdef __UNIX_LIKE__
76     #include <sys/types.h>
77     #include <sys/stat.h>
78     #endif // __UNIX_LIKE__
79    
80     // ----------------------------------------------------------------------------
81     // private functions
82     // ----------------------------------------------------------------------------
83    
84     // get the address object for the given server name, the caller must delete it
85     static wxSockAddress *
86     GetAddressFromName(const wxString& serverName, const wxString& host = wxEmptyString)
87     {
88     // we always use INET sockets under non-Unix systems
89     #if defined(__UNIX__) && !defined(__WINDOWS__) && !defined(__WINE__) && (!defined(__WXMAC__) || defined(__DARWIN__))
90     // under Unix, if the server name looks like a path, create a AF_UNIX
91     // socket instead of AF_INET one
92     if ( serverName.Find(_T('/')) != wxNOT_FOUND )
93     {
94     wxUNIXaddress *addr = new wxUNIXaddress;
95     addr->Filename(serverName);
96    
97     return addr;
98     }
99     #endif // Unix/!Unix
100     {
101     wxIPV4address *addr = new wxIPV4address;
102     addr->Service(serverName);
103     if ( !host.empty() )
104     {
105     addr->Hostname(host);
106     }
107    
108     return addr;
109     }
110     }
111    
112     // --------------------------------------------------------------------------
113     // wxTCPEventHandler stuff (private class)
114     // --------------------------------------------------------------------------
115    
116     class wxTCPEventHandler : public wxEvtHandler
117     {
118     public:
119     wxTCPEventHandler() : wxEvtHandler() {}
120    
121     void Client_OnRequest(wxSocketEvent& event);
122     void Server_OnRequest(wxSocketEvent& event);
123    
124     DECLARE_EVENT_TABLE()
125     DECLARE_NO_COPY_CLASS(wxTCPEventHandler)
126     };
127    
128     enum
129     {
130     _CLIENT_ONREQUEST_ID = 1000,
131     _SERVER_ONREQUEST_ID
132     };
133    
134     static wxTCPEventHandler *gs_handler = NULL;
135    
136     // ==========================================================================
137     // implementation
138     // ==========================================================================
139    
140     IMPLEMENT_DYNAMIC_CLASS(wxTCPServer, wxServerBase)
141     IMPLEMENT_DYNAMIC_CLASS(wxTCPClient, wxClientBase)
142     IMPLEMENT_CLASS(wxTCPConnection, wxConnectionBase)
143    
144     // --------------------------------------------------------------------------
145     // wxTCPClient
146     // --------------------------------------------------------------------------
147    
148     wxTCPClient::wxTCPClient () : wxClientBase()
149     {
150     }
151    
152     wxTCPClient::~wxTCPClient ()
153     {
154     }
155    
156     bool wxTCPClient::ValidHost(const wxString& host)
157     {
158     wxIPV4address addr;
159    
160     return addr.Hostname(host);
161     }
162    
163     wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host,
164     const wxString& serverName,
165     const wxString& topic)
166     {
167     wxSockAddress *addr = GetAddressFromName(serverName, host);
168     if ( !addr )
169     return NULL;
170    
171     wxSocketClient *client = new wxSocketClient(SCKIPC_FLAGS);
172     wxSocketStream *stream = new wxSocketStream(*client);
173     wxDataInputStream *data_is = new wxDataInputStream(*stream);
174     wxDataOutputStream *data_os = new wxDataOutputStream(*stream);
175    
176     bool ok = client->Connect(*addr);
177     delete addr;
178    
179     if ( ok )
180     {
181     unsigned char msg;
182    
183     // Send topic name, and enquire whether this has succeeded
184     data_os->Write8(IPC_CONNECT);
185     data_os->WriteString(topic);
186    
187     msg = data_is->Read8();
188    
189     // OK! Confirmation.
190     if (msg == IPC_CONNECT)
191     {
192     wxTCPConnection *connection = (wxTCPConnection *)OnMakeConnection ();
193    
194     if (connection)
195     {
196     if (connection->IsKindOf(CLASSINFO(wxTCPConnection)))
197     {
198     connection->m_topic = topic;
199     connection->m_sock = client;
200     connection->m_sockstrm = stream;
201     connection->m_codeci = data_is;
202     connection->m_codeco = data_os;
203     client->SetEventHandler(*gs_handler, _CLIENT_ONREQUEST_ID);
204     client->SetClientData(connection);
205     client->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
206     client->Notify(true);
207     return connection;
208     }
209     else
210     {
211     delete connection;
212     // and fall through to delete everything else
213     }
214     }
215     }
216     }
217    
218     // Something went wrong, delete everything
219     delete data_is;
220     delete data_os;
221     delete stream;
222     client->Destroy();
223    
224     return NULL;
225     }
226    
227     wxConnectionBase *wxTCPClient::OnMakeConnection()
228     {
229     return new wxTCPConnection();
230     }
231    
232     // --------------------------------------------------------------------------
233     // wxTCPServer
234     // --------------------------------------------------------------------------
235    
236     wxTCPServer::wxTCPServer () : wxServerBase()
237     {
238     m_server = NULL;
239     }
240    
241     bool wxTCPServer::Create(const wxString& serverName)
242     {
243     // Destroy previous server, if any
244     if (m_server)
245     {
246     m_server->SetClientData(NULL);
247     m_server->Destroy();
248     m_server = NULL;
249     }
250    
251     wxSockAddress *addr = GetAddressFromName(serverName);
252     if ( !addr )
253     return false;
254    
255     #ifdef __UNIX_LIKE__
256     mode_t umaskOld;
257     if ( addr->Type() == wxSockAddress::UNIX )
258     {
259     // ensure that the file doesn't exist as otherwise calling socket() would
260     // fail
261     int rc = remove(serverName.fn_str());
262     if ( rc < 0 && errno != ENOENT )
263     {
264     delete addr;
265    
266     return false;
267     }
268    
269     // also set the umask to prevent the others from reading our file
270     umaskOld = umask(077);
271     }
272     else
273     {
274     // unused anyhow but shut down the compiler warnings
275     umaskOld = 0;
276     }
277     #endif // __UNIX_LIKE__
278    
279     // Create a socket listening on the specified port
280     m_server = new wxSocketServer(*addr, SCKIPC_FLAGS);
281    
282     #ifdef __UNIX_LIKE__
283     if ( addr->Type() == wxSockAddress::UNIX )
284     {
285     // restore the umask
286     umask(umaskOld);
287    
288     // save the file name to remove it later
289     m_filename = serverName;
290     }
291     #endif // __UNIX_LIKE__
292    
293     delete addr;
294    
295     if (!m_server->Ok())
296     {
297     m_server->Destroy();
298     m_server = NULL;
299    
300     return false;
301     }
302    
303     m_server->SetEventHandler(*gs_handler, _SERVER_ONREQUEST_ID);
304     m_server->SetClientData(this);
305     m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
306     m_server->Notify(true);
307    
308     return true;
309     }
310    
311     wxTCPServer::~wxTCPServer()
312     {
313     if (m_server)
314     {
315     m_server->SetClientData(NULL);
316     m_server->Destroy();
317     }
318    
319     #ifdef __UNIX_LIKE__
320     if ( !m_filename.empty() )
321     {
322     if ( remove(m_filename.fn_str()) != 0 )
323     {
324     wxLogDebug(_T("Stale AF_UNIX file '%s' left."), m_filename.c_str());
325     }
326     }
327     #endif // __UNIX_LIKE__
328     }
329    
330     wxConnectionBase *wxTCPServer::OnAcceptConnection( const wxString& WXUNUSED(topic) )
331     {
332     return new wxTCPConnection();
333     }
334    
335     // --------------------------------------------------------------------------
336     // wxTCPConnection
337     // --------------------------------------------------------------------------
338    
339     wxTCPConnection::wxTCPConnection () : wxConnectionBase()
340     {
341     m_sock = NULL;
342     m_sockstrm = NULL;
343     m_codeci = NULL;
344     m_codeco = NULL;
345     }
346    
347     wxTCPConnection::wxTCPConnection(wxChar *buffer, int size)
348     : wxConnectionBase(buffer, size)
349     {
350     m_sock = NULL;
351     m_sockstrm = NULL;
352     m_codeci = NULL;
353     m_codeco = NULL;
354     }
355    
356     wxTCPConnection::~wxTCPConnection ()
357     {
358     Disconnect();
359    
360     if (m_sock)
361     {
362     m_sock->SetClientData(NULL);
363     m_sock->Destroy();
364     }
365    
366     /* Delete after destroy */
367     wxDELETE(m_codeci);
368     wxDELETE(m_codeco);
369     wxDELETE(m_sockstrm);
370     }
371    
372     void wxTCPConnection::Compress(bool WXUNUSED(on))
373     {
374     // Use wxLZWStream
375     }
376    
377     // Calls that CLIENT can make.
378     bool wxTCPConnection::Disconnect ()
379     {
380     if ( !GetConnected() )
381     return true;
382     // Send the the disconnect message to the peer.
383     m_codeco->Write8(IPC_DISCONNECT);
384     m_sock->Notify(false);
385     m_sock->Close();
386     SetConnected(false);
387    
388     return true;
389     }
390    
391     bool wxTCPConnection::Execute(const wxChar *data, int size, wxIPCFormat format)
392     {
393     if (!m_sock->IsConnected())
394     return false;
395    
396     // Prepare EXECUTE message
397     m_codeco->Write8(IPC_EXECUTE);
398     m_codeco->Write8(format);
399    
400     if (size < 0)
401     size = (wxStrlen(data) + 1) * sizeof(wxChar); // includes final NUL
402    
403     m_codeco->Write32(size);
404     m_sockstrm->Write(data, size);
405    
406     return true;
407     }
408    
409     wxChar *wxTCPConnection::Request (const wxString& item, int *size, wxIPCFormat format)
410     {
411     if (!m_sock->IsConnected())
412     return NULL;
413    
414     m_codeco->Write8(IPC_REQUEST);
415     m_codeco->WriteString(item);
416     m_codeco->Write8(format);
417    
418     // If Unpack doesn't initialize it.
419     int ret;
420    
421     ret = m_codeci->Read8();
422     if (ret == IPC_FAIL)
423     return NULL;
424     else
425     {
426     size_t s;
427    
428     s = m_codeci->Read32();
429    
430     wxChar *data = GetBufferAtLeast( s );
431     wxASSERT_MSG(data != NULL,
432     _T("Buffer too small in wxTCPConnection::Request") );
433     m_sockstrm->Read(data, s);
434    
435     if (size)
436     *size = s;
437     return data;
438     }
439     }
440    
441     bool wxTCPConnection::Poke (const wxString& item, wxChar *data, int size, wxIPCFormat format)
442     {
443     if (!m_sock->IsConnected())
444     return false;
445    
446     m_codeco->Write8(IPC_POKE);
447     m_codeco->WriteString(item);
448     m_codeco->Write8(format);
449    
450     if (size < 0)
451     size = (wxStrlen(data) + 1) * sizeof(wxChar); // includes final NUL
452    
453     m_codeco->Write32(size);
454     m_sockstrm->Write(data, size);
455    
456     return true;
457     }
458    
459     bool wxTCPConnection::StartAdvise (const wxString& item)
460     {
461     int ret;
462    
463     if (!m_sock->IsConnected())
464     return false;
465    
466     m_codeco->Write8(IPC_ADVISE_START);
467     m_codeco->WriteString(item);
468    
469     ret = m_codeci->Read8();
470    
471     if (ret != IPC_FAIL)
472     return true;
473     else
474     return false;
475     }
476    
477     bool wxTCPConnection::StopAdvise (const wxString& item)
478     {
479     int msg;
480    
481     if (!m_sock->IsConnected())
482     return false;
483    
484     m_codeco->Write8(IPC_ADVISE_STOP);
485     m_codeco->WriteString(item);
486    
487     msg = m_codeci->Read8();
488    
489     if (msg != IPC_FAIL)
490     return true;
491     else
492     return false;
493     }
494    
495     // Calls that SERVER can make
496     bool wxTCPConnection::Advise (const wxString& item,
497     wxChar *data, int size, wxIPCFormat format)
498     {
499     if (!m_sock->IsConnected())
500     return false;
501    
502     m_codeco->Write8(IPC_ADVISE);
503     m_codeco->WriteString(item);
504     m_codeco->Write8(format);
505    
506     if (size < 0)
507     size = (wxStrlen(data) + 1) * sizeof(wxChar); // includes final NUL
508    
509     m_codeco->Write32(size);
510     m_sockstrm->Write(data, size);
511    
512     return true;
513     }
514    
515     // --------------------------------------------------------------------------
516     // wxTCPEventHandler (private class)
517     // --------------------------------------------------------------------------
518    
519     BEGIN_EVENT_TABLE(wxTCPEventHandler, wxEvtHandler)
520     EVT_SOCKET(_CLIENT_ONREQUEST_ID, wxTCPEventHandler::Client_OnRequest)
521     EVT_SOCKET(_SERVER_ONREQUEST_ID, wxTCPEventHandler::Server_OnRequest)
522     END_EVENT_TABLE()
523    
524     void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event)
525     {
526     wxSocketBase *sock = event.GetSocket();
527     if (!sock) { /* No socket, no glory */
528     return ;
529     }
530     wxSocketNotify evt = event.GetSocketEvent();
531     wxTCPConnection *connection = (wxTCPConnection *)(sock->GetClientData());
532    
533     // This socket is being deleted; skip this event
534     if (!connection)
535     return;
536    
537     wxDataInputStream *codeci;
538     wxDataOutputStream *codeco;
539     wxSocketStream *sockstrm;
540     wxString topic_name = connection->m_topic;
541     wxString item;
542    
543     // We lost the connection: destroy everything
544     if (evt == wxSOCKET_LOST)
545     {
546     sock->Notify(false);
547     sock->Close();
548     connection->OnDisconnect();
549     return;
550     }
551    
552     // Receive message number.
553     codeci = connection->m_codeci;
554     codeco = connection->m_codeco;
555     sockstrm = connection->m_sockstrm;
556     int msg = codeci->Read8();
557    
558     switch (msg)
559     {
560     case IPC_EXECUTE:
561     {
562     wxChar *data;
563     size_t size;
564     wxIPCFormat format;
565    
566     format = (wxIPCFormat)codeci->Read8();
567     size = codeci->Read32();
568    
569     data = connection->GetBufferAtLeast( size );
570     wxASSERT_MSG(data != NULL,
571     _T("Buffer too small in wxTCPEventHandler::Client_OnRequest") );
572     sockstrm->Read(data, size);
573    
574     connection->OnExecute (topic_name, data, size, format);
575    
576     break;
577     }
578     case IPC_ADVISE:
579     {
580     wxChar *data;
581     size_t size;
582     wxIPCFormat format;
583    
584     item = codeci->ReadString();
585     format = (wxIPCFormat)codeci->Read8();
586     size = codeci->Read32();
587     data = connection->GetBufferAtLeast( size );
588     wxASSERT_MSG(data != NULL,
589     _T("Buffer too small in wxTCPEventHandler::Client_OnRequest") );
590     sockstrm->Read(data, size);
591    
592     connection->OnAdvise (topic_name, item, data, size, format);
593    
594     break;
595     }
596     case IPC_ADVISE_START:
597     {
598     item = codeci->ReadString();
599    
600     bool ok = connection->OnStartAdvise (topic_name, item);
601     if (ok)
602     codeco->Write8(IPC_ADVISE_START);
603     else
604     codeco->Write8(IPC_FAIL);
605    
606     break;
607     }
608     case IPC_ADVISE_STOP:
609     {
610     item = codeci->ReadString();
611    
612     bool ok = connection->OnStopAdvise (topic_name, item);
613     if (ok)
614     codeco->Write8(IPC_ADVISE_STOP);
615     else
616     codeco->Write8(IPC_FAIL);
617    
618     break;
619     }
620     case IPC_POKE:
621     {
622     wxIPCFormat format;
623     size_t size;
624     wxChar *data;
625    
626     item = codeci->ReadString();
627     format = (wxIPCFormat)codeci->Read8();
628     size = codeci->Read32();
629     data = connection->GetBufferAtLeast( size );
630     wxASSERT_MSG(data != NULL,
631     _T("Buffer too small in wxTCPEventHandler::Client_OnRequest") );
632     sockstrm->Read(data, size);
633    
634     connection->OnPoke (topic_name, item, data, size, format);
635    
636     break;
637     }
638     case IPC_REQUEST:
639     {
640     wxIPCFormat format;
641    
642     item = codeci->ReadString();
643     format = (wxIPCFormat)codeci->Read8();
644    
645     int user_size = -1;
646     wxChar *user_data = connection->OnRequest (topic_name, item, &user_size, format);
647    
648     if (user_data)
649     {
650     codeco->Write8(IPC_REQUEST_REPLY);
651    
652     if (user_size == -1)
653     user_size = (wxStrlen(user_data) + 1) * sizeof(wxChar); // includes final NUL
654    
655     codeco->Write32(user_size);
656     sockstrm->Write(user_data, user_size);
657     }
658     else
659     codeco->Write8(IPC_FAIL);
660    
661     break;
662     }
663     case IPC_DISCONNECT:
664     {
665     sock->Notify(false);
666     sock->Close();
667     connection->SetConnected(false);
668     connection->OnDisconnect();
669     break;
670     }
671     default:
672     codeco->Write8(IPC_FAIL);
673     break;
674     }
675     }
676    
677     void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event)
678     {
679     wxSocketServer *server = (wxSocketServer *) event.GetSocket();
680     if (!server) { /* No server, Then exit */
681     return ;
682     }
683     wxTCPServer *ipcserv = (wxTCPServer *) server->GetClientData();
684    
685     // This socket is being deleted; skip this event
686     if (!ipcserv)
687     return;
688    
689     if (event.GetSocketEvent() != wxSOCKET_CONNECTION)
690     return;
691    
692     // Accept the connection, getting a new socket
693     wxSocketBase *sock = server->Accept();
694     if (!sock) { /* No socket, no glory */
695     return ;
696     }
697     if (!sock->Ok())
698     {
699     sock->Destroy();
700     return;
701     }
702    
703     wxSocketStream *stream = new wxSocketStream(*sock);
704     wxDataInputStream *codeci = new wxDataInputStream(*stream);
705     wxDataOutputStream *codeco = new wxDataOutputStream(*stream);
706    
707     int msg;
708     msg = codeci->Read8();
709    
710     if (msg == IPC_CONNECT)
711     {
712     wxString topic_name;
713     topic_name = codeci->ReadString();
714    
715     wxTCPConnection *new_connection =
716     (wxTCPConnection *)ipcserv->OnAcceptConnection (topic_name);
717    
718     if (new_connection)
719     {
720     if (new_connection->IsKindOf(CLASSINFO(wxTCPConnection)))
721     {
722     // Acknowledge success
723     codeco->Write8(IPC_CONNECT);
724     new_connection->m_topic = topic_name;
725     new_connection->m_sock = sock;
726     new_connection->m_sockstrm = stream;
727     new_connection->m_codeci = codeci;
728     new_connection->m_codeco = codeco;
729     sock->SetEventHandler(*gs_handler, _CLIENT_ONREQUEST_ID);
730     sock->SetClientData(new_connection);
731     sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
732     sock->Notify(true);
733     return;
734     }
735     else
736     {
737     delete new_connection;
738     // and fall through to delete everything else
739     }
740     }
741     }
742    
743     // Something went wrong, send failure message and delete everything
744     codeco->Write8(IPC_FAIL);
745    
746     delete codeco;
747     delete codeci;
748     delete stream;
749     sock->Destroy();
750     }
751    
752     // --------------------------------------------------------------------------
753     // wxTCPEventHandlerModule (private class)
754     // --------------------------------------------------------------------------
755    
756     class wxTCPEventHandlerModule: public wxModule
757     {
758     DECLARE_DYNAMIC_CLASS(wxTCPEventHandlerModule)
759    
760     public:
761     bool OnInit() { gs_handler = new wxTCPEventHandler(); return true; }
762     void OnExit() { wxDELETE(gs_handler); }
763     };
764    
765     IMPLEMENT_DYNAMIC_CLASS(wxTCPEventHandlerModule, wxModule)
766    
767    
768     #endif
769     // wxUSE_SOCKETS && wxUSE_IPC && wxUSE_STREAMS

  ViewVC Help
Powered by ViewVC 1.1.22