From a324a7bccf4bda8f4f2bf09daee8104cae953cee Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Thu, 22 Jul 1999 17:51:54 +0000 Subject: [PATCH] Added GSocket for Unix (only GTK for the moment) Updated wxSocket to use GSocket API Added a progress bar to client.cpp Added CopyTo to wxMemoryOutputStream to copy the internal buffer to a specified buffer. Various changes/fixes to the high-level protocols FTP/HTTP Various Unicode fixes Removed sckint.* git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3085 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gsocket.h | 233 +++++++++ include/wx/mstream.h | 2 + include/wx/sckaddr.h | 64 +-- include/wx/sckint.h | 158 ------ include/wx/sckipc.h | 4 +- include/wx/sckstrm.h | 4 +- include/wx/socket.h | 141 ++---- include/wx/textctrl.h | 2 +- samples/wxsocket/client.cpp | 57 ++- samples/wxsocket/server.cpp | 13 +- src/common/ffile.cpp | 14 + src/common/ftp.cpp | 27 +- src/common/http.cpp | 66 ++- src/common/log.cpp | 5 +- src/common/mstream.cpp | 11 + src/common/sckaddr.cpp | 341 +++---------- src/common/sckint.cpp | 609 ----------------------- src/common/sckipc.cpp | 24 +- src/common/sckstrm.cpp | 39 +- src/common/socket.cpp | 928 ++++++++++++----------------------- src/common/stream.cpp | 6 +- src/common/textcmn.cpp | 2 +- src/common/url.cpp | 3 +- src/common/wfstream.cpp | 5 +- src/gtk/Makefile.am | 3 +- src/gtk/gsockgtk.c | 100 ++++ src/gtk1/Makefile.am | 3 +- src/gtk1/gsockgtk.c | 100 ++++ src/unix/gsocket.c | 940 ++++++++++++++++++++++++++++++++++++ src/unix/gsockunx.h | 57 +++ 30 files changed, 2069 insertions(+), 1892 deletions(-) create mode 100644 include/wx/gsocket.h delete mode 100644 include/wx/sckint.h delete mode 100644 src/common/sckint.cpp create mode 100644 src/gtk/gsockgtk.c create mode 100644 src/gtk1/gsockgtk.c create mode 100644 src/unix/gsocket.c create mode 100644 src/unix/gsockunx.h diff --git a/include/wx/gsocket.h b/include/wx/gsocket.h new file mode 100644 index 0000000000..096cff1666 --- /dev/null +++ b/include/wx/gsocket.h @@ -0,0 +1,233 @@ +/* ------------------------------------------------------------------------- + * Project: GSocket (Generic Socket) + * Name: gsocket.h + * Purpose: GSocket include file (system independent) + * CVSID: $Id$ + * Log: $Log$ + * Log: Revision 1.1 1999/07/22 17:51:47 GL + * Log: Added GSocket for Unix (only GTK for the moment) + * Log: Updated wxSocket to use GSocket API + * Log: Added a progress bar to client.cpp + * Log: Added CopyTo to wxMemoryOutputStream to copy the internal buffer to a specified buffer. + * Log: Various changes/fixes to the high-level protocols FTP/HTTP + * Log: Various Unicode fixes + * Log: Removed sckint.* + * Log: + * Log: Revision 1.2 1999/07/18 15:54:28 guilhem + * Log: Copyright, etc. + * Log: + * ------------------------------------------------------------------------- + */ +#ifndef __GSOCKET_H +#define __GSOCKET_H + +#include + +#if !defined(__cplusplus) + +typedef int bool; + +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +typedef struct _GSocket GSocket; +typedef struct _GAddress GAddress; + +typedef enum { + GSOCK_NOFAMILY = 0, + GSOCK_INET, + GSOCK_INET6, + GSOCK_UNIX +} GAddressType; + +typedef enum { + GSOCK_STREAMED, + GSOCK_UNSTREAMED +} GSocketStream; + +typedef enum { + GSOCK_NOERROR = 0, + GSOCK_INVOP, + GSOCK_IOERR, + GSOCK_INVADDR, + GSOCK_INVSOCK, + GSOCK_NOHOST, + GSOCK_INVPORT +} GSocketError; + +typedef enum { + GSOCK_INPUT = 0, + GSOCK_OUTPUT = 1, + GSOCK_CONNECTION = 2, + GSOCK_LOST = 3, + GSOCK_MAX_EVENT = 4 +} GSocketEvent; + +enum { + GSOCK_INPUT_FLAG = 1 << GSOCK_INPUT, + GSOCK_OUTPUT_FLAG = 1 << GSOCK_OUTPUT, + GSOCK_CONNECTION_FLAG = 1 << GSOCK_CONNECTION, + GSOCK_LOST_FLAG = 1 << GSOCK_LOST, +}; + +typedef int GSocketEventFlags; + +typedef void (*GSocketFallback)(GSocket *socket, GSocketEvent event, + char *cdata); + +#ifdef __cplusplus +extern "C" { +#endif + +/* Constructors / Destructors */ + +GSocket *GSocket_new(); +void GSocket_destroy(GSocket *socket); + +/* This will disable all IO calls to this socket but errors are still available */ +void GSocket_Shutdown(GSocket *socket); + +/* Address handling */ + +GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address); +GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address); +GAddress *GSocket_GetLocal(GSocket *socket); +GAddress *GSocket_GetPeer(GSocket *socket); + +/* Non-oriented connections handlers */ + +GSocketError GSocket_SetNonOriented(GSocket *socket); + +/* Server specific parts */ + +/* + GSocket_SetServer() setup the socket as a server. It uses the "Local" field + of GSocket. "Local" must be set by GSocket_SetLocal() before + GSocket_SetServer() is called. In the other case, it returns GSOCK_INVADDR. +*/ +GSocketError GSocket_SetServer(GSocket *socket); + +/* + GSocket_WaitConnection() waits for an incoming client connection. +*/ +GSocket *GSocket_WaitConnection(GSocket *socket); + +/* Client specific parts */ + +/* + GSocket_Connect() establishes a client connection to a server using the "Peer" + field of GSocket. "Peer" must be set by GSocket_SetPeer() before + GSocket_Connect() is called. In the other case, it returns GSOCK_INVADDR. +*/ +GSocketError GSocket_Connect(GSocket *socket, GSocketStream stream); + +/* Generic IO */ + +/* Like recv(), send(), ... */ +/* + NOTE: In case we read from a non-oriented connection, the incoming (outgoing) + connection address is stored in the "Local" ("Peer") field. +*/ +int GSocket_Read(GSocket *socket, char *buffer, int size); +int GSocket_Write(GSocket *socket, const char *buffer, + int size); +bool GSocket_DataAvailable(GSocket *socket); + +/* Flags */ + +/* + GSocket_SetBlocking() puts the socket in non-blocking mode. This is useful + if we don't want to wait. +*/ +void GSocket_SetBlocking(GSocket *socket, bool block); + +/* + GSocket_GetError() returns the last error occured on the socket stream. +*/ + +GSocketError GSocket_GetError(GSocket *socket); + +/* Callbacks */ + +/* + Only one fallback is possible for each event (INPUT, OUTPUT, CONNECTION, LOST) + INPUT: The function is called when there is at least a byte in the + input buffer + OUTPUT: The function is called when the system is sure the next write call + will not block + CONNECTION: Two cases is possible: + Client socket -> the connection is established + Server socket -> a client request a connection + LOST: the connection is lost + + SetFallback accepts a combination of these flags so a same callback can + receive different events. + + An event is generated only once and its state is reseted when the relative + IO call is requested. + For example: INPUT -> GSocket_Read() + CONNECTION -> GSocket_Accept() +*/ +void GSocket_SetFallback(GSocket *socket, GSocketEventFlags event, + GSocketFallback fallback, char *cdata); + +/* + UnsetFallback will disables all fallbacks specified by "event". + NOTE: event may be a combination of flags +*/ +void GSocket_UnsetFallback(GSocket *socket, GSocketEventFlags event); + +/* GAddress */ + +GAddress *GAddress_new(); +GAddress *GAddress_copy(GAddress *address); +void GAddress_destroy(GAddress *address); + +void GAddress_SetFamily(GAddress *address, GAddressType type); +GAddressType GAddress_GetFamily(GAddress *address); + +/* + The use of any of the next functions will set the address family to the adapted + one. For example if you use GAddress_INET_SetHostName, address family will be AF_INET + implicitely +*/ + +GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname); +GSocketError GAddress_INET_SetHostAddress(GAddress *address, + unsigned long hostaddr); +GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port); +GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port); + +GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, + size_t sbuf); +unsigned long GAddress_INET_GetHostAddress(GAddress *address); +unsigned short GAddress_INET_GetPort(GAddress *address); + +/* TODO: Define specific parts (INET6, UNIX) */ + +GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path); +GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf); + +/* + * System specific functions + */ + +/* On systems needing an event id */ +void GSocket_SetEventID(GSocket *socket, unsigned long evt_id); + +/* On systems which don't have background refresh */ +void GSocket_DoEvent(unsigned long evt_id); + +#ifdef __cplusplus +}; +#endif + +#endif + /* __GSOCKET_H */ diff --git a/include/wx/mstream.h b/include/wx/mstream.h index 65e67aa24f..c16cfea2ed 100644 --- a/include/wx/mstream.h +++ b/include/wx/mstream.h @@ -45,6 +45,8 @@ class wxMemoryOutputStream: public wxOutputStream { wxStreamBuffer *OutputStreamBuffer() const { return m_o_streambuf; } + size_t CopyTo(char *buffer, size_t len) const; + protected: wxStreamBuffer *m_o_streambuf; diff --git a/include/wx/sckaddr.h b/include/wx/sckaddr.h index b182548948..1ea7a599dd 100644 --- a/include/wx/sckaddr.h +++ b/include/wx/sckaddr.h @@ -20,52 +20,42 @@ #if wxUSE_SOCKETS -#if defined(__WINDOWS__) && defined(WXSOCK_INTERNAL) -#include - -#elif defined(__UNIX__) && defined(WXSOCK_INTERNAL) - -#include -#include -#include -#endif - #include "wx/string.h" +#include "gsocket.h" + class WXDLLEXPORT wxSockAddress : public wxObject { DECLARE_ABSTRACT_CLASS(wxSockAddress) public: typedef enum { IPV4=1, IPV6=2, UNIX=3 } Addr; - wxSockAddress() {}; - virtual ~wxSockAddress() {}; + wxSockAddress(); + virtual ~wxSockAddress(); + + virtual void Clear(); + virtual int Type() = 0; - virtual void Clear() = 0; + GAddress *GetAddress() const { return m_address; } + void SetAddress(GAddress *address); + const wxSockAddress& operator =(const wxSockAddress& addr); - virtual void Build(struct sockaddr*& addr, size_t& len) = 0; - virtual void Disassemble(struct sockaddr *addr, size_t len) = 0; - virtual int SockAddrLen() = 0; + void CopyObject(wxObject& dest) const; - virtual int GetFamily() = 0; - virtual int Type() = 0; +protected: + GAddress *m_address; }; 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(); + bool Hostname(const wxString& name); + bool Hostname(unsigned long addr); + bool Service(const wxString& name); + bool Service(unsigned short port); + bool LocalHost(); wxString Hostname(); unsigned short Service(); @@ -73,8 +63,6 @@ public: 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; } }; @@ -87,9 +75,6 @@ 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); @@ -99,11 +84,6 @@ public: 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 @@ -119,17 +99,9 @@ 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 diff --git a/include/wx/sckint.h b/include/wx/sckint.h deleted file mode 100644 index 103595f5f6..0000000000 --- a/include/wx/sckint.h +++ /dev/null @@ -1,158 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: sckint.h -// Purpose: Socket internal classes -// Author: Guilhem Lavaux -// Modified by: -// Created: April 1999 -// RCS-ID: $Id$ -// Copyright: (c) Guilhem Lavaux -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// -#ifndef _WX_NETWORK_SOCKET_INT_H -#define _WX_NETWORK_SOCKET_INT_H - -#ifdef __GNUG__ -#pragma interface -#endif - -#include "wx/defs.h" - -#if wxUSE_SOCKETS - -#include "wx/object.h" -#include "wx/list.h" -#include "wx/socket.h" -#include "wx/thread.h" - -// Socket state -class SocketState -{ - public: - // TRUE if the background notifyier is on. - bool notify_state; - // Specifies which events we want to be notified. - wxSocketBase::wxRequestNotify evt_notify_state; - // Socket flags. - wxSocketBase::wxSockFlags socket_flags; - // Pointer to the C callback function. - wxSocketBase::wxSockCbk c_callback; - char *c_callback_data; -}; - -// Socket request -class SockRequest -{ - public: - // Buffer where to get/put data. - char *buffer; - // Size of the buffer. - size_t size; - // Number of bytes really read/written. - size_t io_nbytes; - // Error. - unsigned int error; - // Type of the request. - wxSocketBase::wxRequestNotify type; - // Timeout (in milliseconds). - unsigned int timeout; - // TRUE if the buffer has been processed. - bool done; - // TRUE if we must wait for the request completion, in the other case an - // event will be sent to the main thread when the request is finished. - bool wait; -}; - -class wxSocketInternal; - -#if wxUSE_THREADS -class SocketWaiter: public wxThread { - public: - SocketWaiter(wxSocketBase *socket, wxSocketInternal *internal); - ~SocketWaiter(); - - // Thread Entry point - // --- - virtual void *Entry(); - - protected: - void ProcessReadEvent(); - void ProcessWriteEvent(); - - public: - wxSocketBase *m_socket; - wxSocketInternal *m_internal; - int m_fd; -}; -#endif - -class SocketRequester -#if wxUSE_THREADS - : public wxThread -#endif - { - public: - SocketRequester(wxSocketBase *socket, wxSocketInternal *internal); - ~SocketRequester(); - - void ProcessWaitEvent(SockRequest *req); - void ProcessReadEvent(SockRequest *req); - void ProcessWriteEvent(SockRequest *req); - - bool WaitFor(wxSocketBase::wxRequestNotify req, int millisec); - -#if wxUSE_THREADS - // Thread Entry point - // --- - virtual void *Entry(); -#endif - - public: - wxSocketBase *m_socket; - wxSocketInternal *m_internal; - int m_fd; -}; - -class wxSocketInternal { - public: - wxSocketInternal(wxSocketBase *socket); - ~wxSocketInternal(); - - // wxSocket thread manager - // ----------------------- - void AcquireData(); - void ReleaseData(); - void AcquireFD(); - void ReleaseFD(); - - int GetFD() { return m_fd; } - void SetFD(int fd) { m_fd = fd; } - - void ResumeWaiter(); - void StopWaiter(); - void ResumeRequester(); - void StopRequester(); - - void QueueRequest(SockRequest *request, bool async); - void WaitForEnd(SockRequest *request); - - // Used by SocketRequester - SockRequest *WaitForReq(); - void EndRequest(SockRequest *req); - public: - wxSocketBase *m_socket; -#if wxUSE_THREADS - wxMutex m_socket_locker, m_fd_locker, m_request_locker, m_end_requester; - wxCondition m_socket_cond; - SocketWaiter *m_thread_waiter; -#endif - SocketRequester *m_thread_requester; - wxList m_requests; - int m_fd; - bool m_invalid_requester; -}; - -#endif - // wxUSE_SOCKETS - -#endif - // _WX_NETWORK_SOCKET_INT_H diff --git a/include/wx/sckipc.h b/include/wx/sckipc.h index ef78d5f866..18e1a1908f 100644 --- a/include/wx/sckipc.h +++ b/include/wx/sckipc.h @@ -63,9 +63,9 @@ protected: friend class wxTCPServer; friend class wxTCPClient; friend void Client_OnRequest(wxSocketBase&, - wxSocketBase::wxRequestEvent, char *); + GSocketEvent, char *); friend void Server_OnRequest(wxSocketServer&, - wxSocketBase::wxRequestEvent, char *); + GSocketEvent, char *); public: wxTCPConnection(char *buffer, int size); diff --git a/include/wx/sckstrm.h b/include/wx/sckstrm.h index e22c65baf4..a330bb173f 100644 --- a/include/wx/sckstrm.h +++ b/include/wx/sckstrm.h @@ -27,7 +27,6 @@ class WXDLLEXPORT wxSocketOutputStream : public wxOutputStream wxSocketOutputStream(wxSocketBase& s); ~wxSocketOutputStream(); - wxOutputStream& Write(const void *buffer, size_t size); off_t SeekO( off_t WXUNUSED(pos), wxSeekMode WXUNUSED(mode) ) { return -1; } off_t TellO() @@ -45,7 +44,6 @@ class WXDLLEXPORT wxSocketInputStream : public wxInputStream wxSocketInputStream(wxSocketBase& s); ~wxSocketInputStream(); - wxInputStream& Read(void *buffer, size_t size); off_t SeekI( off_t WXUNUSED(pos), wxSeekMode WXUNUSED(mode) ) { return -1; } off_t TellI() @@ -69,4 +67,4 @@ class WXDLLEXPORT wxSocketStream : public wxSocketInputStream, // wxUSE_SOCKETS && wxUSE_STREAMS #endif - // __SCK_STREAM_H__ \ No newline at end of file + // __SCK_STREAM_H__ diff --git a/include/wx/socket.h b/include/wx/socket.h index 36a0934e45..b2dcf6056a 100644 --- a/include/wx/socket.h +++ b/include/wx/socket.h @@ -20,23 +20,6 @@ #if wxUSE_SOCKETS -// --------------------------------------------------------------------------- -// Windows(tm) specific -// --------------------------------------------------------------------------- -#if defined(__WINDOWS__) && defined(WXSOCK_INTERNAL) -#include -#include -#endif // defined(__WINDOWS__) && defined(WXSOCK_INTERNAL) - -// --------------------------------------------------------------------------- -// Unix specific -// --------------------------------------------------------------------------- -#if defined(__UNIX__) && defined(WXSOCK_INTERNAL) -#include -#include -#include -#endif // defined(__UNIX__) && defined(WXSOCK_INTERNAL) - // --------------------------------------------------------------------------- // wxSocket headers (generic) // --------------------------------------------------------------------------- @@ -48,48 +31,46 @@ #endif #include "wx/sckaddr.h" +#include "gsocket.h" class WXDLLEXPORT wxSocketEvent; -class WXDLLEXPORT wxSocketHandler; -class wxSocketInternal; class WXDLLEXPORT wxSocketBase : public wxEvtHandler { DECLARE_CLASS(wxSocketBase) -#ifdef __WXMAC__ - friend void wxMacSocketOnRequestProc(void *refcon , short event) ; -#endif 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, REQ_WAIT=0x40}; - 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; enum wxSockType { SOCK_CLIENT, SOCK_SERVER, SOCK_INTERNAL, SOCK_UNINIT }; - typedef void (*wxSockCbk)(wxSocketBase& sock,wxRequestEvent evt,char *cdata); + typedef void (*wxSockCbk)(wxSocketBase& sock,GSocketEvent evt,char *cdata); protected: - wxSockFlags m_flags; + GSocket *m_socket; // wxSocket socket + wxSockFlags m_flags; // wxSocket flags wxSockType m_type; // wxSocket type - bool m_connected, m_connecting; // State of the socket - int m_fd; // Socket file descriptors - wxList m_states; // States list - int m_id; // Socket id (for event handler) - wxSocketHandler *m_handler; // the current socket handler - wxRequestNotify m_neededreq; // Specify which requet signals we need - unsigned long m_timeout; + GSocketEventFlags m_neededreq; // Specify which requet signals we need size_t m_lcount; // Last IO request size - int m_error; // Last IO error - wxSocketInternal *m_internal; + unsigned long m_timeout; // IO timeout value + char *m_unread; // Pushback buffer size_t m_unrd_size; // Pushback buffer size - wxSockCbk m_cbk; - char *m_cdata; - bool m_notify_state; + size_t m_unrd_cur; // Pushback pointer + + wxSockCbk m_cbk; // C callback + char *m_cdata; // C callback data + + bool m_connected; // Connected ? + bool m_notify_state; // Notify state + int m_id; // Socket id (for event handler) + + enum { + DEFER_READ, DEFER_WRITE, NO_DEFER + } m_defering; // Defering state + char *m_defer_buffer; // Defering target buffer + size_t m_defer_nbytes; // Defering buffer size + + wxList m_states; // Stack of states public: wxSocketBase(); @@ -110,14 +91,15 @@ public: 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 Ok() const { return (m_socket != NULL); }; + inline bool Error() const + { return (GSocket_GetError(m_socket) != GSOCK_NOERROR); }; inline bool IsConnected() const { return m_connected; }; inline bool IsDisconnected() const { return !IsConnected(); }; - inline bool IsNoWait() const { return m_flags & NOWAIT; }; + inline bool IsNoWait() const { return ((m_flags & NOWAIT) != 0); }; bool IsData() const; inline size_t LastCount() const { return m_lcount; } - inline int LastError() const { return m_error; } + inline GSocketError LastError() const { return GSocket_GetError(m_socket); } inline wxSockType GetType() const { return m_type; } void SetFlags(wxSockFlags _flags); @@ -144,11 +126,11 @@ public: 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); + void SetNotify(GSocketEventFlags flags); + virtual void OnRequest(GSocketEvent req_evt); // Public internal callback - virtual void OldOnNotify(wxRequestEvent WXUNUSED(evt)); + virtual void OldOnNotify(GSocketEvent WXUNUSED(evt)); // Some info on the socket... virtual bool GetPeer(wxSockAddress& addr_man) const; @@ -158,9 +140,9 @@ public: void Notify(bool notify); // So you can know what the socket driver is looking for ... - inline wxRequestNotify NeededReq() const { return m_neededreq; } + inline GSocketEventFlags NeededReq() const { return m_neededreq; } - static wxRequestNotify EventToNotify(wxRequestEvent evt); + static GSocketEventFlags EventToNotify(GSocketEvent evt); protected: friend class wxSocketServer; @@ -178,18 +160,13 @@ protected: #endif bool _Wait(long seconds, long microseconds, int type); - - // Set "my" handler - inline virtual void SetHandler(wxSocketHandler *handler) - { m_handler = handler; } + int DeferRead(char *buffer, size_t nbytes); + int DeferWrite(const char *buffer, size_t nbytes); + void DoDefer(GSocketEvent evt); + // 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); }; //////////////////////////////////////////////////////////////////////// @@ -221,45 +198,7 @@ public: bool WaitOnConnect(long seconds = -1, long microseconds = 0); - virtual void OnRequest(wxRequestEvent flags); -}; - -//////////////////////////////////////////////////////////////////////// - -class WXDLLEXPORT wxSocketHandler : public wxObject -{ - DECLARE_CLASS(wxSocketHandler) -protected: - wxList *socks; - -public: - enum SockStatus { SOCK_NONE, SOCK_DATA, SOCK_CONNECT, SOCK_DISCONNECT, - SOCK_ERROR }; - static wxSocketHandler *master; - - 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; } + virtual void OnRequest(GSocketEvent flags); }; class WXDLLEXPORT wxSocketEvent : public wxEvent { @@ -267,13 +206,13 @@ class WXDLLEXPORT wxSocketEvent : public wxEvent { public: wxSocketEvent(int id = 0); - wxSocketBase::wxRequestEvent SocketEvent() const { return m_skevt; } + GSocketEvent SocketEvent() const { return m_skevt; } wxSocketBase *Socket() const { return m_socket; } void CopyObject(wxObject& obj_d) const; public: - wxSocketBase::wxRequestEvent m_skevt; + GSocketEvent m_skevt; wxSocketBase *m_socket; }; diff --git a/include/wx/textctrl.h b/include/wx/textctrl.h index 1718f73664..0de57cdcf6 100644 --- a/include/wx/textctrl.h +++ b/include/wx/textctrl.h @@ -145,7 +145,7 @@ public: wxTextCtrl& operator<<(long i); wxTextCtrl& operator<<(float f); wxTextCtrl& operator<<(double d); - wxTextCtrl& operator<<(const char c); + wxTextCtrl& operator<<(const wxChar c); // obsolete functions #if WXWIN_COMPATIBILITY diff --git a/samples/wxsocket/client.cpp b/samples/wxsocket/client.cpp index 646aabfe8c..feb050d03a 100644 --- a/samples/wxsocket/client.cpp +++ b/samples/wxsocket/client.cpp @@ -28,6 +28,7 @@ #include "wx/url.h" #include "wx/protocol/http.h" #include "wx/thread.h" +#include "wx/progdlg.h" #if defined(__WXMOTIF__) || defined(__WXGTK__) #include "mondrian.xpm" @@ -58,6 +59,8 @@ public: void OnExecCloseConnection(wxCommandEvent& evt); void UpdateStatus(); + void Download(wxInputStream *input); + DECLARE_EVENT_TABLE() }; @@ -72,7 +75,7 @@ class MyClient: public wxSocketClient public: MyFrame *frame; - void OnNotify(wxRequestNotify WXUNUSED(flags)) { frame->UpdateStatus(); } + void OnNotify(GSocketEventFlags WXUNUSED(flags)) { frame->UpdateStatus(); } }; // ID for the menu quit command @@ -134,14 +137,10 @@ 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::wxSockFlags) (wxSocketBase::WAITALL | wxSocketBase::SPEED)); - wxSocketHandler::Master().Register(sock); sock->frame = this; - sock->SetNotify(wxSocketBase::REQ_LOST); + sock->SetNotify(GSOCK_LOST_FLAG); CreateStatusBar(2); UpdateStatus(); } @@ -169,6 +168,7 @@ void MyFrame::OnExecOpenConnection(wxCommandEvent& WXUNUSED(evt)) addr.Service(3000); sock->SetNotify(0); sock->Connect(addr, TRUE); + sock->SetFlags(wxSocketBase::NONE); if (!sock->IsConnected()) wxMessageBox("Can't connect to the specified host", "Alert !"); @@ -177,8 +177,7 @@ void MyFrame::OnExecOpenConnection(wxCommandEvent& WXUNUSED(evt)) void MyFrame::OnExecCloseConnection(wxCommandEvent& WXUNUSED(evt)) { - if (sock) - sock->Close(); + sock->Close(); UpdateStatus(); } @@ -271,6 +270,43 @@ void MyFrame::OnExecTest1(wxCommandEvent& WXUNUSED(evt)) delete dlgbox; } + +void MyFrame::Download(wxInputStream *input) +{ + wxProgressDialog progress("Downloading ...", "0% downloaded"); + wxBufferedInputStream buf_in(*input); + wxFileOutputStream f_out("test.url"); + + size_t file_size = input->StreamSize(); + size_t downloaded; + int BUFSIZE = (file_size > 100) ? (file_size / 100) : file_size; + int bytes_read = BUFSIZE; + wxString message; + int percents; + + char *buf; + +// TODO: Support for streams which don't support StreamSize + + buf = new char[BUFSIZE]; + + downloaded = 0; + bytes_read = BUFSIZE; + while (downloaded < file_size && bytes_read != 0) { + bytes_read = buf_in.Read(buf, BUFSIZE).LastRead(); + f_out.Write(buf, bytes_read); + downloaded += bytes_read; + + percents = downloaded * 100 / file_size; + + message = _T(""); + message << percents << _T("% downloaded"); + progress.Update(percents, message); + } + + delete[] buf; +} + void MyFrame::OnExecUrlTest(wxCommandEvent& WXUNUSED(evt)) { wxString urlname = wxGetTextFromUser("Enter an URL to get", @@ -284,11 +320,8 @@ void MyFrame::OnExecUrlTest(wxCommandEvent& WXUNUSED(evt)) error.Printf(_T("Error in getting data from the URL. (error = %d)"), url.GetError()); wxMessageBox(error, "Alert !"); } else { - wxFileOutputStream *str_out = new wxFileOutputStream("test.url"); - str_out->Write(*datas); + Download(datas); - wxMessageBox(_T("Success !! Click on OK to see the text."), "OK"); delete datas; - delete str_out; } } diff --git a/samples/wxsocket/server.cpp b/samples/wxsocket/server.cpp index 56f2dfc303..c7bbd60c87 100644 --- a/samples/wxsocket/server.cpp +++ b/samples/wxsocket/server.cpp @@ -111,7 +111,7 @@ void MyFrame::OnSockRequest(wxSocketEvent& evt) printf("OnSockRequest OK\n"); printf("OnSockRequest (event = %d)\n",evt.SocketEvent()); switch (evt.SocketEvent()) { - case wxSocketBase::EVT_READ: + case GSOCK_INPUT: unsigned char c; sock->Read((char *)&c, 1); @@ -119,7 +119,7 @@ void MyFrame::OnSockRequest(wxSocketEvent& evt) ExecTest1(sock); break; - case wxSocketBase::EVT_LOST: + case GSOCK_LOST: printf("Destroying socket\n"); wxPendingDelete.Append(sock); UpdateStatus(-1); @@ -127,7 +127,6 @@ void MyFrame::OnSockRequest(wxSocketEvent& evt) break; } printf("OnSockRequest Exiting\n"); - sock->SetNotify(wxSocketBase::REQ_READ | wxSocketBase::REQ_LOST); } void MyFrame::OnSockRequestServer(wxSocketEvent& evt) @@ -151,10 +150,10 @@ void MyFrame::OnSockRequestServer(wxSocketEvent& evt) return; UpdateStatus(1); - sock2->SetFlags(wxSocketBase::SPEED); + sock2->SetFlags(wxSocketBase::NONE); sock2->Notify(TRUE); sock2->SetEventHandler(*this, SKDEMO_SOCKET); - server->SetNotify(wxSocketBase::REQ_ACCEPT); + sock2->SetNotify(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG); } // My frame Constructor @@ -166,11 +165,9 @@ MyFrame::MyFrame(wxFrame *frame): addr.Service(3000); // Init all - wxSocketHandler::Master(); sock = new wxSocketServer(addr); - wxSocketHandler::Master().Register(sock); - sock->SetNotify(wxSocketBase::REQ_ACCEPT); + sock->SetNotify(GSOCK_CONNECTION_FLAG); sock->SetEventHandler(*this, SKDEMO_SOCKET_SERV); sock->SetFlags(wxSocketBase::SPEED); sock->Notify(TRUE); diff --git a/src/common/ffile.cpp b/src/common/ffile.cpp index f880a43134..4449ec42a2 100644 --- a/src/common/ffile.cpp +++ b/src/common/ffile.cpp @@ -56,7 +56,21 @@ bool wxFFile::Open(const wxChar *filename, const char *mode) { wxASSERT_MSG( !m_fp, _T("should close or detach the old file first") ); +#if wxUSE_UNICODE + char *tmp_fname; + size_t fname_len; + + fname_len = wxStrlen(filename)+1; + tmp_fname = new char[fname_len]; + wxWX2MB(tmp_fname, filename, fname_len); + + m_fp = fopen(tmp_fname, mode); + + delete tmp_fname; +#else m_fp = fopen(filename, mode); +#endif + if ( !m_fp ) { diff --git a/src/common/ftp.cpp b/src/common/ftp.cpp index b513f7e404..c9e56751ee 100644 --- a/src/common/ftp.cpp +++ b/src/common/ftp.cpp @@ -69,6 +69,7 @@ wxFTP::wxFTP() m_passwd += wxGetHostName(); SetNotify(0); + SetFlags(NONE); } wxFTP::~wxFTP() @@ -81,11 +82,6 @@ wxFTP::~wxFTP() //////////////////////////////////////////////////////////////// bool wxFTP::Connect(wxSockAddress& addr, bool WXUNUSED(wait)) { - if (!m_handler) { - m_lastError = wxPROTO_NOHNDLR; - return FALSE; - } - if (!wxProtocol::Connect(addr)) { m_lastError = wxPROTO_NETERR; return FALSE; @@ -256,7 +252,7 @@ public: size_t StreamSize() const { return m_ftpsize; } virtual ~wxInputFTPStream(void) { - if (LastError() != wxStream_NOERROR) + if (LastError() == wxStream_NOERROR) m_ftp->GetResult('2'); else m_ftp->Abort(); @@ -284,15 +280,15 @@ wxSocketClient *wxFTP::GetPort() { wxIPV4address addr; wxSocketClient *client; - struct sockaddr sin; int a[6]; wxString straddr; int addr_pos; + wxUint16 port; + wxUint32 hostaddr; if (!SendCommand(_T("PASV"), '2')) return NULL; - sin.sa_family = AF_INET; addr_pos = m_lastResult.Find(_T('(')); if (addr_pos == -1) { m_lastError = wxPROTO_PROTERR; @@ -300,16 +296,15 @@ wxSocketClient *wxFTP::GetPort() } straddr = m_lastResult(addr_pos+1, m_lastResult.Length()); wxSscanf((const wxChar *)straddr,_T("%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)); + hostaddr = (wxUint16)a[5] << 24 | (wxUint16)a[4] << 16 | + (wxUint16)a[3] << 8 | a[2]; + addr.Hostname(hostaddr); + + port = (wxUint16)a[0] << 8 | a[1]; + addr.Service(port); - client = m_handler->CreateClient(); + client = new wxSocketClient(); if (!client->Connect(addr)) { delete client; return NULL; diff --git a/src/common/http.cpp b/src/common/http.cpp index 06cfbd02e8..cb194e82d3 100644 --- a/src/common/http.cpp +++ b/src/common/http.cpp @@ -46,7 +46,7 @@ wxHTTP::wxHTTP() m_addr = NULL; m_read = FALSE; - SetNotify(REQ_LOST); + SetNotify(GSOCK_LOST_FLAG); } wxHTTP::~wxHTTP() @@ -120,8 +120,8 @@ bool wxHTTP::ParseHeaders() m_read = TRUE; while (1) { - m_error = GetLine(this, line); - if (m_error != wxPROTO_NOERR) + m_perr = GetLine(this, line); + if (m_perr != wxPROTO_NOERR) return FALSE; if (line.Length() == 0) @@ -154,7 +154,7 @@ bool wxHTTP::Connect(const wxString& host) if (!addr->Hostname(host)) { delete m_addr; m_addr = NULL; - m_error = wxPROTO_NETERR; + m_perr = wxPROTO_NETERR; return FALSE; } @@ -166,22 +166,25 @@ bool wxHTTP::Connect(const wxString& host) bool wxHTTP::Connect(wxSockAddress& addr, bool WXUNUSED(wait)) { - struct sockaddr *raw_addr; - size_t len; - - m_addr = (wxSockAddress *)(addr.GetClassInfo()->CreateObject()); - - addr.Build(raw_addr, len); - m_addr->Disassemble(raw_addr, len); + if (m_addr) { + delete m_addr; + m_addr = NULL; + Close(); + } + m_addr = (wxSockAddress *) addr.Clone(); return TRUE; } bool wxHTTP::BuildRequest(const wxString& path, wxHTTP_Req req) { wxChar *tmp_buf; - wxChar buf[200]; - wxWX2MBbuf pathbuf(200); + wxChar buf[200]; // 200 is arbitrary. +#if wxUNICODE + wxWX2MBbuf pathbuf((size_t)200); +#else + const wxWX2MBbuf pathbuf; +#endif wxString tmp_str; switch (req) { @@ -197,14 +200,14 @@ bool wxHTTP::BuildRequest(const wxString& path, wxHTTP_Req req) Notify(FALSE); tmp_str = wxURL::ConvertToValidURI(path); - wxSprintf(buf, _T("%s %s\n\r"), tmp_buf, tmp_str.GetData()); + wxSprintf(buf, _T("%s %s HTTP/1.0\n\r"), tmp_buf, tmp_str.GetData()); pathbuf = wxConvLibc.cWX2MB(buf); - Write(pathbuf, strlen(pathbuf)); + Write(pathbuf, strlen(MBSTRINGCAST pathbuf)); SendHeaders(); Write("\n\r", 2); - m_error = GetLine(this, tmp_str); - if (m_error != wxPROTO_NOERR) { + m_perr = GetLine(this, tmp_str); + if (m_perr != wxPROTO_NOERR) { RestoreState(); return FALSE; } @@ -228,7 +231,7 @@ bool wxHTTP::BuildRequest(const wxString& path, wxHTTP_Req req) case 200: break; default: - m_error = wxPROTO_NOFILE; + m_perr = wxPROTO_NOFILE; RestoreState(); return FALSE; } @@ -242,12 +245,29 @@ class wxHTTPStream : public wxSocketInputStream { public: wxHTTP *m_http; size_t m_httpsize; + unsigned long m_read_bytes; wxHTTPStream(wxHTTP *http) : wxSocketInputStream(*http), m_http(http) {} size_t StreamSize() const { return m_httpsize; } virtual ~wxHTTPStream(void) { m_http->Abort(); } + +protected: + size_t OnSysRead(void *buffer, size_t bufsize); }; +size_t wxHTTPStream::OnSysRead(void *buffer, size_t bufsize) +{ + size_t ret; + + if (m_httpsize > 0 && m_read_bytes >= m_httpsize) + return 0; + + ret = wxSocketInputStream::OnSysRead(buffer, bufsize); + m_read_bytes += ret; + + return ret; +} + bool wxHTTP::Abort(void) { return wxSocketClient::Close(); @@ -258,7 +278,7 @@ wxInputStream *wxHTTP::GetInputStream(const wxString& path) wxHTTPStream *inp_stream = new wxHTTPStream(this); if (!m_addr || m_connected) { - m_error = wxPROTO_CONNERR; + m_perr = wxPROTO_CONNERR; return NULL; } @@ -268,11 +288,15 @@ wxInputStream *wxHTTP::GetInputStream(const wxString& path) if (!BuildRequest(path, wxHTTP_GET)) return NULL; - wxPrintf(_T("Len = %s\n"), WXSTRINGCAST GetHeader(_T("Content-Length"))); if (!GetHeader(_T("Content-Length")).IsEmpty()) inp_stream->m_httpsize = wxAtoi(WXSTRINGCAST GetHeader(_T("Content-Length"))); + else + inp_stream->m_httpsize = (size_t)-1; + + inp_stream->m_read_bytes = 0; + + Notify(FALSE); - SetFlags(WAITALL); return inp_stream; } diff --git a/src/common/log.cpp b/src/common/log.cpp index b71af7bd54..318f0706b3 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -47,6 +47,7 @@ #include "wx/file.h" #include "wx/textfile.h" #include "wx/utils.h" +#include "wx/wxchar.h" #include "wx/log.h" // other standard headers @@ -322,7 +323,7 @@ void wxLog::TimeStamp(wxString *str) wxChar buf[256]; time_t timeNow; (void)time(&timeNow); - wxStrftime(buf, WXSIZEOF(buf), ms_timestamp, localtime(&timeNow)); +// wxStrftime(buf, WXSIZEOF(buf), ms_timestamp, localtime(&timeNow)); str->Empty(); *str << buf << _T(": "); @@ -896,7 +897,7 @@ wxLog *wxLog::ms_pLogger = (wxLog *)NULL; bool wxLog::ms_doLog = TRUE; bool wxLog::ms_bAutoCreate = TRUE; -const wxChar *wxLog::ms_timestamp = "%X"; // time only, no date +const wxChar *wxLog::ms_timestamp = _T("%X"); // time only, no date wxTraceMask wxLog::ms_ulTraceMask = (wxTraceMask)0; wxArrayString wxLog::ms_aTraceMasks; diff --git a/src/common/mstream.cpp b/src/common/mstream.cpp index 4555d35062..04501d5e5d 100644 --- a/src/common/mstream.cpp +++ b/src/common/mstream.cpp @@ -99,5 +99,16 @@ off_t wxMemoryOutputStream::OnSysTell() const return m_o_streambuf->Tell(); } +size_t wxMemoryOutputStream::CopyTo(char *buffer, size_t len) const +{ + if (!buffer) + return 0; + + if (len > StreamSize()) + len = StreamSize(); + + memcpy(buffer, m_o_streambuf->GetBufferStart(), len); + return len; +} #endif diff --git a/src/common/sckaddr.cpp b/src/common/sckaddr.cpp index ab9a1f78c6..e6f63b2ca3 100644 --- a/src/common/sckaddr.cpp +++ b/src/common/sckaddr.cpp @@ -22,9 +22,6 @@ #if wxUSE_SOCKETS -#ifndef WX_PRECOMP -#endif - #include #include #include @@ -33,43 +30,10 @@ #include #endif -#include "wx/defs.h" -#include "wx/object.h" - -#if defined(__WXMAC__) -#include "/wx/mac/macsock.h" -#endif - -#if defined(__WINDOWS__) -#include -#endif // __WINDOWS__ - -#if defined(__UNIX__) -#ifdef VMS -#include -#include -#else -#include -#include -#include -#include -#endif -#include -#include - -#ifdef __SUN__ -extern "C" -{ - struct hostent *gethostbyname(const char *name); - int gethostname(char *name, int namelen); -}; -#endif - -#endif // __UNIX__ - -#include "wx/sckaddr.h" - -#define CHECK_ADDRTYPE(var, type) +#include +#include +#include +#include #if !USE_SHARED_LIBRARY IMPLEMENT_ABSTRACT_CLASS(wxSockAddress, wxObject) @@ -82,343 +46,178 @@ IMPLEMENT_DYNAMIC_CLASS(wxUNIXaddress, wxSockAddress) #endif #endif -wxIPV4address::wxIPV4address() +// --------------------------------------------------------------------------- +// wxIPV4address +// --------------------------------------------------------------------------- + +wxSockAddress::wxSockAddress() { - m_addr = new sockaddr_in; - Clear(); + m_address = GAddress_new(); } -wxIPV4address::~wxIPV4address() +wxSockAddress::~wxSockAddress() { + GAddress_destroy(m_address); } -int wxIPV4address::SockAddrLen() +void wxSockAddress::SetAddress(GAddress *address) { - return sizeof(*m_addr); + GAddress_destroy(m_address); + m_address = GAddress_copy(address); } -int wxIPV4address::GetFamily() +const wxSockAddress& wxSockAddress::operator=(const wxSockAddress& addr) { - return AF_INET; + SetAddress(addr.GetAddress()); + return *this; } -void wxIPV4address::Clear() +void wxSockAddress::CopyObject(wxObject& dest) const { - memset(m_addr, 0, sizeof(*m_addr)); - m_addr->sin_family = AF_INET; - m_addr->sin_addr.s_addr = INADDR_ANY; + wxSockAddress *addr = (wxSockAddress *)&dest; + + wxObject::CopyObject(dest); + addr->SetAddress(GetAddress()); } -/* -const wxSockAddress& wxIPV4address::operator =(const wxSockAddress& addr) -{ - wxIPV4address *ip_addr = (wxIPV4address *)&addr; - CHECK_ADDRTYPE(addr, wxIPV4address); - m_addr = ip_addr->m_addr; - return *this; +void wxSockAddress::Clear() +{ + GAddress_destroy(m_address); + m_address = GAddress_new(); } -*/ -bool wxIPV4address::Hostname(const wxString& name) +// --------------------------------------------------------------------------- +// wxIPV4address +// --------------------------------------------------------------------------- + +wxIPV4address::wxIPV4address() + : wxSockAddress() { - struct hostent *theHostent; - struct in_addr *addr; - - if (name.IsNull()) - return FALSE; - - if (!name.IsNumber()) { - if ((theHostent = gethostbyname(name.fn_str())) == 0) { - return FALSE; - } - } else { -#ifdef __WXMAC__ - long len_addr = inet_addr(name.fn_str()).s_addr ; -#else - long len_addr = inet_addr(name.fn_str()); -#endif - if (len_addr == -1) - return FALSE; - m_addr->sin_addr.s_addr = len_addr; - return TRUE; - } +} - addr = (struct in_addr *) *(theHostent->h_addr_list); +wxIPV4address::~wxIPV4address() +{ +} - m_addr->sin_addr.s_addr = addr[0].s_addr; - return TRUE; +bool wxIPV4address::Hostname(const wxString& name) +{ + return (GAddress_INET_SetHostName(m_address, name.fn_str()) == GSOCK_NOERROR); } bool wxIPV4address::Hostname(unsigned long addr) { - m_addr->sin_addr.s_addr = htonl(addr); - return TRUE; + /* Need API */ + return TRUE; } bool wxIPV4address::Service(const wxString& name) { - struct servent *theServent; - - if (name.IsNull()) - return FALSE; - - if (!name.IsNumber()) { - if ((theServent = getservbyname(name.fn_str(), "tcp")) == 0) - return FALSE; - } else { - if ((theServent = getservbyport(wxAtoi(name), "tcp")) == 0) { - m_addr->sin_port = htons(wxAtoi(name)); - return TRUE; - } - } - - m_addr->sin_port = theServent->s_port; - return TRUE; + return (GAddress_INET_SetPortName(m_address, name.fn_str()) == GSOCK_NOERROR); } bool wxIPV4address::Service(unsigned short port) { - m_addr->sin_port = htons(port); - return TRUE; + return (GAddress_INET_SetPort(m_address, port) == GSOCK_NOERROR); } bool wxIPV4address::LocalHost() { - static char buf[256]; - - if (gethostname(buf, sizeof(buf)) < 0) - return Hostname("localhost"); - else - return Hostname(buf); + return (GAddress_INET_SetHostName(m_address, "localhost") == GSOCK_NOERROR); } wxString wxIPV4address::Hostname() { - struct hostent *h_ent; - - h_ent = gethostbyaddr((char *)&(m_addr->sin_addr), sizeof(m_addr->sin_addr), - GetFamily()); - - if (!h_ent) - return wxString(""); - else - return wxString(h_ent->h_name); -} - -unsigned short wxIPV4address::Service() -{ - return ntohs(m_addr->sin_port); -} + char hostname[1024]; -void wxIPV4address::Build(struct sockaddr *&addr, size_t& len) -{ - addr = (struct sockaddr *)m_addr; - len = sizeof(*m_addr); + hostname[0] = 0; + GAddress_INET_GetHostName(m_address, hostname, 1024); + return wxString(hostname); } -void wxIPV4address::Disassemble(struct sockaddr *addr, size_t len) +unsigned short wxIPV4address::Service() { - if (len != sizeof(*m_addr)) - return; - *m_addr = *(struct sockaddr_in *)addr; + return GAddress_INET_GetPort(m_address); } #ifdef IPV6_ENABLE +// --------------------------------------------------------------------------- +// wxIPV6address +// --------------------------------------------------------------------------- wxIPV6address::wxIPV6address() + : wxSockAddress() { - 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 *theHostent; - struct in_addr *addr; - - if (name.IsNull()) - return FALSE; - - if (!name.IsNumber()) { - hostent = gethostbyname2((char*) name, AF_INET6); - if (!theHostent) - return FALSE; - } else { - // Don't how to do - return FALSE; - } - - addr = (struct in6_addr *) *(theHostent->h_addr_list); - - m_addr->sin6_addr.s6_addr = addr[0].s6_addr; - return TRUE; + return (GAddress_INET_SetHostName(m_address, name.fn_str()) == GSOCK_NOERROR); } bool wxIPV6address::Hostname(unsigned char addr[16]) { - m_addr->sin6_addr.s6_addr = addr; return TRUE; } bool wxIPV6address::Service(const char *name) { - struct servent *theServent; - - if (!name || !strlen(name)) - return FALSE; - - if (!isdigit(*name)) { - if ((theServent = getservbyname((char*) name, "tcp")) == 0) - return FALSE; - } else { - if ((theServent = getservbyport(atoi(name), "tcp")) == 0) { - m_addr->sin_port = htons(atoi(name)); - return TRUE; - } - } - - m_addr->sin_port = theServent->s_port; - return TRUE; + return (GAddress_INET_SetPortName(m_address, name.fn_str()) == GSOCK_NOERROR); } bool wxIPV6address::Service(unsigned short port) { - m_addr->sin_port = htons(port); - return TRUE; + return (GAddress_INET_SetPort(m_address, port) == GSOCK_NOERROR); } bool wxIPV6address::LocalHost() { - static char buf[256]; - - if (gethostname(buf, sizeof(buf)) < 0) - return Hostname("localhost"); - else - return Hostname(buf); + return (GAddress_INET_SetHostName(m_address, "localhost") == GSOCK_NOERROR); } 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); + return wxString(GAddress_INET_GetHostName(m_address)); } 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; + return GAddress_INET_GetPort(m_address); } #endif #ifdef __UNIX__ -#include +// --------------------------------------------------------------------------- +// wxUNIXaddress +// --------------------------------------------------------------------------- wxUNIXaddress::wxUNIXaddress() + : wxSockAddress() { - 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", MBSTRINGCAST fname.mb_str()); + GAddress_UNIX_SetPath(m_address, fname.fn_str()); } wxString wxUNIXaddress::Filename() { - return wxString(m_addr->sun_path); -} + char path[1024]; -void wxUNIXaddress::Build(struct sockaddr*& addr, size_t& len) -{ - addr = (struct sockaddr *)m_addr; - len = sizeof(*m_addr); + path[0] = 0; + GAddress_UNIX_GetPath(m_address, path, 1024); + return wxString(path); } -void wxUNIXaddress::Disassemble(struct sockaddr *addr, size_t len) -{ - if (len != sizeof(*m_addr)) - return; - *m_addr = *(struct sockaddr_un *)addr; -} #endif #endif diff --git a/src/common/sckint.cpp b/src/common/sckint.cpp deleted file mode 100644 index f2d56164b0..0000000000 --- a/src/common/sckint.cpp +++ /dev/null @@ -1,609 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Name: sckint.cpp -// Purpose: Socket internal classes -// Authors: Guilhem Lavaux -// Created: April 1999 -// Updated: -// Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux -// RCS_ID: $Id$ -// License: see wxWindows license -/////////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "sckint.h" -#endif - -// For compilers that support precompilation, includes "wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#if wxUSE_SOCKETS - -#define WXSOCK_INTERNAL -#include "wx/object.h" -#include "wx/list.h" -#include "wx/socket.h" -#include "wx/thread.h" -#include "wx/sckint.h" -#include "wx/sckint.h" -#include "wx/utils.h" - -// IRIX requires bstring.h be included to use select() -#ifdef sgi - #include -#endif // IRIX - -#ifndef __WXSTUBS__ - -#include -#include -#include - -// ----------------------- -// System specific headers -// ----------------------- - -#ifdef __WXMAC__ -// in order to avoid problems with our c library and double definitions -#define close closesocket -#define ioctl ioctlsocket - -#include -#endif - -#if defined(__WINDOWS__) -#include -#endif // __WINDOWS__ - -#if defined(__UNIX__) - -#ifdef VMS -#include -#else -#include -#endif -#include - -#include -#include - -#ifdef sun -#include -#endif - -#endif // __UNIX__ - -#include -#include - -#ifdef __VISUALC__ -#include -#endif - -// Constants -#define READ_MASK wxSocketBase::REQ_READ | wxSocketBase::REQ_ACCEPT | wxSocketBase::REQ_LOST -#define WRITE_MASK wxSocketBase::REQ_WRITE | wxSocketBase::REQ_CONNECT - -// -------------------------------------------------------------- -// --------- SocketWaiter --------------------------------------- -// -------------------------------------------------------------- - -#if wxUSE_THREADS -SocketWaiter::SocketWaiter(wxSocketBase *socket, - wxSocketInternal *internal) - : wxThread(), - m_socket(socket), m_internal(internal), m_fd(internal->GetFD()) -{ -} - -SocketWaiter::~SocketWaiter() -{ -} - -void SocketWaiter::ProcessReadEvent() -{ - int ret; - char c; - - m_internal->AcquireFD(); - ret = recv(m_fd, &c, 1, MSG_PEEK); - m_internal->ReleaseFD(); - - // We are a server => emit a EVT_ACCEPT event. - if (ret == -1 && m_socket->GetType() == wxSocketBase::SOCK_SERVER) { - m_socket->OnRequest(wxSocketBase::EVT_ACCEPT); - return; - } - - // Else, no error => there is something to be read else - // we've lost the connection. - if (ret > 0) { - m_socket->OnRequest(wxSocketBase::EVT_READ); - } else { - m_socket->OnRequest(wxSocketBase::EVT_LOST); - m_internal->ReleaseData(); // In that case, we mustn't forget to unlock the mutex. - Exit(NULL); - } -} - -void SocketWaiter::ProcessWriteEvent() -{ - if (m_socket->IsConnected()) - m_socket->OnRequest(wxSocketBase::EVT_CONNECT); - else - m_socket->OnRequest(wxSocketBase::EVT_WRITE); -} - -void *SocketWaiter::Entry() -{ - struct timeval tv; - fd_set sockrd_set, sockwr_set; - wxSocketEvent event; - int ret; - - while (1) { - // We won't wait. - tv.tv_sec = 0; - tv.tv_usec = 0; - - FD_ZERO(&sockrd_set); - FD_ZERO(&sockwr_set); - - m_internal->AcquireData(); - - if ((m_socket->NeededReq() & READ_MASK) != 0) - FD_SET(m_fd, &sockrd_set); - if ((m_socket->NeededReq() & WRITE_MASK) != 0) - FD_SET(m_fd, &sockwr_set); - - m_internal->AcquireFD(); - ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv); - m_internal->ReleaseFD(); - - if (FD_ISSET(m_fd, &sockrd_set)) - ProcessReadEvent(); - - if (FD_ISSET(m_fd, &sockwr_set)) - ProcessWriteEvent(); - - m_internal->ReleaseData(); - -#if wxUSE_THREADS -#ifdef Yield -#undef Yield -#endif -#endif - - // We wait for 100 ms to prevent the CPU from burning. - wxUsleep(100); - - // Check whether we should exit. - if (TestDestroy()) - return NULL; - } - return NULL; -} - -#endif - -// -------------------------------------------------------------- -// --------- SocketRequester ------------------------------------ -// -------------------------------------------------------------- - -SocketRequester::SocketRequester(wxSocketBase *socket, - wxSocketInternal *internal) - : -#if wxUSE_THREADS - wxThread(), -#endif - m_socket(socket), m_internal(internal), m_fd(internal->GetFD()) -{ -} - -SocketRequester::~SocketRequester() -{ -} - -bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req, int millisec) -{ - int ret; - struct timeval tv; - fd_set sockrd_set, sockwr_set; - - // We won't wait. - tv.tv_sec = millisec / 1000; - tv.tv_usec = (millisec % 1000) * 1000; - - FD_ZERO(&sockrd_set); - FD_ZERO(&sockwr_set); - if ((req & READ_MASK) != 0) - FD_SET(m_fd, &sockrd_set); - if ((req & WRITE_MASK) != 0) - FD_SET(m_fd, &sockwr_set); - - m_internal->AcquireFD(); - ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv); - m_internal->ReleaseFD(); - - return (ret != 0); -} - -void SocketRequester::ProcessReadEvent(SockRequest *req) -{ - int ret; - size_t len; - - // We'll wait for the first byte, in case a "timeout event" occurs it returns // immediately - if (!WaitFor(wxSocketBase::REQ_READ, req->timeout)) { - m_internal->EndRequest(req); - return; - } - - m_internal->AcquireFD(); - ret = recv(m_fd, req->buffer, req->size, - (req->type == wxSocketBase::REQ_PEEK) ? MSG_PEEK : 0); - m_internal->ReleaseFD(); - - // An error occured, we exit. - if (ret < 0) { - req->error = errno; - m_internal->EndRequest(req); - return; - } - len = ret; - - // If the buffer isn't full (and we want it to be full), we don't unqueue it. - if ((len < req->size) && (m_socket->GetFlags() & wxSocketBase::WAITALL)) { - req->size -= len; - req->io_nbytes += len; - req->buffer += len; - - if (len == 0) - m_internal->EndRequest(req); - return; - } - // The End. - req->io_nbytes += len; - m_internal->EndRequest(req); -} - -void SocketRequester::ProcessWriteEvent(SockRequest *req) -{ - int ret; - size_t len; - - if (!WaitFor(wxSocketBase::REQ_WRITE, req->timeout)) { - m_internal->EndRequest(req); - return; - } - - m_internal->AcquireFD(); - ret = send(m_fd, req->buffer, req->size, 0); - m_internal->ReleaseFD(); - if (ret < 0) { - req->error = errno; - m_internal->EndRequest(req); - return; - } - len = ret; - if ((len < req->size) && ((m_socket->GetFlags() & wxSocketBase::WAITALL) != 0)) { - req->size -= len; - req->io_nbytes += len; - req->buffer += len; - return; - } - req->io_nbytes += len; - m_internal->EndRequest(req); -} - -void SocketRequester::ProcessWaitEvent(SockRequest *req) -{ - if (WaitFor(req->type, req->timeout)) - req->io_nbytes = 1; // We put 1 in the counter to tell the requester - // there is no timeout. - else - req->io_nbytes = 0; - - m_internal->EndRequest(req); -} - - -#if wxUSE_THREADS -void *SocketRequester::Entry() -{ - SockRequest *req; - - m_internal->m_request_locker.Lock(); - while (1) { - // Wait for a new request or a destroy message. - req = m_internal->WaitForReq(); - m_internal->m_end_requester.Lock(); - if (req == NULL) { - m_internal->m_invalid_requester = TRUE; - m_internal->m_end_requester.Unlock(); - m_internal->m_request_locker.Unlock(); - return NULL; - } - m_internal->m_end_requester.Unlock(); - - if ((req->type & wxSocketBase::REQ_WAIT) != 0) { - ProcessWaitEvent(req); - continue; - } - - switch (req->type) { - case wxSocketBase::REQ_READ: - case wxSocketBase::REQ_PEEK: - ProcessReadEvent(req); - break; - case wxSocketBase::REQ_WRITE: - ProcessWriteEvent(req); - break; - } - } - return NULL; -} -#endif - -// -------------------------------------------------------------- -// --------- wxSocketInternal ----------------------------------- -// -------------------------------------------------------------- - -wxSocketInternal::wxSocketInternal(wxSocketBase *socket) -{ - m_socket = socket; - m_thread_requester = NULL; - m_thread_waiter = NULL; - m_invalid_requester = TRUE; -} - -wxSocketInternal::~wxSocketInternal() -{ - StopRequester(); - wxASSERT(m_thread_requester == NULL); - StopWaiter(); - wxASSERT(m_thread_waiter == NULL); -} - -// ---------------------------------------------------------------------- -// WaitForReq: it is called by SocketRequester and should return the next -// socket request if available -// ---------------------------------------------------------------------- -SockRequest *wxSocketInternal::WaitForReq() -{ -#if wxUSE_THREADS - wxNode *node; - - // First try. - node = m_requests.First(); - if (node == NULL) { - m_socket_cond.Wait(m_request_locker, 10, 0); - - // Second try, if it is unsuccessul we give up. - node = m_requests.First(); - if (node == NULL) - return NULL; - } - - return (SockRequest *)node->Data(); -#else - return NULL; -#endif -} - -// ---------------------------------------------------------------------- -// EndRequest: Should be called to finalize a request -// ---------------------------------------------------------------------- -void wxSocketInternal::EndRequest(SockRequest *req) -{ - wxNode *node = NULL; - - req->done = TRUE; - - node = m_requests.Member((wxObject *)req); - if (node != NULL) - delete node; -} - -void wxSocketInternal::AcquireData() -{ -#if wxUSE_THREADS - m_socket_locker.Lock(); -#endif -} - -void wxSocketInternal::ReleaseData() -{ -#if wxUSE_THREADS - m_socket_locker.Unlock(); -#endif -} - -void wxSocketInternal::AcquireFD() -{ -#if wxUSE_THREADS - m_fd_locker.Lock(); -#endif -} - -void wxSocketInternal::ReleaseFD() -{ -#if wxUSE_THREADS - m_fd_locker.Unlock(); -#endif -} - -void wxSocketInternal::ResumeRequester() -{ -#if wxUSE_THREADS - wxThreadError err; - - wxASSERT(m_invalid_requester); - - m_end_requester.Lock(); - - if (m_thread_requester != NULL) { - m_thread_requester->Delete(); // We must join it. - delete m_thread_requester; - } - - m_invalid_requester = FALSE; - - m_end_requester.Unlock(); - - m_thread_requester = new SocketRequester(m_socket, this); - - err = m_thread_requester->Create(); - wxASSERT(err == wxTHREAD_NO_ERROR); - - err = m_thread_requester->Run(); - wxASSERT(err == wxTHREAD_NO_ERROR); -#else - if (!m_invalid_requester) - return; - m_thread_requester = new SocketRequester(m_socket, this); - m_invalid_requester = FALSE; -#endif -} - -void wxSocketInternal::StopRequester() -{ -#if wxUSE_THREADS - m_end_requester.Lock(); - if (m_invalid_requester) { - m_end_requester.Unlock(); - if (m_thread_requester) { - m_thread_requester->Delete(); - delete m_thread_requester; - m_thread_requester = NULL; - } - m_invalid_requester = TRUE; - return; - } - m_end_requester.Unlock(); - - wxASSERT(m_thread_requester != NULL); - - m_request_locker.Lock(); - - // Send a signal to the requester. - m_socket_cond.Signal(); - - m_request_locker.Unlock(); - - // Finish the destruction of the requester. - m_thread_requester->Delete(); - - delete m_thread_requester; - m_thread_requester = NULL; - m_invalid_requester = TRUE; -#else - delete m_thread_requester; - m_thread_requester = NULL; - m_invalid_requester = TRUE; -#endif -} - -void wxSocketInternal::ResumeWaiter() -{ -#if wxUSE_THREADS - wxThreadError err; - - if (m_thread_waiter != NULL) - return; - - m_thread_waiter = new SocketWaiter(m_socket, this); - - m_thread_waiter->SetPriority(WXTHREAD_MIN_PRIORITY); - - err = m_thread_waiter->Create(); - wxASSERT(err == wxTHREAD_NO_ERROR); - - err = m_thread_waiter->Run(); - wxASSERT(err == wxTHREAD_NO_ERROR); -#endif -} - -void wxSocketInternal::StopWaiter() -{ -#if wxUSE_THREADS - if (m_thread_waiter == NULL) - return; - - m_thread_waiter->Delete(); - - delete m_thread_waiter; - m_thread_waiter = NULL; -#endif -} - -// ---------------------------------------------------------------------- -// QueueRequest: -// ---------------------------------------------------------------------- -void wxSocketInternal::QueueRequest(SockRequest *request, bool async) -{ - if (m_invalid_requester) - ResumeRequester(); - -#if wxUSE_THREADS - if (async) { - - m_request_locker.Lock(); - request->done = FALSE; - m_requests.Append((wxObject *)request); - m_socket_cond.Signal(); - m_request_locker.Unlock(); - - // Wake up - - if (request->wait) { - if (wxThread::IsMain()) - while (!request->done) { - wxYield(); - } - else - while (!request->done) { - wxThread::Yield(); - } - } - } else { - m_request_locker.Lock(); -#endif - - if ((request->type & wxSocketBase::REQ_WAIT) != 0) { - m_thread_requester->ProcessWaitEvent(request); - } else { - - request->done = FALSE; - - switch (request->type) { - case wxSocketBase::REQ_PEEK: - case wxSocketBase::REQ_READ: - m_thread_requester->ProcessReadEvent(request); - break; - case wxSocketBase::REQ_WRITE: - m_thread_requester->ProcessWriteEvent(request); - break; - } - } - request->done = TRUE; -#if wxUSE_THREADS - m_request_locker.Unlock(); - } -#endif -} - -void wxSocketInternal::WaitForEnd(SockRequest *request) -{ -#if wxUSE_THREADS - // TODOTODO -#endif -} - -#endif - // __WXSTUBS__ - -#endif - // wxUSE_SOCKETS diff --git a/src/common/sckipc.cpp b/src/common/sckipc.cpp index 694b94d336..27dae77d32 100644 --- a/src/common/sckipc.cpp +++ b/src/common/sckipc.cpp @@ -60,10 +60,10 @@ enum { #endif void Server_OnRequest(wxSocketServer& server, - wxSocketBase::wxRequestEvent evt, + GSocketEvent evt, char *cdata); void Client_OnRequest(wxSocketBase& sock, - wxSocketBase::wxRequestEvent evt, + GSocketEvent evt, char *cdata); // --------------------------------------------------------------------------- @@ -91,13 +91,12 @@ wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host, const wxString& topic) { wxIPV4address addr; - wxSocketHandler *hsock = &wxSocketHandler::Master(); - wxSocketClient *client = hsock->CreateClient(); + wxSocketClient *client = new wxSocketClient(); wxSocketStream *stream = new wxSocketStream(*client); wxDataInputStream data_is(*stream); wxDataOutputStream data_os(*stream); - client->SetNotify(wxSocketBase::REQ_READ | wxSocketBase::REQ_LOST); + client->SetNotify(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG); addr.Service(server_name); addr.Hostname(host); @@ -156,15 +155,14 @@ wxTCPServer::wxTCPServer (void) 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 = new wxSocketServer(addr); server->Callback((wxSocketBase::wxSockCbk)Server_OnRequest); - server->SetNotify(wxSocketBase::REQ_ACCEPT); + server->SetNotify(GSOCK_CONNECTION_FLAG); server->CallbackData((char *)this); @@ -338,7 +336,7 @@ bool wxTCPConnection::Advise (const wxString& item, return TRUE; } -void Client_OnRequest(wxSocketBase& sock, wxSocketBase::wxRequestEvent evt, +void Client_OnRequest(wxSocketBase& sock, GSocketEvent evt, char *cdata) { int msg = 0; @@ -350,7 +348,7 @@ void Client_OnRequest(wxSocketBase& sock, wxSocketBase::wxRequestEvent evt, wxString item; // The socket handler signals us that we lost the connection: destroy all. - if (evt == wxSocketBase::EVT_LOST) { + if (evt == GSOCK_LOST) { sock.Close(); connection->OnDisconnect(); return; @@ -466,20 +464,20 @@ void Client_OnRequest(wxSocketBase& sock, wxSocketBase::wxRequestEvent evt, } void Server_OnRequest(wxSocketServer& server, - wxSocketBase::wxRequestEvent evt, char *cdata) + GSocketEvent evt, char *cdata) { wxTCPServer *ipcserv = (wxTCPServer *)cdata; wxSocketStream *stream; wxDataInputStream *codeci; wxDataOutputStream *codeco; - if (evt != wxSocketBase::EVT_ACCEPT) + if (evt != GSOCK_CONNECTION) return; /* Accept the connection, getting a new socket */ wxSocketBase *sock = server.Accept(); sock->Notify(FALSE); - sock->SetNotify(wxSocketBase::REQ_READ | wxSocketBase::REQ_LOST); + sock->SetNotify(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG); stream = new wxSocketStream(*sock); codeci = new wxDataInputStream(*stream); diff --git a/src/common/sckstrm.cpp b/src/common/sckstrm.cpp index f7796cea3b..df93922870 100644 --- a/src/common/sckstrm.cpp +++ b/src/common/sckstrm.cpp @@ -42,15 +42,21 @@ wxSocketOutputStream::~wxSocketOutputStream() { } -wxOutputStream& wxSocketOutputStream::Write(const void *buffer, size_t size) -{ - m_lastcount = m_o_socket->Write((const char *)buffer, size).LastCount(); - return *this; -} - size_t wxSocketOutputStream::OnSysWrite(const void *buffer, size_t size) { - return m_o_socket->Write((const char *)buffer, size).LastCount(); + size_t ret; + + ret = m_o_socket->Write((const char *)buffer, size).LastCount(); + switch (m_o_socket->LastError()) { + case GSOCK_NOERROR: + m_lasterror = wxStream_NOERROR; + break; + default: + m_lasterror = wxStream_READ_ERR; + break; + } + return ret; + } // --------------------------------------------------------------------------- @@ -66,15 +72,20 @@ wxSocketInputStream::~wxSocketInputStream() { } -wxInputStream& wxSocketInputStream::Read(void *buffer, size_t size) -{ - m_lastcount = m_i_socket->Read((char *)buffer, size).LastCount(); - return *this; -} - size_t wxSocketInputStream::OnSysRead(void *buffer, size_t size) { - return m_i_socket->Read((char *)buffer, size).LastCount(); + size_t ret; + + ret = m_i_socket->Read((char *)buffer, size).LastCount(); + switch (m_i_socket->LastError()) { + case GSOCK_NOERROR: + m_lasterror = wxStream_NOERROR; + break; + default: + m_lasterror = wxStream_WRITE_ERR; + break; + } + return ret; } // --------------------------------------------------------------------------- diff --git a/src/common/socket.cpp b/src/common/socket.cpp index 052078b3b4..4e12e8971b 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -1,11 +1,10 @@ //////////////////////////////////////////////////////////////////////////////// // Name: socket.cpp // Purpose: Socket handler classes -// Authors: Guilhem Lavaux (completely rewritten from a basic API of Andrew -// Davidson(1995) in wxWeb) +// Authors: Guilhem Lavaux // Created: April 1997 -// Updated: April 1999 -// Copyright: (C) 1999 1998, 1997, Guilhem Lavaux +// Updated: July 1999 +// Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux // RCS_ID: $Id$ // License: see wxWindows license //////////////////////////////////////////////////////////////////////////////// @@ -13,10 +12,6 @@ #pragma implementation "socket.h" #endif -#ifdef __MWERKS__ -typedef int socklen_t ; -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -34,132 +29,18 @@ typedef int socklen_t ; #include #include #include - -// IRIX requires bstring.h be included to use select() -#ifdef sgi - #include -#endif // IRIX - -// Not enough OS behaviour defined for wxStubs -#ifndef __WXSTUBS__ +#include #include #include #include -///////////////////////////////////////////////////////////////////////////// -// System specific headers -///////////////////////////////////////////////////////////////////////////// -#ifdef __WXMAC__ -// in order to avoid problems with our c library and double definitions -#define close closesocket -#define ioctl ioctlsocket - -#include - -#endif - -#if defined(__WINDOWS__) -#include -#endif // __WINDOWS__ - -#if defined(__UNIX__) - -#ifdef VMS -#include -#else -#include -#endif -#include - -#include -#include - -#ifdef sun -#include -#endif - -#endif // __UNIX__ - -#include -#include - -#ifdef __VISUALC__ -#include -#endif - ///////////////////////////////////////////////////////////////////////////// // wxSocket headers ///////////////////////////////////////////////////////////////////////////// #include -#define WXSOCK_INTERNAL #include #include -#include - -// ---------------------- -// Some patch ----- BEGIN -// ---------------------- -#ifdef __WINDOWS__ -#define close closesocket -#define ioctl ioctlsocket -#ifdef errno -#undef errno -#endif -#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 __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( __VISUALC__ ) -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 - -// ------------------- -// Some patch ---- END -// ------------------- - -#ifdef GetClassInfo -#undef GetClassInfo -#endif - -// -------------------------------------------------------------- -// Module -// -------------------------------------------------------------- -class wxSocketModule: public wxModule -{ - DECLARE_DYNAMIC_CLASS(wxSocketModule) -public: - wxSocketModule() {} - bool OnInit(); - void OnExit(); -}; // -------------------------------------------------------------- // ClassInfos @@ -168,76 +49,76 @@ public: IMPLEMENT_CLASS(wxSocketBase, wxObject) IMPLEMENT_CLASS(wxSocketServer, wxSocketBase) IMPLEMENT_CLASS(wxSocketClient, wxSocketBase) -IMPLEMENT_CLASS(wxSocketHandler, wxObject) IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent) -IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule) #endif +class wxSocketState : public wxObject { +public: + bool notify_state; + GSocketEventFlags evt_notify_state; + wxSocketBase::wxSockFlags socket_flags; + wxSocketBase::wxSockCbk c_callback; + char *c_callback_data; + +public: + wxSocketState() : wxObject() {} +}; + // -------------------------------------------------------------- // --------- 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_id(-1), - m_handler(0), - m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)), - m_timeout(3600), - m_unread(NULL), m_unrd_size(0), + m_socket(NULL), m_flags(_flags), m_type(_type), + m_neededreq(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG), + m_lcount(0), m_timeout(3600), + m_unread(NULL), m_unrd_size(0), m_unrd_cur(0), m_cbk(NULL), m_cdata(NULL), - m_notify_state(FALSE) + m_connected(FALSE), m_notify_state(FALSE), m_id(-1), + m_defering(NO_DEFER), + m_states() { - m_internal = new wxSocketInternal(this); } wxSocketBase::wxSocketBase() : wxEvtHandler(), - m_flags(WAITALL), m_type(SOCK_UNINIT), m_connected(FALSE), - m_connecting(FALSE), m_fd(INVALID_SOCKET), - m_id(-1), m_handler(0), - m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)), - m_timeout(3600), - m_unread(NULL), m_unrd_size(0), + m_socket(NULL), m_flags((wxSockFlags)SPEED | WAITALL), m_type(SOCK_UNINIT), + m_neededreq(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG), + m_lcount(0), m_timeout(3600), + m_unread(NULL), m_unrd_size(0), m_unrd_cur(0), m_cbk(NULL), m_cdata(NULL), - m_notify_state(FALSE) + m_connected(FALSE), m_notify_state(FALSE), m_id(-1), + m_defering(NO_DEFER), + m_states() { - m_internal = new wxSocketInternal(this); } // -------------------------------------------------------------- -// wxSocketBase +// wxSocketBase destructor // -------------------------------------------------------------- wxSocketBase::~wxSocketBase() { - // First, close the file descriptor. - Close(); - if (m_unread) free(m_unread); - // Unregister from the handler database. - if (m_handler) - m_handler->UnRegister(this); - // Destroy all saved states. - m_states.DeleteContents(TRUE); + // At last, close the file descriptor. + Close(); - // Destroy the socket manager. - delete m_internal; + if (m_socket) + GSocket_destroy(m_socket); } bool wxSocketBase::Close() { - if (m_fd != INVALID_SOCKET) + if (m_socket) { if (m_notify_state == TRUE) Notify(FALSE); // Shutdown the connection. - shutdown(m_fd, 2); - close(m_fd); - m_fd = INVALID_SOCKET; + GSocket_Shutdown(m_socket); m_connected = FALSE; } @@ -248,19 +129,75 @@ bool wxSocketBase::Close() // wxSocketBase base IO function // -------------------------------------------------------------- +int wxSocketBase::DeferRead(char *buffer, size_t nbytes) +{ + GSocketEventFlags old_event_flags; + bool old_notify_state; + + wxASSERT(m_defering == NO_DEFER); + + m_defering = DEFER_READ; + + old_event_flags = NeededReq(); + old_notify_state = m_notify_state; + + SetNotify(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG); + Notify(TRUE); + + m_defer_buffer = buffer; + m_defer_nbytes = nbytes; + while (m_defer_buffer != NULL) + wxYield(); + + Notify(old_notify_state); + SetNotify(old_event_flags); + + m_defering = NO_DEFER; + + return nbytes-m_defer_nbytes; +} + wxSocketBase& wxSocketBase::Read(char* buffer, size_t nbytes) { + int ret = 1; + m_lcount = GetPushback(buffer, nbytes, FALSE); nbytes -= m_lcount; buffer += m_lcount; + if (!m_connected) + return *this; + // 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); + if ((m_flags & SPEED) != 0) { + + if ((m_flags & WAITALL) != 0) { + while (ret > 0 && nbytes > 0) { + ret = GSocket_Read(m_socket, buffer, nbytes); + m_lcount += ret; + buffer += ret; + nbytes -= ret; + } + // In case the last call was an error ... + if (ret < 0) + m_lcount ++; + } else { + ret = GSocket_Read(m_socket, buffer, nbytes); + if (ret > 0) + m_lcount += ret; + } + + } else { + ret = DeferRead(buffer, nbytes); + + if (ret > 0) + m_lcount += ret; + } return *this; } @@ -315,34 +252,62 @@ wxSocketBase& wxSocketBase::ReadMsg(char* buffer, size_t nbytes) 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 -// we return *this either way, so a smart optimizer will -// optimize the following sequence out; I'm leaving it in anyway if (sig != 0xdeadfeed) - return *this; + wxLogDebug(_T("Warning: invalid signature returned to ReadMsg\n")); return *this; } wxSocketBase& wxSocketBase::Peek(char* buffer, size_t nbytes) { - m_lcount = GetPushback(buffer, nbytes, TRUE); - if (nbytes-m_lcount == 0) - { - return *this; - } - buffer += m_lcount; - nbytes -= m_lcount; - - WantBuffer(buffer, nbytes, EVT_PEEK); + Read(buffer, nbytes); + CreatePushbackAfter(buffer, nbytes); return *this; } +int wxSocketBase::DeferWrite(const char *buffer, size_t nbytes) +{ + GSocketEventFlags old_event_flags; + bool old_notify_state; + + wxASSERT(m_defering == NO_DEFER); + + m_defering = DEFER_WRITE; + + old_event_flags = NeededReq(); + old_notify_state = m_notify_state; + + SetNotify(GSOCK_OUTPUT_FLAG | GSOCK_LOST_FLAG); + Notify(TRUE); + + m_defer_buffer = (char *)buffer; + m_defer_nbytes = nbytes; + while (m_defer_buffer != NULL) + wxYield(); + + Notify(old_notify_state); + SetNotify(old_event_flags); + + m_defering = NO_DEFER; + + return nbytes-m_defer_nbytes; +} + wxSocketBase& wxSocketBase::Write(const char *buffer, size_t nbytes) { - m_lcount = 0; - WantBuffer((char *)buffer, nbytes, EVT_WRITE); + int ret; + + if ((m_flags & SPEED) != 0) + ret = GSocket_Write(m_socket, buffer, nbytes); + else + ret = DeferWrite(buffer, nbytes); + + if (ret != -1) + m_lcount += ret; + return *this; } @@ -399,25 +364,43 @@ wxSocketBase& wxSocketBase::Unread(const char *buffer, size_t nbytes) bool wxSocketBase::IsData() const { - struct timeval tv; - fd_set sock_set; - - if (m_fd < 0) + if (!m_socket) return FALSE; - if (m_unrd_size > 0) - return TRUE; - m_internal->AcquireFD(); + return (GSocket_DataAvailable(m_socket)); +} + +void wxSocketBase::DoDefer(GSocketEvent req_evt) +{ + int ret; - tv.tv_sec = 0; - tv.tv_usec = 0; - FD_ZERO(&sock_set); - FD_SET(m_fd, &sock_set); - select(m_fd+1, &sock_set, NULL, NULL, &tv); + if (req_evt == GSOCK_LOST) { + Close(); + m_defer_buffer = NULL; + return; + } + switch (m_defering) { + case DEFER_READ: + ret = GSocket_Read(m_socket, m_defer_buffer, m_defer_nbytes); + break; + case DEFER_WRITE: + ret = GSocket_Write(m_socket, m_defer_buffer, m_defer_nbytes); + break; + default: + ret = -1; + break; + } - m_internal->ReleaseFD(); + m_defer_nbytes -= ret; - return (FD_ISSET(m_fd, &sock_set) != 0); + if (ret < 0) + m_defer_nbytes++; + + if ((m_flags & WAITALL) == 0 || m_defer_nbytes == 0 || ret < 0) { + m_defer_buffer = NULL; + Notify(FALSE); + } else + m_defer_buffer += ret; } // --------------------------------------------------------------------- @@ -443,64 +426,35 @@ void wxSocketBase::Discard() #undef MAX_BUFSIZE } -// If what? Who seems to need unsigned int? -// BTW uint isn't even defined on wxMSW for VC++ for some reason. Even if it -// were, getpeername/getsockname don't take unsigned int*, they take int*. -// -// Under glibc 2.0.7, socketbits.h declares socklen_t to be unsigned int -// and it uses *socklen_t as the 3rd parameter. Robert. - -// JACS - How can we detect this? -// Meanwhile, if your compiler complains about socklen_t, -// switch lines below. - -#if wxHAVE_GLIBC2 -# define wxSOCKET_INT socklen_t -#else -# define wxSOCKET_INT int -#endif - // -------------------------------------------------------------- // wxSocketBase socket info functions // -------------------------------------------------------------- bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const { - struct sockaddr my_addr; - wxSOCKET_INT len_addr = sizeof(my_addr); + GAddress *peer; - if (m_fd < 0) + if (!m_socket) return FALSE; - m_internal->AcquireFD(); + peer = GSocket_GetPeer(m_socket); + addr_man.SetAddress(peer); + GAddress_destroy(peer); - if (getpeername(m_fd, (struct sockaddr *)&my_addr, &len_addr) < 0) { - m_internal->ReleaseFD(); - return FALSE; - } - - m_internal->ReleaseFD(); - addr_man.Disassemble(&my_addr, len_addr); return TRUE; } bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const { - struct sockaddr my_addr; - wxSOCKET_INT len_addr = sizeof(my_addr); + GAddress *local; - if (m_fd < 0) + if (!m_socket) return FALSE; - m_internal->AcquireFD(); - - if (getsockname(m_fd, (struct sockaddr *)&my_addr, &len_addr) < 0) { - m_internal->ReleaseFD(); - return FALSE; - } - m_internal->ReleaseFD(); + local = GSocket_GetLocal(m_socket); + addr_man.SetAddress(local); + GAddress_destroy(local); - addr_man.Disassemble(&my_addr, len_addr); return TRUE; } @@ -510,7 +464,9 @@ bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const void wxSocketBase::SaveState() { - SocketState *state = new SocketState; + wxSocketState *state; + + state = new wxSocketState(); state->notify_state = m_notify_state; state->evt_notify_state = m_neededreq; @@ -518,24 +474,22 @@ void wxSocketBase::SaveState() state->c_callback = m_cbk; state->c_callback_data = m_cdata; - m_states.Append((wxObject *)state); + m_states.Append(state); } void wxSocketBase::RestoreState() { wxNode *node; - SocketState *state; + wxSocketState *state; node = m_states.Last(); if (!node) return; - state = (SocketState *)node->Data(); + state = (wxSocketState *)node->Data(); SetFlags(state->socket_flags); - m_internal->AcquireData(); m_neededreq = state->evt_notify_state; - m_internal->ReleaseData(); m_cbk = state->c_callback; m_cdata = state->c_callback_data; Notify(state->notify_state); @@ -568,68 +522,89 @@ char *wxSocketBase::CallbackData(char *data) // --------- wxSocketBase wait functions ------------------------ // -------------------------------------------------------------- +class _wxSocketInternalTimer: public wxTimer { + public: + int *m_state; + + void Notify() + { + *m_state = GSOCK_MAX_EVENT; // Just to say it's a timeout. + } +}; + +static void wx_socket_wait(GSocket *socket, GSocketEvent event, char *cdata) +{ + int *state = (int *)cdata; + + *state = event; +} + bool wxSocketBase::_Wait(long seconds, long milliseconds, int type) { - SockRequest *req; + bool old_notify_state = m_notify_state; + int state = 0; + _wxSocketInternalTimer timer; - if ((!m_connected && !m_connecting) || m_fd < 0) + if (!m_connected || !m_socket) return FALSE; - req = new SockRequest; + timer.m_state = &state; + + Notify(FALSE); + + timer.Start(seconds * 1000 + milliseconds, TRUE); + GSocket_SetFallback(m_socket, type, wx_socket_wait, (char *)&state); - req->type = REQ_WAIT | type; - req->timeout = seconds * 1000 + milliseconds; - req->done = FALSE; - req->buffer = NULL; - req->size = 0; - req->error = 0; - req->wait = TRUE; - m_internal->QueueRequest(req, TRUE); + while (state == 0) + wxYield(); - return (req->io_nbytes != 0); + GSocket_UnsetFallback(m_socket, type); + timer.Stop(); + + Notify(old_notify_state); + + return (state != GSOCK_MAX_EVENT); } bool wxSocketBase::Wait(long seconds, long milliseconds) { - return _Wait(seconds, milliseconds, REQ_ACCEPT | REQ_CONNECT | - REQ_READ | REQ_WRITE | REQ_LOST); + return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG | + GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG); } bool wxSocketBase::WaitForRead(long seconds, long milliseconds) { - return _Wait(seconds, milliseconds, REQ_READ | REQ_LOST); + return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG); } bool wxSocketBase::WaitForWrite(long seconds, long milliseconds) { - return _Wait(seconds, milliseconds, REQ_WRITE); + return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG | GSOCK_LOST_FLAG); } bool wxSocketBase::WaitForLost(long seconds, long milliseconds) { - return _Wait(seconds, milliseconds, REQ_LOST); + return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG); } // -------------------------------------------------------------- // --------- wxSocketBase callback management ------------------- // -------------------------------------------------------------- -wxSocketBase::wxRequestNotify wxSocketBase::EventToNotify(wxRequestEvent evt) +GSocketEventFlags wxSocketBase::EventToNotify(GSocketEvent 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; + case GSOCK_INPUT: + return GSOCK_INPUT_FLAG; + case GSOCK_OUTPUT: + return GSOCK_OUTPUT_FLAG; + case GSOCK_CONNECTION: + return GSOCK_CONNECTION_FLAG; + case GSOCK_LOST_FLAG: + return GSOCK_LOST_FLAG; + default: + return 0; } return 0; } @@ -637,10 +612,6 @@ wxSocketBase::wxRequestNotify wxSocketBase::EventToNotify(wxRequestEvent evt) void wxSocketBase::SetFlags(wxSockFlags _flags) { m_flags = _flags; - if (_flags & SPEED) { - // SPEED and WAITALL are antagonists. - m_flags = (wxSockFlags)(m_flags & ~WAITALL); - } } wxSocketBase::wxSockFlags wxSocketBase::GetFlags() const @@ -648,69 +619,66 @@ wxSocketBase::wxSockFlags wxSocketBase::GetFlags() const return m_flags; } -void wxSocketBase::SetNotify(wxRequestNotify flags) +void wxSocketBase::SetNotify(GSocketEventFlags flags) { /* Check if server */ if (m_type != SOCK_SERVER) - flags &= ~REQ_ACCEPT; + flags &= ~GSOCK_CONNECTION_FLAG; - m_internal->AcquireData(); m_neededreq = flags; - m_internal->ReleaseData(); if (m_neededreq == 0) - m_internal->StopWaiter(); + Notify(FALSE); else Notify(m_notify_state); } +// -------------------------------------------------------------- +// Automatic notifier +// -------------------------------------------------------------- + +static void wx_socket_fallback(GSocket *socket, GSocketEvent event, char *cdata) +{ + wxSocketBase *sckobj = (wxSocketBase *)cdata; + + sckobj->OnRequest(event); +} + void wxSocketBase::Notify(bool notify) { m_notify_state = notify; - if (m_fd == INVALID_SOCKET) + if (!m_socket) return; - if (notify) - m_internal->ResumeWaiter(); - else - m_internal->StopWaiter(); + GSocket_UnsetFallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG | + GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG); + if (!notify) + return; + + GSocket_SetFallback(m_socket, m_neededreq, wx_socket_fallback, (char *)this); } -void wxSocketBase::OnRequest(wxRequestEvent req_evt) +void wxSocketBase::OnRequest(GSocketEvent req_evt) { wxSocketEvent event(m_id); - wxRequestNotify notify = EventToNotify(req_evt); + GSocketEventFlags notify = EventToNotify(req_evt); + + if (m_defering != NO_DEFER) { + DoDefer(req_evt); + return; + } if ((m_neededreq & notify) == notify) { event.m_socket = this; event.m_skevt = req_evt; ProcessEvent(event); - // TODOTODO - // OldOnNotify(req_evt); - - // We disable the event reporting. - m_neededreq &= ~notify; + OldOnNotify(req_evt); } -} - -wxSocketEvent::wxSocketEvent(int id) - : wxEvent(id) -{ - wxEventType type = (wxEventType)wxEVT_SOCKET; - - SetEventType(type); -} - -void wxSocketEvent::CopyObject(wxObject& obj_d) const -{ - wxSocketEvent *event = (wxSocketEvent *)&obj_d; - - wxEvent::CopyObject(obj_d); - event->m_skevt = m_skevt; - event->m_socket = m_socket; + if (req_evt == GSOCK_LOST) + Close(); } -void wxSocketBase::OldOnNotify(wxRequestEvent evt) +void wxSocketBase::OldOnNotify(GSocketEvent evt) { } @@ -736,6 +704,7 @@ void wxSocketBase::CreatePushbackAfter(const char *buffer, size_t size) m_unread = (char *) realloc(m_unread, m_unrd_size+size); else m_unread = (char *) malloc(size); + curr_pos = m_unread + m_unrd_size; memcpy(curr_pos, buffer, size); @@ -744,18 +713,21 @@ void wxSocketBase::CreatePushbackAfter(const char *buffer, size_t 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; + if (m_unread == NULL) + m_unread = (char *)malloc(size); + else { + char *tmp; - memcpy(new_buf, buffer, size); - if (m_unrd_size != 0) { - memcpy(curr_pos, m_unread, m_unrd_size); + tmp = (char *)malloc(m_unrd_size + size); + memcpy(tmp+size, m_unread, m_unrd_size); free(m_unread); + + m_unread = tmp; } - m_unread = new_buf; + m_unrd_size += size; + + memcpy(m_unread, buffer, size); } size_t wxSocketBase::GetPushback(char *buffer, size_t size, bool peek) @@ -763,63 +735,23 @@ 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 (size > (m_unrd_size-m_unrd_cur)) + size = m_unrd_size-m_unrd_cur; + memcpy(buffer, (m_unread+m_unrd_cur), size); if (!peek) { - m_unrd_size -= size; - if (m_unrd_size == 0) { + m_unrd_cur += size; + if (m_unrd_size == m_unrd_cur) { free(m_unread); m_unread = NULL; + m_unrd_size = 0; + m_unrd_cur = 0; } } return size; } -// -------------------------------------------------------------- -// --------- wxSocketBase buffer core requester ----------------- -// -------------------------------------------------------------- - -void wxSocketBase::WantBuffer(char *buffer, size_t nbytes, - wxRequestEvent evt) -{ - bool buf_timed_out; - - if (m_fd == INVALID_SOCKET || !m_handler || !m_connected) - return; - - SockRequest *buf = new SockRequest; - - SaveState(); - buf->buffer = buffer; - buf->size = nbytes; - buf->done = FALSE; - buf->type = EventToNotify(evt); - buf->io_nbytes = 0; - buf->error = 0; - buf->wait = TRUE; - buf->timeout = 1000; - buf_timed_out = FALSE; - - if ((m_flags & SPEED) != 0) - m_internal->QueueRequest(buf, FALSE); - else - if ((m_flags & NOWAIT) != 0) - m_internal->QueueRequest(buf, TRUE); - else - m_internal->QueueRequest(buf, TRUE); - m_lcount += buf->io_nbytes; - if (buf_timed_out) - m_error = ETIMEDOUT; - else - m_error = buf->error; - - delete buf; - RestoreState(); -} - // -------------------------------------------------------------- // wxSocketServer // -------------------------------------------------------------- @@ -828,28 +760,18 @@ wxSocketServer::wxSocketServer(wxSockAddress& addr_man, wxSockFlags flags) : wxSocketBase(flags, SOCK_SERVER) { - m_fd = socket(addr_man.GetFamily(), SOCK_STREAM, 0); + m_socket = GSocket_new(); - if (m_fd == INVALID_SOCKET) + if (!m_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; + GSocket_SetLocal(m_socket, addr_man.GetAddress()); + if (GSocket_SetServer(m_socket) != GSOCK_NOERROR) { + GSocket_destroy(m_socket); + m_socket = NULL; return; } - m_internal->SetFD(m_fd); - Notify(TRUE); } @@ -859,32 +781,14 @@ wxSocketServer::wxSocketServer(wxSockAddress& addr_man, bool wxSocketServer::AcceptWith(wxSocketBase& sock) { - int fd2; - - m_internal->AcquireFD(); - if ((fd2 = accept(m_fd, 0, 0)) < 0) { - m_internal->ReleaseFD(); - return FALSE; - } - m_internal->ReleaseFD(); + GSocket *child_socket; - 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)); + child_socket = GSocket_WaitConnection(m_socket); sock.m_type = SOCK_INTERNAL; - sock.m_fd = fd2; + sock.m_socket = child_socket; sock.m_connected = TRUE; - sock.m_internal->SetFD(fd2); - - sock.m_internal->ResumeWaiter(); - return TRUE; } @@ -897,9 +801,6 @@ wxSocketBase *wxSocketServer::Accept() if (!AcceptWith(*sock)) return NULL; - if (m_handler) - m_handler->Register(sock); - return sock; } @@ -926,46 +827,28 @@ wxSocketClient::~wxSocketClient() // -------------------------------------------------------------- bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) ) { - struct linger linger; - if (IsConnected()) Close(); + // This should never happen. + if (m_socket) + GSocket_destroy(m_socket); + // Initializes all socket stuff ... // -------------------------------- - m_fd = socket(addr_man.GetFamily(), SOCK_STREAM, 0); + m_socket = GSocket_new(); - if (m_fd < 0) + if (!m_socket) 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) + // Update the flags of m_socket. + SetFlags(m_flags); + GSocket_SetPeer(m_socket, addr_man.GetAddress()); + if (GSocket_Connect(m_socket, GSOCK_STREAMED) != GSOCK_NOERROR) { return FALSE; - - m_internal->SetFD(m_fd); + } // Enables bg events. // ------------------ @@ -977,7 +860,7 @@ bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) ) bool wxSocketClient::WaitOnConnect(long seconds, long microseconds) { - int ret = _Wait(seconds, microseconds, REQ_CONNECT | REQ_LOST); + int ret = _Wait(seconds, microseconds, GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG); if (ret) m_connected = TRUE; @@ -985,13 +868,13 @@ bool wxSocketClient::WaitOnConnect(long seconds, long microseconds) return m_connected; } -void wxSocketClient::OnRequest(wxRequestEvent evt) +void wxSocketClient::OnRequest(GSocketEvent evt) { - if (evt == EVT_CONNECT) + if (evt == GSOCK_CONNECTION) { if (m_connected) { - m_neededreq &= ~REQ_CONNECT; + m_neededreq &= ~GSOCK_CONNECTION_FLAG; return; } m_connected = TRUE; @@ -1000,198 +883,27 @@ void wxSocketClient::OnRequest(wxRequestEvent evt) wxSocketBase::OnRequest(evt); } -///////////////////////////////////////////////////////////////// -// wxSocketHandler /////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// - -wxSocketHandler *wxSocketHandler::master = NULL; -#if defined(__WINDOWS__) -static int win_initialized = 0; -#endif - -// -------------------------------------------------------------- -// --------- wxSocketHandler CONSTRUCTOR ------------------------ -// -------------------------------------------------------------- -wxSocketHandler::wxSocketHandler() -{ -#if defined(__WINDOWS__) - if (!win_initialized) - { - WSADATA wsaData; - - WSAStartup((1 << 8) | 1, &wsaData); - win_initialized = 1; - } -#endif - - socks = new wxList; - -#ifndef __WINDOWS__ - signal(SIGPIPE, SIG_IGN); -#endif -} - // -------------------------------------------------------------- -// --------- wxSocketHandler DESTRUCTOR ------------------------- +// wxSocketEvent // -------------------------------------------------------------- -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__ - WSACleanup(); - win_initialized = 0; -#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); - } -} - -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->SetHandler(NULL); - return; - } - } -} - -unsigned long wxSocketHandler::Count() const -{ - return socks->Number(); -} - -// -------------------------------------------------------------- -// --------- wxSocketHandler "big" wait functions --------------- -// -------------------------------------------------------------- - -int wxSocketHandler::Wait(long seconds, long microseconds) -{ - // TODO Needs the completely asynchronous notifier. - - /* - int i; - int on_wait; - 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; - */ - return 0; -} - -void wxSocketHandler::YieldSock() -{ - wxNode *node; - - // Nothing to do anymore here except waiting for the queue emptying. - for (node = socks->First(); node; node=node->Next()) { - wxSocketBase *sock = (wxSocketBase *)node->Data(); - - sock->m_internal->WaitForEnd(NULL); - } -} - -// -------------------------------------------------------------- -// --------- wxSocketHandler: create and register the socket ---- -// -------------------------------------------------------------- -wxSocketServer *wxSocketHandler::CreateServer(wxSockAddress& addr, - wxSocketBase::wxSockFlags flags) +wxSocketEvent::wxSocketEvent(int id) + : wxEvent(id) { - wxSocketServer *serv = new wxSocketServer(addr, flags); + wxEventType type = (wxEventType)wxEVT_SOCKET; - Register(serv); - return serv; + SetEventType(type); } -wxSocketClient *wxSocketHandler::CreateClient(wxSocketBase::wxSockFlags flags) +void wxSocketEvent::CopyObject(wxObject& obj_d) const { - wxSocketClient *client = new wxSocketClient(flags); - - Register(client); - return client; -} + wxSocketEvent *event = (wxSocketEvent *)&obj_d; -bool wxSocketModule::OnInit() -{ - wxSocketHandler::master = new wxSocketHandler(); - return TRUE; -} + wxEvent::CopyObject(obj_d); -void wxSocketModule::OnExit() -{ - delete wxSocketHandler::master; - wxSocketHandler::master = NULL; + event->m_skevt = m_skevt; + event->m_socket = m_socket; } -#endif - // __WXSTUBS__ - #endif // wxUSE_SOCKETS diff --git a/src/common/stream.cpp b/src/common/stream.cpp index 9b83250f1c..61de20d228 100644 --- a/src/common/stream.cpp +++ b/src/common/stream.cpp @@ -480,6 +480,9 @@ size_t wxInputStream::GetWBack(char *buf, size_t bsize) { size_t s_toget = m_wbacksize-m_wbackcur; + if (!m_wback) + return 0; + if (bsize < s_toget) s_toget = bsize; @@ -697,8 +700,8 @@ wxInputStream& wxBufferedInputStream::Read(void *buffer, size_t size) char *buf = (char *)buffer; retsize = GetWBack(buf, size); + m_lastcount = retsize; if (retsize == size) { - m_lastcount = size; m_lasterror = wxStream_NOERROR; return *this; } @@ -753,6 +756,7 @@ wxBufferedOutputStream::~wxBufferedOutputStream() wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size) { + m_lastcount = 0; m_o_streambuf->Write(buffer, size); return *this; } diff --git a/src/common/textcmn.cpp b/src/common/textcmn.cpp index ccaa6e3bfa..d45fbb7505 100644 --- a/src/common/textcmn.cpp +++ b/src/common/textcmn.cpp @@ -148,7 +148,7 @@ wxTextCtrl& wxTextCtrlBase::operator<<(long i) return *TEXTCTRL(this); } -wxTextCtrl& wxTextCtrlBase::operator<<(const char c) +wxTextCtrl& wxTextCtrlBase::operator<<(const wxChar c) { return operator<<(wxString(c)); } diff --git a/src/common/url.cpp b/src/common/url.cpp index 3c8aebe2dc..06d8020749 100644 --- a/src/common/url.cpp +++ b/src/common/url.cpp @@ -208,7 +208,6 @@ bool wxURL::FetchProtocol() m_protoinfo = info; m_protocol = (wxProtocol *)m_protoinfo->m_cinfo->CreateObject(); - wxSocketHandler::Master().Register(m_protocol); return TRUE; } info = info->next; @@ -323,7 +322,7 @@ wxString wxURL::ConvertToValidURI(const wxString& uri) if (!isalpha(c) && c != _T('.') && c != _T('+') && c != _T('.') && c != _T('/')) { - hexa_code.Printf(_T("%02X"), c); + hexa_code.Printf(_T("%%%02X"), c); out_str += hexa_code; } else out_str += c; diff --git a/src/common/wfstream.cpp b/src/common/wfstream.cpp index 599c2f2fad..50c662d35c 100644 --- a/src/common/wfstream.cpp +++ b/src/common/wfstream.cpp @@ -138,7 +138,10 @@ wxFileOutputStream::~wxFileOutputStream() size_t wxFileOutputStream::OnSysWrite(const void *buffer, size_t size) { size_t ret = m_file->Write(buffer, size); - m_lasterror = wxStream_EOF; // TODO + if (m_file->Error()) + m_lasterror = wxStream_WRITE_ERR; + else + m_lasterror = wxStream_NOERROR; return ret; } diff --git a/src/gtk/Makefile.am b/src/gtk/Makefile.am index 83384cee93..616dce4f61 100644 --- a/src/gtk/Makefile.am +++ b/src/gtk/Makefile.am @@ -29,6 +29,8 @@ libwx_gtk_la_SOURCES = \ win_gtk.c \ extended.c \ parser.c \ + gsocket.c \ + gsockgtk.c \ \ cmndata.cpp \ config.cpp \ @@ -80,7 +82,6 @@ libwx_gtk_la_SOURCES = \ resource.cpp \ sckaddr.cpp \ sckfile.cpp \ - sckint.cpp \ sckipc.cpp \ sckstrm.cpp \ serbase.cpp \ diff --git a/src/gtk/gsockgtk.c b/src/gtk/gsockgtk.c new file mode 100644 index 0000000000..85816cbddb --- /dev/null +++ b/src/gtk/gsockgtk.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include "../unix/gsockunx.h" + +void _GSocket_GDK_Input(gpointer data, gint source, GdkInputCondition condition) +{ + GSocket *socket = (GSocket *)data; + + switch (condition) { + case GDK_INPUT_READ: + _GSocket_Detected_Read(socket); + break; + case GDK_INPUT_WRITE: + _GSocket_Detected_Write(socket); + break; + default: + break; + } +} + +void _GSocket_GUI_Init(GSocket *socket) +{ + int i; + gint *m_id; + + socket->m_gui_dependent = (char *)malloc(sizeof(gint)*3); + m_id = (gint *)(socket->m_gui_dependent); + + for (i=0;i<3;i++) + m_id[i] = -1; +} + +void _GSocket_GUI_Destroy(GSocket *socket) +{ + int i; + gint *m_id; + + m_id = (gint *)(socket->m_gui_dependent); + + for (i=0;i<3;i++) + if (m_id[i] == -1) + gdk_input_remove(m_id[i]); + + free(socket->m_gui_dependent); +} + +void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent event) +{ + GdkInputCondition flag; + int c; + gint *m_id; + + m_id = (gint *)(socket->m_gui_dependent); + + switch (event) { + case GSOCK_CONNECTION: + case GSOCK_LOST: + case GSOCK_INPUT: c = 0; flag = GDK_INPUT_READ; break; + case GSOCK_OUTPUT: c = 1;flag = GDK_INPUT_WRITE; break; + default: return; + } + + if (m_id[c] != -1) + gdk_input_remove(m_id[c]); + + m_id[c] = gdk_input_add(socket->m_fd, flag, + _GSocket_GDK_Input, (gpointer)socket); +} + +void _GSocket_Uninstall_Fallback(GSocket *socket, GSocketEvent event) +{ + int c; + gint *m_id; + + m_id = (gint *)(socket->m_gui_dependent); + + switch (event) { + case GSOCK_CONNECTION: + case GSOCK_LOST: + case GSOCK_INPUT: c = 0; break; + case GSOCK_OUTPUT: c = 1; break; + default: return; + } + + if (m_id[c] != -1) + gdk_input_remove(m_id[c]); + + m_id[c] = -1; +} + +unsigned long GSocket_GetEventID(GSocket *socket) +{ + return 0; +} + +void GSocket_DoEvent(unsigned long evt_id) +{ +} diff --git a/src/gtk1/Makefile.am b/src/gtk1/Makefile.am index 83384cee93..616dce4f61 100644 --- a/src/gtk1/Makefile.am +++ b/src/gtk1/Makefile.am @@ -29,6 +29,8 @@ libwx_gtk_la_SOURCES = \ win_gtk.c \ extended.c \ parser.c \ + gsocket.c \ + gsockgtk.c \ \ cmndata.cpp \ config.cpp \ @@ -80,7 +82,6 @@ libwx_gtk_la_SOURCES = \ resource.cpp \ sckaddr.cpp \ sckfile.cpp \ - sckint.cpp \ sckipc.cpp \ sckstrm.cpp \ serbase.cpp \ diff --git a/src/gtk1/gsockgtk.c b/src/gtk1/gsockgtk.c new file mode 100644 index 0000000000..85816cbddb --- /dev/null +++ b/src/gtk1/gsockgtk.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include "../unix/gsockunx.h" + +void _GSocket_GDK_Input(gpointer data, gint source, GdkInputCondition condition) +{ + GSocket *socket = (GSocket *)data; + + switch (condition) { + case GDK_INPUT_READ: + _GSocket_Detected_Read(socket); + break; + case GDK_INPUT_WRITE: + _GSocket_Detected_Write(socket); + break; + default: + break; + } +} + +void _GSocket_GUI_Init(GSocket *socket) +{ + int i; + gint *m_id; + + socket->m_gui_dependent = (char *)malloc(sizeof(gint)*3); + m_id = (gint *)(socket->m_gui_dependent); + + for (i=0;i<3;i++) + m_id[i] = -1; +} + +void _GSocket_GUI_Destroy(GSocket *socket) +{ + int i; + gint *m_id; + + m_id = (gint *)(socket->m_gui_dependent); + + for (i=0;i<3;i++) + if (m_id[i] == -1) + gdk_input_remove(m_id[i]); + + free(socket->m_gui_dependent); +} + +void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent event) +{ + GdkInputCondition flag; + int c; + gint *m_id; + + m_id = (gint *)(socket->m_gui_dependent); + + switch (event) { + case GSOCK_CONNECTION: + case GSOCK_LOST: + case GSOCK_INPUT: c = 0; flag = GDK_INPUT_READ; break; + case GSOCK_OUTPUT: c = 1;flag = GDK_INPUT_WRITE; break; + default: return; + } + + if (m_id[c] != -1) + gdk_input_remove(m_id[c]); + + m_id[c] = gdk_input_add(socket->m_fd, flag, + _GSocket_GDK_Input, (gpointer)socket); +} + +void _GSocket_Uninstall_Fallback(GSocket *socket, GSocketEvent event) +{ + int c; + gint *m_id; + + m_id = (gint *)(socket->m_gui_dependent); + + switch (event) { + case GSOCK_CONNECTION: + case GSOCK_LOST: + case GSOCK_INPUT: c = 0; break; + case GSOCK_OUTPUT: c = 1; break; + default: return; + } + + if (m_id[c] != -1) + gdk_input_remove(m_id[c]); + + m_id[c] = -1; +} + +unsigned long GSocket_GetEventID(GSocket *socket) +{ + return 0; +} + +void GSocket_DoEvent(unsigned long evt_id) +{ +} diff --git a/src/unix/gsocket.c b/src/unix/gsocket.c new file mode 100644 index 0000000000..7456ccf635 --- /dev/null +++ b/src/unix/gsocket.c @@ -0,0 +1,940 @@ +/* ------------------------------------------------------------------------- + * Project: GSocket (Generic Socket) for WX + * Name: gsocket.c + * Purpose: GSocket main Unix file + * CVSID: $Id$ + * Log: $Log$ + * Log: Revision 1.1 1999/07/22 17:51:54 GL + * Log: Added GSocket for Unix (only GTK for the moment) + * Log: Updated wxSocket to use GSocket API + * Log: Added a progress bar to client.cpp + * Log: Added CopyTo to wxMemoryOutputStream to copy the internal buffer to a specified buffer. + * Log: Various changes/fixes to the high-level protocols FTP/HTTP + * Log: Various Unicode fixes + * Log: Removed sckint.* + * Log: + * Log: Revision 1.2 1999/07/18 15:52:34 guilhem + * Log: * Copyright, etc. + * Log: + * ------------------------------------------------------------------------- + */ + +#include +#include +#ifdef vms +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef sun +#include +#endif + +#ifdef sgi + #include +#endif + +#include + +#include +#include "gsockunx.h" + +/* Constructors / Destructors */ + +GSocket *GSocket_new() +{ + int i; + GSocket *socket; + + socket = (GSocket *)malloc(sizeof(GSocket)); + + socket->m_fd = -1; + for (i=0;im_fbacks[i] = NULL; + socket->m_iocalls[i] = FALSE; + } + socket->m_local = NULL; + socket->m_peer = NULL; + socket->m_error = GSOCK_NOERROR; + socket->m_server = FALSE; + socket->m_stream = TRUE; + socket->m_gui_dependent = NULL; + socket->m_blocking = FALSE; + + _GSocket_GUI_Init(socket); + + return socket; +} + +void GSocket_destroy(GSocket *socket) +{ + assert(socket != NULL); + + _GSocket_GUI_Destroy(socket); + + if (socket->m_fd != -1) + GSocket_Shutdown(socket); + + if (socket->m_local) + GAddress_destroy(socket->m_local); + + if (socket->m_peer) + GAddress_destroy(socket->m_peer); + + free(socket); +} + +void GSocket_Shutdown(GSocket *socket) +{ + int evt; + + assert(socket != NULL); + + if (socket->m_fd != -1) { + shutdown(socket->m_fd, 2); + close(socket->m_fd); + socket->m_fd = -1; + } + + for (evt=0;evtm_fd != -1 && !socket->m_server)) + return GSOCK_INVSOCK; + + if (address == NULL || address->m_family == GSOCK_NOFAMILY) + return GSOCK_INVADDR; + + if (socket->m_local) + GAddress_destroy(socket->m_local); + + socket->m_local = GAddress_copy(address); + + return GSOCK_NOERROR; +} + +GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address) +{ + if (socket == NULL) + return GSOCK_INVSOCK; + + if (address == NULL || address->m_family == GSOCK_NOFAMILY) { + socket->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + if (socket->m_peer) + GAddress_destroy(socket->m_peer); + + socket->m_peer = GAddress_copy(address); + + return GSOCK_NOERROR; +} + +GAddress *GSocket_GetLocal(GSocket *socket) +{ + GAddress *address; + struct sockaddr addr; + socklen_t size; + + assert(socket != NULL); + + if (socket->m_local) + return GAddress_copy(socket->m_local); + + if (socket->m_fd == -1) { + socket->m_error = GSOCK_INVSOCK; + return NULL; + } + + size = sizeof(addr); + + if (getsockname(socket->m_fd, &addr, &size) < 0) { + socket->m_error = GSOCK_IOERR; + return NULL; + } + + address = GAddress_new(); + _GAddress_translate_from(address, &addr, size); + + return address; +} + +GAddress *GSocket_GetPeer(GSocket *socket) +{ + assert(socket != NULL); + + if (socket->m_peer) + return GAddress_copy(socket->m_peer); + + return NULL; +} + +/* Server specific parts */ + +/* + GSocket_SetServer() setup the socket as a server. It uses the "Local" field + of GSocket. "Local" must be set by GSocket_SetLocal() before + GSocket_SetServer() is called. GSOCK_INVSOCK if socket has been initialized. + In the other cases, it returns GSOCK_INVADDR. +*/ +GSocketError GSocket_SetServer(GSocket *sck) +{ + int type; + + assert(sck != NULL); + + if (sck->m_fd != -1) { + sck->m_error = GSOCK_INVSOCK; + return GSOCK_INVSOCK; + } + + if (!sck->m_local) { + sck->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + if (sck->m_stream) + type = SOCK_STREAM; + else + type = SOCK_DGRAM; + + sck->m_fd = socket(sck->m_local->m_realfamily, type, 0); + + if (sck->m_fd == -1) { + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) { + close(sck->m_fd); + sck->m_fd = -1; + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + if (listen(sck->m_fd, 5) < 0) { + close(sck->m_fd); + sck->m_fd = -1; + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + sck->m_server = TRUE; + + return GSOCK_NOERROR; + +} + +/* + GSocket_WaitConnection() waits for an incoming client connection. +*/ +GSocket *GSocket_WaitConnection(GSocket *socket) +{ + GSocket *connection; + + assert(socket != NULL); + + if (socket->m_fd == -1 || !socket->m_server) { + socket->m_error = GSOCK_INVSOCK; + return NULL; + } + + _GSocket_Enable(socket, GSOCK_CONNECTION); + + connection = GSocket_new(); + + connection->m_fd = accept(socket->m_fd, NULL, NULL); + if (connection->m_fd == -1) { + GSocket_destroy(connection); + socket->m_error = GSOCK_IOERR; + return NULL; + } + + connection->m_stream = TRUE; + connection->m_server = FALSE; + connection->m_oriented = TRUE; + + return connection; +} + +/* Non oriented connections */ + +GSocketError GSocket_SetNonOriented(GSocket *sck) +{ + assert(sck != NULL); + + if (sck->m_fd != -1) { + sck->m_error = GSOCK_INVSOCK; + return GSOCK_INVSOCK; + } + + if (!sck->m_local) { + sck->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + sck->m_stream = FALSE; + sck->m_server = FALSE; + sck->m_oriented = FALSE; + + sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0); + + if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) { + close(sck->m_fd); + sck->m_fd = -1; + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + return GSOCK_NOERROR; +} + +/* Client specific parts */ + +/* + GSocket_Connect() establishes a client connection to a server using the "Peer" + field of GSocket. "Peer" must be set by GSocket_SetPeer() before + GSocket_Connect() is called. In the other case, it returns GSOCK_INVADDR. +*/ +GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream) +{ + int type; + + assert(sck != NULL); + + if (sck->m_fd != -1) { + sck->m_error = GSOCK_INVSOCK; + return GSOCK_INVSOCK; + } + + if (!sck->m_peer) { + sck->m_error = GSOCK_INVADDR; + return GSOCK_INVADDR; + } + + sck->m_stream = (stream == GSOCK_STREAMED); + sck->m_oriented = TRUE; + + if (sck->m_stream) + type = SOCK_STREAM; + else + type = SOCK_DGRAM; + + sck->m_fd = socket(sck->m_peer->m_realfamily, type, 0); + + if (sck->m_fd == -1) { + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + if (connect(sck->m_fd, sck->m_peer->m_addr, + sck->m_peer->m_len) != 0) { + close(sck->m_fd); + sck->m_fd = -1; + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; + } + + sck->m_server = FALSE; + + return GSOCK_NOERROR; +} + +/* Generic IO */ + +/* Like recv(), send(), ... */ +int GSocket_Read(GSocket *socket, char *buffer, int size) +{ + assert(socket != NULL); + + if (socket->m_fd == -1 || socket->m_server) { + socket->m_error = GSOCK_INVSOCK; + return -1; + } + + _GSocket_Enable(socket, GSOCK_INPUT); + + if (socket->m_oriented) + return _GSocket_Recv_Stream(socket, buffer, size); + else + return _GSocket_Recv_Dgram(socket, buffer, size); +} + +int GSocket_Write(GSocket *socket, const char *buffer, + int size) +{ + assert(socket != NULL); + + if (socket->m_fd == -1 || socket->m_server) { + socket->m_error = GSOCK_INVSOCK; + return -1; + } + + _GSocket_Enable(socket, GSOCK_OUTPUT); + + if (socket->m_oriented) + return _GSocket_Send_Stream(socket, buffer, size); + else + return _GSocket_Send_Dgram(socket, buffer, size); +} + +bool GSocket_DataAvailable(GSocket *socket) +{ + fd_set read_set; + struct timeval tv; + + assert(socket != NULL); + + if (socket->m_fd == -1 || socket->m_server) { + socket->m_error = GSOCK_INVSOCK; + return FALSE; + } + + FD_ZERO(&read_set); + FD_SET(socket->m_fd, &read_set); + + tv.tv_sec = 0; + tv.tv_usec = 0; + + select(socket->m_fd+1, &read_set, NULL, NULL, &tv); + + return FD_ISSET(socket->m_fd, &read_set); +} + +/* Flags */ + +/* + GSocket_SetBlocking() puts the socket in non-blocking mode. This is useful + if we don't want to wait. +*/ +void GSocket_SetBlocking(GSocket *socket, bool block) +{ + assert(socket != NULL); + + socket->m_blocking = block; + + if (socket->m_fd != -1) + ioctl(socket->m_fd, FIONBIO, &block); +} + +/* + GSocket_GetError() returns the last error occured on the socket stream. +*/ + +GSocketError GSocket_GetError(GSocket *socket) +{ + assert(socket != NULL); + + return socket->m_error; +} + +/* Callbacks */ + +/* + Only one fallback is possible for each event (INPUT, OUTPUT, CONNECTION) + INPUT: The function is called when there is at least a byte in the + input buffer + OUTPUT: The function is called when the system is sure the next write call + will not block + CONNECTION: Two cases is possible: + Client socket -> the connection is established + Server socket -> a client request a connection + LOST: the connection is lost + + SetFallback accepts a combination of these flags so a same callback can + receive different events. + + An event is generated only once and its state is reseted when the relative + IO call is requested. + For example: INPUT -> GSocket_Read() + CONNECTION -> GSocket_Accept() +*/ +void GSocket_SetFallback(GSocket *socket, GSocketEventFlags event, + GSocketFallback fallback, char *cdata) +{ + int count; + + assert (socket != NULL); + + for (count=0;countm_fbacks[count] = fallback; + socket->m_data[count] = cdata; + + _GSocket_Install_Fallback(socket, count); + _GSocket_Enable(socket, count); + } + } +} + +/* + UnsetFallback will disables all fallbacks specified by "event". + NOTE: event may be a combination of flags +*/ +void GSocket_UnsetFallback(GSocket *socket, GSocketEventFlags event) +{ + int count = 0; + + assert(socket != NULL); + + for (count=0;countm_fbacks[count] = NULL; + _GSocket_Uninstall_Fallback(socket, count); + } + } +} + +#define CALL_FALLBACK(socket, event) \ +if (socket->m_iocalls[event] && \ + socket->m_fbacks[event]) {\ + _GSocket_Disable(socket, event); \ + socket->m_fbacks[event](socket, event, \ + socket->m_data[event]); \ +} + +#define MASK_SIGNAL() \ +{ \ + void (*old_handler)(int); \ +\ + old_handler = signal(SIGPIPE, SIG_IGN); + +#define UNMASK_SIGNAL() \ + signal(SIGPIPE, old_handler); \ +} + +void _GSocket_Enable(GSocket *socket, GSocketEvent event) +{ + socket->m_iocalls[event] = TRUE; + if (socket->m_fbacks[event]) + _GSocket_Install_Fallback(socket, event); +} + +void _GSocket_Disable(GSocket *socket, GSocketEvent event) +{ + socket->m_iocalls[event] = FALSE; + if (socket->m_fbacks[event]) + _GSocket_Uninstall_Fallback(socket, event); +} + +int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size) +{ + int ret; + + MASK_SIGNAL(); + ret = recv(socket->m_fd, buffer, size, 0); + UNMASK_SIGNAL(); + if (ret == -1) { + socket->m_error = GSOCK_IOERR; + return -1; + } + return ret; +} + +int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size) +{ + struct sockaddr from; + int fromlen, ret; + + fromlen = sizeof(from); + + MASK_SIGNAL(); + ret = recvfrom(socket->m_fd, buffer, size, 0, &from, &fromlen); + UNMASK_SIGNAL(); + if (ret == -1) { + socket->m_error = GSOCK_IOERR; + return -1; + } + + if (!socket->m_peer) + socket->m_peer = GAddress_new(); + _GAddress_translate_from(socket->m_peer, &from, fromlen); + + return ret; +} + +int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size) +{ + int ret; + + MASK_SIGNAL(); + ret = send(socket->m_fd, buffer, size, 0); + UNMASK_SIGNAL(); + if (ret == -1) { + socket->m_error = GSOCK_IOERR; + return -1; + } + return ret; +} + +int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size) +{ + struct sockaddr *addr; + int len, ret; + + if (!socket->m_peer) { + socket->m_error = GSOCK_INVADDR; + return -1; + } + + _GAddress_translate_to(socket->m_peer, &addr, &len); + + MASK_SIGNAL(); + ret = sendto(socket->m_fd, buffer, size, 0, addr, len); + UNMASK_SIGNAL(); + if (ret == -1) { + socket->m_error = GSOCK_IOERR; + return -1; + } + + free(addr); + + return ret; +} + +void _GSocket_Detected_Read(GSocket *socket) +{ + char c; + int ret; + + if (socket->m_stream) { + ret = recv(socket->m_fd, &c, 1, MSG_PEEK); + + if (ret < 0 && socket->m_server) { + CALL_FALLBACK(socket, GSOCK_CONNECTION); + return; + } + + if (ret > 0) { + CALL_FALLBACK(socket, GSOCK_INPUT); + } else { + CALL_FALLBACK(socket, GSOCK_LOST); + } + } +} + +void _GSocket_Detected_Write(GSocket *socket) +{ + CALL_FALLBACK(socket, GSOCK_OUTPUT); +} + +#undef CALL_FALLBACK +#undef MASK_SIGNAL +#undef UNMASK_SIGNAL + +/* + * ------------------------------------------------------------------------- + * GAddress + * ------------------------------------------------------------------------- + */ + +#define CHECK_ADDRESS(address, family, retval) \ +{ \ + if (address->m_family == GSOCK_NOFAMILY) \ + _GAddress_Init_##family(address); \ + if (address->m_family != GSOCK_##family) {\ + address->m_error = GSOCK_INVADDR; \ + return retval; \ + } \ +} + +GAddress *GAddress_new() +{ + GAddress *address; + + address = (GAddress *)malloc(sizeof(GAddress)); + + address->m_family = GSOCK_NOFAMILY; + address->m_addr = NULL; + address->m_len = 0; + + return address; +} + +GAddress *GAddress_copy(GAddress *address) +{ + GAddress *addr2; + + assert(address != NULL); + + addr2 = (GAddress *)malloc(sizeof(GAddress)); + memcpy(addr2, address, sizeof(GAddress)); + + if (address->m_addr) { + addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len); + memcpy(addr2->m_addr, address->m_addr, addr2->m_len); + } + + return addr2; +} + +void GAddress_destroy(GAddress *address) +{ + assert(address != NULL); + + free(address); +} + +void GAddress_SetFamily(GAddress *address, GAddressType type) +{ + assert(address != NULL); + + address->m_family = type; +} + +GAddressType GAddress_GetFamily(GAddress *address) +{ + assert(address != NULL); + + return address->m_family; +} + +void _GAddress_translate_from(GAddress *address, struct sockaddr *addr, int len){ + address->m_realfamily = addr->sa_family; + switch (addr->sa_family) { + case AF_INET: + address->m_family = GSOCK_INET; + break; + case AF_UNIX: + address->m_family = GSOCK_UNIX; + break; + case AF_INET6: + address->m_family = GSOCK_INET6; + break; + default: + /* TODO error */ + } + + if (address->m_addr) + free(address->m_addr); + + address->m_len = len; + address->m_addr = (struct sockaddr *)malloc(len); + memcpy(address->m_addr, addr, len); +} + +void _GAddress_translate_to(GAddress *address, + struct sockaddr **addr, int *len) +{ + if (!address->m_addr) { + /* TODO error */ + return; + } + + *len = address->m_len; + *addr = (struct sockaddr *)malloc(address->m_len); + memcpy(*addr, address->m_addr, address->m_len); +} + +/* + * ------------------------------------------------------------------------- + * Internet address family + * ------------------------------------------------------------------------- + */ + +void _GAddress_Init_INET(GAddress *address) +{ + address->m_len = sizeof(struct sockaddr_in); + address->m_addr = (struct sockaddr *)malloc(address->m_len); + address->m_family = GSOCK_INET; + address->m_realfamily = PF_INET; + ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET; + ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY; +} + +GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname) +{ + struct hostent *he; + struct in_addr *addr; + + assert(address != NULL); + + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr); + + /* only name for the moment */ + if (inet_aton(hostname, addr) == 0) { + struct in_addr *array_addr; + + if ((he = gethostbyname(hostname)) == NULL) { + address->m_error = GSOCK_NOHOST; + return GSOCK_NOHOST; + } + array_addr = (struct in_addr *) *(he->h_addr_list); + addr->s_addr = array_addr[0].s_addr; + } + return GSOCK_NOERROR; +} + +GSocketError GAddress_INET_SetHostAddress(GAddress *address, + unsigned long hostaddr) +{ + struct in_addr *addr; + + assert(address != NULL); + + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr); + addr->s_addr = hostaddr; + + return GSOCK_NOERROR; +} + +GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port) +{ + struct servent *se; + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + if (!port) { + address->m_error = GSOCK_INVPORT; + return GSOCK_INVOP; + } + + /* TODO: TCP or UDP */ + se = getservbyname(port, "tcp"); + if (!se) { + if (isdigit(port[0])) { + int port_int; + + port_int = atoi(port); + addr = (struct sockaddr_in *)address->m_addr; + addr->sin_port = htons(port_int); + return GSOCK_NOERROR; + } + + address->m_error = GSOCK_INVPORT; + return GSOCK_INVPORT; + } + + addr = (struct sockaddr_in *)address->m_addr; + addr->sin_port = se->s_port; + + return GSOCK_NOERROR; +} + +GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port) +{ + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + addr = (struct sockaddr_in *)address->m_addr; + addr->sin_port = htons(port); + + return GSOCK_NOERROR; +} + +GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf) +{ + struct hostent *he; + char *addr_buf; + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, GSOCK_INVADDR); + + addr = (struct sockaddr_in *)address->m_addr; + addr_buf = (char *)&(addr->sin_addr); + + he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET); + if (he == NULL) { + address->m_error = GSOCK_NOHOST; + return GSOCK_NOHOST; + } + + strncpy(hostname, he->h_name, sbuf); + + return GSOCK_NOERROR; +} + +unsigned long GAddress_INET_GetHostAddress(GAddress *address) +{ + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, 0); + + addr = (struct sockaddr_in *)address->m_addr; + + return addr->sin_addr.s_addr; +} + +unsigned short GAddress_INET_GetPort(GAddress *address) +{ + struct sockaddr_in *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, INET, 0); + + addr = (struct sockaddr_in *)address->m_addr; + return ntohs(addr->sin_port); +} + +/* + * ------------------------------------------------------------------------- + * Unix address family + * ------------------------------------------------------------------------- + */ + +void _GAddress_Init_UNIX(GAddress *address) +{ + address->m_len = sizeof(struct sockaddr_un); + address->m_addr = (struct sockaddr *)malloc(address->m_len); + address->m_family = GSOCK_UNIX; + address->m_realfamily = PF_UNIX; + ((struct sockaddr_un *)address->m_addr)->sun_family = AF_UNIX; + ((struct sockaddr_un *)address->m_addr)->sun_path[0] = 0; +} + +GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path) +{ + struct sockaddr_un *addr; + + assert(address != NULL); + + CHECK_ADDRESS(address, UNIX, GSOCK_INVADDR); + + addr = ((struct sockaddr_un *)address->m_addr); + memcpy(addr->sun_path, path, strlen(path)); + + return GSOCK_NOERROR; +} + +GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf) +{ + struct sockaddr_un *addr; + + assert(address != NULL); + CHECK_ADDRESS(address, UNIX, GSOCK_INVADDR); + + addr = (struct sockaddr_un *)address->m_addr; + + strncpy(path, addr->sun_path, sbuf); + + return GSOCK_NOERROR; +} diff --git a/src/unix/gsockunx.h b/src/unix/gsockunx.h new file mode 100644 index 0000000000..5294e6f84b --- /dev/null +++ b/src/unix/gsockunx.h @@ -0,0 +1,57 @@ +#ifndef __GSOCK_UNX_H +#define __GSOCK_UNX_H + +#include + +/* Definition of GSocket */ +struct _GSocket { + int m_fd; + GAddress *m_local, *m_peer; + GSocketError m_error; + + bool m_blocking, m_server, m_stream, m_oriented; + + /* Fallbacks */ + GSocketFallback m_fbacks[GSOCK_MAX_EVENT]; + char *m_data[GSOCK_MAX_EVENT]; + + /* IO calls associated */ + bool m_iocalls[GSOCK_MAX_EVENT]; + + char *m_gui_dependent; +}; + +/* Definition of GAddress */ +struct _GAddress { + struct sockaddr *m_addr; + size_t m_len; + + GAddressType m_family; + int m_realfamily; + + GSocketError m_error; +}; + +void _GSocket_Enable(GSocket *socket, GSocketEvent event); +void _GSocket_Disable(GSocket *socket, GSocketEvent event); +int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size); +int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size); +int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size); +int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size); +void _GSocket_Install_Fallback(GSocket *socket, GSocketEvent count); +void _GSocket_Uninstall_Fallback(GSocket *socket, GSocketEvent count); +void _GSocket_Detected_Read(GSocket *socket); +void _GSocket_Detected_Write(GSocket *socket); +void _GSocket_GUI_Init(GSocket *socket); +void _GSocket_GUI_Destroy(GSocket *socket); +void _GAddress_translate_from(GAddress *address, + struct sockaddr *addr, int len); +void _GAddress_translate_to(GAddress *address, + struct sockaddr **addr, int *len); + +/* Internet address family */ +void _GAddress_Init_INET(GAddress *address); +/* Local address family */ +void _GAddress_Init_UNIX(GAddress *address); + +#endif -- 2.45.2