From f4ada568223b79c8a5769cc351c36a8e2ccd7841 Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Sun, 6 Sep 1998 18:28:00 +0000 Subject: [PATCH] * Added wxsocket lib and sample (I hope I don't forget some file) * Updated some wx data and makefiles * Updates on wxStream (reorganization) makefile for Windows will nearly follow wxSocket should work on wxGTK (I've tested it) * IPC over Network is included git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@684 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/datstrm.h | 10 +- include/wx/fstream.h | 9 +- include/wx/protocol/file.h | 35 + include/wx/protocol/ftp.h | 74 ++ include/wx/protocol/http.h | 48 + include/wx/protocol/protocol.h | 79 ++ include/wx/sckaddr.h | 136 +++ include/wx/sckipc.h | 132 +++ include/wx/sckstrm.h | 62 ++ include/wx/socket.h | 336 +++++++ include/wx/stream.h | 84 +- include/wx/tokenzr.h | 40 + include/wx/url.h | 70 ++ samples/wxsocket/Makefile | 1 + samples/wxsocket/Makefile.in | 28 + samples/wxsocket/client.cpp | 281 ++++++ samples/wxsocket/client.def | 8 + samples/wxsocket/client.rc | 3 + samples/wxsocket/connect.ico | Bin 0 -> 766 bytes samples/wxsocket/makefile.b32 | 86 ++ samples/wxsocket/makefile.g95 | 75 ++ samples/wxsocket/makefile.nt | 58 ++ samples/wxsocket/mondrian.ico | Bin 0 -> 766 bytes samples/wxsocket/mondrian.xpm | 44 + samples/wxsocket/server.cpp | 189 ++++ samples/wxsocket/server.def | 8 + samples/wxsocket/server.rc | 4 + src/common/datstrm.cpp | 17 + src/common/ftp.cpp | 378 ++++++++ src/common/http.cpp | 251 ++++++ src/common/protocol.cpp | 109 +++ src/common/sckaddr.cpp | 391 ++++++++ src/common/sckfile.cpp | 40 + src/common/sckipc.cpp | 503 +++++++++++ src/common/sckstrm.cpp | 68 ++ src/common/socket.cpp | 1532 ++++++++++++++++++++++++++++++++ src/common/stream.cpp | 33 +- src/common/tokenzr.cpp | 104 +++ src/common/url.cpp | 277 ++++++ src/gtk.inc | 10 + src/gtk/data.cpp | 44 + src/gtk1/data.cpp | 44 + 42 files changed, 5666 insertions(+), 35 deletions(-) create mode 100644 include/wx/protocol/file.h create mode 100644 include/wx/protocol/ftp.h create mode 100644 include/wx/protocol/http.h create mode 100644 include/wx/protocol/protocol.h create mode 100644 include/wx/sckaddr.h create mode 100644 include/wx/sckipc.h create mode 100644 include/wx/sckstrm.h create mode 100644 include/wx/socket.h create mode 100644 include/wx/tokenzr.h create mode 100644 include/wx/url.h create mode 100644 samples/wxsocket/Makefile create mode 100644 samples/wxsocket/Makefile.in create mode 100644 samples/wxsocket/client.cpp create mode 100644 samples/wxsocket/client.def create mode 100644 samples/wxsocket/client.rc create mode 100644 samples/wxsocket/connect.ico create mode 100644 samples/wxsocket/makefile.b32 create mode 100644 samples/wxsocket/makefile.g95 create mode 100644 samples/wxsocket/makefile.nt create mode 100644 samples/wxsocket/mondrian.ico create mode 100644 samples/wxsocket/mondrian.xpm create mode 100644 samples/wxsocket/server.cpp create mode 100644 samples/wxsocket/server.def create mode 100644 samples/wxsocket/server.rc create mode 100644 src/common/ftp.cpp create mode 100644 src/common/http.cpp create mode 100644 src/common/protocol.cpp create mode 100644 src/common/sckaddr.cpp create mode 100644 src/common/sckfile.cpp create mode 100644 src/common/sckipc.cpp create mode 100644 src/common/sckstrm.cpp create mode 100644 src/common/socket.cpp create mode 100644 src/common/tokenzr.cpp create mode 100644 src/common/url.cpp diff --git a/include/wx/datstrm.h b/include/wx/datstrm.h index de87a83323..230d5253b6 100644 --- a/include/wx/datstrm.h +++ b/include/wx/datstrm.h @@ -18,7 +18,7 @@ #include -class wxDataInputStream: public wxFilterInputStream { +class wxDataInputStream: virtual public wxFilterInputStream { public: wxDataInputStream(wxInputStream& s); virtual ~wxDataInputStream(); @@ -31,7 +31,7 @@ public: wxString ReadString(); }; -class wxDataOutputStream: public wxFilterOutputStream { +class wxDataOutputStream: virtual public wxFilterOutputStream { public: wxDataOutputStream(wxOutputStream& s); virtual ~wxDataOutputStream(); @@ -44,5 +44,11 @@ class wxDataOutputStream: public wxFilterOutputStream { void WriteString(const wxString& string); }; +class wxDataStream: public wxDataInputStream, public wxDataOutputStream, + public wxFilterStream { + public: + wxDataStream(wxStream& stream); +}; + #endif // _WX_DATSTREAM_H_ diff --git a/include/wx/fstream.h b/include/wx/fstream.h index 3fb395951c..dbe1abb1f8 100644 --- a/include/wx/fstream.h +++ b/include/wx/fstream.h @@ -22,7 +22,8 @@ protected: bool m_file_destroy; }; -class wxFileInputStream: public wxInputStream, virtual public wxFileStreamBase { +class wxFileInputStream: virtual public wxInputStream, + virtual public wxFileStreamBase { public: wxFileInputStream(const wxString& fileName); virtual ~wxFileInputStream(); @@ -39,7 +40,8 @@ class wxFileInputStream: public wxInputStream, virtual public wxFileStreamBase { off_t DoTellInput() const; }; -class wxFileOutputStream: public wxOutputStream, virtual public wxFileStreamBase { +class wxFileOutputStream: virtual public wxOutputStream, + virtual public wxFileStreamBase { public: wxFileOutputStream(const wxString& fileName); virtual ~wxFileOutputStream(); @@ -60,7 +62,8 @@ class wxFileOutputStream: public wxOutputStream, virtual public wxFileStreamBase off_t DoTellOutput() const; }; -class wxFileStream: public wxFileInputStream, public wxFileOutputStream { +class wxFileStream: public wxStream, + public wxFileInputStream, public wxFileOutputStream { public: wxFileStream(const wxString& fileName); virtual ~wxFileStream(); diff --git a/include/wx/protocol/file.h b/include/wx/protocol/file.h new file mode 100644 index 0000000000..773cdcc5b2 --- /dev/null +++ b/include/wx/protocol/file.h @@ -0,0 +1,35 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: file.h +// Purpose: File protocol +// Author: Guilhem Lavaux +// Modified by: +// Created: 1997 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// +#ifndef __WX_PROTO_FILE_H__ +#define __WX_PROTO_FILE_H__ + +#ifdef __GNUG__ +#pragma interface "sckfile.h" +#endif + +#include "wx/protocol/protocol.h" +#include "wx/url.h" + +class WXDLLEXPORT wxFileProto: public wxProtocol { + DECLARE_DYNAMIC_CLASS(wxFileProto) + DECLARE_PROTOCOL(wxFileProto) +protected: + wxProtocolError m_error; +public: + wxFileProto(); + ~wxFileProto(); + + wxProtocolError GetError() { return m_error; } + bool Abort() { return TRUE; } + wxInputStream *GetInputStream(const wxString& path); +}; + +#endif diff --git a/include/wx/protocol/ftp.h b/include/wx/protocol/ftp.h new file mode 100644 index 0000000000..7fca01f8b7 --- /dev/null +++ b/include/wx/protocol/ftp.h @@ -0,0 +1,74 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: ftp.h +// Purpose: FTP protocol +// Author: Vadim Zeitlin +// Modified by: +// Created: 07/07/1997 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// +#ifndef __WX_FTP_H__ +#define __WX_FTP_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/object.h" +#include "wx/sckaddr.h" +#include "wx/protocol/protocol.h" +#include "wx/url.h" + +class WXDLLEXPORT wxFTP : public wxProtocol { + DECLARE_DYNAMIC_CLASS(wxFTP) + DECLARE_PROTOCOL(wxFTP) +public: + typedef enum { ASCII, BINARY } wxFTPmode; + + wxFTP(); + ~wxFTP(); + + bool Close(); + bool Connect(wxSockAddress& addr); + bool Connect(const wxString& host); + + void SetUser(const wxString& user) { m_user = user; } + void SetPassword(const wxString& passwd) { m_passwd = passwd; } + + // Low-level methods + bool SendCommand(const wxString& command, char exp_ret); + inline virtual wxProtocolError GetError() + { return m_lastError; } + const wxString& GetLastResult(); // Get the complete return + + // Filesystem commands + bool ChDir(const wxString& dir); + bool MkDir(const wxString& dir); + bool RmDir(const wxString& dir); + wxString Pwd(); + bool Rename(const wxString& src, const wxString& dst); + bool RmFile(const wxString& path); + + // Download methods + bool Abort(); + wxInputStream *GetInputStream(const wxString& path); + wxOutputStream *GetOutputStream(const wxString& path); + + // List method + wxList *GetList(const wxString& wildcard); + +protected: + wxString m_user, m_passwd; + wxString m_lastResult; + wxProtocolError m_lastError; + bool m_streaming; + + friend class wxInputFTPStream; + friend class wxOutputFTPStream; + + wxSocketClient *GetPort(); + bool GetResult(char exp); +}; + +#endif diff --git a/include/wx/protocol/http.h b/include/wx/protocol/http.h new file mode 100644 index 0000000000..97282b5665 --- /dev/null +++ b/include/wx/protocol/http.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: http.h +// Purpose: HTTP protocol +// Author: Guilhem Lavaux +// Modified by: +// Created: August 1997 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// +#ifndef _WX_HTTP_H +#define _WX_HTTP_H + +#include "wx/list.h" +#include "wx/protocol/protocol.h" + +class WXDLLEXPORT wxHTTP : public wxProtocol { + DECLARE_DYNAMIC_CLASS(wxHTTP) + DECLARE_PROTOCOL(wxHTTP) +protected: + wxProtocolError m_perr; + wxList m_headers; + bool m_read; + wxSockAddress *m_addr; +public: + wxHTTP(); + ~wxHTTP(); + + bool Connect(const wxString& host); + bool Connect(wxSockAddress& addr); + bool Abort(); + wxInputStream *GetInputStream(const wxString& path); + inline wxProtocolError GetError() { return m_perr; } + wxString GetContentType(); + + void SetHeader(const wxString& header, const wxString& h_data); + wxString GetHeader(const wxString& header); + +protected: + typedef enum { + wxHTTP_GET + } wxHTTP_Req; + bool BuildRequest(const wxString& path, wxHTTP_Req req); + void SendHeaders(); + bool ParseHeaders(); +}; + +#endif diff --git a/include/wx/protocol/protocol.h b/include/wx/protocol/protocol.h new file mode 100644 index 0000000000..c3773a750d --- /dev/null +++ b/include/wx/protocol/protocol.h @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: protocol.h +// Purpose: Protocol base class +// Author: Guilhem Lavaux +// Modified by: +// Created: 10/07/1997 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// +#ifndef _WX_PROTOCOL_PROTOCOL_H +#define _WX_PROTOCOL_PROTOCOL_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/object.h" +#include "wx/string.h" +#include "wx/stream.h" +#include "wx/socket.h" + +typedef enum { + wxPROTO_NOERR = 0, + wxPROTO_NETERR, + wxPROTO_PROTERR, + wxPROTO_CONNERR, + wxPROTO_INVVAL, + wxPROTO_NOHNDLR, + wxPROTO_NOFILE, + wxPROTO_ABRT, + wxPROTO_RCNCT, + wxPROTO_STREAMING +} wxProtocolError; + +// For protocols +#define DECLARE_PROTOCOL(class) \ +public: \ + static wxProtoInfo g_proto_##class; + +#define IMPLEMENT_PROTOCOL(class, name, serv, host) \ +wxProtoInfo class::g_proto_##class(name, serv, host, CLASSINFO(class)); + +class WXDLLEXPORT wxProtoInfo : public wxObject { + DECLARE_DYNAMIC_CLASS(wxProtoInfo) +protected: + wxProtoInfo *next; + wxString m_protoname; + wxString prefix; + wxString m_servname; + wxClassInfo *m_cinfo; + bool m_needhost; + + friend class wxURL; +public: + wxProtoInfo(const char *name, const char *serv_name, const bool need_host1, + wxClassInfo *info); +}; + +class WXDLLEXPORT wxProtocol : public wxSocketClient { + DECLARE_ABSTRACT_CLASS(wxProtocol) +public: + wxProtocol(); + + bool Reconnect(); + virtual bool Connect(const wxString& host) { return FALSE; } + virtual bool Connect(wxSockAddress& addr) { return wxSocketClient::Connect(addr); } + + virtual bool Abort() = 0; + virtual wxInputStream *GetInputStream(const wxString& path) = 0; + virtual wxProtocolError GetError() = 0; + virtual wxString GetContentType() { return (char *)NULL; } + virtual void SetUser(const wxString& user) {} + virtual void SetPassword(const wxString& passwd) {} +}; + +wxProtocolError WXDLLEXPORT GetLine(wxSocketBase *sock, wxString& result); + +#endif diff --git a/include/wx/sckaddr.h b/include/wx/sckaddr.h new file mode 100644 index 0000000000..392a9d1387 --- /dev/null +++ b/include/wx/sckaddr.h @@ -0,0 +1,136 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: sckaddr.h +// Purpose: Network address classes +// Author: Guilhem Lavaux +// Modified by: +// Created: 26/04/1997 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// +#ifndef _WX_NETWORK_ADDRESS_H +#define _WX_NETWORK_ADDRESS_H + +#if defined(__WINDOWS__) && defined(WXSOCK_INTERNAL) +#include + +#elif defined(__UNIX__) && defined(WXSOCK_INTERNAL) + +#include +#include +#include +#endif + +#ifdef __GNUG__ +#pragma interface +#endif + +#ifdef WXPREC +#include +#else +#include +#endif + +class WXDLLEXPORT wxSockAddress : public wxObject { + DECLARE_ABSTRACT_CLASS(wxSockAddress) +public: + typedef enum { IPV4=1, IPV6=2, UNIX=3 } Addr; + + wxSockAddress() {}; + virtual ~wxSockAddress() {}; + + virtual void Clear() = 0; + + virtual void Build(struct sockaddr*& addr, size_t& len) = 0; + virtual void Disassemble(struct sockaddr *addr, size_t len) = 0; + virtual int SockAddrLen() = 0; + + virtual int GetFamily() = 0; + virtual int Type() = 0; +}; + +class WXDLLEXPORT wxIPV4address : public wxSockAddress { + DECLARE_DYNAMIC_CLASS(wxIPV4address) +private: + struct sockaddr_in *m_addr; +public: + wxIPV4address(); + virtual ~wxIPV4address(); + + virtual void Clear(); +// const wxSockAddress& operator =(const wxSockAddress& addr); + + virtual bool Hostname(const wxString& name); + virtual bool Hostname(unsigned long addr); + virtual bool Service(const wxString& name); + virtual bool Service(unsigned short port); + virtual bool LocalHost(); + + wxString Hostname(); + unsigned short Service(); + + void Build(struct sockaddr*& addr, size_t& len); + void Disassemble(struct sockaddr *addr, size_t len); + + inline int SockAddrLen(); + inline int GetFamily(); + inline int Type() { return wxSockAddress::IPV4; } +}; + +#ifdef ENABLE_IPV6 +class WXDLLEXPORT wxIPV6address : public wxSockAddress { + DECLARE_DYNAMIC_CLASS(wxIPV6address) +private: + struct sockaddr_in6 *m_addr; +public: + wxIPV6address(); + ~wxIPV6address(); + + void Clear(); +// const wxSockAddress& operator =(const wxSockAddress& addr); + + bool Hostname(const wxString& name); + bool Hostname(unsigned char addr[16]); + bool Service(const wxString& name); + bool Service(unsigned short port); + bool LocalHost(); + + wxString Hostname() const; + unsigned short Service() const; + + void Build(struct sockaddr*& addr, size_t& len); + void Disassemble(struct sockaddr *addr, size_t len); + + inline int SockAddrLen(); + inline int GetFamily(); + inline int Type() { return wxSockAddress::IPV6; } +}; +#endif + +#ifdef __UNIX__ +#include + +class WXDLLEXPORT wxUNIXaddress : public wxSockAddress { + DECLARE_DYNAMIC_CLASS(wxUNIXaddress) +private: + struct sockaddr_un *m_addr; +public: + wxUNIXaddress(); + ~wxUNIXaddress(); + + void Clear(); +// const wxSockAddress& operator =(const wxSockAddress& addr); + + void Filename(const wxString& name); + wxString Filename(); + + void Build(struct sockaddr*& addr, size_t& len); + void Disassemble(struct sockaddr *addr, size_t len); + + inline int SockAddrLen(); + inline int GetFamily(); + inline int Type() { return wxSockAddress::UNIX; } +}; +#endif + +#endif diff --git a/include/wx/sckipc.h b/include/wx/sckipc.h new file mode 100644 index 0000000000..8ca86b2ae2 --- /dev/null +++ b/include/wx/sckipc.h @@ -0,0 +1,132 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: sckipc.h +// Purpose: Interprocess communication +// Author: Julian Smart/Guilhem Lavaux (big rewrite) +// Modified by: Guilhem Lavaux 1997 +// Created: 1993 +// RCS-ID: $Id$ +// Copyright: (c) 1993 Julian Smart +// (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// +#ifndef _WX_SCKIPC_H +#define _WX_SCKIPC_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/defs.h" +#include "wx/setup.h" +#include "wx/ipcbase.h" +#include "wx/socket.h" +#include "wx/sckstrm.h" +#include "wx/datstrm.h" + +/* + * Mini-DDE implementation + + Most transactions involve a topic name and an item name (choose these + as befits your application). + + A client can: + + - ask the server to execute commands (data) associated with a topic + - request data from server by topic and item + - poke data into the server + - ask the server to start an advice loop on topic/item + - ask the server to stop an advice loop + + A server can: + + - respond to execute, request, poke and advice start/stop + - send advise data to client + + Note that this limits the server in the ways it can send data to the + client, i.e. it can't send unsolicited information. + * + */ + +class wxTCPServer; +class wxTCPClient; +class wxTCPConnection: public wxConnectionBase +{ + DECLARE_DYNAMIC_CLASS(wxTCPConnection) + +protected: + wxSocketBase *m_sock; + wxSocketStream *m_sockstrm; + wxDataStream *m_codec; + wxString m_topic; + + friend class wxTCPServer; + friend class wxTCPClient; + friend void Client_OnRequest(wxSocketBase&, + wxSocketBase::wxRequestEvent, char *); + friend void Server_OnRequest(wxSocketServer&, + wxSocketBase::wxRequestEvent, char *); +public: + + wxTCPConnection(char *buffer, int size); + wxTCPConnection(); + virtual ~wxTCPConnection(); + + // Calls that CLIENT can make + bool Execute(char *data, int size = -1, + wxDataFormat format = wxDF_TEXT); + char *Request(const wxString& item, int *size = NULL, + wxDataFormat format = wxDF_TEXT); + bool Poke(const wxString& item, char *data, int size = -1, + wxDataFormat format = wxDF_TEXT); + bool StartAdvise(const wxString& item); + bool StopAdvise(const wxString& item); + + // Calls that SERVER can make + bool Advise(const wxString& item, char *data, int size = -1, + wxDataFormat format = wxDF_TEXT); + + // Calls that both can make + bool Disconnect(); + + // Called when we lost the peer. + bool OnDisconnect() { return TRUE; } + + // To enable the compressor + void Compress(bool on); +}; + +class wxTCPServer: public wxServerBase +{ + DECLARE_DYNAMIC_CLASS(wxTCPServer) + +public: + wxTCPConnection *topLevelConnection; + + wxTCPServer(); + virtual ~wxTCPServer(); + + // Returns FALSE if can't create server (e.g. port number is already in use) + virtual bool Create(const wxString& server_name); + virtual wxConnectionBase *OnAcceptConnection(const wxString& topic); +}; + +class wxTCPClient: public wxClientBase +{ + DECLARE_DYNAMIC_CLASS(wxTCPClient) + +public: + wxTCPClient(); + virtual ~wxTCPClient(); + + virtual bool ValidHost(const wxString& host); + // Call this to make a connection. + // Returns NULL if cannot. + virtual wxConnectionBase *MakeConnection(const wxString& host, + const wxString& server, + const wxString& topic); + + // Tailor this to return own connection. + virtual wxConnectionBase *OnMakeConnection(); +}; + +#endif // ipcsock.h diff --git a/include/wx/sckstrm.h b/include/wx/sckstrm.h new file mode 100644 index 0000000000..3d55f1b85e --- /dev/null +++ b/include/wx/sckstrm.h @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: sckstrm.h +// Purpose: wxSocket*Stream +// Author: Guilhem Lavaux +// Modified by: +// Created: 17/07/97 +// RCS-ID: $Id$ +// Copyright: (c) +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// +#ifndef __SCK_STREAM_H__ +#define __SCK_STREAM_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/stream.h" +#include "wx/socket.h" + +class WXDLLEXPORT wxSocketOutputStream : public wxOutputStream +{ + public: + wxSocketOutputStream(wxSocketBase& s); + virtual ~wxSocketOutputStream(); + + wxOutputStream& Write(const void *buffer, size_t size); + off_t SeekO(off_t pos, wxSeekMode mode) { return -1; } + off_t TellO() { return -1; } + + bool Bad() { return m_o_socket->IsDisconnected(); } + size_t LastWrite() { return m_o_socket->LastCount(); } + protected: + wxSocketBase *m_o_socket; +}; + +class WXDLLEXPORT wxSocketInputStream : public wxInputStream +{ + public: + wxSocketInputStream(wxSocketBase& s); + ~wxSocketInputStream(); + + wxInputStream& Read(void *buffer, size_t size); + off_t SeekI(off_t pos, wxSeekMode mode) { return -1; } + off_t TellI() { return -1; } + + bool Eof() { return m_i_socket->IsDisconnected(); } + size_t LastRead() { return m_i_socket->LastCount(); } + protected: + wxSocketBase *m_i_socket; +}; + +class WXDLLEXPORT wxSocketStream : public wxSocketInputStream, + public wxSocketOutputStream, + public wxStream { + + public: + wxSocketStream(wxSocketBase& i_s, wxSocketBase& o_s); + wxSocketStream(wxSocketBase& s); +}; + +#endif diff --git a/include/wx/socket.h b/include/wx/socket.h new file mode 100644 index 0000000000..a65b4683cd --- /dev/null +++ b/include/wx/socket.h @@ -0,0 +1,336 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: socket.h +// Purpose: Socket handling classes +// Author: Guilhem Lavaux +// Modified by: +// Created: April 1997 +// RCS-ID: $Id$ +// Copyright: (c) Guilhem Lavaux +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// +#ifndef _WX_NETWORK_SOCKET_H +#define _WX_NETWORK_SOCKET_H + +#ifdef __GNUG__ +#pragma interface +#endif + +// --------------------------------------------------------------------------- +// Windows(tm) specific +// --------------------------------------------------------------------------- +#if defined(__WINDOWS__) && defined(WXSOCK_INTERNAL) +#include +#include + +struct wxSockInternal { + UINT my_msg; +}; + +struct wxSockHandlerInternal { + HWND sockWin; + UINT firstAvailableMsg; +}; +#endif // defined(__WINDOWS__) && defined(WXSOCK_INTERNAL) + +// --------------------------------------------------------------------------- +// Unix specific +// --------------------------------------------------------------------------- +#if defined(__UNIX__) && defined(WXSOCK_INTERNAL) +#include +#include +#include + +// --------------------------------------------------------------------------- +// Athena specific +// --------------------------------------------------------------------------- +#if defined(__WXXT__) || defined(__WXMOTIF__) +#include + +struct wxSockInternal { + XtInputId sock_inputid, sock_outputid, sock_exceptid; +}; +#endif + +// --------------------------------------------------------------------------- +// GTK specific +// --------------------------------------------------------------------------- +#if defined(__WXGTK__) +#include + +struct wxSockInternal { + gint sock_inputid, sock_outputid, sock_exceptid; +}; +#endif + +#endif // defined(__UNIX__) && defined(WXSOCK_INTERNAL) + +// --------------------------------------------------------------------------- +// wxSocket headers (generic) +// --------------------------------------------------------------------------- +#ifdef WXPREC +#include +#else +#include +#endif +#include "wx/sckaddr.h" + +class WXDLLEXPORT wxSocketEvent; +class WXDLLEXPORT wxSocketHandler; +class WXDLLEXPORT wxSocketBase : public wxEvtHandler +{ + DECLARE_CLASS(wxSocketBase) +public: + + enum wxSockFlags { NONE=0, NOWAIT=1, WAITALL=2, SPEED=4 }; + // Type of request + enum { REQ_READ=0x1, REQ_PEEK=0x2, REQ_WRITE=0x4, REQ_LOST=0x8, + REQ_ACCEPT=0x10, REQ_CONNECT=0x20}; + enum { EVT_READ=0, EVT_PEEK=1, EVT_WRITE=2, EVT_LOST=3, EVT_ACCEPT=4, + EVT_CONNECT=5 }; + + typedef int wxRequestNotify; + typedef int wxRequestEvent; + typedef void (*wxSockCbk)(wxSocketBase& sock,wxRequestEvent evt,char *cdata); + +protected: + wxList req_list[EVT_WRITE+1]; + + // Internal use for SaveState() and RestoreState() + class wxSockState : public wxObject { + public: + bool cbk_on; + wxSockCbk cbk; + char *cdata; + bool notif; + wxRequestNotify cbk_set; + wxSockFlags flags; + }; + typedef struct { + char sig[4]; + char len[4]; + } SockMsg; + enum wxSockType { SOCK_CLIENT, SOCK_SERVER, SOCK_INTERNAL, SOCK_UNINIT }; + + wxSockFlags m_flags; + wxSockType m_type; // wxSocket type + bool m_connected, m_connecting; // State of the socket + int m_fd; // Socket file descriptors + int m_waitflags; // Wait flags + wxList m_states; // States list + wxSockCbk m_cbk; // C callback + char *m_cdata; // C callback data + int m_id; // Socket id (for event handler) + wxSocketHandler *m_handler; // the current socket handler + wxRequestNotify m_neededreq; // Specify which requet signals we need + bool m_cbkon; + char *m_unread; // The unread buf + size_t m_unrd_size; // The size of the unread buf + bool m_processing; // To prevent some endless loop + unsigned long m_timeout; + int m_wantbuf; + size_t m_lcount; // Last IO request size + int m_error; // Last IO error + bool m_notifyme; + + struct wxSockInternal *m_internal; // System specific variables + +public: + wxSocketBase(); + virtual ~wxSocketBase(); + virtual bool Close(); + + // Base IO + wxSocketBase& Peek(char* buffer, size_t nbytes); + wxSocketBase& Read(char* buffer, size_t nbytes); + wxSocketBase& Write(const char *buffer, size_t nbytes); + wxSocketBase& WriteMsg(const char *buffer, size_t nbytes); + wxSocketBase& ReadMsg(char* buffer, size_t nbytes); + wxSocketBase& Unread(const char *buffer, size_t nbytes); + void Discard(); + + // Try not to use this two methods (they sould be protected) + void CreatePushbackAfter(const char *buffer, size_t size); + void CreatePushbackBefore(const char *buffer, size_t size); + + // Status + inline bool Ok() const { return (m_fd < 0 ? 0 : 1); }; + inline bool Error() const { return (m_error != 0); }; + inline bool IsConnected() const { return m_connected; }; + inline bool IsDisconnected() const { return !IsConnected(); }; + inline bool IsNoWait() const { return m_flags & NOWAIT; }; + bool IsData() const; + inline size_t LastCount() const { return m_lcount; } + inline int LastError() const { return m_error; } + + inline void SetFlags(wxSockFlags _flags); + inline void SetTimeout(unsigned long sec) { m_timeout = sec; } + + // seconds = -1 means infinite wait + // seconds = 0 means no wait + // seconds > 0 means specified wait + bool Wait(long seconds = -1, long microseconds = 0); + bool WaitForRead(long seconds = -1, long microseconds = 0); + bool WaitForWrite(long seconds = -1, long microseconds = 0); + bool WaitForLost(long seconds = -1, long microseconds = 0); + + // Save the current state of Socket + void SaveState(); + void RestoreState(); + + // Setup external callback + wxSockCbk Callback(wxSockCbk cbk_); + char *CallbackData(char *data); + + // Setup event handler + void SetEventHandler(wxEvtHandler& evt_hdlr, int id = -1); + + // Method called when it happens something on the socket + void SetNotify(wxRequestNotify flags); + virtual void OnRequest(wxRequestEvent req_evt); + + // Public internal callback + virtual void OldOnNotify(wxRequestEvent WXUNUSED(evt)); + + // Some info on the socket... + virtual bool GetPeer(wxSockAddress& addr_man) const; + virtual bool GetLocal(wxSockAddress& addr_man) const; + + // Install or uninstall callbacks + void Notify(bool notify); + + // So you can know what the socket driver is looking for ... + inline wxRequestNotify NeededReq() const { return m_neededreq; } + + static wxRequestNotify EventToNotify(wxRequestEvent evt); + +protected: + friend class wxSocketServer; + friend class wxSocketHandler; + + wxSocketBase(wxSockFlags flags, wxSockType type); + + bool _Wait(long seconds, long microseconds, int type); + + // Set "my" handler + inline virtual void SetHandler(wxSocketHandler *handler) + { m_handler = handler; } + + // Activate or disactivate callback + void SetupCallbacks(); + void DestroyCallbacks(); + + // Pushback library + size_t GetPushback(char *buffer, size_t size, bool peek); + + // To prevent many read or write on the same socket at the same time + // ==> cause strange things :-) + void WantSpeedBuffer(char *buffer, size_t size, wxRequestEvent req); + void WantBuffer(char *buffer, size_t size, wxRequestEvent req); + + virtual bool DoRequests(wxRequestEvent req); +}; + +//////////////////////////////////////////////////////////////////////// + +class WXDLLEXPORT wxSocketServer : public wxSocketBase +{ + DECLARE_CLASS(wxSocketServer) +public: + + // 'service' can be a name or a port-number + + wxSocketServer(wxSockAddress& addr_man, wxSockFlags flags = wxSocketBase::NONE); + + wxSocketBase* Accept(); + bool AcceptWith(wxSocketBase& sock); + virtual void OnRequest(wxRequestEvent flags); +}; + +//////////////////////////////////////////////////////////////////////// + +class WXDLLEXPORT wxSocketClient : public wxSocketBase +{ + DECLARE_CLASS(wxSocketClient) +public: + + wxSocketClient(wxSockFlags flags = wxSocketBase::NONE); + virtual ~wxSocketClient(); + + virtual bool Connect(wxSockAddress& addr_man, bool wait = TRUE); + + bool WaitOnConnect(long seconds = -1); + + virtual void OnRequest(wxRequestEvent flags); +}; + +//////////////////////////////////////////////////////////////////////// + +class WXDLLEXPORT wxSocketHandler : public wxObject +{ + DECLARE_CLASS(wxSocketHandler) +protected: + static wxSocketHandler *master; +#if defined(__WINDOWS__) + wxList *smsg_list; + struct wxSockHandlerInternal *internal; +#endif + wxList *socks; + +public: + enum SockStatus { SOCK_NONE, SOCK_DATA, SOCK_CONNECT, SOCK_DISCONNECT, + SOCK_ERROR }; + + wxSocketHandler(); + virtual ~wxSocketHandler(); + + void Register(wxSocketBase* sock); + void UnRegister(wxSocketBase* sock); + + unsigned long Count() const; + + // seconds = -1 means indefinite wait + // seconds = 0 means no wait + // seconds > 0 means specified wait + + int Wait(long seconds = -1, long microseconds = 0); + void YieldSock(); + + wxSocketServer *CreateServer + (wxSockAddress& addr, + wxSocketBase::wxSockFlags flags = wxSocketBase::NONE); + wxSocketClient *CreateClient + (wxSocketBase::wxSockFlags flags = wxSocketBase::NONE); + + // Create or reuse a socket handler + static wxSocketHandler& Master() + { return *((master) ? (master) : (master = new wxSocketHandler())); } + +#if defined(WXSOCK_INTERNAL) && defined(__WINDOWS__) + + friend LRESULT APIENTRY _EXPORT wxSocketHandlerWndProc(HWND hWnd, + UINT message, WPARAM wParam, LPARAM lParam); + + UINT NewMessage(wxSocketBase *sock); + void DestroyMessage(UINT msg); + + HWND GetHWND() const; +#endif +}; + +class WXDLLEXPORT wxSocketEvent : public wxEvent { + DECLARE_DYNAMIC_CLASS(wxSocketEvent) +public: + wxSocketEvent(int id = 0); + + wxSocketBase::wxRequestEvent SocketEvent() const { return m_skevt; } +public: + wxSocketBase::wxRequestEvent m_skevt; +}; + +typedef void (wxEvtHandler::*wxSocketEventFunction)(wxSocketEvent&); + +#define wxEVT_SOCKET wxEVT_FIRST+301 + +#define EVT_SOCKET(id, func) { wxEVT_SOCKET, id, 0, (wxObjectEventFunction) (wxEventFunction) (wxSocketEventFunction) & func }, + +#endif diff --git a/include/wx/stream.h b/include/wx/stream.h index d966c7da37..428dbaab1f 100644 --- a/include/wx/stream.h +++ b/include/wx/stream.h @@ -29,6 +29,10 @@ typedef wxOutputStream& (*__wxOutputManip)(wxOutputStream&); wxOutputStream& WXDLLEXPORT wxEndL(wxOutputStream& o_stream); +// --------------------------------------------------------------------------- +// Stream buffer +// --------------------------------------------------------------------------- + class WXDLLEXPORT wxStreamBuffer { public: wxStreamBuffer(wxInputStream& stream); @@ -63,16 +67,17 @@ class WXDLLEXPORT wxStreamBuffer { wxOutputStream *m_ostream; }; -/* - * wxStream: base classes - */ +// --------------------------------------------------------------------------- +// wxStream: base classes +// --------------------------------------------------------------------------- + class WXDLLEXPORT wxInputStream { public: wxInputStream(); virtual ~wxInputStream(); // IO functions - virtual char Peek() = 0; + virtual char Peek() { return 0; } virtual char GetC(); virtual wxInputStream& Read(void *buffer, size_t size); wxInputStream& Read(wxOutputStream& stream_out); @@ -108,9 +113,11 @@ class WXDLLEXPORT wxInputStream { wxInputStream(wxStreamBuffer *buffer); - virtual size_t DoRead(void *buffer, size_t size) = 0; - virtual off_t DoSeekInput(off_t pos, wxSeekMode mode) = 0; - virtual off_t DoTellInput() const = 0; + virtual size_t DoRead(void *buffer, size_t size) { return 0; } + virtual off_t DoSeekInput(off_t pos, wxSeekMode mode) + { return wxInvalidOffset; } + virtual off_t DoTellInput() const + { return wxInvalidOffset; } protected: bool m_eof, m_i_destroybuf; @@ -158,9 +165,11 @@ class WXDLLEXPORT wxOutputStream { wxOutputStream(wxStreamBuffer *buffer); - virtual size_t DoWrite(const void *buffer, size_t size) = 0; - virtual off_t DoSeekOutput(off_t pos, wxSeekMode mode) = 0; - virtual off_t DoTellOutput() const = 0; + virtual size_t DoWrite(const void *buffer, size_t size) { return 0; } + virtual off_t DoSeekOutput(off_t pos, wxSeekMode mode) + { return wxInvalidOffset; } + virtual off_t DoTellOutput() const + { return wxInvalidOffset; } protected: bool m_bad, m_o_destroybuf; @@ -168,48 +177,65 @@ class WXDLLEXPORT wxOutputStream { wxStreamBuffer *m_o_streambuf; }; -/* - * "Filter" streams - */ +class wxStream: virtual public wxInputStream, + virtual public wxOutputStream +{ + public: + wxStream(); +}; + +// --------------------------------------------------------------------------- +// "Filter" streams +// --------------------------------------------------------------------------- -class WXDLLEXPORT wxFilterInputStream: public wxInputStream { +class WXDLLEXPORT wxFilterInputStream: virtual public wxInputStream { public: + wxFilterInputStream(); wxFilterInputStream(wxInputStream& stream); - virtual ~wxFilterInputStream(); + ~wxFilterInputStream(); - virtual char Peek() { return m_parent_i_stream->Peek(); } + char Peek() { return m_parent_i_stream->Peek(); } - virtual bool Eof() const { return m_parent_i_stream->Eof(); } - virtual size_t LastRead() const { return m_parent_i_stream->LastRead(); } - virtual off_t TellI() const { return m_parent_i_stream->TellI(); } + bool Eof() const { return m_parent_i_stream->Eof(); } + size_t LastRead() const { return m_parent_i_stream->LastRead(); } + off_t TellI() const { return m_parent_i_stream->TellI(); } protected: - virtual size_t DoRead(void *buffer, size_t size); - virtual off_t DoSeekInput(off_t pos, wxSeekMode mode); - virtual off_t DoTellInput() const; + size_t DoRead(void *buffer, size_t size); + off_t DoSeekInput(off_t pos, wxSeekMode mode); + off_t DoTellInput() const; protected: wxInputStream *m_parent_i_stream; }; -class WXDLLEXPORT wxFilterOutputStream: public wxOutputStream { +class WXDLLEXPORT wxFilterOutputStream: virtual public wxOutputStream { public: + wxFilterOutputStream(); wxFilterOutputStream(wxOutputStream& stream); virtual ~wxFilterOutputStream(); - virtual bool Bad() const { return m_parent_o_stream->Bad(); } - virtual size_t LastWrite() const { return m_parent_o_stream->LastWrite(); } - virtual off_t TellO() const { return m_parent_o_stream->TellO(); } + bool Bad() const { return m_parent_o_stream->Bad(); } + size_t LastWrite() const { return m_parent_o_stream->LastWrite(); } + off_t TellO() const { return m_parent_o_stream->TellO(); } protected: // The forward is implicitely done by wxStreamBuffer. - virtual size_t DoWrite(const void *buffer, size_t size); - virtual off_t DoSeekOutput(off_t pos, wxSeekMode mode); - virtual off_t DoTellOutput() const; + size_t DoWrite(const void *buffer, size_t size); + off_t DoSeekOutput(off_t pos, wxSeekMode mode); + off_t DoTellOutput() const; protected: wxOutputStream *m_parent_o_stream; }; +class WXDLLEXPORT wxFilterStream: public wxStream, + virtual public wxFilterInputStream, + virtual public wxFilterOutputStream { + public: + wxFilterStream(wxStream& stream); + wxFilterStream(); +}; + #endif diff --git a/include/wx/tokenzr.h b/include/wx/tokenzr.h new file mode 100644 index 0000000000..7942996e29 --- /dev/null +++ b/include/wx/tokenzr.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: tokenzr.h +// Purpose: String tokenizer +// Author: Guilhem Lavaux +// Modified by: +// Created: 04/22/98 +// RCS-ID: $Id$ +// Copyright: (c) Guilhem Lavaux +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_TOKENZRH +#define _WX_TOKENZRH + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/object.h" +#include "wx/string.h" + +class wxStringTokenizer : wxObject { +public: + wxStringTokenizer(const wxString& to_tokenize, + const wxString& delims = " \t\r\n", + bool ret_delim = FALSE); + ~wxStringTokenizer(); + + int CountTokens(); + bool HasMoreToken(); + wxString NextToken(); + wxString GetString() { return m_string; } +protected: + off_t FindDelims(const wxString& str, const wxString& delims); +protected: + wxString m_string, m_delims; + bool m_retdelims; +}; + +#endif diff --git a/include/wx/url.h b/include/wx/url.h new file mode 100644 index 0000000000..dae1c6ec30 --- /dev/null +++ b/include/wx/url.h @@ -0,0 +1,70 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: url.h +// Purpose: URL parser +// Author: Guilhem Lavaux +// Modified by: +// Created: 20/07/1997 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// +#ifndef _WX_URL_H +#define _WX_URL_H + +#ifdef __GNUG__ +#pragma interface +#endif + +// wxWindows header +#include "wx/object.h" + +// wxSocket headers +#include "wx/protocol/protocol.h" +#include "wx/protocol/http.h" + +typedef enum { + wxURL_NOERR = 0, + wxURL_SNTXERR, + wxURL_NOPROTO, + wxURL_NOHOST, + wxURL_NOPATH, + wxURL_CONNERR, + wxURL_PROTOERR +} wxURLError; + +class WXDLLEXPORT wxURL : public wxObject { + DECLARE_DYNAMIC_CLASS(wxURL) +protected: + static wxProtoInfo *g_protocols; + static wxHTTP g_proxy; + wxProtoInfo *m_protoinfo; + wxProtocol *m_protocol; + wxHTTP m_proxy; + wxURLError m_error; + wxString m_protoname, m_hostname, m_servname, m_path, m_url; + + bool PrepProto(wxString& url); + bool PrepHost(wxString& url); + bool PrepPath(wxString& url); + bool ParseURL(); + void CleanData(); + bool FetchProtocol(); + + friend class wxProtoInfo; +public: + + wxURL(const wxString& url); + virtual ~wxURL(); + + inline wxString GetProtocolName() const + { return m_protoinfo->m_protoname; } + inline wxProtocol& GetProtocol() { return *m_protocol; } + inline wxURLError GetError() const { return m_error; } + + wxInputStream *GetInputStream(); + + static void SetDefaultProxy(const wxString& url_proxy); + void SetProxy(const wxString& url_proxy); +}; + +#endif diff --git a/samples/wxsocket/Makefile b/samples/wxsocket/Makefile new file mode 100644 index 0000000000..bccce53f76 --- /dev/null +++ b/samples/wxsocket/Makefile @@ -0,0 +1 @@ +include ../../setup/general/makeapp diff --git a/samples/wxsocket/Makefile.in b/samples/wxsocket/Makefile.in new file mode 100644 index 0000000000..68ded4e305 --- /dev/null +++ b/samples/wxsocket/Makefile.in @@ -0,0 +1,28 @@ +# WXXT base directory +WXBASEDIR=@WXBASEDIR@ + +# set the OS type for compilation +OS=@OS@ +# compile a library only +RULE=bin2 + +# define library name +BIN_TARGET=client +BIN2_TARGET=server +# define library sources +BIN_SRC= client.cpp +BIN2_SRC= server.cpp + +#define library objects +BIN_OBJ= client.o +BIN2_OBJ= server.o + +# additional things needed to link +BIN_LINK= +BIN2_LINK= + +# additional things needed to compile +ADD_COMPILE= + +# include the definitions now +include ../../../template.mak diff --git a/samples/wxsocket/client.cpp b/samples/wxsocket/client.cpp new file mode 100644 index 0000000000..4d27104c2b --- /dev/null +++ b/samples/wxsocket/client.cpp @@ -0,0 +1,281 @@ +/* + * File: client.cpp + * Purpose: wxSocket: client demo + * Author: LAVAUX Guilhem (from minimal.cc) + * Created: June 1997 + * Updated: + * Copyright: (c) 1993, AIAI, University of Edinburgh + * (C) 1997, LAVAUX Guilhem + */ +#ifdef __GNUG__ +#pragma implementation +#pragma interface +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif +#include "wx/socket.h" +#include "wx/url.h" +#include "wx/protocol/http.h" + +// Define a new application type +class MyApp: public wxApp +{ public: + virtual bool OnInit(void); +}; + +class MyClient; + +// Define a new frame type +class MyFrame: public wxFrame +{ + DECLARE_CLASS(MyFrame) +public: + MyClient *sock; + + MyFrame(void); + virtual ~MyFrame(); + void OnCloseTest(wxCommandEvent& evt); + void OnExecTest1(wxCommandEvent& evt); + void OnExecUrlTest(wxCommandEvent& evt); + void OnQuitApp(wxCommandEvent& evt); + void OnExecOpenConnection(wxCommandEvent& evt); + void OnExecCloseConnection(wxCommandEvent& evt); + void UpdateStatus(); + + DECLARE_EVENT_TABLE() +}; + + +IMPLEMENT_CLASS(MyFrame, wxFrame) + +/* + * Define a new derived SocketClient + */ +class MyClient: public wxSocketClient +{ +public: + MyFrame *frame; + + void OnNotify(wxRequestNotify WXUNUSED(flags)) { frame->UpdateStatus(); } +}; + +// ID for the menu quit command +const SKDEMO_QUIT = 101; +const SKDEMO_CONNECT = 102; +const SKDEMO_TEST1 = 103; +const SKDEMO_TEST2 = 104; +const SKDEMO_CLOSE = 105; +const SKDEMO_TEST3 = 106; +const ID_TEST_CLOSE = 107; + +IMPLEMENT_APP(MyApp) + +/* + * `Main program' equivalent, creating windows and returning main app frame + */ +bool MyApp::OnInit(void) +{ + // Create the main frame window + MyFrame *frame = new MyFrame(); + + // Give it an icon +#ifdef wx_msw + frame->SetIcon(new wxIcon("mondrian")); +#endif +#ifdef wx_x + frame->SetIcon(new wxIcon("mondrian.xbm")); +#endif + + // Make a menubar + wxMenu *file_menu = new wxMenu(); + + file_menu->Append(SKDEMO_QUIT, "Exit"); + wxMenuBar *menu_bar = new wxMenuBar; + menu_bar->Append(file_menu, "File"); + + wxMenu *socket_menu = new wxMenu(); + socket_menu->Append(SKDEMO_CONNECT, "Open session"); + socket_menu->AppendSeparator(); + socket_menu->Append(SKDEMO_TEST1, "Start test 1"); + socket_menu->Append(SKDEMO_TEST2, "Start test 2"); + socket_menu->AppendSeparator(); + socket_menu->Append(SKDEMO_CLOSE, "Close session"); + socket_menu->AppendSeparator(); + socket_menu->Append(SKDEMO_TEST3, "Start URL test"); + + menu_bar->Append(socket_menu, "Socket"); + + frame->SetMenuBar(menu_bar); + + // Make a panel with a message + (void)new wxPanel(frame, 0, 0, 300, 100); + + // Show the frame + frame->Show(TRUE); + + // Return the main frame window + return true; +} + +/* + * MyFrame Constructor + */ +MyFrame::MyFrame(): + wxFrame(NULL, -1, "wxSocket client demo", + wxDefaultPosition, wxSize(300, 200), wxDEFAULT_FRAME_STYLE) +{ + // Init all + wxSocketHandler::Master(); + + sock = new MyClient(); + sock->SetFlags(wxSocketBase::WAITALL); + wxSocketHandler::Master().Register(sock); + sock->frame = this; + sock->SetNotify(wxSocketBase::REQ_LOST); + CreateStatusBar(2); + UpdateStatus(); +} + +MyFrame::~MyFrame() +{ + delete sock; +} + +void MyFrame::OnQuitApp(wxCommandEvent& WXUNUSED(evt)) +{ + Close(TRUE); +} + +void MyFrame::OnExecOpenConnection(wxCommandEvent& WXUNUSED(evt)) +{ + wxIPV4address addr; + + if (sock->IsConnected()) + sock->Close(); + + wxString hname = wxGetTextFromUser("Enter the address of the wxSocket Sample Server", + "Connect ...", "localhost"); + addr.Hostname(hname); + addr.Service(3000); + sock->SetNotify(0); + sock->Connect(addr, TRUE); + if (!sock->IsConnected()) + wxMessageBox("Can't connect to the specified host", "Alert !"); + + UpdateStatus(); +} + +void MyFrame::OnExecCloseConnection(wxCommandEvent& WXUNUSED(evt)) +{ + if (sock) + sock->Close(); + UpdateStatus(); +} + +BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_BUTTON(ID_TEST_CLOSE, MyFrame::OnCloseTest) + EVT_MENU(SKDEMO_TEST1, MyFrame::OnExecTest1) + EVT_MENU(SKDEMO_TEST3, MyFrame::OnExecUrlTest) + EVT_MENU(SKDEMO_QUIT, MyFrame::OnQuitApp) + EVT_MENU(SKDEMO_CONNECT, MyFrame::OnExecOpenConnection) + EVT_MENU(SKDEMO_CLOSE, MyFrame::OnExecCloseConnection) +END_EVENT_TABLE() + +void MyFrame::OnCloseTest(wxCommandEvent& evt) +{ + wxButton *button = (wxButton *)evt.GetEventObject(); + wxDialog *dlg = (wxDialog *)button->GetParent(); + + dlg->EndModal(0); +} + +void MyFrame::UpdateStatus() +{ + if (!sock->IsConnected()) { + SetStatusText("Not connected", 0); + SetStatusText("", 1); + } else { + wxIPV4address addr; + char s[100]; + + sock->GetPeer(addr); + sprintf(s, "Connected to %s", (const char *)addr.Hostname()); + SetStatusText(s, 0); + sprintf(s, "Service: %d", addr.Service()); + SetStatusText(s, 1); + } +} + +void MyFrame::OnExecTest1(wxCommandEvent& WXUNUSED(evt)) +{ + if (!sock->IsConnected()) + return; + + wxDialog *dlgbox = new wxDialog(this, -1, "Test 1", wxDefaultPosition, wxSize(410, 270)); + wxTextCtrl *text_win = new wxTextCtrl(dlgbox, -1, "", + wxPoint(0, 0), wxSize(400, 200), + wxTE_MULTILINE); + (void)new wxButton(dlgbox, ID_TEST_CLOSE, "Close", + wxPoint(100, 210), wxSize(100, 40)); + char *buf, *buf2; + + dlgbox->Layout(); + dlgbox->Show(TRUE); + + text_win->WriteText("Initializing test 1 ...\n"); + + /* Init */ + buf = copystring("Salut ! Salut ! Salut ! Salut Toto\n"); + buf2 = new char[strlen(buf)+1]; + char c = 0xbe; + sock->WriteMsg(&c, 1); + + /* No 1 */ + text_win->WriteText("Sending some byte to the server ..."); + sock->Write(buf, strlen(buf)+1); + text_win->WriteText("done\n"); + text_win->WriteText("Receiving some byte from the server ..."); + sock->Read(buf2, strlen(buf)+1); + text_win->WriteText("done\n"); + + text_win->WriteText("Comparing the two buffers ..."); + if (memcmp(buf, buf2, strlen(buf)+1) != 0) { + text_win->WriteText("Fail\n"); + sock->Close(); + UpdateStatus(); + } else + text_win->WriteText("done\nTest 1 passed !\n"); + + dlgbox->Layout(); + dlgbox->ShowModal(); + + delete [] buf; + delete [] buf2; + delete text_win; + delete dlgbox; +} + +void MyFrame::OnExecUrlTest(wxCommandEvent& WXUNUSED(evt)) +{ + wxString urlname = wxGetTextFromUser("Enter the address of the wxSocket Sample Server", + "Connect ...", "localhost"); + + wxURL url(urlname); + wxInputStream *datas = url.GetInputStream(); + + if (!datas) + wxMessageBox("Error in getting data from the URL.", "Alert !"); + else { + wxMessageBox("Success !!", "OK !"); + delete datas; + } +} diff --git a/samples/wxsocket/client.def b/samples/wxsocket/client.def new file mode 100644 index 0000000000..786b7d609a --- /dev/null +++ b/samples/wxsocket/client.def @@ -0,0 +1,8 @@ +NAME Client +DESCRIPTION 'Client' +EXETYPE WINDOWS +STUB 'WINSTUB.EXE' +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE +HEAPSIZE 1024 +STACKSIZE 8192 diff --git a/samples/wxsocket/client.rc b/samples/wxsocket/client.rc new file mode 100644 index 0000000000..fbba8add6c --- /dev/null +++ b/samples/wxsocket/client.rc @@ -0,0 +1,3 @@ +mondrian ICON mondrian.ico +conn_icn ICON connect.ico +#include "wx.rc" diff --git a/samples/wxsocket/connect.ico b/samples/wxsocket/connect.ico new file mode 100644 index 0000000000000000000000000000000000000000..74f006f82a3440425c3074f976c52a3405cf9427 GIT binary patch literal 766 zcmc&wF%E+;3^Y}xveBtCW1rC{v32#>FCZcD6&`@pZ*(fGND=AT7eK8#b*Y0LU(Rvx ziDX!1c@(q9PUM9B3@_mqcqV&95e4_%6eJi`ZiqV zYUUL2&Fruiuzthi2hWC8s-GhHrQg(!iVivHsjll$hau)g==(kr&&_?ot<{I&>Gj}S z^jq&6j;X)(Bj)?|>j_)x_8aEBTmMZT_RH7#iCJ&@5O4aV_r0Jh!W%C@;9U + +# Change WXDIR or WXWIN to wherever wxWindows is found +#WXWIN = $(WX) +WXDIR = $(WXWIN) +WXINC = $(WXDIR)\include\msw + +WXSOCKDIR = $(WXDIR)\contrib\wxsock +WXSOCKINC = $(WXSOCKDIR) +WXSOCKLIB = $(WXSOCKDIR)\lib\wxsock.lib $(WXSOCKDIR)\lib\zlib.lib +INC=-I$(WXBASEINC) -I$(WXINC) -I$(WXSOCKINC) + +WXLIB = $(WXDIR)\lib\wx.lib + +LIBS=$(WXSOCKLIB) wsock32.lib $(LIBS) +#LIBS=$(WXLIB) $(WXSTRINGLIB) oldnames libw llibcew llibce commdlg shell + +all: client.exe server.exe + +wx: + cd $(WXDIR)\src\msw + nmake -f makefile.nt + cd $(ITSYDIR) + +client.exe: $(WXDIR)\src\msw\dummy.obj $(WXLIB) $(WXSTRINGLIB) client.obj\ + client.res + $(link) -out:client.exe $(LINKFLAGS) $(DUMMYOBJ) client.obj \ + client.res $(LIBS) + +server.exe: $(WXDIR)\src\msw\dummy.obj $(WXLIB) $(WXSTRINGLIB) server.obj + $(link) -out:server.exe $(LINKFLAGS) $(DUMMYOBJ) server.obj $(LIBS) + +client.obj: client.$(SRCSUFF) + $(cc) $(CPPFLAGS2) /c /Tp $*.$(SRCSUFF) + +client.res: client.rc $(WXDIR)\include\msw\wx.rc + $(rc) -r /i$(WXDIR)\include\msw /i$(WXDIR)\contrib\fafa -fo$@ client.rc + + +server.obj: server.$(SRCSUFF) + $(cc) $(CPPFLAGS2) /c /Tp $*.$(SRCSUFF) + +clean: + -erase *.obj + -erase *.exe + -erase *.lib + -erase *.res + -erase *.sbr + -erase *.pdb diff --git a/samples/wxsocket/mondrian.ico b/samples/wxsocket/mondrian.ico new file mode 100644 index 0000000000000000000000000000000000000000..2310c5d275a87af295d5ea8dc79ea417a5e74c53 GIT binary patch literal 766 zcmZQzU<5)11px*Sc)`TLAO@s0fLH;D9e|jTfdxnc0ZSetIcon(new wxIcon("mondrian")); +#endif +#ifdef wx_x + frame->SetIcon(new wxIcon("aiai.xbm")); +#endif + + // Make a menubar + wxMenu *file_menu = new wxMenu; + + file_menu->Append(SKDEMO_QUIT, "E&xit"); + wxMenuBar *menu_bar = new wxMenuBar; + menu_bar->Append(file_menu, "File"); + frame->SetMenuBar(menu_bar); + + // Make a panel with a message + (void)new wxPanel(frame, 0, 0, 300, 100); + + // Show the frame + frame->Show(TRUE); + + // Return the main frame window + return TRUE; +} + +void MySock::OldOnNotify(wxRequestEvent flags) +{ + extern wxList wxPendingDelete; + + switch (flags) { + case EVT_READ: + unsigned char c; + + ReadMsg((char *)&c, 1); + if (c == 0xbe) + frame->ExecTest1(this); + + break; + case EVT_LOST: + frame->UpdateStatus(-1); + wxPendingDelete.Append(this); + break; + } +} + +void MyServer::OldOnNotify(wxRequestEvent WXUNUSED(flags)) +{ + MySock *sock2 = new MySock(); + + if (!AcceptWith(*sock2)) + return; + + m_handler->Register(sock2); + + sock2->SetFlags(NONE); + sock2->frame = frame; + sock2->SetNotify(REQ_READ | REQ_LOST); + sock2->Notify(TRUE); + frame->UpdateStatus(1); +} + +// My frame Constructor +MyFrame::MyFrame(wxFrame *frame): + wxFrame(frame, -1, "wxSocket sample (server)", wxDefaultPosition, + wxSize(300, 200)) +{ + wxIPV4address addr; + addr.Service(3000); + + // Init all + wxSocketHandler::Master(); + + sock = new MyServer(addr); + wxSocketHandler::Master().Register(sock); + sock->frame = this; + sock->SetNotify(wxSocketBase::REQ_ACCEPT); + sock->Notify(TRUE); + nb_clients = 0; + + CreateStatusBar(1); + UpdateStatus(0); +} + +MyFrame::~MyFrame() +{ + delete sock; +} + +// Intercept menu commands +void MyFrame::Menu_Exit(wxCommandEvent& event) +{ + Close(TRUE); +} + +void MyFrame::ExecTest1(wxSocketBase *sock_o) +{ + char *buf = new char[50]; + size_t l; + + l = sock_o->Read(buf, 50).LastCount(); + sock_o->Write(buf, l); +} + +void MyFrame::UpdateStatus(int incr) +{ + char s[30]; + nb_clients += incr; + sprintf(s, "%d clients connected", nb_clients); + SetStatusText(s); +} diff --git a/samples/wxsocket/server.def b/samples/wxsocket/server.def new file mode 100644 index 0000000000..21027a5c01 --- /dev/null +++ b/samples/wxsocket/server.def @@ -0,0 +1,8 @@ +NAME Server +DESCRIPTION 'Server' +EXETYPE WINDOWS +STUB 'WINSTUB.EXE' +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE +HEAPSIZE 4096 +STACKSIZE 8192 diff --git a/samples/wxsocket/server.rc b/samples/wxsocket/server.rc new file mode 100644 index 0000000000..44854d6660 --- /dev/null +++ b/samples/wxsocket/server.rc @@ -0,0 +1,4 @@ +mondrian ICON "mondrian.ico" +conn_icn ICON "connect.ico" +#include "wx.rc" + diff --git a/src/common/datstrm.cpp b/src/common/datstrm.cpp index 93850acd65..8056bdaded 100644 --- a/src/common/datstrm.cpp +++ b/src/common/datstrm.cpp @@ -26,6 +26,10 @@ #include "wx/datstrm.h" +// --------------------------------------------------------------------------- +// wxDataInputStream +// --------------------------------------------------------------------------- + wxDataInputStream::wxDataInputStream(wxInputStream& s) : wxFilterInputStream(s) { @@ -126,6 +130,10 @@ wxString wxDataInputStream::ReadString() return wx_string; } +// --------------------------------------------------------------------------- +// wxDataOutputStream +// --------------------------------------------------------------------------- + wxDataOutputStream::wxDataOutputStream(wxOutputStream& s) : wxFilterOutputStream(s) { @@ -192,3 +200,12 @@ void wxDataOutputStream::WriteDouble(double d) #endif Write(buf, 10); } + +// --------------------------------------------------------------------------- +// wxDataStream +// --------------------------------------------------------------------------- + +wxDataStream::wxDataStream(wxStream& stream) + : wxDataInputStream(stream), wxDataOutputStream(stream) +{ +} diff --git a/src/common/ftp.cpp b/src/common/ftp.cpp new file mode 100644 index 0000000000..461dd93417 --- /dev/null +++ b/src/common/ftp.cpp @@ -0,0 +1,378 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: ftp.cpp +// Purpose: FTP protocol +// Author: Guilhem Lavaux +// Modified by: +// Created: 07/07/1997 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "ftp.h" +#endif +#include +#include +#include "wx/string.h" +#include "wx/utils.h" +// #include "wx/data.h" +#define WXSOCK_INTERNAL +#include "wx/sckaddr.h" +#undef WXSOCK_INTERNAL +#include "wx/socket.h" +#include "wx/url.h" +#include "wx/sckstrm.h" +#include "wx/protocol/protocol.h" +#include "wx/protocol/ftp.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#define FTP_BSIZE 1024 + +#if !USE_SHARED_LIBRARY +IMPLEMENT_DYNAMIC_CLASS(wxFTP, wxProtocol) +IMPLEMENT_PROTOCOL(wxFTP, "ftp", "ftp", TRUE) +#endif + +//////////////////////////////////////////////////////////////// +////// wxFTP constructor and destructor //////////////////////// +//////////////////////////////////////////////////////////////// + +wxFTP::wxFTP() + : wxProtocol() +{ + char tmp[256]; + + m_lastError = wxPROTO_NOERR; + m_streaming = FALSE; + + m_user = "anonymous"; + wxGetUserName(tmp, 256); + m_passwd.sprintf("%s@",tmp); + wxGetHostName(tmp, 256); + m_passwd += tmp; + + SetNotify(0); +} + +wxFTP::~wxFTP() +{ + SendCommand("QUIT", '2'); +} + +//////////////////////////////////////////////////////////////// +////// wxFTP connect and login methods ///////////////////////// +//////////////////////////////////////////////////////////////// +bool wxFTP::Connect(wxSockAddress& addr) +{ + if (!m_handler) { + m_lastError = wxPROTO_NOHNDLR; + return FALSE; + } + + if (!wxProtocol::Connect(addr)) { + m_lastError = wxPROTO_NETERR; + return FALSE; + } + + if (!m_user || !m_passwd) { + m_lastError = wxPROTO_CONNERR; + return FALSE; + } + + wxString command; + + if (!GetResult('2')) { + Close(); + return FALSE; + } + + command.sprintf("USER %s", (const char *)m_user); + if (!SendCommand(command, '3')) { + Close(); + return FALSE; + } + + command.sprintf("PASS %s", (const char *)m_passwd); + if (!SendCommand(command, '2')) { + Close(); + return FALSE; + } + + return TRUE; +} + +bool wxFTP::Connect(const wxString& host) +{ + wxIPV4address addr; + wxString my_host = host; + + addr.Hostname(my_host); + addr.Service("ftp"); + + return Connect(addr); +} + +bool wxFTP::Close() +{ + if (m_streaming) { + m_lastError = wxPROTO_STREAMING; + return FALSE; + } + if (m_connected) + SendCommand(wxString("QUIT"), '2'); + return wxSocketClient::Close(); +} + +//////////////////////////////////////////////////////////////// +////// wxFTP low-level methods ///////////////////////////////// +//////////////////////////////////////////////////////////////// +bool wxFTP::SendCommand(const wxString& command, char exp_ret) +{ + wxString tmp_str; + + if (m_streaming) { + m_lastError = wxPROTO_STREAMING; + return FALSE; + } + tmp_str = command + "\r\n"; + if (Write((char *)tmp_str.GetData(), tmp_str.Length()).Error()) { + m_lastError = wxPROTO_NETERR; + return FALSE; + } + return GetResult(exp_ret); +} + +bool wxFTP::GetResult(char exp) +{ + if ((m_lastError = GetLine(this, m_lastResult))) + return FALSE; + if (m_lastResult[0UL] != exp) { + m_lastError = wxPROTO_PROTERR; + return FALSE; + } + + if (m_lastResult[3UL] == '-') { + wxString key = m_lastResult.Left((size_t)3); + + key += ' '; + + while (m_lastResult.Index(key) != 0) { + if ((m_lastError = GetLine(this, m_lastResult))) + return FALSE; + } + } + return TRUE; +} + +//////////////////////////////////////////////////////////////// +////// wxFTP low-level methods ///////////////////////////////// +//////////////////////////////////////////////////////////////// +bool wxFTP::ChDir(const wxString& dir) +{ + wxString str = dir; + + str.Prepend("CWD "); + return SendCommand(str, '2'); +} + +bool wxFTP::MkDir(const wxString& dir) +{ + wxString str = dir; + str.Prepend("MKD "); + return SendCommand(str, '2'); +} + +bool wxFTP::RmDir(const wxString& dir) +{ + wxString str = dir; + + str.Prepend("PWD "); + return SendCommand(str, '2'); +} + +wxString wxFTP::Pwd() +{ + int beg, end; + + if (!SendCommand("PWD", '2')) + return wxString((char *)NULL); + + beg = m_lastResult.Find('\"',FALSE); + end = m_lastResult.Find('\"',TRUE); + + return wxString(beg+1, end); +} + +bool wxFTP::Rename(const wxString& src, const wxString& dst) +{ + wxString str; + + str = "RNFR " + src; + if (!SendCommand(str, '3')) + return FALSE; + + str = "RNTO " + dst; + return SendCommand(str, '2'); +} + +bool wxFTP::RmFile(const wxString& path) +{ + wxString str; + + str = "DELE "; + str += path; + return SendCommand(str, '2'); +} + +//////////////////////////////////////////////////////////////// +////// wxFTP download*upload /////////////////////////////////// +//////////////////////////////////////////////////////////////// + +class wxInputFTPStream : public wxSocketInputStream { +public: + wxFTP *m_ftp; + + wxInputFTPStream(wxFTP *ftp_clt, wxSocketBase *sock) + : wxSocketInputStream(*sock), m_ftp(ftp_clt) {} + virtual ~wxInputFTPStream(void) + { + if (Eof()) + m_ftp->GetResult('2'); + else + m_ftp->Abort(); + delete m_i_socket; + } +}; + +class wxOutputFTPStream : public wxSocketOutputStream { +public: + wxFTP *m_ftp; + + wxOutputFTPStream(wxFTP *ftp_clt, wxSocketBase *sock) + : wxSocketOutputStream(*sock), m_ftp(ftp_clt) {} + virtual ~wxOutputFTPStream(void) + { + if (Bad()) + m_ftp->GetResult('2'); + else + m_ftp->Abort(); + delete m_o_socket; + } +}; + +wxSocketClient *wxFTP::GetPort() +{ + wxIPV4address addr; + wxSocketClient *client; + struct sockaddr sin; + int a[6]; + wxString straddr; + int addr_pos; + + if (!SendCommand("PASV", '2')) + return NULL; + + sin.sa_family = AF_INET; + addr_pos = m_lastResult.Find('('); + if (addr_pos == -1) { + m_lastError = wxPROTO_PROTERR; + return NULL; + } + straddr = m_lastResult(addr_pos+1, m_lastResult.Length()); + sscanf((const char *)straddr,"%d,%d,%d,%d,%d,%d",&a[2],&a[3],&a[4],&a[5],&a[0],&a[1]); + sin.sa_data[2] = (char)a[2]; + sin.sa_data[3] = (char)a[3]; + sin.sa_data[4] = (char)a[4]; + sin.sa_data[5] = (char)a[5]; + sin.sa_data[0] = (char)a[0]; + sin.sa_data[1] = (char)a[1]; + + addr.Disassemble(&sin, sizeof(sin)); + + client = m_handler->CreateClient(); + if (!client->Connect(addr)) { + delete client; + return NULL; + } + client->Notify(FALSE); + + return client; +} + +bool wxFTP::Abort(void) +{ + m_streaming = FALSE; + if (!SendCommand("ABOR", '4')) + return FALSE; + return GetResult('2'); +} + +wxInputStream *wxFTP::GetInputStream(const wxString& path) +{ + wxString tmp_str; + + if (!SendCommand("TYPE I", '2')) + return NULL; + + wxSocketClient *sock = GetPort(); + + if (!sock) { + m_lastError = wxPROTO_NETERR; + return NULL; + } + + tmp_str = "RETR " + path; + if (!SendCommand(tmp_str, '1')) + return NULL; + + return new wxInputFTPStream(this, sock); +} + +wxOutputStream *wxFTP::GetOutputStream(const wxString& path) +{ + wxString tmp_str; + + if (!SendCommand("TYPE I", '2')) + return NULL; + + wxSocketClient *sock = GetPort(); + + tmp_str = "STOR " + path; + if (!SendCommand(tmp_str, '1')) + return FALSE; + + return new wxOutputFTPStream(this, sock); +} + +wxList *wxFTP::GetList(const wxString& wildcard) +{ + wxList *file_list = new wxList; + wxSocketBase *sock = GetPort(); + wxString tmp_str = "NLST"; + + if (!wildcard.IsNull()) + tmp_str += wildcard; + + if (!SendCommand(tmp_str, '1')) { + delete sock; + delete file_list; + return NULL; + } + + while (GetLine(sock, tmp_str) == wxPROTO_NOERR) { + file_list->Append((wxObject *)(new wxString(tmp_str))); + } + + if (!GetResult('2')) { + delete sock; + file_list->DeleteContents(TRUE); + delete file_list; + return NULL; + } + + return file_list; +} diff --git a/src/common/http.cpp b/src/common/http.cpp new file mode 100644 index 0000000000..4f90e220e9 --- /dev/null +++ b/src/common/http.cpp @@ -0,0 +1,251 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: http.cpp +// Purpose: HTTP protocol +// Author: Guilhem Lavaux +// Modified by: +// Created: August 1997 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "http.h" +#endif + +#include +#include +#include "wx/string.h" +#include "wx/tokenzr.h" +#include "wx/socket.h" +#include "wx/protocol/protocol.h" +#include "wx/protocol/http.h" +#include "wx/sckstrm.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#if !USE_SHARED_LIBRARY +IMPLEMENT_DYNAMIC_CLASS(wxHTTP, wxProtocol) +IMPLEMENT_PROTOCOL(wxHTTP, "http", "80", TRUE) +#endif + +#define HTTP_BSIZE 2048 + +wxHTTP::wxHTTP() + : wxProtocol(), + m_headers(wxKEY_STRING) +{ + m_addr = NULL; + m_read = FALSE; + + SetNotify(REQ_LOST); +} + +wxHTTP::~wxHTTP() +{ + // wxString isn't a wxObject + wxNode *node = m_headers.First(); + wxString *string; + + while (node) { + string = (wxString *)node->Data(); + delete string; + node = node->Next(); + } +} + +wxString wxHTTP::GetContentType() +{ + return GetHeader("Content-Type"); +} + +void wxHTTP::SetHeader(const wxString& header, const wxString& h_data) +{ + if (m_read) { + m_headers.Clear(); + m_read = FALSE; + } + + wxNode *node = m_headers.Find(header); + + if (!node) + m_headers.Append(header, (wxObject *)(new wxString(h_data))); + else { + wxString *str = (wxString *)node->Data(); + (*str) = h_data; + } +} + +wxString wxHTTP::GetHeader(const wxString& header) +{ + wxNode *node = m_headers.Find(header); + if (!node) + return (char *)NULL; + + return *((wxString *)node->Data()); +} + +void wxHTTP::SendHeaders() +{ + wxNode *head = m_headers.First(); + + while (head) { + wxString *str = (wxString *)head->Data(); + char buf[100]; + + sprintf(buf, "%s: %s\n\r", head->key.string, str->GetData()); + Write(buf, strlen(buf)); + + head = head->Next(); + } +} + +bool wxHTTP::ParseHeaders() +{ + wxString line; + + m_headers.Clear(); + m_read = TRUE; + + while (1) { + m_error = GetLine(this, line); + if (m_error != wxPROTO_NOERR) + return FALSE; + + if (line.Length() == 0) + break; + + int pos = line.Find(':'); + if (pos == -1) + return FALSE; + + wxString left_str = line(0, pos); + wxString right_str = line(pos+1, line.Length()); + + right_str = right_str.Strip(wxString::leading); + + wxString *str = new wxString(right_str); + + m_headers.Append(left_str, (wxObject *) str); + } + return TRUE; +} + +bool wxHTTP::Connect(const wxString& host) +{ + wxIPV4address *addr; + + if (m_connected) { + delete m_addr; + m_addr = NULL; + Close(); + } + + m_addr = addr = new wxIPV4address(); + + if (!addr->Hostname(host)) { + delete m_addr; + m_addr = NULL; + m_error = wxPROTO_NETERR; + return FALSE; + } + + if (!addr->Service("http")) + addr->Service(80); + + return TRUE; +} + +bool wxHTTP::Connect(wxSockAddress& addr) +{ + struct sockaddr *raw_addr; + size_t len; + + m_addr = (wxSockAddress *)(addr.GetClassInfo()->CreateObject()); + + addr.Build(raw_addr, len); + m_addr->Disassemble(raw_addr, len); + + return TRUE; +} + +bool wxHTTP::BuildRequest(const wxString& path, wxHTTP_Req req) +{ + char *tmp_buf; + char buf[HTTP_BSIZE]; + + switch (req) { + case wxHTTP_GET: + tmp_buf = "GET"; + break; + default: + return FALSE; + } + + sprintf(buf, "%s %s HTTP/1.0\n\r", tmp_buf, (const char *)path); + Write(buf, strlen(buf)); + SendHeaders(); + sprintf(buf, "\n\r"); + Write(buf, strlen(buf)); + + wxString tmp_str; + + m_error = GetLine(this, tmp_str); + if (m_error != wxPROTO_NOERR) + return FALSE; + + if (!tmp_str.Contains("HTTP/")) { + // TODO: support HTTP v0.9 which can have no header. + SetHeader("Content-Length", "-1"); + SetHeader("Content-Type", "none/none"); + return TRUE; + } + + wxStringTokenizer token(tmp_str,' '); + wxString tmp_str2; + + token.NextToken(); + tmp_str2 = token.NextToken(); + + switch (atoi(tmp_str2)) { + case 200: + break; + default: + m_error = wxPROTO_NOFILE; + return FALSE; + } + + return ParseHeaders(); +} + +class wxHTTPStream : public wxSocketInputStream { +public: + wxHTTP *m_http; + wxHTTPStream(wxHTTP *http) : wxSocketInputStream(*http), m_http(http) {} + virtual ~wxHTTPStream(void) { m_http->Abort(); } +}; + +bool wxHTTP::Abort(void) +{ + return wxSocketClient::Close(); +} + +wxInputStream *wxHTTP::GetInputStream(const wxString& path) +{ + wxHTTPStream *inp_stream = new wxHTTPStream(this); + + if (!m_addr || m_connected) { + m_error = wxPROTO_CONNERR; + return NULL; + } + + if (!wxProtocol::Connect(*m_addr)) + return NULL; + + if (!BuildRequest(path, wxHTTP_GET)) + return NULL; + + return inp_stream; +} diff --git a/src/common/protocol.cpp b/src/common/protocol.cpp new file mode 100644 index 0000000000..21df7e8997 --- /dev/null +++ b/src/common/protocol.cpp @@ -0,0 +1,109 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: protocol.cpp +// Purpose: Implement protocol base class +// Author: Guilhem Lavaux +// Modified by: +// Created: 07/07/1997 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "protocol.h" +#endif + +#ifdef WXPREC +#include +#else +#include +#endif + +#include "wx/protocol/protocol.h" +#include "wx/url.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +///////////////////////////////////////////////////////////////// +// wxProtoInfo +///////////////////////////////////////////////////////////////// + +/* + * -------------------------------------------------------------- + * --------- wxProtoInfo CONSTRUCTOR ---------------------------- + * -------------------------------------------------------------- + */ + +wxProtoInfo::wxProtoInfo(const char *name, const char *serv, + const bool need_host1, wxClassInfo *info) +{ + m_protoname = name; + m_servname = serv; + m_cinfo = info; + m_needhost = need_host1; + next = wxURL::g_protocols; + wxURL::g_protocols = this; +} + +///////////////////////////////////////////////////////////////// +// wxProtocol /////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + +IMPLEMENT_ABSTRACT_CLASS(wxProtocol, wxSocketClient) + +wxProtocol::wxProtocol() + : wxSocketClient() +{ +} + +bool wxProtocol::Reconnect() +{ + wxIPV4address addr; + + if (!GetPeer(addr)) { + Close(); + return FALSE; + } + if (!Close()) + return FALSE; + if (!Connect(addr)) + return FALSE; + return TRUE; +} + +wxProtocolError GetLine(wxSocketBase *sock, wxString& result) { +#define PROTO_BSIZE 2048 + size_t avail, size; + char tmp_buf[PROTO_BSIZE], tmp_str[PROTO_BSIZE]; + char *ret; + bool found; + + avail = sock->Read(tmp_buf, PROTO_BSIZE).LastCount(); + if (sock->LastError() != 0 || avail == 0) + return wxPROTO_NETERR; + + memcpy(tmp_str, tmp_buf, avail); + +// Not implemented on all systems +// ret = (char *)memccpy(tmp_str, tmp_buf, '\n', avail); + found = FALSE; + for (ret=tmp_str;ret < (tmp_str+avail); ret++) + if (*ret == '\n') { + found = TRUE; + break; + } + + if (!found) + return wxPROTO_PROTERR; + *ret = 0; + + result = tmp_str; + result = result.Left(result.Length()-1); + + size = ret-tmp_str+1; + sock->CreatePushbackBefore(&tmp_buf[size], avail-size); + return wxPROTO_NOERR; +#undef PROTO_BSIZE +} diff --git a/src/common/sckaddr.cpp b/src/common/sckaddr.cpp new file mode 100644 index 0000000000..55a9521b6e --- /dev/null +++ b/src/common/sckaddr.cpp @@ -0,0 +1,391 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: sckaddr.cpp +// Purpose: Network address manager +// Author: Guilhem Lavaux +// Modified by: +// Created: 26/04/97 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "sckaddr.h" +#endif + +#include +#include +#include +#include + +#include "wx/defs.h" +#include "wx/object.h" + +#if defined(__WINDOWS__) +#include +#endif // __WINDOWS__ + +#if defined(__UNIX__) + +#ifdef VMS +#include +#include +#else +#include +#include +#include +#endif +#include +#include + +#endif // __UNIX__ + +#include "wx/sckaddr.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#define CHECK_ADDRTYPE(var, type) + +#if !USE_SHARED_LIBRARY +IMPLEMENT_ABSTRACT_CLASS(wxSockAddress, wxObject) +IMPLEMENT_DYNAMIC_CLASS(wxIPV4address, wxSockAddress) +#ifdef ENABLE_IPV6 +IMPLEMENT_DYNAMIC_CLASS(wxIPV6address, wxSockAddress) +#endif +#ifdef __UNIX__ +IMPLEMENT_DYNAMIC_CLASS(wxUNIXaddress, wxSockAddress) +#endif +#endif + +wxIPV4address::wxIPV4address() +{ + m_addr = new sockaddr_in; + Clear(); +} + +wxIPV4address::~wxIPV4address() +{ +} + +int wxIPV4address::SockAddrLen() +{ + return sizeof(*m_addr); +} + +int wxIPV4address::GetFamily() +{ + return AF_INET; +} + +void wxIPV4address::Clear() +{ + memset(m_addr, 0, sizeof(*m_addr)); + m_addr->sin_family = AF_INET; + m_addr->sin_addr.s_addr = INADDR_ANY; +} + +/* +const wxSockAddress& wxIPV4address::operator =(const wxSockAddress& addr) +{ + wxIPV4address *ip_addr = (wxIPV4address *)&addr; + CHECK_ADDRTYPE(addr, wxIPV4address); + m_addr = ip_addr->m_addr; + return *this; +} +*/ + +bool wxIPV4address::Hostname(const wxString& name) +{ + struct hostent *hostent; + struct in_addr *addr; + + if (name.IsNull()) + return FALSE; + + if (!name.IsNumber()) { + if ((hostent = gethostbyname(name.GetData())) == 0) { + return FALSE; + } + } else { + long len_addr = inet_addr(name.GetData()); + if (len_addr == -1) + return FALSE; + m_addr->sin_addr.s_addr = len_addr; + return TRUE; + } + + addr = (struct in_addr *) *(hostent->h_addr_list); + + m_addr->sin_addr.s_addr = addr[0].s_addr; + return TRUE; +} + +bool wxIPV4address::Hostname(unsigned long addr) +{ + m_addr->sin_addr.s_addr = htonl(addr); + return TRUE; +} + +bool wxIPV4address::Service(const wxString& name) +{ + struct servent *servent; + + if (name.IsNull()) + return FALSE; + + if (!name.IsNumber()) { + if ((servent = getservbyname(name, "tcp")) == 0) + return FALSE; + } else { + if ((servent = getservbyport(atoi(name), "tcp")) == 0) { + m_addr->sin_port = htons(atoi(name)); + return TRUE; + } + } + + m_addr->sin_port = servent->s_port; + return TRUE; +} + +bool wxIPV4address::Service(unsigned short port) +{ + m_addr->sin_port = htons(port); + return TRUE; +} + +bool wxIPV4address::LocalHost() +{ + static char buf[256]; + + if (gethostname(buf, sizeof(buf)) < 0) + return Hostname("localhost"); + else + return Hostname(buf); +} + +wxString wxIPV4address::Hostname() +{ + struct hostent *h_ent; + + h_ent = gethostbyaddr((char *)&(m_addr->sin_addr), sizeof(m_addr->sin_addr), + GetFamily()); + return wxString(h_ent->h_name); +} + +unsigned short wxIPV4address::Service() +{ + return ntohs(m_addr->sin_port); +} + +void wxIPV4address::Build(struct sockaddr *&addr, size_t& len) +{ + addr = (struct sockaddr *)m_addr; + len = sizeof(*m_addr); +} + +void wxIPV4address::Disassemble(struct sockaddr *addr, size_t len) +{ + if (len != sizeof(*m_addr)) + return; + *m_addr = *(struct sockaddr_in *)addr; +} + +#ifdef IPV6_ENABLE + +wxIPV6address::wxIPV6address() +{ + m_addr = new sockaddr_in6; + Clear(); +} + +wxIPV6address::~wxIPV6address() +{ +} + +int wxIPV6address::SockAddrLen() +{ + return sizeof(*m_addr); +} + +int wxIPV6address::GetFamily() +{ + return AF_INET6; +} + +void wxIPV6address::Clear() +{ + memset(m_addr, 0, sizeof(*m_addr)); + m_addr->sin6_family = AF_INET6; + m_addr->sin6_addr.s_addr = INADDR_ANY; +} + +/* +const wxSockAddress& wxIPV6address::operator =(const wxSockAddress& addr) +{ + wxIPV6address *ip_addr = (wxIPV6address *)&addr; + + CHECK_ADDRTYPE(addr, wxIPV6address); + m_addr = ip_addr->m_addr; + return *this; +} +*/ + +bool wxIPV6address::Hostname(const wxString& name) +{ + struct hostent *hostent; + struct in_addr *addr; + + if (name.IsNull()) + return FALSE; + + if (!name.IsNumber()) { + hostent = gethostbyname2((char*) name, AF_INET6); + if (!hostent) + return FALSE; + } else { + // Don't how to do + return FALSE; + } + + addr = (struct in6_addr *) *(hostent->h_addr_list); + + m_addr->sin6_addr.s6_addr = addr[0].s6_addr; + return TRUE; +} + +bool wxIPV6address::Hostname(unsigned char addr[16]) +{ + m_addr->sin6_addr.s6_addr = addr; + return TRUE; +} + +bool wxIPV6address::Service(const char *name) +{ + struct servent *servent; + + if (!name || !strlen(name)) + return FALSE; + + if (!isdigit(*name)) { + if ((servent = getservbyname((char*) name, "tcp")) == 0) + return FALSE; + } else { + if ((servent = getservbyport(atoi(name), "tcp")) == 0) { + m_addr->sin_port = htons(atoi(name)); + return TRUE; + } + } + + m_addr->sin_port = servent->s_port; + return TRUE; +} + +bool wxIPV6address::Service(unsigned short port) +{ + m_addr->sin_port = htons(port); + return TRUE; +} + +bool wxIPV6address::LocalHost() +{ + static char buf[256]; + + if (gethostname(buf, sizeof(buf)) < 0) + return Hostname("localhost"); + else + return Hostname(buf); +} + +const wxString& wxIPV6address::Hostname() +{ + struct hostent *h_ent; + + h_ent = gethostbyaddr((char *)&(m_addr->sin_addr), sizeof(m_addr->sin_addr), + GetFamily()); + return wxString(h_ent->h_name); +} + +unsigned short wxIPV6address::Service() +{ + return ntohs(m_addr->sin_port); +} + +void wxIPV6address::Build(struct sockaddr& *addr, size_t& len) +{ + len = sizeof(*m_addr); + addr = m_addr; +} + +void wxIPV6address::Disassemble(struct sockaddr& *addr, size_t len) +{ + if (len != sizeof(*m_addr)) + return; + *m_addr = *(struct sockaddr_in6 *)addr; +} + +#endif + +#ifdef __UNIX__ +#include + +wxUNIXaddress::wxUNIXaddress() +{ + m_addr = new sockaddr_un; + Clear(); +} + +wxUNIXaddress::~wxUNIXaddress() +{ +} + +int wxUNIXaddress::SockAddrLen() +{ + return sizeof(*m_addr); +} + +int wxUNIXaddress::GetFamily() +{ + return AF_UNIX; +} + +void wxUNIXaddress::Clear() +{ + memset(m_addr, 0, sizeof(m_addr)); + m_addr->sun_family = AF_UNIX; +} + +/* +const wxSockAddress& wxUNIXaddress::operator =(const wxSockAddress& addr) +{ + wxUNIXaddress *unx_addr = (wxUNIXaddress *)&addr; + CHECK_ADDRTYPE(addr, wxUNIXaddress); + m_addr = unx_addr->m_addr; + return *this; +} +*/ + +void wxUNIXaddress::Filename(const wxString& fname) +{ + sprintf(m_addr->sun_path, "%s", WXSTRINGCAST fname); +} + +wxString wxUNIXaddress::Filename() +{ + return wxString(m_addr->sun_path); +} + +void wxUNIXaddress::Build(struct sockaddr*& addr, size_t& len) +{ + addr = (struct sockaddr *)m_addr; + len = sizeof(*m_addr); +} + +void wxUNIXaddress::Disassemble(struct sockaddr *addr, size_t len) +{ + if (len != sizeof(*m_addr)) + return; + *m_addr = *(struct sockaddr_un *)addr; +} +#endif diff --git a/src/common/sckfile.cpp b/src/common/sckfile.cpp new file mode 100644 index 0000000000..b1e60ae4eb --- /dev/null +++ b/src/common/sckfile.cpp @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: sckfile.cpp +// Purpose: File protocol +// Author: Guilhem Lavaux +// Modified by: +// Created: 20/07/97 +// RCS-ID: $Id$ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// +#ifdef __GNUG__ +#pragma implementation "sckfile.h" +#endif +#include +#include +#include +#include "wx/protocol/file.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#if !USE_SHARED_LIBRARY +IMPLEMENT_DYNAMIC_CLASS(wxFileProto, wxProtocol) +IMPLEMENT_PROTOCOL(wxFileProto, "file", NULL, FALSE) +#endif + +wxFileProto::wxFileProto() + : wxProtocol() +{ +} + +wxFileProto::~wxFileProto() +{ +} + +wxInputStream *wxFileProto::GetInputStream(const wxString& path) +{ + return new wxFileInputStream(path); +} diff --git a/src/common/sckipc.cpp b/src/common/sckipc.cpp new file mode 100644 index 0000000000..55fcb3104b --- /dev/null +++ b/src/common/sckipc.cpp @@ -0,0 +1,503 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: sckipc.cpp +// Purpose: Interprocess communication implementation (wxSocket version) +// Author: Julian Smart, Guilhem Lavaux +// Modified by: Guilhem Lavaux (big rewrite) May 1997, 1998 +// Created: 1993 +// RCS-ID: $Id$ +// Copyright: (c) Julian Smart 1993, Guilhem Lavaux 1997, 1998 +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "sckipc.h" +#endif + +#include +#include + +#ifdef WXPREC +#include +#else +#include +#endif + +#include "wx/socket.h" +#include "wx/sckipc.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#if !USE_SHARED_LIBRARY +IMPLEMENT_DYNAMIC_CLASS(wxTCPServer, wxServerBase) +IMPLEMENT_DYNAMIC_CLASS(wxTCPClient, wxClientBase) +IMPLEMENT_DYNAMIC_CLASS(wxTCPConnection, wxConnectionBase) +#endif + +// It seems to be already defined somewhere in the Xt includes. +#ifndef __XT__ +// Message codes +enum { + IPC_EXECUTE = 1, + IPC_REQUEST, + IPC_POKE, + IPC_ADVISE_START, + IPC_ADVISE_REQUEST, + IPC_ADVISE, + IPC_ADVISE_STOP, + IPC_REQUEST_REPLY, + IPC_FAIL, + IPC_CONNECT, + IPC_DISCONNECT +}; +#endif + +void Server_OnRequest(wxSocketServer& server, + wxSocketBase::wxRequestEvent evt, + char *cdata); +void Client_OnRequest(wxSocketBase& sock, + wxSocketBase::wxRequestEvent evt, + char *cdata); + +// --------------------------------------------------------------------------- +// wxTCPClient +// --------------------------------------------------------------------------- + +wxTCPClient::wxTCPClient (void) + : wxClientBase() +{ +} + +wxTCPClient::~wxTCPClient (void) +{ +} + +bool wxTCPClient::ValidHost(const wxString& host) +{ + wxIPV4address addr; + + return addr.Hostname(host); +} + +wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host, + const wxString& server_name, + const wxString& topic) +{ + wxIPV4address addr; + wxSocketHandler *hsock = &wxSocketHandler::Master(); + wxSocketClient *client = hsock->CreateClient(); + wxSocketStream *stream = new wxSocketStream(*client); + wxDataStream data_s(*stream); + + client->SetNotify(wxSocketBase::REQ_READ | wxSocketBase::REQ_LOST); + addr.Service(server_name); + addr.Hostname(host); + + if (!client->Connect(addr)) { + delete client; + return NULL; + } + client->Notify(FALSE); + + // Send topic name, and enquire whether this has succeeded + unsigned char msg; + + data_s.Write8(IPC_CONNECT); + data_s.WriteString(topic); + + msg = data_s.Read8(); + + // OK! Confirmation. + if (msg == IPC_CONNECT) { + wxTCPConnection *connection = (wxTCPConnection *)OnMakeConnection (); + if (connection) { + if (!connection->IsKindOf(CLASSINFO(wxTCPConnection))) { + delete connection; + return NULL; + } + connection->m_topic = topic; + client->Callback(Client_OnRequest); + client->CallbackData((char *)connection); + client->Notify(TRUE); + return connection; + } else { + delete client; + return NULL; + } + } else { + delete client; + return NULL; + } + return NULL; +} + +wxConnectionBase *wxTCPClient::OnMakeConnection() +{ + return new wxTCPConnection; +} + +// --------------------------------------------------------------------------- +// wxTCPServer +// --------------------------------------------------------------------------- + +wxTCPServer::wxTCPServer (void) + : wxServerBase() +{ +} + +bool wxTCPServer::Create(const wxString& server_name) +{ + wxIPV4address addr; + wxSocketHandler *hsock = &wxSocketHandler::Master(); + wxSocketServer *server; + + addr.Service(server_name); + + // Create a socket listening on specified port + server = hsock->CreateServer(addr); + server->Callback((wxSocketBase::wxSockCbk)Server_OnRequest); + server->SetNotify(wxSocketBase::REQ_ACCEPT); + + server->CallbackData((char *)this); + + return TRUE; +} + +wxTCPServer::~wxTCPServer (void) +{ +} + +wxConnectionBase *wxTCPServer::OnAcceptConnection(const wxString& topic) +{ + return new wxTCPConnection(); +} + +// --------------------------------------------------------------------------- +// wxTCPConnection +// --------------------------------------------------------------------------- + +wxTCPConnection::wxTCPConnection (void) + : wxConnectionBase(), + m_sock(NULL), m_sockstrm(NULL), m_codec(NULL) +{ +} + +wxTCPConnection::~wxTCPConnection (void) +{ + wxDELETE(m_sock); + wxDELETE(m_codec); + wxDELETE(m_sockstrm); +} + +void wxTCPConnection::Compress(bool on) +{ + // Use wxLZWStream +} + +// Calls that CLIENT can make. +bool wxTCPConnection::Disconnect (void) +{ + // Send the the disconnect message to the peer. + m_codec->Write8(IPC_DISCONNECT); + m_sock->Close(); + + return TRUE; +} + +bool wxTCPConnection::Execute (char *data, int size, wxDataFormat format) +{ + if (!m_sock->IsConnected()) + return FALSE; + + // Prepare EXECUTE message + m_codec->Write8(IPC_EXECUTE); + m_codec->Write8(format); + if (size < 0) + m_codec->WriteString(data); + else { + m_codec->Write32(size); + m_codec->Write(data, size); + } + + return TRUE; +} + +char *wxTCPConnection::Request (const wxString& item, int *size, wxDataFormat format) +{ + if (!m_sock->IsConnected()) + return NULL; + + m_codec->Write8(IPC_REQUEST); + m_codec->WriteString(item); + m_codec->Write8(format); + + // If Unpack doesn't initialize it. + int ret; + + ret = m_codec->Read8(); + if (ret == IPC_FAIL) + return NULL; + else { + size_t s; + char *data = NULL; + + s = m_codec->Read32(); + data = new char[s]; + m_codec->Read(data, s); + + if (size) + *size = s; + return data; + } +} + +bool wxTCPConnection::Poke (const wxString& item, char *data, int size, wxDataFormat format) +{ + if (!m_sock->IsConnected()) + return FALSE; + + m_codec->Write8(IPC_POKE); + m_codec->WriteString(item); + m_codec->Write8(format); + if (size < 0) + m_codec->WriteString(data); + else { + m_codec->Write32(size); + m_codec->Write(data, size); + } + + return TRUE; +} + +bool wxTCPConnection::StartAdvise (const wxString& item) +{ + int ret; + + if (!m_sock->IsConnected()) + return FALSE; + + m_codec->Write8(IPC_ADVISE_START); + m_codec->WriteString(item); + + ret = m_codec->Read8(); + + if (ret != IPC_FAIL) + return TRUE; + else + return FALSE; +} + +bool wxTCPConnection::StopAdvise (const wxString& item) +{ + int msg; + + if (!m_sock->IsConnected()) + return FALSE; + + m_codec->Write8(IPC_ADVISE_STOP); + m_codec->WriteString(item); + + msg = m_codec->Read8(); + + if (msg != IPC_FAIL) + return TRUE; + else + return FALSE; +} + +// Calls that SERVER can make +bool wxTCPConnection::Advise (const wxString& item, + char *data, int size, wxDataFormat format) +{ + if (!m_sock->IsConnected()) + return FALSE; + + m_codec->Write8(IPC_ADVISE); + m_codec->WriteString(item); + m_codec->Write8(format); + if (size < 0) + m_codec->WriteString(data); + else { + m_codec->Write32(size); + m_codec->Write(data, size); + } + + return TRUE; +} + +void Client_OnRequest(wxSocketBase& sock, wxSocketBase::wxRequestEvent evt, + char *cdata) +{ + int msg = 0; + wxTCPConnection *connection = (wxTCPConnection *)cdata; + wxDataStream *codec; + wxString topic_name = connection->m_topic; + wxString item; + + // The socket handler signals us that we lost the connection: destroy all. + if (evt == wxSocketBase::EVT_LOST) { + sock.Close(); + connection->OnDisconnect(); + return; + } + + // Receive message number. + codec = connection->m_codec; + msg = codec->Read8(); + + switch (msg) { + case IPC_EXECUTE: { + char *data; + size_t size; + wxDataFormat format; + + format = (wxDataFormat)codec->Read8(); + size = codec->Read32(); + data = new char[size]; + codec->Read(data, size); + + connection->OnExecute (topic_name, data, size, format); + + delete [] data; + break; + } + case IPC_ADVISE: { + char *data; + size_t size; + wxDataFormat format; + + item = codec->ReadString(); + format = (wxDataFormat)codec->Read8(); + size = codec->Read32(); + data = new char[size]; + codec->Read(data, size); + + connection->OnAdvise (topic_name, item, data, size, format); + + delete [] data; + break; + } + case IPC_ADVISE_START: { + item = codec->ReadString(); + + bool ok = connection->OnStartAdvise (topic_name, item); + if (ok) + codec->Write8(IPC_ADVISE_START); + else + codec->Write8(IPC_FAIL); + + break; + } + case IPC_ADVISE_STOP: { + item = codec->ReadString(); + + bool ok = connection->OnStopAdvise (topic_name, item); + if (ok) + codec->Write8(IPC_ADVISE_STOP); + else + codec->Write8(IPC_FAIL); + + break; + } + case IPC_POKE: { + wxDataFormat format; + size_t size; + char *data; + + item = codec->ReadString(); + format = (wxDataFormat)codec->Read8(); + size = codec->Read32(); + data = new char[size]; + codec->Read(data, size); + + connection->OnPoke (topic_name, item, data, size, format); + + delete [] data; + + break; + } + case IPC_REQUEST: { + wxDataFormat format; + + item = codec->ReadString(); + format = (wxDataFormat)codec->Read8(); + + int user_size = -1; + char *user_data = connection->OnRequest (topic_name, item, &user_size, format); + + if (user_data) { + codec->Write8(IPC_REQUEST_REPLY); + if (user_size != -1) { + codec->Write32(user_size); + codec->Write(user_data, user_size); + } else + codec->WriteString(user_data); + } else + codec->Write8(IPC_FAIL); + + break; + } + case IPC_DISCONNECT: { + sock.Close(); + connection->OnDisconnect(); + break; + } + default: + codec->Write8(IPC_FAIL); + break; + } +} + +void Server_OnRequest(wxSocketServer& server, + wxSocketBase::wxRequestEvent evt, char *cdata) +{ + wxTCPServer *ipcserv = (wxTCPServer *)cdata; + wxSocketStream *stream; + wxDataStream *codec; + + if (evt != wxSocketBase::EVT_ACCEPT) + return; + + /* Accept the connection, getting a new socket */ + wxSocketBase *sock = server.Accept(); + sock->Notify(FALSE); + sock->SetNotify(wxSocketBase::REQ_READ | wxSocketBase::REQ_LOST); + + stream = new wxSocketStream(*sock); + codec = new wxDataStream(*stream); + + if (!sock->Ok()) + return; + + int msg; + msg = codec->Read8(); + + if (msg == IPC_CONNECT) { + wxString topic_name; + topic_name = codec->ReadString(); + + /* Register new socket with the notifier */ + wxTCPConnection *new_connection = + (wxTCPConnection *)ipcserv->OnAcceptConnection (topic_name); + if (new_connection) { + if (!new_connection->IsKindOf(CLASSINFO(wxTCPConnection))) { + delete new_connection; + codec->Write8(IPC_FAIL); + return; + } + // Acknowledge success + codec->Write8(IPC_CONNECT); + + new_connection->m_topic = topic_name; + new_connection->m_sockstrm = stream; + new_connection->m_codec = codec; + sock->Callback(Client_OnRequest); + sock->CallbackData((char *)new_connection); + sock->Notify(TRUE); + } else { + // Send failure message + codec->Write8(IPC_FAIL); + } + } +} diff --git a/src/common/sckstrm.cpp b/src/common/sckstrm.cpp new file mode 100644 index 0000000000..c0846c46aa --- /dev/null +++ b/src/common/sckstrm.cpp @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: sckstrm.h +// Purpose: wxSocket*Stream +// Author: Guilhem Lavaux +// Modified by: +// Created: 17/07/97 +// RCS-ID: $Id$ +// Copyright: (c) +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// +#ifdef __GNUG__ +#pragma implementation "sckstrm.h" +#endif + +#include "wx/stream.h" +#include "wx/socket.h" +#include "wx/sckstrm.h" + +// --------------------------------------------------------------------------- +// wxSocketOutputStream +// --------------------------------------------------------------------------- + +wxSocketOutputStream::wxSocketOutputStream(wxSocketBase& s) + : m_o_socket(&s) +{ +} + +wxSocketOutputStream::~wxSocketOutputStream() +{ +} + +wxOutputStream& wxSocketOutputStream::Write(const void *buffer, size_t size) +{ + m_o_socket->Write((const char *)buffer, size); + return *this; +} + +// --------------------------------------------------------------------------- +// wxSocketInputStream +// --------------------------------------------------------------------------- + +wxSocketInputStream::wxSocketInputStream(wxSocketBase& s) + : m_i_socket(&s) +{ +} + +wxSocketInputStream::~wxSocketInputStream() +{ +} + +wxInputStream& wxSocketInputStream::Read(void *buffer, size_t size) +{ + m_i_socket->Read((char *)buffer, size); + return *this; +} + +// --------------------------------------------------------------------------- +// wxSocketStream (IO) +// --------------------------------------------------------------------------- +wxSocketStream::wxSocketStream(wxSocketBase& i_s, wxSocketBase& o_s) + : wxSocketInputStream(i_s), wxSocketOutputStream(o_s) +{ +} + +wxSocketStream::wxSocketStream(wxSocketBase& s) + : wxSocketInputStream(s), wxSocketOutputStream(s) +{ +} diff --git a/src/common/socket.cpp b/src/common/socket.cpp new file mode 100644 index 0000000000..f880c2d6e5 --- /dev/null +++ b/src/common/socket.cpp @@ -0,0 +1,1532 @@ +//////////////////////////////////////////////////////////////////////////////// +// Name: socket.cpp +// Purpose: Socket handler classes +// Authors: Guilhem Lavaux (completely rewritten from a basic API of Andrew +// Davidson(1995) in wxWeb) +// Created: April 1997 +// Updated: March 1998 +// Copyright: (C) 1998, 1997, Guilhem Lavaux +// RCS_ID: $Id$ +// License: see wxWindows license +//////////////////////////////////////////////////////////////////////////////// +#ifdef __GNUG__ +#pragma implementation "socket.h" +#pragma interface +#pragma implementation "socket.cpp" +#endif + +///////////////////////////////////////////////////////////////////////////// +// wxWindows headers +///////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + +#include +#include +#include + +///////////////////////////////////////////////////////////////////////////// +// System specific headers +///////////////////////////////////////////////////////////////////////////// +#if defined(__WINDOWS__) +#include +#endif // __WINDOWS__ + +#if defined(__UNIX__) + +#ifdef VMS +#include +#else +#include +#endif +#include + +#include +#include + +#endif // __UNIX__ + +#include +#include + +#if defined(__WXMOTIF__) || defined(__WXXT__) +#include + +///////////////////////////// +// Needs internal variables +///////////////////////////// +#ifdef __WXXT__ +#define Uses_XtIntrinsic +#endif + +#endif + +#if defined(__WXGTK__) +#include +#endif + +///////////////////////////////////////////////////////////////////////////// +// wxSocket headers +///////////////////////////////////////////////////////////////////////////// +#define WXSOCK_INTERNAL +#include "wx/sckaddr.h" +#include "wx/socket.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +///////////////////////////////////////////////////////////////////////////// +// Some patch ///// BEGIN +///////////////////////////////////////////////////////////////////////////// +#ifdef __WINDOWS__ +#define close closesocket +#define ioctl ioctlsocket +#define errno WSAGetLastError() +#ifdef EWOULDBLOCK +#undef EWOULDBLOCK +#endif +#define EWOULDBLOCK WSAEWOULDBLOCK +#define ETIMEDOUT WSAETIMEDOUT +#undef EINTR +#define EINTR WSAEINTR +#endif + +#ifndef __WINDOWS__ +#define INVALID_SOCKET -1 +#endif + +#ifdef __WXMOTIF__ +#define wxAPP_CONTEXT wxTheApp->appContext +#endif + +#ifdef __WINDOWS__ +// This is an MS TCP/IP routine and is not needed here. Some WinSock +// implementations (such as PC-NFS) will require you to include this +// or a similar routine (see appendix in WinSock doc or help file). + +#if defined( NEED_WSAFDIsSet ) || defined( _MSC_VER ) +int PASCAL FAR __WSAFDIsSet(SOCKET fd, fd_set FAR *set) +{ + int i = set->fd_count; + + while (i--) + { + if (set->fd_array[i] == fd) + return 1; + } + + return 0; +} +#endif +#endif + +#if defined(__WINDOWS__) +#define PROCESS_EVENTS() wxYield() +#elif defined(__WXXT__) || defined(__WXMOTIF__) +#define PROCESS_EVENTS() XtAppProcessEvent(wxAPP_CONTEXT, XtIMAll) +#elif defined(__WXGTK__) +#define PROCESS_EVENTS() gtk_main_iteration() +#endif + +///////////////////////////////////////////////////////////////////////////// +// Some patch ///// END +///////////////////////////////////////////////////////////////////////////// + +// -------------------------------------------------------------- +// ClassInfos +// -------------------------------------------------------------- +#if !USE_SHARED_LIBRARY +IMPLEMENT_CLASS(wxSocketBase, wxObject) +IMPLEMENT_CLASS(wxSocketServer, wxSocketBase) +IMPLEMENT_CLASS(wxSocketClient, wxSocketBase) +IMPLEMENT_CLASS(wxSocketHandler, wxObject) +IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent) +#endif + +class wxSockWakeUp : public wxTimer { +public: + int *my_id; + int n_val; + wxSocketBase *sock; + + wxSockWakeUp(wxSocketBase *_sock, int *id, int new_val) { + my_id = id; n_val = new_val; + sock = _sock; + } + virtual void Notify() { + *my_id = n_val; + if (sock) sock->Notify(FALSE); + } +}; + +/// Socket request +class SockRequest : public wxObject { +public: + char *buffer; + size_t size, nbytes; + bool done; + int error; + wxSockWakeUp *auto_wakeup; + wxSocketBase::wxRequestNotify type; +}; + + +///////////////////////////////////////////////////////////////////////////// +// Some internal define +///////////////////////////////////////////////////////////////////////////// + +// -------------------------------------------------------------- +// --------- wxSocketBase CONSTRUCTOR --------------------------- +// -------------------------------------------------------------- +wxSocketBase::wxSocketBase(wxSocketBase::wxSockFlags _flags, + wxSocketBase::wxSockType _type) : + wxEvtHandler(), + m_flags(_flags), m_type(_type), m_connected(FALSE), m_connecting(FALSE), + m_fd(INVALID_SOCKET), m_waitflags(0), m_cbk(0), m_cdata(0), m_id(-1), + m_handler(0), + m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)), + m_cbkon(FALSE), + m_unread(NULL), m_unrd_size(0), + m_processing(FALSE), + m_timeout(3600), m_wantbuf(0) +{ + m_internal = new wxSockInternal; +#if defined(__WXXT__) || defined(__WXMOTIF__) || defined(__WXGTK__) + m_internal->sock_inputid = 0; + m_internal->sock_outputid = 0; + m_internal->sock_exceptid = 0; +#endif +#ifdef __WINDOWS__ + m_internal->my_msg = 0; +#endif +} + +wxSocketBase::wxSocketBase() : + wxEvtHandler(), + m_flags(WAITALL), m_type(SOCK_UNINIT), m_connected(FALSE), + m_connecting(FALSE), m_fd(INVALID_SOCKET), m_waitflags(0), + m_cbk(0), m_cdata(0), + m_id(-1), m_handler(0), + m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)), + m_cbkon(FALSE), + m_unread(NULL), m_unrd_size(0), + m_processing(FALSE), + m_timeout(3600), m_wantbuf(0) +{ + m_internal = new wxSockInternal; +#if defined(__WXXT__) || defined(__WXMOTIF__) || defined(__WXGTK__) + m_internal->sock_inputid = 0; + m_internal->sock_outputid = 0; + m_internal->sock_exceptid = 0; +#endif +#ifdef __WINDOWS__ + m_internal->my_msg = 0; +#endif +} + +// -------------------------------------------------------------- +// --------- wxSocketBase CONSTRUCTOR --------------------------- +// -------------------------------------------------------------- +wxSocketBase::~wxSocketBase() +{ + DestroyCallbacks(); + Close(); + + if (m_unread) + free(m_unread); + if (m_handler) { +#ifdef __WINDOWS__ + if (m_internal->my_msg) + m_handler->DestroyMessage(m_internal->my_msg); +#endif + m_handler->UnRegister(this); + } + m_states.DeleteContents(TRUE); + + delete m_internal; +} + +bool wxSocketBase::Close() +{ + if (m_fd != INVALID_SOCKET) { + for (int i=0;i<3;i++) { + wxNode *n, *node = req_list[i].First(); + + while (node) { + SockRequest *req = (SockRequest *)node->Data(); + req->done = TRUE; + + n = node->Next(); + delete node; + node = n; + } + } + + DestroyCallbacks(); + shutdown(m_fd, 2); + close(m_fd); + m_fd = INVALID_SOCKET; + m_connected = FALSE; + } + + return TRUE; +} + +// -------------------------------------------------------------- +// --------- wxSocketBase base IO functions --------------------- +// -------------------------------------------------------------- +wxSocketBase& wxSocketBase::Read(char* buffer, size_t nbytes) +{ + m_lcount = GetPushback(buffer, nbytes, FALSE); + + // If we have got the whole needed buffer or if we don't want to + // wait then it returns immediately. + if (!nbytes || (m_lcount && !(m_flags & WAITALL)) ) + return *this; + + WantBuffer(buffer, nbytes, EVT_READ); + + return *this; +} + +wxSocketBase& wxSocketBase::Peek(char* buffer, size_t nbytes) +{ + size_t nbytes_old = nbytes; + + nbytes -= GetPushback(buffer, nbytes, TRUE); + if (!nbytes) { + m_lcount = nbytes_old; + return *this; + } + + WantBuffer(buffer, nbytes, EVT_PEEK); + + return *this; +} + +wxSocketBase& wxSocketBase::Write(const char *buffer, size_t nbytes) +{ + WantBuffer((char *)buffer, nbytes, EVT_WRITE); + return *this; +} + +wxSocketBase& wxSocketBase::ReadMsg(char* buffer, size_t nbytes) +{ + SockMsg msg; + size_t len, len2, sig; + + Read((char *)&msg, sizeof(msg)); + if (m_lcount != sizeof(msg)) + return *this; + + sig = msg.sig[0] & 0xff; + sig |= (size_t)(msg.sig[1] & 0xff) << 8; + sig |= (size_t)(msg.sig[2] & 0xff) << 16; + sig |= (size_t)(msg.sig[3] & 0xff) << 24; + + if (sig != 0xfeeddead) + return *this; + len = msg.len[0] & 0xff; + len |= (size_t)(msg.len[1] & 0xff) << 8; + len |= (size_t)(msg.len[2] & 0xff) << 16; + len |= (size_t)(msg.len[3] & 0xff) << 24; + len2 = len; + if (len > nbytes) + len = nbytes; + else + len2 = 0; + + if (Read(buffer, len).LastCount() != len) + return *this; + if (len2 && (Read(NULL, len2).LastCount() != len2)) + return *this; + if (Read((char *)&msg, sizeof(msg)).LastCount() != sizeof(msg)) + return *this; + + sig = msg.sig[0] & 0xff; + sig |= (size_t)(msg.sig[1] & 0xff) << 8; + sig |= (size_t)(msg.sig[2] & 0xff) << 16; + sig |= (size_t)(msg.sig[3] & 0xff) << 24; +// ERROR + if (sig != 0xdeadfeed) + return *this; + + return *this; +} + +wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, size_t nbytes) +{ + SockMsg msg; + + msg.sig[0] = 0xad; + msg.sig[1] = 0xde; + msg.sig[2] = 0xed; + msg.sig[3] = 0xfe; + + msg.len[0] = nbytes & 0xff; + msg.len[1] = (nbytes >> 8) & 0xff; + msg.len[2] = (nbytes >> 16) & 0xff; + msg.len[3] = (nbytes >> 24) & 0xff; + + if (Write((char *)&msg, sizeof(msg)).LastCount() < sizeof(msg)) + return *this; + if (Write(buffer, nbytes).LastCount() < nbytes) + return *this; + + msg.sig[0] = 0xed; + msg.sig[1] = 0xfe; + msg.sig[2] = 0xad; + msg.sig[3] = 0xde; + msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = 0; + Write((char *)&msg, sizeof(msg)); + + return *this; +} + +wxSocketBase& wxSocketBase::Unread(const char *buffer, size_t nbytes) +{ + CreatePushbackAfter(buffer, nbytes); + return *this; +} + +bool wxSocketBase::IsData() const +{ + struct timeval tv; + fd_set sock_set; + + if (m_fd < 0) + return FALSE; + if (m_unrd_size > 0) + return TRUE; + + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&sock_set); + FD_SET(m_fd, &sock_set); + select(FD_SETSIZE, &sock_set, NULL, NULL, &tv); + return FD_ISSET(m_fd, &sock_set); +} + +// --------------------------------------------------------------------- +// --------- wxSocketBase Discard(): deletes all byte in the input queue +// --------------------------------------------------------------------- +void wxSocketBase::Discard() +{ +#define MAX_BUFSIZE (10*1024) + char *my_data = new char[MAX_BUFSIZE]; + size_t recv_size = MAX_BUFSIZE; + + SaveState(); + SetFlags((wxSockFlags)(NOWAIT | SPEED)); + + while (recv_size == MAX_BUFSIZE) { + recv_size = Read(my_data, MAX_BUFSIZE).LastCount(); + } + + RestoreState(); + delete [] my_data; + +#undef MAX_BUFSIZE +} + +// -------------------------------------------------------------- +// --------- wxSocketBase socket info functions ----------------- +// -------------------------------------------------------------- +bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const +{ + struct sockaddr my_addr; + size_t len_addr = sizeof(my_addr); + + if (m_fd < 0) + return FALSE; + +#ifdef __WINDOWS__ + if (getpeername(m_fd, (struct sockaddr *)&my_addr, (int *)&len_addr) < 0) +#else + if (getpeername(m_fd, (struct sockaddr *)&my_addr, (unsigned int *)&len_addr) < 0) +#endif + return FALSE; + + addr_man.Disassemble(&my_addr, len_addr); + return TRUE; +} + +bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const +{ + struct sockaddr my_addr; + size_t len_addr = sizeof(my_addr); + + if (m_fd < 0) + return FALSE; + +#ifdef __WINDOWS__ + if (getsockname(m_fd, (struct sockaddr *)&my_addr, (int *)&len_addr) < 0) +#else + if (getsockname(m_fd, (struct sockaddr *)&my_addr, (unsigned int *)&len_addr) < 0) +#endif + return FALSE; + + addr_man.Disassemble(&my_addr, len_addr); + return TRUE; +} + +// -------------------------------------------------------------- +// --------- wxSocketBase wait functions ------------------------ +// -------------------------------------------------------------- +void wxSocketBase::SaveState() +{ + wxSockState *state = new wxSockState; + + state->cbk_on = m_cbkon; + state->cbk_set= m_neededreq; + state->cbk = m_cbk; + state->cdata = m_cdata; + state->flags = m_flags; + state->notif = m_notifyme; + + m_states.Append(state); +} + +void wxSocketBase::RestoreState() +{ + wxNode *node; + + node = m_states.Last(); + if (!node) + return; + + wxSockState *state = (wxSockState *)node->Data(); + + SetFlags(state->flags); + m_neededreq = state->cbk_set; + m_cbk = state->cbk; + m_cdata = state->cdata; + m_notifyme = state->notif; + if (state->cbk_on) + SetupCallbacks(); + else + DestroyCallbacks(); + + delete node; + delete state; +} + +// -------------------------------------------------------------- +// --------- wxSocketBase wait functions ------------------------ +// -------------------------------------------------------------- +// +bool wxSocketBase::_Wait(long seconds, long microseconds, int type) +{ + if ((!m_connected && !m_connecting) || m_fd < 0) + return FALSE; + + wxSockWakeUp wakeup(this, &m_waitflags, 0); + + SaveState(); + SetNotify((wxRequestNotify)type); + SetupCallbacks(); + + if (seconds != -1) + wakeup.Start((int)(seconds*1000 + (microseconds / 1000)), TRUE); + + m_waitflags = 0x80 | type; + while (m_waitflags & 0x80) + PROCESS_EVENTS(); + + RestoreState(); + + if (m_waitflags & 0x40) { + m_waitflags = 0; + return TRUE; + } + m_waitflags = 0; + + return FALSE; +} + +bool wxSocketBase::Wait(long seconds, long microseconds) +{ + return _Wait(seconds, microseconds, REQ_ACCEPT | REQ_CONNECT | + REQ_READ | REQ_WRITE | REQ_LOST); +} + +bool wxSocketBase::WaitForRead(long seconds, long microseconds) +{ + return _Wait(seconds, microseconds, REQ_READ | REQ_LOST); +} + +bool wxSocketBase::WaitForWrite(long seconds, long microseconds) +{ + return _Wait(seconds, microseconds, REQ_WRITE); +} + +bool wxSocketBase::WaitForLost(long seconds, long microseconds) +{ + return _Wait(seconds, microseconds, REQ_LOST); +} + +// -------------------------------------------------------------- +// --------- wxSocketBase callback management ------------------- +// -------------------------------------------------------------- + +#if defined(__WXMOTIF__) || defined(__WXXT__) || defined(__WXGTK__) +#if defined(__WXMOTIF__) || defined(__WXXT__) +static void wx_socket_read(XtPointer client, int *fid, + XtInputId *WXUNUSED(id)) +#define fd *fid +#else +static void wx_socket_read(gpointer client, gint fd, + GdkInputCondition WXUNUSED(cond)) +#define fd fd +#endif +{ + wxSocketBase *sock = (wxSocketBase *)client; + char c; + int i; + + i = recv(fd, &c, 1, MSG_PEEK); + + if (i == -1 && (sock->NeededReq() & wxSocketBase::REQ_ACCEPT)) { + sock->OnRequest(wxSocketBase::EVT_ACCEPT); + return; + } + + if (i != 0) { + if (!(sock->NeededReq() & wxSocketBase::REQ_READ)) + return; + + sock->OnRequest(wxSocketBase::EVT_READ); + } else { + if (!(sock->NeededReq() & wxSocketBase::REQ_LOST)) { + sock->Close(); + return; + } + + sock->OnRequest(wxSocketBase::EVT_LOST); + } +} +#undef fd + +#if defined(__WXMOTIF__) || defined(__WXXT__) +static void wx_socket_write(XtPointer client, int *WXUNUSED(fid), + XtInputId *WXUNUSED(id)) +#else +static void wx_socket_write(gpointer client, gint WXUNUSED(fd), + GdkInputCondition WXUNUSED(cond)) +#endif +{ + wxSocketBase *sock = (wxSocketBase *)client; + + if (!sock->IsConnected()) + sock->OnRequest(wxSocketBase::EVT_CONNECT); + else + sock->OnRequest(wxSocketBase::EVT_WRITE); +} +#endif + +#ifdef wx_xview +Notify_value wx_sock_read_xview (Notify_client client, int fd) +{ + wxSocketBase *sock = (wxSocketBase *)client; + char c; + int i; + + i = recv(fd, &c, 1, MSG_PEEK); + + if (i == -1 && (sock->NeededReq() & wxSocketBase::REQ_ACCEPT)) { + sock->OnRequest(wxSocketBase::EVT_ACCEPT); + return; + } + + /* Bytes arrived */ + if (i != 0) { + if (!(sock->NeededReq() & wxSocketBase::REQ_READ)) + return (Notify_value) FALSE; + + sock->OnRequest(wxSocketBase::EVT_READ); + } else { + if (!(sock->NeededReq() & wxSocketBase::REQ_LOST)) + return; + + sock->OnRequest(wxSocketBase::EVT_LOST); + } + + return (Notify_value) FALSE; +} + +Notify_value wx_sock_write_xview (Notify_client client, int fd) +{ + wxSocketBase *sock = (wxSocketBase *)client; + + if (!sock->IsConnected()) + sock->OnRequest(wxSocketBase::EVT_CONNECT); + else + sock->OnRequest(wxSocketBase::EVT_WRITE); + + return (Notify_value) TRUE; +} +#endif + +wxSocketBase::wxRequestNotify wxSocketBase::EventToNotify(wxRequestEvent evt) +{ + switch (evt) { + case EVT_READ: + return REQ_READ; + case EVT_PEEK: + return REQ_PEEK; + case EVT_WRITE: + return REQ_WRITE; + case EVT_LOST: + return REQ_LOST; + case EVT_ACCEPT: + return REQ_ACCEPT; + case EVT_CONNECT: + return REQ_CONNECT; + } + return 0; +} + +void wxSocketBase::SetFlags(wxSockFlags _flags) +{ + m_flags = _flags; + if (_flags & SPEED) { + unsigned long flag = 0; + ioctl(m_fd, FIONBIO, &flag); + + // SPEED and WAITALL are antagonists. + m_flags = (wxSockFlags)(m_flags & ~WAITALL); + + Notify(FALSE); + } else { + unsigned long flag = 1; + ioctl(m_fd, FIONBIO, &flag); + } +} + +void wxSocketBase::SetNotify(wxRequestNotify flags) +{ + wxRequestNotify old_needed_req = m_neededreq; + if (flags & REQ_ACCEPT) { + /* Check if server */ + if (!(GetClassInfo()->IsKindOf(CLASSINFO(wxSocketServer)))) + flags &= ~REQ_ACCEPT; + } + m_neededreq = flags; + if (m_cbkon && old_needed_req != flags) + SetupCallbacks(); +} + +void wxSocketBase::SetupCallbacks() +{ + if (m_fd == INVALID_SOCKET || !m_handler || (m_flags & SPEED)) + return; + +#if defined(__WXMOTIF__) || defined(__WXXT__) || defined(__WXGTK__) + if (m_cbkon) + DestroyCallbacks(); + if (m_neededreq & (REQ_ACCEPT | REQ_READ | REQ_LOST)) { +#ifdef __WXGTK__ + m_internal->sock_inputid = gdk_input_add(m_fd, GDK_INPUT_READ, + wx_socket_read, (gpointer)this); +#else + m_internal->sock_inputid = XtAppAddInput (wxAPP_CONTEXT, m_fd, + (XtPointer *) XtInputReadMask, + (XtInputCallbackProc) wx_socket_read, + (XtPointer) this); +#endif + } + if (m_neededreq & (REQ_CONNECT | REQ_WRITE)) { +#ifdef __WXGTK__ + m_internal->sock_inputid = gdk_input_add(m_fd, GDK_INPUT_WRITE, + wx_socket_write, (gpointer)this); +#else + m_internal->sock_outputid = XtAppAddInput (wxAPP_CONTEXT, m_fd, + (XtPointer *) XtInputWriteMask, + (XtInputCallbackProc) wx_socket_write, + (XtPointer) this); +#endif + } +#endif +#ifdef __WINDOWS__ + WORD mask = 0; + + if (m_neededreq & REQ_READ) + mask |= FD_READ; + if (m_neededreq & REQ_WRITE) + mask |= FD_WRITE; + if (m_neededreq & REQ_LOST) + mask |= FD_CLOSE; + if (m_neededreq & REQ_ACCEPT) + mask |= FD_ACCEPT; + if (m_neededreq & REQ_CONNECT) + mask |= FD_CONNECT; + + if (!m_internal->my_msg) + m_internal->my_msg = m_handler->NewMessage(this); + WSAAsyncSelect(m_fd, m_handler->GetHWND(), m_internal->my_msg, mask); +#endif + m_cbkon = TRUE; + m_processing = FALSE; +} + +void wxSocketBase::DestroyCallbacks() +{ + if (!m_cbkon || !m_handler) + return; + m_cbkon = FALSE; + m_processing = FALSE; +#if defined(__WXMOTIF__) || defined(__WXXT__) + if (m_internal->sock_inputid > 0) + XtRemoveInput(m_internal->sock_inputid); + m_internal->sock_inputid = 0; + if (m_internal->sock_outputid > 0) + XtRemoveInput(m_internal->sock_outputid); + m_internal->sock_outputid = 0; +#endif +#ifdef __WXGTK__ + if (m_internal->sock_inputid > 0) + gdk_input_remove(m_internal->sock_inputid); + m_internal->sock_inputid = 0; + if (m_internal->sock_outputid > 0) + gdk_input_remove(m_internal->sock_outputid); + m_internal->sock_outputid = 0; +#endif +#ifdef __WINDOWS__ + WSAAsyncSelect(m_fd, m_handler->GetHWND(), 0, 0); +#endif +} + +void wxSocketBase::Notify(bool notify) +{ + if (m_notifyme == notify) + return; + if (notify) + SetupCallbacks(); + else + DestroyCallbacks(); + m_notifyme = notify; +} + +void wxSocketBase::OnRequest(wxRequestEvent req_evt) +{ + wxRequestNotify req_notif = EventToNotify(req_evt); + + // Mask the current event + SetNotify(m_neededreq & ~req_notif); + + if (req_evt <= EVT_WRITE && DoRequests(req_evt)) + return; + + if (m_waitflags & 0xF0) { + // Wake up + if ((m_waitflags & 0x0F) == req_evt) { + m_waitflags = 0x80; +#ifndef __WXGTK__ + DestroyCallbacks(); // I disable it to prevent infinite loop on X11. +#endif + } + return; + } + + if (req_evt == EVT_LOST) { + m_connected = FALSE; + Close(); + } + if (m_notifyme) + OldOnNotify(req_evt); + + // Unmask + SetNotify(m_neededreq | req_notif); +} + +wxSocketEvent::wxSocketEvent(int id) + : wxEvent(id) +{ + wxEventType type = (wxEventType)wxEVT_SOCKET; + + SetEventType(type); +} + +void wxSocketBase::OldOnNotify(wxRequestEvent evt) +{ + wxSocketEvent event(m_id); + + event.SetEventObject(this); + event.m_skevt = evt; + ProcessEvent(event); + + if (m_cbk) + m_cbk(*this, evt, m_cdata); +} + +// -------------------------------------------------------------- +// --------- wxSocketBase functions [Callback, CallbackData] ---- +// -------------------------------------------------------------- +wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSocketBase::wxSockCbk _cbk) +{ + wxSockCbk old_cbk = m_cbk; + + m_cbk = _cbk; + return old_cbk; +} + +char *wxSocketBase::CallbackData(char *cdata_) +{ + char *old_cdata = m_cdata; + + m_cdata = cdata_; + return old_cdata; +} + +void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id) +{ + SetNextHandler(&h_evt); + m_id = id; +} + +// -------------------------------------------------------------- +// --------- wxSocketBase pushback library ---------------------- +// -------------------------------------------------------------- +void wxSocketBase::CreatePushbackAfter(const char *buffer, size_t size) +{ + char *curr_pos; + + m_unread = (char *) realloc(m_unread, m_unrd_size+size); + curr_pos = m_unread + m_unrd_size; + + memcpy(curr_pos, buffer, size); + m_unrd_size += size; +} + +void wxSocketBase::CreatePushbackBefore(const char *buffer, size_t size) +{ + char *curr_pos, *new_buf; + + new_buf = (char *) malloc(m_unrd_size+size); + curr_pos = new_buf + size; + + memcpy(new_buf, buffer, size); + memcpy(curr_pos, m_unread, m_unrd_size); + + free(m_unread); + m_unread = new_buf; + m_unrd_size += size; +} + +size_t wxSocketBase::GetPushback(char *buffer, size_t size, bool peek) +{ + if (!m_unrd_size) + return 0; + + if (size > m_unrd_size) + size = m_unrd_size; + memcpy(buffer, m_unread, size); + + if (!peek) { + m_unrd_size -= size; + if (!m_unrd_size) { + free(m_unread); + m_unread = NULL; + } + } + + return size; +} + +// -------------------------------------------------------------- +// --------- wxSocketBase "multi-thread" core ------------------- +// -------------------------------------------------------------- + +bool wxSocketBase::DoRequests(wxRequestEvent req_flag) +{ + wxNode *node = req_list[req_flag].First(); + size_t len; + int ret; + + if (!node) + return FALSE; + + SockRequest *req = (SockRequest *)node->Data(); + + delete node; + + switch (req->type) { + case EVT_READ: + case EVT_PEEK: + ret = recv(m_fd, req->buffer, req->size, + (req->type == EVT_PEEK) ? MSG_PEEK : 0); + if (ret < 0) { + req->error = errno; + req->done = TRUE; + break; + } + len = ret; + if ((len < req->size) && (m_flags & WAITALL)) { + req->size -= len; + req->nbytes += len; + req->buffer += len; + req->auto_wakeup->Start(m_timeout*1000, TRUE); + req_list[req_flag].Insert(req); + break; + } + req->done = TRUE; + req->nbytes += len; +#ifndef __WXGTK__ + DestroyCallbacks(); +#endif + break; + case EVT_WRITE: + ret = send(m_fd, req->buffer, req->size, 0); + if (ret < 0) { + req->error = errno; + req->done = TRUE; + break; + } + len = ret; + if ((len < req->size) && (m_flags & WAITALL)) { + req->size -= len; + req->nbytes += len; + req->buffer += len; + req->auto_wakeup->Start(m_timeout*1000, TRUE); + req_list[req_flag].Insert(req); + break; + } + req->done = TRUE; + req->nbytes += len; +#ifndef __WXGTK__ + DestroyCallbacks(); +#endif + break; + default: + return FALSE; + } + return TRUE; +} + +void wxSocketBase::WantSpeedBuffer(char *buffer, size_t nbytes, + wxRequestEvent evt) +{ + int ret; + + switch (evt) { + case EVT_PEEK: + case EVT_READ: + ret = read(m_fd, buffer, nbytes); + break; + case EVT_WRITE: + ret = write(m_fd, buffer, nbytes); + break; + } + if (ret < 0) { + m_lcount = 0; + m_error = errno; + } else + m_lcount = ret; +} + +void wxSocketBase::WantBuffer(char *buffer, size_t nbytes, + wxRequestEvent evt) +{ + bool buf_timed_out; + + if (m_fd == INVALID_SOCKET || !m_handler || !m_connected) + return; + + if (m_flags & SPEED) { + WantSpeedBuffer(buffer, nbytes, evt); + return; + } + + SockRequest *buf = new SockRequest; + wxSockWakeUp s_wake(NULL, (int *)&buf_timed_out, (int)TRUE); + + m_wantbuf++; + req_list[evt].Append(buf); + + SaveState(); + SetNotify(REQ_LOST | EventToNotify(evt)); + SetupCallbacks(); + buf->buffer = buffer; + buf->size = nbytes; + buf->done = FALSE; + buf->type = evt; + buf->nbytes = 0; + buf->auto_wakeup = &s_wake; + buf->error = 0; + buf_timed_out = FALSE; + + s_wake.Start(m_timeout*1000, TRUE); + if (m_flags & NOWAIT) { + DoRequests(evt); + } else { + while (!buf->done && !buf_timed_out) + PROCESS_EVENTS(); + } + m_wantbuf--; + m_lcount = buf->nbytes; + if (buf_timed_out) + m_error = ETIMEDOUT; + else + m_error = buf->error; + + delete buf; + RestoreState(); +} + +// -------------------------------------------------------------- +// wxSocketServer /////////////////////////////////////////////// +// -------------------------------------------------------------- + +// -------------------------------------------------------------- +// --------- wxSocketServer CONSTRUCTOR ------------------------- +// -------------------------------------------------------------- +wxSocketServer::wxSocketServer(wxSockAddress& addr_man, + wxSockFlags flags) : + wxSocketBase(flags, SOCK_SERVER) +{ + m_fd = socket(addr_man.GetFamily(), SOCK_STREAM, 0); + + if (m_fd == INVALID_SOCKET) + return; + + int flag = 1; + setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(int)); + + struct sockaddr *myaddr; + size_t len; + + addr_man.Build(myaddr, len); + if (bind(m_fd, myaddr, addr_man.SockAddrLen()) < 0) + return; + + if (listen(m_fd, 5) < 0) { + m_fd = INVALID_SOCKET; + return; + } +} + +// -------------------------------------------------------------- +// --------- wxSocketServer Accept ------------------------------ +// -------------------------------------------------------------- +bool wxSocketServer::AcceptWith(wxSocketBase& sock) +{ + int fd2; + + if ((fd2 = accept(m_fd, 0, 0)) < 0) + return FALSE; + + struct linger linger; + linger.l_onoff = 0; + linger.l_linger = 1; + + setsockopt(fd2, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger)); + + int flag = 0; + setsockopt(fd2, SOL_SOCKET, SO_KEEPALIVE, (char*)&flag, sizeof(int)); + + if (!(sock.m_flags & SPEED)) { + unsigned long flag2 = 1; + ioctl(fd2, FIONBIO, &flag2); + } + + sock.m_type = SOCK_INTERNAL; + sock.m_fd = fd2; + sock.m_connected = TRUE; + + return TRUE; +} + +wxSocketBase *wxSocketServer::Accept() +{ + wxSocketBase* sock = new wxSocketBase(); + + sock->SetFlags((wxSockFlags)m_flags); + + if (!AcceptWith(*sock)) + return NULL; + + if (m_handler) + m_handler->Register(sock); + + return sock; +} + +// -------------------------------------------------------------- +// --------- wxSocketServer callbacks --------------------------- +// -------------------------------------------------------------- +void wxSocketServer::OnRequest(wxRequestEvent evt) +{ + if (evt == EVT_ACCEPT) { + OldOnNotify(EVT_ACCEPT); + } +} + +// -------------------------------------------------------------- +// wxSocketClient /////////////////////////////////////////////// +// -------------------------------------------------------------- + +// --------- wxSocketClient CONSTRUCTOR ------------------------- +// -------------------------------------------------------------- +wxSocketClient::wxSocketClient(wxSockFlags _flags) : + wxSocketBase(_flags, SOCK_CLIENT) +{ +} + +// -------------------------------------------------------------- +// --------- wxSocketClient DESTRUCTOR -------------------------- +// -------------------------------------------------------------- +wxSocketClient::~wxSocketClient() +{ +} + +// -------------------------------------------------------------- +// --------- wxSocketClient Connect functions ------------------- +// -------------------------------------------------------------- +bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait) +{ + struct linger linger; + + if (IsConnected()) + Close(); + + m_fd = socket(addr_man.GetFamily(), SOCK_STREAM, 0); + + if (m_fd < 0) + return FALSE; + + m_connected = FALSE; + + linger.l_onoff = 1; + linger.l_linger = 5; + setsockopt(m_fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger)); + + // Stay in touch with the state of things... + + unsigned long flag = 1; + setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&flag, sizeof(int)); + + // Disable the nagle algorithm, which delays sends till the + // buffer is full (or a certain time period has passed?)... + +#if defined(__WINDOWS__) || (defined(IPPROTO_TCP) && defined(TCP_NODELAY)) + flag = 1; + setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int)); +#endif + + struct sockaddr *remote; + size_t len; + + addr_man.Build(remote, len); + + if (connect(m_fd, remote, len) != 0) + return FALSE; + + if (!(m_flags & SPEED)) { + flag = 1; + ioctl(m_fd, FIONBIO, &flag); + } + + Notify(TRUE); + + m_connected = TRUE; + return TRUE; +} + +bool wxSocketClient::WaitOnConnect(long seconds) +{ + int ret = _Wait(seconds, 0, REQ_CONNECT | REQ_LOST); + + if (ret) + m_connected = TRUE; + + return m_connected; +} + +void wxSocketClient::OnRequest(wxRequestEvent evt) +{ + if (evt == EVT_CONNECT) { + if (m_connected) { + SetNotify(m_neededreq & ~REQ_CONNECT); + return; + } + m_waitflags = 0x40; + m_connected = TRUE; + OldOnNotify(EVT_CONNECT); + DestroyCallbacks(); + return; + } + wxSocketBase::OnRequest(evt); +} + +///////////////////////////////////////////////////////////////// +// wxSocketHandler /////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + +wxSocketHandler *wxSocketHandler::master = NULL; +#if defined(__WINDOWS__) +static int win_initialized = 0; +#endif + +// -------------------------------------------------------------- +// --------- wxSocketHandler CONSTRUCTOR ------------------------ +// -------------------------------------------------------------- +#ifdef __WINDOWS__ + +extern char wxPanelClassName[]; + +LRESULT APIENTRY _EXPORT wxSocketHandlerWndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + wxSocketHandler *h_sock = (wxSocketHandler *)GetWindowLong(hWnd, GWL_USERDATA); + wxNode *node = h_sock->smsg_list->Find(message); + wxSocketBase *sock; + wxSocketBase::wxRequestEvent sk_req; + UINT event = WSAGETSELECTEVENT(lParam); + + if (!node) + return DefWindowProc(hWnd, message, wParam, lParam); + + sock = (wxSocketBase *)node->Data(); + + switch (event) { + case FD_READ: + sk_req = wxSocketBase::EVT_READ; + break; + case FD_WRITE: + sk_req = wxSocketBase::EVT_WRITE; + break; + case FD_CLOSE: + sk_req = wxSocketBase::EVT_LOST; + break; + case FD_ACCEPT: + sk_req = wxSocketBase::EVT_ACCEPT; + break; + case FD_CONNECT: + sk_req = wxSocketBase::EVT_CONNECT; + break; + } + sock->OnRequest(sk_req); + + return (LRESULT)0; +} + +FARPROC wxSocketSubClassProc = NULL; + +#endif + +wxSocketHandler::wxSocketHandler() +{ +#if defined(__WINDOWS__) + if (!win_initialized) { + WSADATA wsaData; + + WSAStartup((1 << 8) | 1, &wsaData); + win_initialized = 1; + } + internal = new wxSockHandlerInternal; + internal->sockWin = ::CreateWindow(wxPanelClassName, NULL, 0, + 0, 0, 0, 0, NULL, (HMENU) NULL, + wxhInstance, 0); + + // Subclass the window + if (!wxSocketSubClassProc) + wxSocketSubClassProc = MakeProcInstance((FARPROC) wxSocketHandlerWndProc, wxhInstance); + ::SetWindowLong(internal->sockWin, GWL_WNDPROC, (LONG) wxSocketSubClassProc); + ::SetWindowLong(internal->sockWin, GWL_USERDATA, (LONG) this); + + internal->firstAvailableMsg = 5000; + smsg_list = new wxList(wxKEY_INTEGER); +#endif + + socks = new wxList; + +#ifndef __WINDOWS__ + signal(SIGPIPE, SIG_IGN); +#endif +} + +// -------------------------------------------------------------- +// --------- wxSocketHandler DESTRUCTOR ------------------------- +// -------------------------------------------------------------- +wxSocketHandler::~wxSocketHandler() +{ + wxNode *next_node, *node = socks->First(); + + while (node) { + wxSocketBase* sock = (wxSocketBase*)node->Data(); + + delete sock; + next_node = node->Next(); + delete node; + node = next_node; + } + + delete socks; + +#ifdef __WINDOWS__ + delete smsg_list; + + ::DestroyWindow(internal->sockWin); + WSACleanup(); + win_initialized = 0; + + delete internal; +#endif +} + +// -------------------------------------------------------------- +// --------- wxSocketHandler registering functions -------------- +// -------------------------------------------------------------- +void wxSocketHandler::Register(wxSocketBase* sock) +{ + wxNode *node; + + for (node = socks->First(); node != NULL; node = node->Next()) { + wxSocketBase* s = (wxSocketBase*)node->Data(); + + if (s == sock) + return; + } + + if (sock) { + socks->Append(sock); + sock->SetHandler(this); + sock->SetupCallbacks(); + } +} + +void wxSocketHandler::UnRegister(wxSocketBase* sock) +{ + wxNode *node; + + for (node = socks->First(); node; node = node->Next()) { + wxSocketBase* s = (wxSocketBase*)node->Data(); + + if (s == sock) { + delete node; + sock->DestroyCallbacks(); + sock->SetHandler(NULL); + return; + } + } +} + +unsigned long wxSocketHandler::Count() const +{ + return socks->Number(); +} + +// -------------------------------------------------------------- +// --------- wxSocketHandler "big" wait functions --------------- +// -------------------------------------------------------------- +void handler_cbk(wxSocketBase& sock, + wxSocketBase::wxRequestEvent WXUNUSED(flags), + char *cdata) +{ + int *a_wait = (int *)cdata; + + (*a_wait)++; + sock.Notify(FALSE); +} + +int wxSocketHandler::Wait(long seconds, long microseconds) +{ + int i; + int on_wait; + wxSockWakeUp s_wake(NULL, &on_wait, -2); + wxNode *node; + + for (node = socks->First(), i=0; node; node = node->Next(), i++) { + wxSocketBase *sock = (wxSocketBase *)node->Data(); + + sock->SaveState(); + + sock->SetupCallbacks(); + + sock->Callback(handler_cbk); + sock->CallbackData((char *)&on_wait); + } + on_wait = 0; + if (seconds != -1) + s_wake.Start((seconds*1000) + (microseconds/1000), TRUE); + + while (!on_wait) + PROCESS_EVENTS(); + + for (node = socks->First(), i=0; node; node = node->Next(), i++) { + wxSocketBase *sock = (wxSocketBase *)node->Data(); + + sock->RestoreState(); + } + + if (on_wait == -2) + return 0; + + return on_wait; +} + +void wxSocketHandler::YieldSock() +{ + wxNode *node; + + for (node = socks->First(); node; node = node->Next() ) { + wxSocketBase *sock = (wxSocketBase *)node->Data(); + + sock->SaveState(); + + sock->SetFlags(wxSocketBase::SPEED); + if (sock->IsData()) + sock->DoRequests(wxSocketBase::EVT_READ); + sock->DoRequests(wxSocketBase::EVT_WRITE); + + sock->RestoreState(); + } +} + +// -------------------------------------------------------------- +// --------- wxSocketHandler: create and register the socket ---- +// -------------------------------------------------------------- +wxSocketServer *wxSocketHandler::CreateServer(wxSockAddress& addr, + wxSocketBase::wxSockFlags flags) +{ + wxSocketServer *serv = new wxSocketServer(addr, flags); + + Register(serv); + return serv; +} + +wxSocketClient *wxSocketHandler::CreateClient(wxSocketBase::wxSockFlags flags) +{ + wxSocketClient *client = new wxSocketClient(flags); + + Register(client); + return client; +} + +#ifdef __WINDOWS__ +// -------------------------------------------------------------- +// --------- wxSocketHandler: Windows specific methods ---------- +// -------------------------------------------------------------- +UINT wxSocketHandler::NewMessage(wxSocketBase *sock) +{ + internal->firstAvailableMsg++; + smsg_list->Append(internal->firstAvailableMsg, sock); + return internal->firstAvailableMsg; +} + +void wxSocketHandler::DestroyMessage(UINT msg) +{ + wxNode *node = smsg_list->Find(msg); + delete node; +} + +HWND wxSocketHandler::GetHWND() const +{ + return internal->sockWin; +} + +#endif diff --git a/src/common/stream.cpp b/src/common/stream.cpp index f25f6381fb..d546ab473f 100644 --- a/src/common/stream.cpp +++ b/src/common/stream.cpp @@ -549,9 +549,23 @@ wxOutputStream& wxOutputStream::operator<<(wxObject& obj) return *this; } +// ---------------------------------------------------------------------------- +// wxStream +// ---------------------------------------------------------------------------- + +wxStream::wxStream() + : wxInputStream(), wxOutputStream() +{ +} + // ---------------------------------------------------------------------------- // wxFilterInputStream // ---------------------------------------------------------------------------- +wxFilterInputStream::wxFilterInputStream() + : wxInputStream(NULL) +{ +} + wxFilterInputStream::wxFilterInputStream(wxInputStream& stream) : wxInputStream(NULL) { @@ -578,10 +592,14 @@ off_t wxFilterInputStream::DoTellInput() const return m_parent_i_stream->TellI(); } - // ---------------------------------------------------------------------------- // wxFilterOutputStream // ---------------------------------------------------------------------------- +wxFilterOutputStream::wxFilterOutputStream() + : wxOutputStream(NULL) +{ +} + wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream) : wxOutputStream(NULL) { @@ -608,6 +626,19 @@ off_t wxFilterOutputStream::DoTellOutput() const return m_parent_o_stream->TellO(); } +// ---------------------------------------------------------------------------- +// wxFilterStream +// ---------------------------------------------------------------------------- + +wxFilterStream::wxFilterStream() +{ +} + +wxFilterStream::wxFilterStream(wxStream& stream) + : wxFilterInputStream(stream), wxFilterOutputStream(stream) +{ +} + // ---------------------------------------------------------------------------- // Some IOManip function // ---------------------------------------------------------------------------- diff --git a/src/common/tokenzr.cpp b/src/common/tokenzr.cpp new file mode 100644 index 0000000000..eb99237711 --- /dev/null +++ b/src/common/tokenzr.cpp @@ -0,0 +1,104 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: tokenzr.cpp +// Purpose: String tokenizer +// Author: Guilhem Lavaux +// Modified by: +// Created: 04/22/98 +// RCS-ID: $Id$ +// Copyright: (c) Guilhem Lavaux +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "tokenzr.h" +#endif + +#include "wx/object.h" +#include "wx/string.h" +#include "wx/tokenzr.h" + +wxStringTokenizer::wxStringTokenizer(const wxString& to_tokenize, + const wxString& delims, + bool ret_delims) + : wxObject() +{ + m_string = to_tokenize; + m_delims = delims; + m_retdelims = ret_delims; +} + +wxStringTokenizer::~wxStringTokenizer() +{ +} + +off_t wxStringTokenizer::FindDelims(const wxString& str, const wxString& delims) +{ + int i, j; + register int s_len = str.Length(), + len = delims.Length(); + + for (i=0;i +#include + +// wxWindows headers +#include +#include +#include + +// wxSocket header +#include "wx/url.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#if !USE_SHARED_LIBRARY +IMPLEMENT_CLASS(wxProtoInfo, wxObject) +IMPLEMENT_CLASS(wxURL, wxObject) +#endif + +// Protocols list +wxProtoInfo *wxURL::g_protocols = NULL; +wxHTTP wxURL::g_proxy; + +///////////////////////////////////////////////////////////////// +// wxURL //////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + +/* + * -------------------------------------------------------------- + * --------- wxURL CONSTRUCTOR DESTRUCTOR ----------------------- + * -------------------------------------------------------------- + */ + +wxURL::wxURL(const wxString& url) +{ + m_protocol = NULL; + if (g_proxy.IsConnected()) { + m_protocol = &g_proxy; + m_protoname = "proxy"; + m_path = url; + return; + } + m_url = url; + m_error = wxURL_NOERR; +} + +bool wxURL::ParseURL() +{ + wxString last_url = m_url; + + // Clean up + CleanData(); + + // Extract protocol name + if (!PrepProto(last_url)) { + m_error = wxURL_SNTXERR; + return FALSE; + } + + // Find and create the protocol object + if (!FetchProtocol()) { + m_error = wxURL_NOPROTO; + return FALSE; + } + + // Do we need a host name ? + if (m_protoinfo->m_needhost) { + // Extract it + if (!PrepHost(last_url)) { + m_error = wxURL_SNTXERR; + return FALSE; + } + } + + // Extract full path + if (!PrepPath(last_url)) { + m_error = wxURL_NOPATH; + return FALSE; + } + + m_error = wxURL_NOERR; + return TRUE; +} + +void wxURL::CleanData() +{ + if (m_protoname != "proxy") + delete m_protocol; +} + +wxURL::~wxURL() +{ + CleanData(); +} + +/* + * -------------------------------------------------------------- + * --------- wxURL urls decoders -------------------------------- + * -------------------------------------------------------------- + */ +bool wxURL::PrepProto(wxString& url) +{ + int pos; + + // Find end + pos = url.Find(':'); + if (pos == -1) + return FALSE; + + m_protoname = url(0, pos); + + url = url(pos+1, url.Length()); + + return TRUE; +} + +bool wxURL::PrepHost(wxString& url) +{ + int pos, pos2; + + if ((url[0UL] != '/') || (url[1UL] != '/')) + return FALSE; + + url = url(2, url.Length()); + + pos = url.Find('/'); + if (pos == -1) + return FALSE; + + pos2 = url.Find(':'); + if (pos2 != -1 && pos2 < pos) { + m_servname = url(pos2, pos); + if (!m_servname.IsNumber()) + return FALSE; + pos2 = pos; + } + + m_hostname = url(0, pos); + + url = url(url.Find('/'), url.Length()); + + return TRUE; +} + +bool wxURL::PrepPath(wxString& url) +{ + if (url.Length() != 0) + m_path = url; + else + m_path = "/"; + return TRUE; +} + +bool wxURL::FetchProtocol() +{ + wxProtoInfo *info = g_protocols; + + while (info) { + if (m_protoname == info->m_protoname) { + if (m_servname.IsNull()) + m_servname = info->m_servname; + + m_protoinfo = info; + m_protocol = (wxProtocol *)m_protoinfo->m_cinfo->CreateObject(); + wxSocketHandler::Master().Register(m_protocol); + return TRUE; + } + info = info->next; + } + return FALSE; +} + +/* + * -------------------------------------------------------------- + * --------- wxURL get ------------------------------------------ + * -------------------------------------------------------------- + */ +wxInputStream *wxURL::GetInputStream(void) +{ + wxIPV4address addr; + wxInputStream *the_i_stream = NULL; + + if (!m_protocol) + if (!ParseURL()) + return NULL; + + if (!m_protocol) { + m_error = wxURL_NOPROTO; + return NULL; + } + + m_error = wxURL_NOERR; + if (m_protoinfo->m_needhost) { + if (!addr.Hostname(m_hostname)) { + m_error = wxURL_NOHOST; + return NULL; + } + + addr.Service(m_servname); + + if (!m_protocol->Connect(addr)) { + m_error = wxURL_CONNERR; + return NULL; + } + } + + the_i_stream = m_protocol->GetInputStream(m_path); + if (!the_i_stream) { + m_error = wxURL_PROTOERR; + return NULL; + } + + return the_i_stream; +} + +void wxURL::SetDefaultProxy(const wxString& url_proxy) +{ + g_proxy.Close(); + + if (url_proxy.IsNull()) + return; + + wxString tmp_str = url_proxy; + int pos = tmp_str.Find(':'); + wxString hostname = tmp_str(0, pos), + port = tmp_str(pos, tmp_str.Length()-pos); + wxIPV4address addr; + + addr.Hostname(hostname); + addr.Service(port); + + g_proxy.Connect(addr); +} + +void wxURL::SetProxy(const wxString& url_proxy) +{ + if (url_proxy.IsNull()) { + m_proxy.Close(); + return; + } + + CleanData(); + + wxString tmp_str; + wxString hostname, port; + int pos; + wxIPV4address addr; + + tmp_str = url_proxy; + pos = tmp_str.Find(':'); + hostname = tmp_str(0, pos); + port = tmp_str(pos, tmp_str.Length()-pos); + + addr.Hostname(hostname); + addr.Service(port); + + m_proxy.Connect(addr); + + m_protocol = &m_proxy; + m_protoname = "proxy"; + m_path = url_proxy; +} diff --git a/src/gtk.inc b/src/gtk.inc index 76e934d2ce..8465dc4630 100644 --- a/src/gtk.inc +++ b/src/gtk.inc @@ -51,9 +51,19 @@ LIB_CPP_SRC=\ common/mstream.cpp \ common/zstream.cpp \ common/objstrm.cpp \ + common/sckstrm.cpp \ common/validate.cpp \ common/valtext.cpp \ common/wxexpr.cpp \ + common/tokenzr.cpp \ + common/socket.cpp \ + common/sckaddr.cpp \ + common/protocol.cpp \ + common/url.cpp \ + common/http.cpp \ + common/ftp.cpp \ + common/sckfile.cpp \ + common/sckipc.cpp \ \ gtk/accel.cpp \ gtk/app.cpp \ diff --git a/src/gtk/data.cpp b/src/gtk/data.cpp index 8e02841a18..a0ab3cea95 100644 --- a/src/gtk/data.cpp +++ b/src/gtk/data.cpp @@ -400,6 +400,50 @@ IMPLEMENT_DYNAMIC_CLASS(wxToolBar95, wxToolBarBase) #endif +#include "wx/sckaddr.h" + +IMPLEMENT_DYNAMIC_CLASS(wxIPV4address, wxSockAddress) +#ifdef ENABLE_IPV6 +IMPLEMENT_DYNAMIC_CLASS(wxIPV6address, wxSockAddress) +#endif +#ifndef __UNIX__ +IMPLEMENT_DYNAMIC_CLASS(wxUNIXaddress, wxSockAddress) +#endif + +#include "wx/socket.h" + +IMPLEMENT_CLASS(wxSocketBase, wxEvtHandler) +IMPLEMENT_CLASS(wxSocketClient, wxSocketBase) +IMPLEMENT_CLASS(wxSocketServer, wxSocketBase) +IMPLEMENT_CLASS(wxSocketHandler, wxObject) +IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent) + +#include "wx/url.h" + +IMPLEMENT_CLASS(wxProtoInfo, wxObject) +IMPLEMENT_CLASS(wxURL, wxObject) + +#include "wx/protocol/http.h" + +IMPLEMENT_DYNAMIC_CLASS(wxHTTP, wxProtocol) +IMPLEMENT_PROTOCOL(wxHTTP, "http", "80", TRUE) + +#include "wx/protocol/ftp.h" + +IMPLEMENT_DYNAMIC_CLASS(wxFTP, wxProtocol) +IMPLEMENT_PROTOCOL(wxFTP, "ftp", "ftp", TRUE) + +#include "wx/protocol/sckfile.h" + +IMPLEMENT_DYNAMIC_CLASS(wxFileProto, wxProtocol) +IMPLEMENT_PROTOCOL(wxFileProto, "file", NULL, FALSE) + +#include "wx/sckipc.h" + +IMPLEMENT_DYNAMIC_CLASS(wxTCPServer, wxServerBase) +IMPLEMENT_DYNAMIC_CLASS(wxTCPClient, wxClientBase) +IMPLEMENT_DYNAMIC_CLASS(wxTCPConnection, wxConnectionBase) + #include "wx/statusbr.h" IMPLEMENT_DYNAMIC_CLASS(wxStatusBar, wxWindow) diff --git a/src/gtk1/data.cpp b/src/gtk1/data.cpp index 8e02841a18..a0ab3cea95 100644 --- a/src/gtk1/data.cpp +++ b/src/gtk1/data.cpp @@ -400,6 +400,50 @@ IMPLEMENT_DYNAMIC_CLASS(wxToolBar95, wxToolBarBase) #endif +#include "wx/sckaddr.h" + +IMPLEMENT_DYNAMIC_CLASS(wxIPV4address, wxSockAddress) +#ifdef ENABLE_IPV6 +IMPLEMENT_DYNAMIC_CLASS(wxIPV6address, wxSockAddress) +#endif +#ifndef __UNIX__ +IMPLEMENT_DYNAMIC_CLASS(wxUNIXaddress, wxSockAddress) +#endif + +#include "wx/socket.h" + +IMPLEMENT_CLASS(wxSocketBase, wxEvtHandler) +IMPLEMENT_CLASS(wxSocketClient, wxSocketBase) +IMPLEMENT_CLASS(wxSocketServer, wxSocketBase) +IMPLEMENT_CLASS(wxSocketHandler, wxObject) +IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent) + +#include "wx/url.h" + +IMPLEMENT_CLASS(wxProtoInfo, wxObject) +IMPLEMENT_CLASS(wxURL, wxObject) + +#include "wx/protocol/http.h" + +IMPLEMENT_DYNAMIC_CLASS(wxHTTP, wxProtocol) +IMPLEMENT_PROTOCOL(wxHTTP, "http", "80", TRUE) + +#include "wx/protocol/ftp.h" + +IMPLEMENT_DYNAMIC_CLASS(wxFTP, wxProtocol) +IMPLEMENT_PROTOCOL(wxFTP, "ftp", "ftp", TRUE) + +#include "wx/protocol/sckfile.h" + +IMPLEMENT_DYNAMIC_CLASS(wxFileProto, wxProtocol) +IMPLEMENT_PROTOCOL(wxFileProto, "file", NULL, FALSE) + +#include "wx/sckipc.h" + +IMPLEMENT_DYNAMIC_CLASS(wxTCPServer, wxServerBase) +IMPLEMENT_DYNAMIC_CLASS(wxTCPClient, wxClientBase) +IMPLEMENT_DYNAMIC_CLASS(wxTCPConnection, wxConnectionBase) + #include "wx/statusbr.h" IMPLEMENT_DYNAMIC_CLASS(wxStatusBar, wxWindow) -- 2.45.2