From c9bccf239c1506c7eea0bddea44d9e4b76ad1d93 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 29 Dec 2008 14:35:48 +0000 Subject: [PATCH] replaced unweildy GAddress functions with wxSockAddressImpl class, similarly to GSocket -> wxSocketImpl transition; share more code between IPv4 and IPv6 branches git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57635 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/private/sckaddr.h | 294 +++++++++++ include/wx/private/socket.h | 103 +--- include/wx/sckaddr.h | 159 +++--- src/common/sckaddr.cpp | 923 +++++++++++++++++++++++++++------- src/common/socket.cpp | 232 +++------ src/msw/sockmsw.cpp | 505 ------------------- src/unix/sockunix.cpp | 950 +---------------------------------- 7 files changed, 1184 insertions(+), 1982 deletions(-) create mode 100644 include/wx/private/sckaddr.h diff --git a/include/wx/private/sckaddr.h b/include/wx/private/sckaddr.h new file mode 100644 index 0000000000..eafa8fdccb --- /dev/null +++ b/include/wx/private/sckaddr.h @@ -0,0 +1,294 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/private/sockaddr.h +// Purpose: wxSockAddressImpl +// Author: Vadim Zeitlin +// Created: 2008-12-28 +// RCS-ID: $Id$ +// Copyright: (c) 2008 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PRIVATE_SOCKADDR_H_ +#define _WX_PRIVATE_SOCKADDR_H_ + +#ifdef __WXMSW__ + #include "wx/msw/wrapwin.h" +#elif defined(__VMS__) + #include + + struct sockaddr_un + { + u_char sun_len; /* sockaddr len including null */ + u_char sun_family; /* AF_UNIX */ + char sun_path[108]; /* path name (gag) */ + }; +#else // generic Unix + #include + #include + #include + #include +#endif // platform + +#include // for calloc() + +// this is a wrapper for sockaddr_storage if it's available or just sockaddr +// otherwise +union wxSockAddressStorage +{ +#if wxUSE_IPV6 + sockaddr_storage addr_storage; +#endif + sockaddr addr; +}; + +// ---------------------------------------------------------------------------- +// helpers for wxSockAddressImpl +// ---------------------------------------------------------------------------- + +// helper class mapping sockaddr_xxx types to corresponding AF_XXX values +// +// FIXME-VC6: we could leave the template undefined if not for VC6 which +// absolutely does need to have a generic version defining the +// template "interface" to compile the code below +template struct AddressFamily { enum { value = AF_UNSPEC }; }; + +template <> struct AddressFamily { enum { value = AF_INET }; }; + +#if wxUSE_IPV6 +template <> struct AddressFamily { enum { value = AF_INET6 }; }; +#endif // wxUSE_IPV6 + +#ifdef wxHAS_UNIX_DOMAIN_SOCKETS +template <> struct AddressFamily { enum { value = AF_UNIX }; }; +#endif // wxHAS_UNIX_DOMAIN_SOCKETS + +// ---------------------------------------------------------------------------- +// wxSockAddressImpl +// ---------------------------------------------------------------------------- + +// Represents a socket endpoint, e.g. an (address, port) pair for PF_INET +// sockets. It can be initialized from an existing sockaddr struct and also +// provides access to sockaddr stored internally so that it can be easily used +// with e.g. connect(2). +// +// This class also performs (synchronous, hence potentially long) name lookups +// if necessary, i.e. if the host name strings don't contain addresses in +// numerical form (quad dotted for IPv4 or standard hexadecimal for IPv6). +// Notice that internally the potentially Unicode host names are encoded as +// UTF-8 before being passed to the lookup function but the host names should +// really be ASCII anyhow. +class wxSockAddressImpl +{ +public: + // as this is passed to socket() it should be a PF_XXX and not AF_XXX (even + // though they're the same in practice) + enum Family + { + FAMILY_INET = PF_INET, +#if wxUSE_IPV6 + FAMILY_INET6 = PF_INET6, +#endif +#ifdef wxHAS_UNIX_DOMAIN_SOCKETS + FAMILY_UNIX = PF_UNIX, +#endif + FAMILY_UNSPEC = PF_UNSPEC + }; + + // default ctor creates uninitialized object, use one of CreateXXX() below + wxSockAddressImpl() + { + InitUnspec(); + } + + // ctor from an existing sockaddr + wxSockAddressImpl(const sockaddr& addr, int len) + { + switch ( addr.sa_family ) + { + case PF_INET: +#if wxUSE_IPV6 + case PF_INET6: +#endif +#ifdef wxHAS_UNIX_DOMAIN_SOCKETS + case PF_UNIX: +#endif + m_family = static_cast(addr.sa_family); + break; + + default: + wxFAIL_MSG( "unsupported socket address family" ); + InitUnspec(); + return; + } + + InitFromSockaddr(addr, len); + } + + // copy ctor and assignment operators + wxSockAddressImpl(const wxSockAddressImpl& other) + { + InitFromOther(other); + } + + wxSockAddressImpl& operator=(const wxSockAddressImpl& other) + { + free(m_addr); + + InitFromOther(other); + + return *this; + } + + // dtor frees the memory used by m_addr + ~wxSockAddressImpl() + { + free(m_addr); + } + + + // reset the address to the initial uninitialized state + void Clear() + { + free(m_addr); + + InitUnspec(); + } + + // initialize the address to be of specific address family, it must be + // currently uninitialized (you may call Clear() to achieve this) + void CreateINET(); + void CreateINET6(); +#ifdef wxHAS_UNIX_DOMAIN_SOCKETS + void CreateUnix(); +#endif // wxHAS_UNIX_DOMAIN_SOCKETS + + // simple accessors + Family GetFamily() const { return m_family; } + bool Is(Family family) const { return m_family == family; } + bool IsOk() const { return m_family != FAMILY_UNSPEC; } + const sockaddr *GetAddr() const { return m_addr; } + sockaddr *GetWritableAddr() { return m_addr; } + int GetLen() const { return m_len; } + + // accessors for INET or INET6 address families +#if wxUSE_IPV6 + #define CALL_IPV4_OR_6(func, args) \ + Is(FAMILY_INET6) ? func##6(args) : func##4(args) + #define CALL_IPV4_OR_6_VOID(func) \ + Is(FAMILY_INET6) ? func##6() : func##4() +#else + #define CALL_IPV4_OR_6(func, args) func##4(args) + #define CALL_IPV4_OR_6_VOID(func) func##4() +#endif // IPv6 support on/off + + wxString GetHostName() const; + bool SetHostName(const wxString& name) + { + return CALL_IPV4_OR_6(SetHostName, (name)); + } + + wxUint16 GetPort() const { return CALL_IPV4_OR_6_VOID(GetPort); } + bool SetPort(wxUint16 port) { return CALL_IPV4_OR_6(SetPort, (port)); } + bool SetPortName(const wxString& name, const char *protocol); + + bool SetToAnyAddress() { return CALL_IPV4_OR_6_VOID(SetToAnyAddress); } + +#undef CALL_IPV4_OR_6 + + // accessors for INET addresses only + bool GetHostAddress(wxUint32 *address) const; + bool SetHostAddress(wxUint32 address); + + bool SetToBroadcastAddress() { return SetHostAddress(INADDR_BROADCAST); } + + // accessors for INET6 addresses only +#if wxUSE_IPV6 + bool GetHostAddress(in6_addr *address) const; + bool SetHostAddress(const in6_addr& address); +#endif // wxUSE_IPV6 + +#ifdef wxHAS_UNIX_DOMAIN_SOCKETS + // methods valid for Unix address family addresses only + bool SetPath(const wxString& path); + wxString GetPath() const; +#endif // wxHAS_UNIX_DOMAIN_SOCKETS + +private: + void DoAlloc(int len) + { + m_addr = static_cast(calloc(1, len)); + m_len = len; + } + + // FIXME-VC6: VC6 doesn't grok Foo() call syntax so we need the extra + // dummy parameter of type T, use the macros in sckaddr.cpp to + // hide it + template + T *Alloc(T *) + { + DoAlloc(sizeof(T)); + + return reinterpret_cast(m_addr); + } + + template + T *Get(T *) const + { + wxCHECK_MSG( static_cast(m_family) == AddressFamily::value, + NULL, + "socket address family mismatch" ); + + return reinterpret_cast(m_addr); + } + + void InitUnspec() + { + m_family = FAMILY_UNSPEC; + m_addr = NULL; + m_len = 0; + } + + void InitFromSockaddr(const sockaddr& addr, int len) + { + DoAlloc(len); + memcpy(m_addr, &addr, len); + } + + void InitFromOther(const wxSockAddressImpl& other) + { + m_family = other.m_family; + + if ( other.m_addr ) + { + InitFromSockaddr(*other.m_addr, other.m_len); + } + else // no address to copy + { + m_addr = NULL; + m_len = 0; + } + } + + // IPv4/6 implementations of public functions + bool SetHostName4(const wxString& name); + + bool SetPort4(wxUint16 port); + wxUint16 GetPort4() const; + + bool SetToAnyAddress4() { return SetHostAddress(INADDR_ANY); } + +#if wxUSE_IPV6 + bool SetHostName6(const wxString& name); + + bool SetPort6(wxUint16 port); + wxUint16 GetPort6() const; + + bool SetToAnyAddress6(); +#endif // wxUSE_IPV6 + + Family m_family; + sockaddr *m_addr; + int m_len; +}; + +#endif // _WX_PRIVATE_SOCKADDR_H_ diff --git a/include/wx/private/socket.h b/include/wx/private/socket.h index d25f8d0481..e736a83dbd 100644 --- a/include/wx/private/socket.h +++ b/include/wx/private/socket.h @@ -42,6 +42,7 @@ #if wxUSE_SOCKETS #include "wx/socket.h" +#include "wx/private/sckaddr.h" #include @@ -90,23 +91,8 @@ #define SOCKET_ERROR (-1) #endif -#if wxUSE_IPV6 - typedef struct sockaddr_storage wxSockAddr; -#else - typedef struct sockaddr wxSockAddr; -#endif - -enum GAddressType -{ - wxSOCKET_NOFAMILY = 0, - wxSOCKET_INET, - wxSOCKET_INET6, - wxSOCKET_UNIX -}; - typedef int wxSocketEventFlags; -struct GAddress; class wxSocketImpl; /* @@ -200,16 +186,16 @@ public: m_initialSendBufferSize = send; } - wxSocketError SetLocal(GAddress *address); - wxSocketError SetPeer(GAddress *address); + wxSocketError SetLocal(const wxSockAddressImpl& address); + wxSocketError SetPeer(const wxSockAddressImpl& address); // accessors // --------- bool IsServer() const { return m_server; } - GAddress *GetLocal(); - GAddress *GetPeer(); + const wxSockAddressImpl& GetLocal(); // non const as may update m_local + const wxSockAddressImpl& GetPeer() const { return m_peer; } wxSocketError GetError() const { return m_error; } bool IsOk() const { return m_error == wxSOCKET_NOERROR; } @@ -303,8 +289,8 @@ public: int m_initialRecvBufferSize; int m_initialSendBufferSize; - GAddress *m_local; - GAddress *m_peer; + wxSockAddressImpl m_local, + m_peer; wxSocketError m_error; bool m_stream; @@ -332,7 +318,7 @@ private: // check that the socket wasn't created yet and that the given address // (either m_local or m_peer depending on the socket kind) is valid and // set m_error and return false if this is not the case - bool PreCreateCheck(GAddress *addr); + bool PreCreateCheck(const wxSockAddressImpl& addr); // set the given socket option: this just wraps setsockopt(SOL_SOCKET) int SetSocketOption(int optname, int optval) @@ -378,79 +364,6 @@ private: #include "wx/unix/private/sockunix.h" #endif - -/* GAddress */ - -// TODO: make GAddress a real class instead of this mix of C and C++ - -// Represents a socket endpoint, i.e. -- in spite of its name -- not an address -// but an (address, port) pair -struct GAddress -{ - struct sockaddr *m_addr; - size_t m_len; - - GAddressType m_family; - int m_realfamily; - - wxSocketError m_error; -}; - -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 specific one. For example if you use GAddress_INET_SetHostName, - * address family will be implicitly set to AF_INET. - */ - -wxSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname); -wxSocketError GAddress_INET_SetBroadcastAddress(GAddress *address); -wxSocketError GAddress_INET_SetAnyAddress(GAddress *address); -wxSocketError GAddress_INET_SetHostAddress(GAddress *address, - unsigned long hostaddr); -wxSocketError GAddress_INET_SetPortName(GAddress *address, const char *port, - const char *protocol); -wxSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port); - -wxSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, - size_t sbuf); -unsigned long GAddress_INET_GetHostAddress(GAddress *address); -unsigned short GAddress_INET_GetPort(GAddress *address); - -wxSocketError _GAddress_translate_from(GAddress *address, - struct sockaddr *addr, int len); -wxSocketError _GAddress_translate_to (GAddress *address, - struct sockaddr **addr, int *len); -wxSocketError _GAddress_Init_INET(GAddress *address); - -#if wxUSE_IPV6 - -wxSocketError GAddress_INET6_SetHostName(GAddress *address, const char *hostname); -wxSocketError GAddress_INET6_SetAnyAddress(GAddress *address); -wxSocketError GAddress_INET6_SetHostAddress(GAddress *address, - struct in6_addr hostaddr); -wxSocketError GAddress_INET6_SetPortName(GAddress *address, const char *port, - const char *protocol); -wxSocketError GAddress_INET6_SetPort(GAddress *address, unsigned short port); - -wxSocketError GAddress_INET6_GetHostName(GAddress *address, char *hostname, - size_t sbuf); -wxSocketError GAddress_INET6_GetHostAddress(GAddress *address,struct in6_addr *hostaddr); -unsigned short GAddress_INET6_GetPort(GAddress *address); - -#endif // wxUSE_IPV6 - -// these functions are available under all platforms but only implemented under -// Unix ones, elsewhere they just return wxSOCKET_INVADDR -wxSocketError _GAddress_Init_UNIX(GAddress *address); -wxSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path); -wxSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf); - #endif /* wxUSE_SOCKETS */ #endif /* _WX_PRIVATE_SOCKET_H_ */ diff --git a/include/wx/sckaddr.h b/include/wx/sckaddr.h index 8dd3a80a5e..3fbb01ce98 100644 --- a/include/wx/sckaddr.h +++ b/include/wx/sckaddr.h @@ -18,18 +18,19 @@ #include "wx/string.h" -struct GAddress; +class wxSockAddressImpl; // Any socket address kind class WXDLLIMPEXP_NET wxSockAddress : public wxObject { public: - enum + enum Family { - IPV4 = 1, - IPV6 = 2, - UNIX = 3 - } Addr; + NONE, + IPV4, + IPV6, + UNIX + }; wxSockAddress(); wxSockAddress(const wxSockAddress& other); @@ -38,7 +39,7 @@ public: wxSockAddress& operator=(const wxSockAddress& other); virtual void Clear(); - virtual int Type() = 0; + virtual Family Type() = 0; // we need to be able to create copies of the addresses polymorphically // (i.e. without knowing the exact address class) @@ -46,11 +47,11 @@ public: // implementation only, don't use - GAddress *GetAddress() const { return m_address; } - void SetAddress(GAddress *address); + const wxSockAddressImpl& GetAddress() const { return *m_impl; } + void SetAddress(const wxSockAddressImpl& address); protected: - GAddress *m_address; + wxSockAddressImpl *m_impl; private: void Init(); @@ -61,24 +62,47 @@ private: class WXDLLIMPEXP_NET wxIPaddress : public wxSockAddress { public: - wxIPaddress(); - wxIPaddress(const wxIPaddress& other); - virtual ~wxIPaddress(); + wxIPaddress() : wxSockAddress() { } + wxIPaddress(const wxIPaddress& other) + : wxSockAddress(other), + m_origHostname(other.m_origHostname) + { + } + + bool operator==(const wxIPaddress& addr) const; - virtual bool Hostname(const wxString& name) = 0; - virtual bool Service(const wxString& name) = 0; - virtual bool Service(unsigned short port) = 0; + bool Hostname(const wxString& name); + bool Service(const wxString& name); + bool Service(unsigned short port); - virtual bool LocalHost() = 0; + bool LocalHost(); virtual bool IsLocalHost() const = 0; - virtual bool AnyAddress() = 0; - virtual bool BroadcastAddress() = 0; + bool AnyAddress(); virtual wxString IPAddress() const = 0; - virtual wxString Hostname() const = 0; - virtual unsigned short Service() const = 0; + wxString Hostname() const; + unsigned short Service() const; + + wxString OrigHostname() const { return m_origHostname; } + +protected: + // get m_impl initialized to the right family if it hadn't been done yet + wxSockAddressImpl& GetImpl(); + const wxSockAddressImpl& GetImpl() const + { + return const_cast(this)->GetImpl(); + } + + // host name originally passed to Hostname() + wxString m_origHostname; + +private: + // create the wxSockAddressImpl object of the correct family if it's + // currently uninitialized + virtual void DoInitImpl() = 0; + DECLARE_ABSTRACT_CLASS(wxIPaddress) }; @@ -87,47 +111,29 @@ public: class WXDLLIMPEXP_NET wxIPV4address : public wxIPaddress { public: - wxIPV4address(); - wxIPV4address(const wxIPV4address& other); - virtual ~wxIPV4address(); - - bool operator==(const wxIPV4address& addr) const; + wxIPV4address() : wxIPaddress() { } + wxIPV4address(const wxIPV4address& other) : wxIPaddress(other) { } // implement wxSockAddress pure virtuals: - virtual int Type() { return wxSockAddress::IPV4; } - virtual wxSockAddress *Clone() const; + virtual Family Type() { return IPV4; } + virtual wxSockAddress *Clone() const { return new wxIPV4address(*this); } // implement wxIPaddress pure virtuals: - - // handles the usual dotted quad format too - virtual bool Hostname(const wxString& name); - virtual bool Service(const wxString& name); - virtual bool Service(unsigned short port); - - // localhost (127.0.0.1) - virtual bool LocalHost(); virtual bool IsLocalHost() const; - // any (0.0.0.0) - virtual bool AnyAddress(); - // all (255.255.255.255) - virtual bool BroadcastAddress(); - - // a.b.c.d virtual wxString IPAddress() const; - virtual wxString Hostname() const; - virtual unsigned short Service() const; - // IPv4-specific methods: - bool Hostname(unsigned long addr); - wxString OrigHostname() { return m_origHostname; } + + bool BroadcastAddress(); + + using wxIPaddress::Hostname; private: - wxString m_origHostname; + virtual void DoInitImpl(); DECLARE_DYNAMIC_CLASS(wxIPV4address) }; @@ -139,78 +145,63 @@ private: class WXDLLIMPEXP_NET wxIPV6address : public wxIPaddress { public: - wxIPV6address(); - wxIPV6address(const wxIPV6address& other); - virtual ~wxIPV6address(); + wxIPV6address() : wxIPaddress() { } + wxIPV6address(const wxIPV6address& other) : wxIPaddress(other) { } // implement wxSockAddress pure virtuals: - - virtual int Type() { return wxSockAddress::IPV6; } + virtual Family Type() { return IPV6; } virtual wxSockAddress *Clone() const { return new wxIPV6address(*this); } // implement wxIPaddress pure virtuals: - - virtual bool Hostname(const wxString& name); - virtual bool Service(const wxString& name); - virtual bool Service(unsigned short port); - - // localhost (0000:0000:0000:0000:0000:0000:0000:0001 (::1)) - virtual bool LocalHost(); virtual bool IsLocalHost() const; - // any (0000:0000:0000:0000:0000:0000:0000:0000 (::)) - virtual bool AnyAddress(); - // all (?) - virtual bool BroadcastAddress(); - - // 3ffe:ffff:0100:f101:0210:a4ff:fee3:9566 virtual wxString IPAddress() const; - virtual wxString Hostname() const; - virtual unsigned short Service() const; - - // IPv6-specific methods: - bool Hostname(unsigned char addr[16]); + using wxIPaddress::Hostname; + private: - wxString m_origHostname; + virtual void DoInitImpl(); DECLARE_DYNAMIC_CLASS(wxIPV6address) }; #endif // wxUSE_IPV6 -#if defined(__UNIX__) && !defined(__WINE__) - -#include -#ifndef __VMS__ - #include +// Unix domain sockets are only available under, well, Unix +#if defined(__UNIX__) && !defined(__WINDOWS__) && !defined(__WINE__) + #define wxHAS_UNIX_DOMAIN_SOCKETS #endif +#ifdef wxHAS_UNIX_DOMAIN_SOCKETS + // A Unix domain socket address class WXDLLIMPEXP_NET wxUNIXaddress : public wxSockAddress { public: - wxUNIXaddress(); - wxUNIXaddress(const wxUNIXaddress& other); - virtual ~wxUNIXaddress(); + wxUNIXaddress() : wxSockAddress() { } + wxUNIXaddress(const wxUNIXaddress& other) : wxSockAddress(other) { } void Filename(const wxString& name); - wxString Filename(); + wxString Filename() const; - virtual int Type() { return wxSockAddress::UNIX; } + virtual Family Type() { return UNIX; } virtual wxSockAddress *Clone() const { return new wxUNIXaddress(*this); } private: - struct sockaddr_un *m_addr; + wxSockAddressImpl& GetUNIX(); + const wxSockAddressImpl& GetUNIX() const + { + return const_cast(this)->GetUNIX(); + } DECLARE_DYNAMIC_CLASS(wxUNIXaddress) }; -#endif // __UNIX__ +#endif // wxHAS_UNIX_DOMAIN_SOCKETS #endif // wxUSE_SOCKETS diff --git a/src/common/sckaddr.cpp b/src/common/sckaddr.cpp index ceccf92083..6f7601842e 100644 --- a/src/common/sckaddr.cpp +++ b/src/common/sckaddr.cpp @@ -2,13 +2,22 @@ // Name: src/common/sckaddr.cpp // Purpose: Network address manager // Author: Guilhem Lavaux -// Modified by: // Created: 26/04/97 +// Modified by: Vadim Zeitlin to use wxSockAddressImpl on 2008-12-28 // RCS-ID: $Id$ // Copyright: (c) 1997, 1998 Guilhem Lavaux +// (c) 2008 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -35,6 +44,20 @@ #include "wx/socket.h" #include "wx/sckaddr.h" #include "wx/private/socket.h" +#include "wx/private/sckaddr.h" + +#ifdef __UNIX__ + #include + #include +#endif // __UNIX__ + +#ifndef INADDR_NONE + #define INADDR_NONE INADDR_ANY +#endif + +// ---------------------------------------------------------------------------- +// wxRTTI macros +// ---------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxSockAddress, wxObject) IMPLEMENT_ABSTRACT_CLASS(wxIPaddress, wxSockAddress) @@ -42,277 +65,837 @@ IMPLEMENT_DYNAMIC_CLASS(wxIPV4address, wxIPaddress) #if wxUSE_IPV6 IMPLEMENT_DYNAMIC_CLASS(wxIPV6address, wxIPaddress) #endif -#if defined(__UNIX__) && !defined(__WINDOWS__) && !defined(__WINE__) +#if defined(__UNIX__) && !defined(__WINDOWS__) && !defined(__WINE__) IMPLEMENT_DYNAMIC_CLASS(wxUNIXaddress, wxSockAddress) #endif -// --------------------------------------------------------------------------- -// wxSockAddress -// --------------------------------------------------------------------------- +// ============================================================================ +// implementation of thread-safe/reentrant functions if they're missing +// ============================================================================ -void wxSockAddress::Init() +// TODO: use POSIX getaddrinfo() (also available in Winsock 2) for simplicity +// and IPv6 support + +#ifdef __WXMSW__ + #define HAVE_INET_ADDR + + #define HAVE_GETHOSTBYNAME + #define HAVE_GETSERVBYNAME + + // under MSW getxxxbyname() functions are MT-safe (but not reentrant) so + // we don't need to serialize calls to them + #define wxHAS_MT_SAFE_GETBY_FUNCS +#endif // __WXMSW__ + +// we assume that we have gethostbyaddr_r() if and only if we have +// gethostbyname_r() and that it uses the similar conventions to it (see +// comment in configure) +#define HAVE_GETHOSTBYADDR HAVE_GETHOSTBYNAME +#ifdef HAVE_FUNC_GETHOSTBYNAME_R_3 + #define HAVE_FUNC_GETHOSTBYADDR_R_3 +#endif +#ifdef HAVE_FUNC_GETHOSTBYNAME_R_5 + #define HAVE_FUNC_GETHOSTBYADDR_R_5 +#endif +#ifdef HAVE_FUNC_GETHOSTBYNAME_R_6 + #define HAVE_FUNC_GETHOSTBYADDR_R_6 +#endif + +// the _r functions need the extra buffer parameter but unfortunately its type +// differs between different systems +#ifdef HAVE_FUNC_GETHOSTBYNAME_R_3 + typedef hostent_data wxGethostBuf; +#else + typedef char wxGethostBuf[1024]; +#endif + +#ifdef HAVE_FUNC_GETSERVBYNAME_R_3 + typedef servent_data wxGetservBuf; +#else + typedef char wxGetservBuf[1024]; +#endif + +#ifdef wxHAS_MT_SAFE_GETBY_FUNCS + #define wxLOCK_GETBY_MUTEX(name) +#else // may need mutexes to protect getxxxbyxxx() calls + #if defined(HAVE_GETHOSTBYNAME) || \ + defined(HAVE_GETHOSTBYADDR) || \ + defined(HAVE_GETSERVBYNAME) + #include "wx/thread.h" + + namespace + { + // these mutexes are used to serialize + wxMutex nameLock, // gethostbyname() + addrLock, // gethostbyaddr() + servLock; // getservbyname() + } + + #define wxLOCK_GETBY_MUTEX(name) wxMutexLocker locker(name ## Lock) + #endif // we don't have _r functions +#endif // wxUSE_THREADS + +namespace { - if ( !wxSocketBase::IsInitialized() ) + +#if defined(HAVE_GETHOSTBYNAME) +hostent *deepCopyHostent(hostent *h, + const hostent *he, + char *buffer, + int size, + int *err) +{ + /* copy old structure */ + memcpy(h, he, sizeof(hostent)); + + /* copy name */ + int len = strlen(h->h_name); + if (len > size) { - // we must do it before using GAddress_XXX functions - (void)wxSocketBase::Initialize(); + *err = ENOMEM; + return NULL; } -} + memcpy(buffer, h->h_name, len); + buffer[len] = '\0'; + h->h_name = buffer; -wxSockAddress::wxSockAddress() -{ - Init(); + /* track position in the buffer */ + int pos = len + 1; + + /* reuse len to store address length */ + len = h->h_length; + + /* ensure pointer alignment */ + unsigned int misalign = sizeof(char *) - pos%sizeof(char *); + if(misalign < sizeof(char *)) + pos += misalign; + + /* leave space for pointer list */ + char **p = h->h_addr_list, **q; + char **h_addr_list = (char **)(buffer + pos); + while(*(p++) != 0) + pos += sizeof(char *); + + /* copy addresses and fill new pointer list */ + for (p = h->h_addr_list, q = h_addr_list; *p != 0; p++, q++) + { + if (size < pos + len) + { + *err = ENOMEM; + return NULL; + } + memcpy(buffer + pos, *p, len); /* copy content */ + *q = buffer + pos; /* set copied pointer to copied content */ + pos += len; + } + *++q = 0; /* null terminate the pointer list */ + h->h_addr_list = h_addr_list; /* copy pointer to pointers */ + + /* ensure word alignment of pointers */ + misalign = sizeof(char *) - pos%sizeof(char *); + if(misalign < sizeof(char *)) + pos += misalign; + + /* leave space for pointer list */ + p = h->h_aliases; + char **h_aliases = (char **)(buffer + pos); + while(*(p++) != 0) + pos += sizeof(char *); + + /* copy aliases and fill new pointer list */ + for (p = h->h_aliases, q = h_aliases; *p != 0; p++, q++) + { + len = strlen(*p); + if (size <= pos + len) + { + *err = ENOMEM; + return NULL; + } + memcpy(buffer + pos, *p, len); /* copy content */ + buffer[pos + len] = '\0'; + *q = buffer + pos; /* set copied pointer to copied content */ + pos += len + 1; + } + *++q = 0; /* null terminate the pointer list */ + h->h_aliases = h_aliases; /* copy pointer to pointers */ + + return h; +} +#endif // HAVE_GETHOSTBYNAME + +hostent *wxGethostbyname_r(const char *hostname, + hostent *h, + wxGethostBuf buffer, + int size, + int *err) +{ + hostent *he; +#if defined(HAVE_FUNC_GETHOSTBYNAME_R_6) + gethostbyname_r(hostname, h, buffer, size, &he, err); +#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5) + he = gethostbyname_r(hostname, h, buffer, size, err); +#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3) + he = gethostbyname_r(hostname, h, &buffer); + *err = h_errno; +#elif defined(HAVE_GETHOSTBYNAME) + wxLOCK_GETBY_MUTEX(name); + + he = gethostbyname(hostname); + *err = h_errno; + + if ( he ) + he = deepCopyHostent(h, he, buffer, size, err); +#else + #error "No gethostbyname[_r]()" +#endif + + return he; +} + +hostent *wxGethostbyaddr_r(const char *addr_buf, + int buf_size, + int proto, + hostent *h, + wxGethostBuf buffer, + int size, + int *err) +{ + hostent *he; +#if defined(HAVE_FUNC_GETHOSTBYADDR_R_6) + gethostbyaddr_r(addr_buf, buf_size, proto, h, buffer, size, &he, err); +#elif defined(HAVE_FUNC_GETHOSTBYADDR_R_5) + he = gethostbyaddr_r(addr_buf, buf_size, proto, h, buffer, size, err); +#elif defined(HAVE_FUNC_GETHOSTBYADDR_R_3) + he = gethostbyaddr_r(addr_buf, buf_size, proto, h, buffer); + *err = h_errno; +#elif defined(HAVE_GETHOSTBYADDR) + wxLOCK_GETBY_MUTEX(addr); + + he = gethostbyaddr(addr_buf, buf_size, proto); + *err = h_errno; + + if ( he ) + he = deepCopyHostent(h, he, buffer, size, err); +#else + #error "No gethostbyaddr[_r]()" +#endif - m_address = GAddress_new(); + return he; } -wxSockAddress::wxSockAddress(const wxSockAddress& other) - : wxObject() +#if defined(HAVE_GETSERVBYNAME) +servent *deepCopyServent(servent *s, + servent *se, + char *buffer, + int size) { - Init(); + /* copy plain old structure */ + memcpy(s, se, sizeof(servent)); - m_address = GAddress_copy(other.m_address); + /* copy name */ + int len = strlen(s->s_name); + if (len >= size) + { + return NULL; + } + memcpy(buffer, s->s_name, len); + buffer[len] = '\0'; + s->s_name = buffer; + + /* track position in the buffer */ + int pos = len + 1; + + /* copy protocol */ + len = strlen(s->s_proto); + if (pos + len >= size) + { + return NULL; + } + memcpy(buffer + pos, s->s_proto, len); + buffer[pos + len] = '\0'; + s->s_proto = buffer + pos; + + /* track position in the buffer */ + pos += len + 1; + + /* ensure pointer alignment */ + unsigned int misalign = sizeof(char *) - pos%sizeof(char *); + if(misalign < sizeof(char *)) + pos += misalign; + + /* leave space for pointer list */ + char **p = s->s_aliases, **q; + char **s_aliases = (char **)(buffer + pos); + while(*(p++) != 0) + pos += sizeof(char *); + + /* copy addresses and fill new pointer list */ + for (p = s->s_aliases, q = s_aliases; *p != 0; p++, q++){ + len = strlen(*p); + if (size <= pos + len) + { + return NULL; + } + memcpy(buffer + pos, *p, len); /* copy content */ + buffer[pos + len] = '\0'; + *q = buffer + pos; /* set copied pointer to copied content */ + pos += len + 1; + } + *++q = 0; /* null terminate the pointer list */ + s->s_aliases = s_aliases; /* copy pointer to pointers */ + return s; +} +#endif // HAVE_GETSERVBYNAME + +servent *wxGetservbyname_r(const char *port, + const char *protocol, + servent *serv, + wxGetservBuf buffer, + int size) +{ + servent *se; +#if defined(HAVE_FUNC_GETSERVBYNAME_R_6) + getservbyname_r(port, protocol, serv, buffer, size, &se); +#elif defined(HAVE_FUNC_GETSERVBYNAME_R_5) + se = getservbyname_r(port, protocol, serv, buffer, size); +#elif defined(HAVE_FUNC_GETSERVBYNAME_R_4) + se = getservbyname_r(port, protocol, serv, &buffer); +#elif defined(HAVE_GETSERVBYNAME) + wxLOCK_GETBY_MUTEX(serv); + + se = getservbyname(port, protocol); + if ( se ) + se = deepCopyServent(serv, se, buffer, size); +#else + #error "No getservbyname[_r]()" +#endif + return se; } -wxSockAddress::~wxSockAddress() +} // anonymous namespace + +// ============================================================================ +// wxSockAddressImpl implementation +// ============================================================================ + +// FIXME-VC6: helper macros to call Alloc/Get() hiding the ugly dummy argument +#define ALLOC(T) Alloc(static_cast(NULL)) +#define GET(T) Get(static_cast(NULL)) + +// ---------------------------------------------------------------------------- +// INET or INET6 address family +// ---------------------------------------------------------------------------- + +wxString wxSockAddressImpl::GetHostName() const { - GAddress_destroy(m_address); + const void *addrbuf; + int addrbuflen; + +#if wxUSE_IPV6 + if ( m_family == FAMILY_INET6 ) + { + sockaddr_in6 * const addr6 = GET(sockaddr_in6); + addrbuf = &addr6->sin6_addr; + addrbuflen = sizeof(addr6->sin6_addr); + } + else +#endif // wxUSE_IPV6 + { + sockaddr_in * const addr = GET(sockaddr_in); + if ( !addr ) + return wxString(); + + addrbuf = &addr->sin_addr; + addrbuflen = sizeof(addr->sin_addr); + } + + hostent he; + wxGethostBuf buffer; + int err; + if ( !wxGethostbyaddr_r + ( + static_cast(addrbuf), + addrbuflen, + m_family, + &he, + buffer, + sizeof(buffer), + &err + ) ) + { + return wxString(); + } + + return wxString::FromUTF8(he.h_name); } -void wxSockAddress::SetAddress(GAddress *address) +bool wxSockAddressImpl::SetPortName(const wxString& name, const char *protocol) { - if ( address != m_address ) + // test whether it's a number first + unsigned long port; + if ( name.ToULong(&port) ) { - GAddress_destroy(m_address); - m_address = GAddress_copy(address); + if ( port > 65535 ) + return false; } + else // it's a service name + { + wxGetservBuf buffer; + servent se; + if ( !wxGetservbyname_r(name.utf8_str(), protocol, &se, + buffer, sizeof(buffer)) ) + return false; + + // s_port is in network byte order and SetPort() uses the host byte + // order and we prefer to reuse it from here instead of assigning to + // sin_port directly + port = ntohs(se.s_port); + } + + return SetPort(port); } -wxSockAddress& wxSockAddress::operator=(const wxSockAddress& addr) +// ---------------------------------------------------------------------------- +// INET address family +// ---------------------------------------------------------------------------- + +void wxSockAddressImpl::CreateINET() { - SetAddress(addr.GetAddress()); - return *this; + wxASSERT_MSG( Is(FAMILY_UNSPEC), "recreating address as different type?" ); + + m_family = FAMILY_INET; + sockaddr_in * const addr = ALLOC(sockaddr_in); + addr->sin_family = FAMILY_INET; } -void wxSockAddress::Clear() +bool wxSockAddressImpl::SetHostName4(const wxString& name) { - GAddress_destroy(m_address); - m_address = GAddress_new(); + sockaddr_in * const addr = GET(sockaddr_in); + if ( !addr ) + return false; + + const wxUTF8Buf namebuf(name.utf8_str()); + + // first check if this is an address in quad dotted notation +#if defined(HAVE_INET_ATON) + if ( inet_aton(namebuf, &addr->sin_addr) ) + return true; +#elif defined(HAVE_INET_ADDR) + addr->sin_addr.s_addr = inet_addr(namebuf); + if ( addr->sin_addr.s_addr != INADDR_NONE ) + return true; +#else + #error "Neither inet_aton() nor inet_addr() is available?" +#endif + + // it's a host name, resolve it + hostent he; + wxGethostBuf buffer; + int err; + if ( !wxGethostbyname_r(namebuf, &he, buffer, sizeof(buffer), &err) ) + return false; + + addr->sin_addr.s_addr = ((in_addr *)he.h_addr)->s_addr; + return true; } -// --------------------------------------------------------------------------- -// wxIPaddress -// --------------------------------------------------------------------------- +bool wxSockAddressImpl::GetHostAddress(wxUint32 *address) const +{ + sockaddr_in * const addr = GET(sockaddr_in); + if ( !addr ) + return false; -wxIPaddress::wxIPaddress() - : wxSockAddress() + *address = ntohl(addr->sin_addr.s_addr); + + return true; +} + +bool wxSockAddressImpl::SetHostAddress(wxUint32 address) { + sockaddr_in * const addr = GET(sockaddr_in); + if ( !addr ) + return false; + + addr->sin_addr.s_addr = htonl(address); + + return true; } -wxIPaddress::wxIPaddress(const wxIPaddress& other) - : wxSockAddress(other) +wxUint16 wxSockAddressImpl::GetPort4() const { + sockaddr_in * const addr = GET(sockaddr_in); + if ( !addr ) + return 0; + + return ntohs(addr->sin_port); } -wxIPaddress::~wxIPaddress() +bool wxSockAddressImpl::SetPort4(wxUint16 port) { + sockaddr_in * const addr = GET(sockaddr_in); + if ( !addr ) + return false; + + addr->sin_port = htons(port); + + return true; } -// --------------------------------------------------------------------------- -// wxIPV4address -// --------------------------------------------------------------------------- +#if wxUSE_IPV6 + +// ---------------------------------------------------------------------------- +// INET6 address family +// ---------------------------------------------------------------------------- -wxIPV4address::wxIPV4address() - : wxIPaddress() +void wxSockAddressImpl::CreateINET6() { + wxASSERT_MSG( Is(FAMILY_UNSPEC), "recreating address as different type?" ); + + m_family = FAMILY_INET6; + sockaddr_in6 * const addr = ALLOC(sockaddr_in6); + addr->sin6_family = FAMILY_INET6; } -wxIPV4address::wxIPV4address(const wxIPV4address& other) - : wxIPaddress(other) +bool wxSockAddressImpl::SetHostName6(const wxString& hostname) { + sockaddr_in6 * const addr = GET(sockaddr_in6); + if ( !addr ) + return false; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo *info = NULL; + int rc = getaddrinfo(hostname.utf8_str(), NULL, &hints, &info); + if ( rc ) + { + // use gai_strerror()? + return false; + } + + wxCHECK_MSG( info, false, "should have info on success" ); + + wxASSERT_MSG( int(info->ai_addrlen) == m_len, "unexpected address length" ); + + memcpy(addr, info->ai_addr, info->ai_addrlen); + freeaddrinfo(info); + + return true; } -wxIPV4address::~wxIPV4address() +bool wxSockAddressImpl::GetHostAddress(in6_addr *address) const { + sockaddr_in6 * const addr = GET(sockaddr_in6); + if ( !addr ) + return false; + + *address = addr->sin6_addr; + + return true; } -bool wxIPV4address::Hostname(const wxString& name) +bool wxSockAddressImpl::SetHostAddress(const in6_addr& address) { - // Some people are sometimes fool. - if (name.empty()) - { - wxLogWarning( _("Trying to solve a NULL hostname: giving up") ); - return false; - } - m_origHostname = name; - return (GAddress_INET_SetHostName(m_address, name.mb_str()) == wxSOCKET_NOERROR); + sockaddr_in6 * const addr = GET(sockaddr_in6); + if ( !addr ) + return false; + + addr->sin6_addr = address; + + return true; } -bool wxIPV4address::Hostname(unsigned long addr) +wxUint16 wxSockAddressImpl::GetPort6() const { - bool rv = (GAddress_INET_SetHostAddress(m_address, addr) == wxSOCKET_NOERROR); - if (rv) - m_origHostname = Hostname(); - else - m_origHostname = wxEmptyString; - return rv; + sockaddr_in6 * const addr = GET(sockaddr_in6); + if ( !addr ) + return 0; + + return ntohs(addr->sin6_port); } -bool wxIPV4address::Service(const wxString& name) +bool wxSockAddressImpl::SetPort6(wxUint16 port) { - return (GAddress_INET_SetPortName(m_address, name.mb_str(), "tcp") == wxSOCKET_NOERROR); + sockaddr_in6 * const addr = GET(sockaddr_in6); + if ( !addr ) + return false; + + addr->sin6_port = htons(port); + + return true; } -bool wxIPV4address::Service(unsigned short port) +bool wxSockAddressImpl::SetToAnyAddress6() +{ + static const in6_addr any = IN6ADDR_ANY_INIT; + + return SetHostAddress(any); +} + +#endif // wxUSE_IPV6 + +#ifdef wxHAS_UNIX_DOMAIN_SOCKETS + +// ---------------------------------------------------------------------------- +// Unix address family +// ---------------------------------------------------------------------------- + +#ifndef UNIX_PATH_MAX + #define UNIX_PATH_MAX (WXSIZEOF(((sockaddr_un *)NULL)->sun_path)) +#endif + +void wxSockAddressImpl::CreateUnix() { - return (GAddress_INET_SetPort(m_address, port) == wxSOCKET_NOERROR); + wxASSERT_MSG( Is(FAMILY_UNSPEC), "recreating address as different type?" ); + + m_family = FAMILY_UNIX; + sockaddr_un * const addr = ALLOC(sockaddr_un); + addr->sun_family = FAMILY_UNIX; + addr->sun_path[0] = '\0'; } -bool wxIPV4address::LocalHost() +bool wxSockAddressImpl::SetPath(const wxString& path) { - return (GAddress_INET_SetHostName(m_address, "localhost") == wxSOCKET_NOERROR); + sockaddr_un * const addr = GET(sockaddr_un); + if ( !addr ) + return false; + + const wxUTF8Buf buf(path.utf8_str()); + if ( strlen(buf) >= UNIX_PATH_MAX ) + return false; + + wxStrlcpy(addr->sun_path, buf, UNIX_PATH_MAX); + + return true; } -bool wxIPV4address::IsLocalHost() const +wxString wxSockAddressImpl::GetPath() const { - return (Hostname() == wxT("localhost") || IPAddress() == wxT("127.0.0.1")); + sockaddr_un * const addr = GET(sockaddr_un); + if ( !addr ) + return wxString(); + + return wxString::FromUTF8(addr->sun_path); } -bool wxIPV4address::BroadcastAddress() +#endif // wxHAS_UNIX_DOMAIN_SOCKETS + +#undef GET +#undef ALLOC + +// ---------------------------------------------------------------------------- +// wxSockAddress +// ---------------------------------------------------------------------------- + +void wxSockAddress::Init() { - return (GAddress_INET_SetBroadcastAddress(m_address) == wxSOCKET_NOERROR); + if ( !wxSocketBase::IsInitialized() ) + { + // we must do it before using any socket functions + (void)wxSocketBase::Initialize(); + } } -bool wxIPV4address::AnyAddress() +wxSockAddress::wxSockAddress() { - return (GAddress_INET_SetAnyAddress(m_address) == wxSOCKET_NOERROR); + Init(); + + m_impl = new wxSockAddressImpl(); } -wxString wxIPV4address::Hostname() const +wxSockAddress::wxSockAddress(const wxSockAddress& other) + : wxObject() { - char hostname[1024]; + Init(); - hostname[0] = 0; - GAddress_INET_GetHostName(m_address, hostname, 1024); - return wxString::FromAscii(hostname); + m_impl = new wxSockAddressImpl(*other.m_impl); } -unsigned short wxIPV4address::Service() const +wxSockAddress::~wxSockAddress() { - return GAddress_INET_GetPort(m_address); + delete m_impl; } -wxSockAddress *wxIPV4address::Clone() const +void wxSockAddress::SetAddress(const wxSockAddressImpl& address) { - wxIPV4address *addr = new wxIPV4address(*this); - addr->m_origHostname = m_origHostname; - return addr; + if ( &address != m_impl ) + { + delete m_impl; + m_impl = new wxSockAddressImpl(address); + } } -wxString wxIPV4address::IPAddress() const +wxSockAddress& wxSockAddress::operator=(const wxSockAddress& addr) { - unsigned long raw = GAddress_INET_GetHostAddress(m_address); - return wxString::Format(_T("%lu.%lu.%lu.%lu"), - (raw>>24) & 0xff, - (raw>>16) & 0xff, - (raw>>8) & 0xff, - raw & 0xff - ); + SetAddress(addr.GetAddress()); + + return *this; } -bool wxIPV4address::operator==(const wxIPV4address& addr) const +void wxSockAddress::Clear() { - return Hostname().Cmp(addr.Hostname()) == 0 && - Service() == addr.Service(); + m_impl->Clear(); } -#if wxUSE_IPV6 -// --------------------------------------------------------------------------- -// wxIPV6address -// --------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// wxIPaddress +// ---------------------------------------------------------------------------- -wxIPV6address::wxIPV6address() - : wxIPaddress() +wxSockAddressImpl& wxIPaddress::GetImpl() { + if ( m_impl->GetFamily() == wxSockAddressImpl::FAMILY_UNSPEC ) + m_impl->CreateINET(); + + return *m_impl; } -wxIPV6address::wxIPV6address(const wxIPV6address& other) - : wxIPaddress(other), m_origHostname(other.m_origHostname) +bool wxIPaddress::Hostname(const wxString& name) { + wxCHECK_MSG( !name.empty(), false, "empty host name is invalid" ); + + m_origHostname = name; + + return GetImpl().SetHostName(name); } -wxIPV6address::~wxIPV6address() +bool wxIPaddress::Service(const wxString& name) { + return GetImpl().SetPortName(name, "tcp"); } -bool wxIPV6address::Hostname(const wxString& name) +bool wxIPaddress::Service(unsigned short port) { - if (name.empty()) - { - wxLogWarning( _("Trying to solve a NULL hostname: giving up") ); - return false; - } - m_origHostname = name; - return (GAddress_INET6_SetHostName(m_address, name.mb_str()) == wxSOCKET_NOERROR); + return GetImpl().SetPort(port); } -bool wxIPV6address::Hostname(unsigned char addr[16]) +bool wxIPaddress::LocalHost() { - wxString name; - unsigned short wk[8]; - for ( int i = 0; i < 8; ++i ) - { - wk[i] = addr[2*i]; - wk[i] <<= 8; - wk[i] |= addr[2*i+1]; - } - name.Printf("%x:%x:%x:%x:%x:%x:%x:%x", - wk[0], wk[1], wk[2], wk[3], wk[4], wk[5], wk[6], wk[7]); - return Hostname(name); + return Hostname("localhost"); } -bool wxIPV6address::Service(const wxString& name) +wxString wxIPaddress::Hostname() const { - return (GAddress_INET6_SetPortName(m_address, name.mb_str(), "tcp") == wxSOCKET_NOERROR); + return GetImpl().GetHostName(); } -bool wxIPV6address::Service(unsigned short port) +unsigned short wxIPaddress::Service() const { - return (GAddress_INET6_SetPort(m_address, port) == wxSOCKET_NOERROR); + return GetImpl().GetPort(); } -bool wxIPV6address::LocalHost() +bool wxIPaddress::operator==(const wxIPaddress& addr) const { - return (GAddress_INET6_SetHostName(m_address, "localhost") == wxSOCKET_NOERROR); + return Hostname().Cmp(addr.Hostname()) == 0 && + Service() == addr.Service(); } -bool wxIPV6address::IsLocalHost() const +bool wxIPaddress::AnyAddress() +{ + return GetImpl().SetToAnyAddress(); +} + +// ---------------------------------------------------------------------------- +// wxIPV4address +// ---------------------------------------------------------------------------- + +void wxIPV4address::DoInitImpl() { - if ( Hostname() == "localhost" ) - return true; + m_impl->CreateINET(); +} - wxString addr = IPAddress(); - return addr == wxT("::1") || - addr == wxT("0:0:0:0:0:0:0:1") || - addr == wxT("::ffff:127.0.0.1"); +bool wxIPV4address::Hostname(unsigned long addr) +{ + if ( !GetImpl().SetHostAddress(addr) ) + { + m_origHostname.clear(); + return false; + } + + m_origHostname = Hostname(); + return true; +} + +bool wxIPV4address::IsLocalHost() const +{ + return Hostname() == "localhost" || IPAddress() == "127.0.0.1"; } -bool wxIPV6address::BroadcastAddress() +wxString wxIPV4address::IPAddress() const { - wxFAIL_MSG( "not implemented" ); + wxUint32 addr; + if ( !GetImpl().GetHostAddress(&addr) ) + return wxString(); - return false; + return wxString::Format + ( + "%lu.%lu.%lu.%lu", + (addr >> 24) & 0xff, + (addr >> 16) & 0xff, + (addr >> 8) & 0xff, + addr & 0xff + ); } -bool wxIPV6address::AnyAddress() +bool wxIPV4address::BroadcastAddress() { - return (GAddress_INET6_SetAnyAddress(m_address) == wxSOCKET_NOERROR); + return GetImpl().SetToBroadcastAddress(); +} + +#if wxUSE_IPV6 + +// --------------------------------------------------------------------------- +// wxIPV6address +// --------------------------------------------------------------------------- + +void wxIPV6address::DoInitImpl() +{ + m_impl->CreateINET6(); +} + +bool wxIPV6address::Hostname(unsigned char addr[16]) +{ + unsigned short wk[8]; + for ( int i = 0; i < 8; ++i ) + { + wk[i] = addr[2*i]; + wk[i] <<= 8; + wk[i] |= addr[2*i+1]; + } + + return Hostname + ( + wxString::Format + ( + "%x:%x:%x:%x:%x:%x:%x:%x", + wk[0], wk[1], wk[2], wk[3], wk[4], wk[5], wk[6], wk[7] + ) + ); +} + +bool wxIPV6address::IsLocalHost() const +{ + if ( Hostname() == "localhost" ) + return true; + + wxString addr = IPAddress(); + return addr == wxT("::1") || + addr == wxT("0:0:0:0:0:0:0:1") || + addr == wxT("::ffff:127.0.0.1"); } wxString wxIPV6address::IPAddress() const { - unsigned char addr[16]; - GAddress_INET6_GetHostAddress(m_address,(in6_addr*)addr); + union + { + in6_addr addr6; + wxUint8 bytes[16]; + } u; + + if ( !GetImpl().GetHostAddress(&u.addr6) ) + return wxString(); + + const wxUint8 * const addr = u.bytes; wxUint16 words[8]; int i, @@ -349,62 +932,32 @@ wxString wxIPV6address::IPAddress() const return result; } -wxString wxIPV6address::Hostname() const -{ - char hostname[1024]; - hostname[0] = 0; - - if ( GAddress_INET6_GetHostName(m_address, - hostname, - WXSIZEOF(hostname)) != wxSOCKET_NOERROR ) - return wxEmptyString; - - return wxString::FromAscii(hostname); -} - -unsigned short wxIPV6address::Service() const -{ - return GAddress_INET6_GetPort(m_address); -} - #endif // wxUSE_IPV6 -#if defined(__UNIX__) && !defined(__WINDOWS__) && !defined(__WINE__) +#ifdef wxHAS_UNIX_DOMAIN_SOCKETS // --------------------------------------------------------------------------- // wxUNIXaddress // --------------------------------------------------------------------------- -wxUNIXaddress::wxUNIXaddress() - : wxSockAddress() -{ -} - -wxUNIXaddress::wxUNIXaddress(const wxUNIXaddress& other) - : wxSockAddress(other) +wxSockAddressImpl& wxUNIXaddress::GetUNIX() { -} + if ( m_impl->GetFamily() == wxSockAddressImpl::FAMILY_UNSPEC ) + m_impl->CreateUnix(); -wxUNIXaddress::~wxUNIXaddress() -{ + return *m_impl; } void wxUNIXaddress::Filename(const wxString& fname) { - GAddress_UNIX_SetPath(m_address, fname.fn_str()); + GetUNIX().SetPath(fname); } -wxString wxUNIXaddress::Filename() +wxString wxUNIXaddress::Filename() const { - char path[1024]; - - path[0] = 0; - GAddress_UNIX_GetPath(m_address, path, 1024); - - return wxString::FromAscii(path); + return GetUNIX().GetPath(); } -#endif // __UNIX__ +#endif // wxHAS_UNIX_DOMAIN_SOCKETS -#endif - // wxUSE_SOCKETS +#endif // wxUSE_SOCKETS diff --git a/src/common/socket.cpp b/src/common/socket.cpp index ccfb23438c..ba15840b28 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -176,8 +176,6 @@ wxSocketImpl::wxSocketImpl(wxSocketBase& wxsocket) : m_wxsocket(&wxsocket) { m_fd = INVALID_SOCKET; - m_local = NULL; - m_peer = NULL; m_error = wxSOCKET_NOERROR; m_server = false; m_stream = true; @@ -194,17 +192,11 @@ wxSocketImpl::wxSocketImpl(wxSocketBase& wxsocket) wxSocketImpl::~wxSocketImpl() { - if (m_fd != INVALID_SOCKET) + if ( m_fd != INVALID_SOCKET ) Shutdown(); - - if (m_local) - GAddress_destroy(m_local); - - if (m_peer) - GAddress_destroy(m_peer); } -bool wxSocketImpl::PreCreateCheck(GAddress *addr) +bool wxSocketImpl::PreCreateCheck(const wxSockAddressImpl& addr) { if ( m_fd != INVALID_SOCKET ) { @@ -212,7 +204,7 @@ bool wxSocketImpl::PreCreateCheck(GAddress *addr) return false; } - if ( !addr || !addr->m_addr ) + if ( !addr.IsOk() ) { m_error = wxSOCKET_INVADDR; return false; @@ -250,16 +242,14 @@ void wxSocketImpl::PostCreation() wxSocketError wxSocketImpl::UpdateLocalAddress() { - WX_SOCKLEN_T lenAddr = sizeof(*m_local->m_addr); - if ( getsockname(m_fd, m_local->m_addr, &lenAddr) != 0 ) + WX_SOCKLEN_T lenAddr = m_local.GetLen(); + if ( getsockname(m_fd, m_local.GetWritableAddr(), &lenAddr) != 0 ) { Close(); m_error = wxSOCKET_IOERR; return m_error; } - m_local->m_len = lenAddr; - return wxSOCKET_NOERROR; } @@ -272,7 +262,7 @@ wxSocketError wxSocketImpl::CreateServer() m_stream = true; // do create the socket - m_fd = socket(m_local->m_realfamily, SOCK_STREAM, 0); + m_fd = socket(m_local.GetFamily(), SOCK_STREAM, 0); if ( m_fd == INVALID_SOCKET ) { @@ -285,7 +275,7 @@ wxSocketError wxSocketImpl::CreateServer() // and then bind to and listen on it // // FIXME: should we test for m_dobind here? - if ( bind(m_fd, m_local->m_addr, m_local->m_len) != 0 ) + if ( bind(m_fd, m_local.GetAddr(), m_local.GetLen()) != 0 ) m_error = wxSOCKET_IOERR; if ( IsOk() ) @@ -309,7 +299,7 @@ wxSocketError wxSocketImpl::CreateClient(bool wait) if ( !PreCreateCheck(m_peer) ) return m_error; - m_fd = socket(m_peer->m_realfamily, SOCK_STREAM, 0); + m_fd = socket(m_peer.GetFamily(), SOCK_STREAM, 0); if ( m_fd == INVALID_SOCKET ) { @@ -320,9 +310,9 @@ wxSocketError wxSocketImpl::CreateClient(bool wait) PostCreation(); // If a local address has been set, then bind to it before calling connect - if ( m_local && m_local->m_addr ) + if ( m_local.IsOk() ) { - if ( bind(m_fd, m_local->m_addr, m_local->m_len) != 0 ) + if ( bind(m_fd, m_local.GetAddr(), m_local.GetLen()) != 0 ) { Close(); m_error = wxSOCKET_IOERR; @@ -331,7 +321,7 @@ wxSocketError wxSocketImpl::CreateClient(bool wait) } // Do connect now - int rc = connect(m_fd, m_peer->m_addr, m_peer->m_len); + int rc = connect(m_fd, m_peer.GetAddr(), m_peer.GetLen()); if ( rc == SOCKET_ERROR ) { wxSocketError err = GetLastError(); @@ -369,7 +359,7 @@ wxSocketError wxSocketImpl::CreateUDP() m_stream = false; m_server = false; - m_fd = socket(m_local->m_realfamily, SOCK_DGRAM, 0); + m_fd = socket(m_local.GetFamily(), SOCK_DGRAM, 0); if ( m_fd == INVALID_SOCKET ) { @@ -381,7 +371,7 @@ wxSocketError wxSocketImpl::CreateUDP() if ( m_dobind ) { - if ( bind(m_fd, m_local->m_addr, m_local->m_len) != 0 ) + if ( bind(m_fd, m_local.GetAddr(), m_local.GetLen()) != 0 ) { Close(); m_error = wxSOCKET_IOERR; @@ -396,18 +386,16 @@ wxSocketError wxSocketImpl::CreateUDP() wxSocketImpl *wxSocketImpl::Accept(wxSocketBase& wxsocket) { - wxSockAddr from; + wxSockAddressStorage from; WX_SOCKLEN_T fromlen = sizeof(from); - const SOCKET fd = accept(m_fd, &from, &fromlen); + const SOCKET fd = accept(m_fd, &from.addr, &fromlen); if ( fd == INVALID_SOCKET ) return NULL; wxSocketImpl * const sock = Create(wxsocket); sock->m_fd = fd; - - sock->m_peer = GAddress_new(); - _GAddress_translate_from(sock->m_peer, &from, fromlen); + sock->m_peer = wxSockAddressImpl(from.addr, fromlen); sock->UnblockAndRegisterWithEventLoop(); @@ -452,107 +440,45 @@ void wxSocketImpl::NotifyOnStateChange(wxSocketNotify event) } /* Address handling */ - -/* - * Set or get the local or peer address for this socket. The 'set' - * functions return wxSOCKET_NOERROR on success, an error code otherwise. - * The 'get' functions return a pointer to a GAddress object on success, - * or NULL otherwise, in which case they set the error code of the - * corresponding socket. - * - * Error codes: - * wxSOCKET_INVSOCK - the socket is not valid. - * wxSOCKET_INVADDR - the address is not valid. - */ -wxSocketError wxSocketImpl::SetLocal(GAddress *address) +wxSocketError wxSocketImpl::SetLocal(const wxSockAddressImpl& local) { - /* the socket must be initialized, or it must be a server */ - if (m_fd != INVALID_SOCKET && !m_server) - { - m_error = wxSOCKET_INVSOCK; - return wxSOCKET_INVSOCK; - } - - /* check address */ - if (address == NULL || address->m_family == wxSOCKET_NOFAMILY) - { - m_error = wxSOCKET_INVADDR; - return wxSOCKET_INVADDR; - } - - if (m_local) - GAddress_destroy(m_local); - - m_local = GAddress_copy(address); - - return wxSOCKET_NOERROR; -} - -wxSocketError wxSocketImpl::SetPeer(GAddress *address) -{ - /* check address */ - if (address == NULL || address->m_family == wxSOCKET_NOFAMILY) - { - m_error = wxSOCKET_INVADDR; - return wxSOCKET_INVADDR; - } + /* the socket must be initialized, or it must be a server */ + if (m_fd != INVALID_SOCKET && !m_server) + { + m_error = wxSOCKET_INVSOCK; + return wxSOCKET_INVSOCK; + } - if (m_peer) - GAddress_destroy(m_peer); + if ( !local.IsOk() ) + { + m_error = wxSOCKET_INVADDR; + return wxSOCKET_INVADDR; + } - m_peer = GAddress_copy(address); + m_local = local; - return wxSOCKET_NOERROR; + return wxSOCKET_NOERROR; } -GAddress *wxSocketImpl::GetLocal() +wxSocketError wxSocketImpl::SetPeer(const wxSockAddressImpl& peer) { - GAddress *address; - wxSockAddr addr; - WX_SOCKLEN_T size = sizeof(addr); - wxSocketError err; - - /* try to get it from the m_local var first */ - if (m_local) - return GAddress_copy(m_local); - - /* else, if the socket is initialized, try getsockname */ - if (m_fd == INVALID_SOCKET) - { - m_error = wxSOCKET_INVSOCK; - return NULL; - } - - if (getsockname(m_fd, (sockaddr*)&addr, &size) == SOCKET_ERROR) - { - m_error = wxSOCKET_IOERR; - return NULL; - } - - /* got a valid address from getsockname, create a GAddress object */ - if ((address = GAddress_new()) == NULL) - { - m_error = wxSOCKET_MEMERR; - return NULL; - } + if ( !peer.IsOk() ) + { + m_error = wxSOCKET_INVADDR; + return wxSOCKET_INVADDR; + } - if ((err = _GAddress_translate_from(address, (sockaddr*)&addr, size)) != wxSOCKET_NOERROR) - { - GAddress_destroy(address); - m_error = err; - return NULL; - } + m_peer = peer; - return address; + return wxSOCKET_NOERROR; } -GAddress *wxSocketImpl::GetPeer() +const wxSockAddressImpl& wxSocketImpl::GetLocal() { - /* try to get it from the m_peer var */ - if (m_peer) - return GAddress_copy(m_peer); + if ( !m_local.IsOk() ) + UpdateLocalAddress(); - return NULL; + return m_local; } // ---------------------------------------------------------------------------- @@ -604,50 +530,34 @@ int wxSocketImpl::SendStream(const void *buffer, int size) int wxSocketImpl::RecvDgram(void *buffer, int size) { - wxSockAddr from; + wxSockAddressStorage from; WX_SOCKLEN_T fromlen = sizeof(from); int ret; DO_WHILE_EINTR( ret, recvfrom(m_fd, static_cast(buffer), size, - 0, &from, &fromlen) ); + 0, &from.addr, &fromlen) ); if ( ret == SOCKET_ERROR ) return SOCKET_ERROR; - /* Translate a system address into a wxSocketImpl address */ - if ( !m_peer ) - m_peer = GAddress_new(); - - m_error = _GAddress_translate_from(m_peer, &from, fromlen); - if ( m_error != wxSOCKET_NOERROR ) - { - GAddress_destroy(m_peer); - m_peer = NULL; + m_peer = wxSockAddressImpl(from.addr, fromlen); + if ( !m_peer.IsOk() ) return -1; - } return ret; } int wxSocketImpl::SendDgram(const void *buffer, int size) { - if ( !m_peer ) + if ( !m_peer.IsOk() ) { m_error = wxSOCKET_INVADDR; return -1; } - struct sockaddr *addr; - int len; - m_error = _GAddress_translate_to(m_peer, &addr, &len); - if ( m_error != wxSOCKET_NOERROR ) - return -1; - int ret; DO_WHILE_EINTR( ret, sendto(m_fd, static_cast(buffer), size, - 0, addr, len) ); - - free(addr); + 0, m_peer.GetAddr(), m_peer.GetLen()) ); return ret; } @@ -1463,36 +1373,28 @@ bool wxSocketBase::WaitForLost(long seconds, long milliseconds) // Get local or peer address // -bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const +bool wxSocketBase::GetPeer(wxSockAddress& addr) const { - GAddress *peer; - - if (!m_impl) - return false; - - peer = m_impl->GetPeer(); + wxCHECK_MSG( m_impl, false, "invalid socket" ); - // copying a null address would just trigger an assert anyway - - if (!peer) + const wxSockAddressImpl& peer = m_impl->GetPeer(); + if ( !peer.IsOk() ) return false; - addr_man.SetAddress(peer); - GAddress_destroy(peer); + addr.SetAddress(peer); return true; } -bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const +bool wxSocketBase::GetLocal(wxSockAddress& addr) const { - GAddress *local; + wxCHECK_MSG( m_impl, false, "invalid socket" ); - if (!m_impl) + const wxSockAddressImpl& local = m_impl->GetLocal(); + if ( !local.IsOk() ) return false; - local = m_impl->GetLocal(); - addr_man.SetAddress(local); - GAddress_destroy(local); + addr.SetAddress(local); return true; } @@ -1700,7 +1602,7 @@ wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek) // Ctor // -------------------------------------------------------------------------- -wxSocketServer::wxSocketServer(const wxSockAddress& addr_man, +wxSocketServer::wxSocketServer(const wxSockAddress& addr, wxSocketFlags flags) : wxSocketBase(flags, wxSOCKET_SERVER) { @@ -1715,7 +1617,7 @@ wxSocketServer::wxSocketServer(const wxSockAddress& addr_man, } // Setup the socket as server - m_impl->SetLocal(addr_man.GetAddress()); + m_impl->SetLocal(addr.GetAddress()); if (GetFlags() & wxSOCKET_REUSEADDR) { m_impl->SetReusable(); @@ -1825,17 +1727,9 @@ wxSocketBase::SetOption(int level, int optname, const void *optval, int optlen) bool wxSocketBase::SetLocal(const wxIPV4address& local) { - GAddress* la = local.GetAddress(); + m_localAddress = local; - // If the address is valid, save it for use when we call Connect - if (la && la->m_addr) - { - m_localAddress = local; - - return true; - } - - return false; + return true; } // ========================================================================== @@ -1890,7 +1784,7 @@ bool wxSocketClient::DoConnect(const wxSockAddress& remote, // Bind to the local IP address and port, when provided or if one had been // set before - if ( !local && m_localAddress.GetAddress() ) + if ( !local && m_localAddress.GetAddress().IsOk() ) local = &m_localAddress; if ( local ) diff --git a/src/msw/sockmsw.cpp b/src/msw/sockmsw.cpp index dc20dcf9ba..33ce4ab540 100644 --- a/src/msw/sockmsw.cpp +++ b/src/msw/sockmsw.cpp @@ -466,509 +466,4 @@ wxSocketError wxSocketImplMSW::GetLastError() const } } -/* - * ------------------------------------------------------------------------- - * GAddress - * ------------------------------------------------------------------------- - */ - -/* CHECK_ADDRESS verifies that the current address family is either - * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it - * initalizes it to be a wxSOCKET_*family*. In other cases, it returns - * an appropiate error code. - * - * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error. - */ -#define CHECK_ADDRESS(address, family) \ -{ \ - if (address->m_family == wxSOCKET_NOFAMILY) \ - if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \ - return address->m_error; \ - if (address->m_family != wxSOCKET_##family) \ - { \ - address->m_error = wxSOCKET_INVADDR; \ - return wxSOCKET_INVADDR; \ - } \ -} - -#define CHECK_ADDRESS_RETVAL(address, family, retval) \ -{ \ - if (address->m_family == wxSOCKET_NOFAMILY) \ - if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \ - return retval; \ - if (address->m_family != wxSOCKET_##family) \ - { \ - address->m_error = wxSOCKET_INVADDR; \ - return retval; \ - } \ -} - - -GAddress *GAddress_new() -{ - GAddress *address; - - if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL) - return NULL; - - address->m_family = wxSOCKET_NOFAMILY; - address->m_addr = NULL; - address->m_len = 0; - - return address; -} - -GAddress *GAddress_copy(GAddress *address) -{ - GAddress *addr2; - - if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL) - return NULL; - - memcpy(addr2, address, sizeof(GAddress)); - - if (address->m_addr) - { - addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len); - if (addr2->m_addr == NULL) - { - free(addr2); - return NULL; - } - memcpy(addr2->m_addr, address->m_addr, addr2->m_len); - } - - return addr2; -} - -void GAddress_destroy(GAddress *address) -{ - if (address->m_addr) - free(address->m_addr); - - free(address); -} - -void GAddress_SetFamily(GAddress *address, GAddressType type) -{ - address->m_family = type; -} - -GAddressType GAddress_GetFamily(GAddress *address) -{ - return address->m_family; -} - -wxSocketError _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 = wxSOCKET_INET; - break; - case AF_UNIX: - address->m_family = wxSOCKET_UNIX; - break; -#if wxUSE_IPV6 - case AF_INET6: - address->m_family = wxSOCKET_INET6; - break; -#endif - default: - { - address->m_error = wxSOCKET_INVOP; - return wxSOCKET_INVOP; - } - } - - if (address->m_addr) - free(address->m_addr); - - address->m_len = len; - address->m_addr = (struct sockaddr *) malloc(len); - - if (address->m_addr == NULL) - { - address->m_error = wxSOCKET_MEMERR; - return wxSOCKET_MEMERR; - } - memcpy(address->m_addr, addr, len); - - return wxSOCKET_NOERROR; -} - -wxSocketError _GAddress_translate_to(GAddress *address, - struct sockaddr **addr, int *len) -{ - if (!address->m_addr) - { - address->m_error = wxSOCKET_INVADDR; - return wxSOCKET_INVADDR; - } - - *len = address->m_len; - *addr = (struct sockaddr *) malloc(address->m_len); - if (*addr == NULL) - { - address->m_error = wxSOCKET_MEMERR; - return wxSOCKET_MEMERR; - } - - memcpy(*addr, address->m_addr, address->m_len); - return wxSOCKET_NOERROR; -} - -/* - * ------------------------------------------------------------------------- - * Internet address family - * ------------------------------------------------------------------------- - */ - -wxSocketError _GAddress_Init_INET(GAddress *address) -{ - address->m_len = sizeof(struct sockaddr_in); - address->m_addr = (struct sockaddr *) malloc(address->m_len); - if (address->m_addr == NULL) - { - address->m_error = wxSOCKET_MEMERR; - return wxSOCKET_MEMERR; - } - - address->m_family = wxSOCKET_INET; - address->m_realfamily = AF_INET; - ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET; - ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname) -{ - struct hostent *he; - struct in_addr *addr; - - CHECK_ADDRESS(address, INET); - - addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr); - - addr->s_addr = inet_addr(hostname); - - /* If it is a numeric host name, convert it now */ - if (addr->s_addr == INADDR_NONE) - { - struct in_addr *array_addr; - - /* It is a real name, we solve it */ - if ((he = gethostbyname(hostname)) == NULL) - { - /* addr->s_addr = INADDR_NONE just done by inet_addr() above */ - address->m_error = wxSOCKET_NOHOST; - return wxSOCKET_NOHOST; - } - array_addr = (struct in_addr *) *(he->h_addr_list); - addr->s_addr = array_addr[0].s_addr; - } - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET_SetBroadcastAddress(GAddress *address) -{ - return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST); -} - -wxSocketError GAddress_INET_SetAnyAddress(GAddress *address) -{ - return GAddress_INET_SetHostAddress(address, INADDR_ANY); -} - -wxSocketError GAddress_INET_SetHostAddress(GAddress *address, - unsigned long hostaddr) -{ - struct in_addr *addr; - - CHECK_ADDRESS(address, INET); - - addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr); - addr->s_addr = htonl(hostaddr); - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET_SetPortName(GAddress *address, const char *port, - const char *protocol) -{ - struct servent *se; - struct sockaddr_in *addr; - - CHECK_ADDRESS(address, INET); - - if (!port) - { - address->m_error = wxSOCKET_INVPORT; - return wxSOCKET_INVPORT; - } - - se = getservbyname(port, protocol); - if (!se) - { - if (isdigit(port[0])) - { - int port_int; - - port_int = atoi(port); - addr = (struct sockaddr_in *)address->m_addr; - addr->sin_port = htons((u_short) port_int); - return wxSOCKET_NOERROR; - } - - address->m_error = wxSOCKET_INVPORT; - return wxSOCKET_INVPORT; - } - - addr = (struct sockaddr_in *)address->m_addr; - addr->sin_port = se->s_port; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port) -{ - struct sockaddr_in *addr; - - CHECK_ADDRESS(address, INET); - - addr = (struct sockaddr_in *)address->m_addr; - addr->sin_port = htons(port); - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf) -{ - struct hostent *he; - char *addr_buf; - struct sockaddr_in *addr; - - CHECK_ADDRESS(address, INET); - - 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 = wxSOCKET_NOHOST; - return wxSOCKET_NOHOST; - } - - strncpy(hostname, he->h_name, sbuf); - - return wxSOCKET_NOERROR; -} - -unsigned long GAddress_INET_GetHostAddress(GAddress *address) -{ - struct sockaddr_in *addr; - - CHECK_ADDRESS_RETVAL(address, INET, 0); - - addr = (struct sockaddr_in *)address->m_addr; - - return ntohl(addr->sin_addr.s_addr); -} - -unsigned short GAddress_INET_GetPort(GAddress *address) -{ - struct sockaddr_in *addr; - - CHECK_ADDRESS_RETVAL(address, INET, 0); - - addr = (struct sockaddr_in *)address->m_addr; - return ntohs(addr->sin_port); -} - - -#if wxUSE_IPV6 -/* - * ------------------------------------------------------------------------- - * Internet IPv6 address family - * ------------------------------------------------------------------------- - */ -#include "ws2tcpip.h" - -#ifdef __VISUALC__ - #pragma comment(lib,"ws2_32") -#endif // __VISUALC__ - -wxSocketError _GAddress_Init_INET6(GAddress *address) -{ - struct in6_addr any_address = IN6ADDR_ANY_INIT; - address->m_len = sizeof(struct sockaddr_in6); - address->m_addr = (struct sockaddr *) malloc(address->m_len); - if (address->m_addr == NULL) - { - address->m_error = wxSOCKET_MEMERR; - return wxSOCKET_MEMERR; - } - memset(address->m_addr,0,address->m_len); - - address->m_family = wxSOCKET_INET6; - address->m_realfamily = AF_INET6; - ((struct sockaddr_in6 *)address->m_addr)->sin6_family = AF_INET6; - ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = any_address; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_SetHostName(GAddress *address, const char *hostname) -{ - CHECK_ADDRESS(address, INET6); - - addrinfo hints; - memset( & hints, 0, sizeof( hints ) ); - hints.ai_family = AF_INET6; - addrinfo * info = 0; - if ( getaddrinfo( hostname, "0", & hints, & info ) || ! info ) - { - address->m_error = wxSOCKET_NOHOST; - return wxSOCKET_NOHOST; - } - - memcpy( address->m_addr, info->ai_addr, info->ai_addrlen ); - freeaddrinfo( info ); - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_SetAnyAddress(GAddress *address) -{ - CHECK_ADDRESS(address, INET6); - - struct in6_addr addr; - memset( & addr, 0, sizeof( addr ) ); - return GAddress_INET6_SetHostAddress(address, addr); -} -wxSocketError GAddress_INET6_SetHostAddress(GAddress *address, - struct in6_addr hostaddr) -{ - CHECK_ADDRESS(address, INET6); - - ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = hostaddr; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_SetPortName(GAddress *address, const char *port, - const char *protocol) -{ - struct servent *se; - struct sockaddr_in6 *addr; - - CHECK_ADDRESS(address, INET6); - - if (!port) - { - address->m_error = wxSOCKET_INVPORT; - return wxSOCKET_INVPORT; - } - - se = getservbyname(port, protocol); - if (!se) - { - if (isdigit((unsigned char) port[0])) - { - int port_int; - - port_int = atoi(port); - addr = (struct sockaddr_in6 *)address->m_addr; - addr->sin6_port = htons((u_short) port_int); - return wxSOCKET_NOERROR; - } - - address->m_error = wxSOCKET_INVPORT; - return wxSOCKET_INVPORT; - } - - addr = (struct sockaddr_in6 *)address->m_addr; - addr->sin6_port = se->s_port; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_SetPort(GAddress *address, unsigned short port) -{ - struct sockaddr_in6 *addr; - - CHECK_ADDRESS(address, INET6); - - addr = (struct sockaddr_in6 *)address->m_addr; - addr->sin6_port = htons(port); - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_GetHostName(GAddress *address, char *hostname, size_t sbuf) -{ - struct hostent *he; - char *addr_buf; - struct sockaddr_in6 *addr; - - CHECK_ADDRESS(address, INET6); - - addr = (struct sockaddr_in6 *)address->m_addr; - addr_buf = (char *)&(addr->sin6_addr); - - he = gethostbyaddr(addr_buf, sizeof(addr->sin6_addr), AF_INET6); - if (he == NULL) - { - address->m_error = wxSOCKET_NOHOST; - return wxSOCKET_NOHOST; - } - - strncpy(hostname, he->h_name, sbuf); - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_GetHostAddress(GAddress *address,struct in6_addr *hostaddr) -{ - CHECK_ADDRESS_RETVAL(address, INET6, wxSOCKET_INVADDR); - *hostaddr = ( (struct sockaddr_in6 *)address->m_addr )->sin6_addr; - return wxSOCKET_NOERROR; -} - -unsigned short GAddress_INET6_GetPort(GAddress *address) -{ - CHECK_ADDRESS_RETVAL(address, INET6, 0); - - return ntohs( ((struct sockaddr_in6 *)address->m_addr)->sin6_port ); -} - -#endif // wxUSE_IPV6 - -/* - * ------------------------------------------------------------------------- - * Unix address family - * ------------------------------------------------------------------------- - */ - -wxSocketError _GAddress_Init_UNIX(GAddress *address) -{ - address->m_error = wxSOCKET_INVADDR; - return wxSOCKET_INVADDR; -} - -wxSocketError GAddress_UNIX_SetPath(GAddress *address, const char *WXUNUSED(path)) -{ - address->m_error = wxSOCKET_INVADDR; - return wxSOCKET_INVADDR; -} - -wxSocketError GAddress_UNIX_GetPath(GAddress *address, char *WXUNUSED(path), size_t WXUNUSED(sbuf)) -{ - address->m_error = wxSOCKET_INVADDR; - return wxSOCKET_INVADDR; -} - #endif // wxUSE_SOCKETS diff --git a/src/unix/sockunix.cpp b/src/unix/sockunix.cpp index d0020dfbdb..6383b54ac5 100644 --- a/src/unix/sockunix.cpp +++ b/src/unix/sockunix.cpp @@ -19,97 +19,21 @@ #include "wx/private/socket.h" #include "wx/unix/private/sockunix.h" -#if defined(__VISAGECPP__) -#define BSD_SELECT /* use Berkeley Sockets select */ -#endif +#include #if defined(__WATCOMC__) -#include -#include + #include #endif -#include #include -#ifdef __VISAGECPP__ -#include -#include -#include -#include -#endif -#include -#include #ifdef HAVE_SYS_SELECT_H # include #endif -#ifdef __VMS__ -#include -struct sockaddr_un -{ - u_char sun_len; /* sockaddr len including null */ - u_char sun_family; /* AF_UNIX */ - char sun_path[108]; /* path name (gag) */ -}; -#else -#include -#include -#endif - -#ifndef __VISAGECPP__ -#include -#include -#include -#include -#include -#include -#else -#include -# if __IBMCPP__ < 400 -#include -#include -#include -#include -#include - -#define EBADF SOCEBADF - -# ifdef min -# undef min -# endif -# else -#include -#include -#include - -#define close(a) soclose(a) -#define select(a,b,c,d,e) bsdselect(a,b,c,d,e) -int _System bsdselect(int, - struct fd_set *, - struct fd_set *, - struct fd_set *, - struct timeval *); -int _System soclose(int); -# endif -#endif #ifdef __EMX__ -#include -#endif - -#include -#include -#include -#include -#ifdef sun -# include -#endif -#ifdef sgi -# include -#endif -#ifdef _AIX -# include + #include #endif -#include #ifndef WX_SOCKLEN_T @@ -130,275 +54,13 @@ int _System soclose(int); #endif /* SOCKLEN_T */ #ifndef SOCKOPTLEN_T -#define SOCKOPTLEN_T WX_SOCKLEN_T + #define SOCKOPTLEN_T WX_SOCKLEN_T #endif -/* UnixWare reportedly needs this for FIONBIO definition */ +// UnixWare reportedly needs this for FIONBIO definition #ifdef __UNIXWARE__ -#include -#endif - -/* - * INADDR_BROADCAST is identical to INADDR_NONE which is not defined - * on all systems. INADDR_BROADCAST should be fine to indicate an error. - */ -#ifndef INADDR_NONE -#define INADDR_NONE INADDR_BROADCAST -#endif - -// ---------------------------------------------------------------------------- -// implementation of thread-safe/reentrant functions if they're missing -// ---------------------------------------------------------------------------- - -#if wxUSE_THREADS && (defined(HAVE_GETHOSTBYNAME) || defined(HAVE_GETSERVBYNAME)) -# include "wx/thread.h" -#endif - -#if defined(HAVE_GETHOSTBYNAME) -static struct hostent * deepCopyHostent(struct hostent *h, - const struct hostent *he, - char *buffer, int size, int *err) -{ - /* copy old structure */ - memcpy(h, he, sizeof(struct hostent)); - - /* copy name */ - int len = strlen(h->h_name); - if (len > size) - { - *err = ENOMEM; - return NULL; - } - memcpy(buffer, h->h_name, len); - buffer[len] = '\0'; - h->h_name = buffer; - - /* track position in the buffer */ - int pos = len + 1; - - /* reuse len to store address length */ - len = h->h_length; - - /* ensure pointer alignment */ - unsigned int misalign = sizeof(char *) - pos%sizeof(char *); - if(misalign < sizeof(char *)) - pos += misalign; - - /* leave space for pointer list */ - char **p = h->h_addr_list, **q; - char **h_addr_list = (char **)(buffer + pos); - while(*(p++) != 0) - pos += sizeof(char *); - - /* copy addresses and fill new pointer list */ - for (p = h->h_addr_list, q = h_addr_list; *p != 0; p++, q++) - { - if (size < pos + len) - { - *err = ENOMEM; - return NULL; - } - memcpy(buffer + pos, *p, len); /* copy content */ - *q = buffer + pos; /* set copied pointer to copied content */ - pos += len; - } - *++q = 0; /* null terminate the pointer list */ - h->h_addr_list = h_addr_list; /* copy pointer to pointers */ - - /* ensure word alignment of pointers */ - misalign = sizeof(char *) - pos%sizeof(char *); - if(misalign < sizeof(char *)) - pos += misalign; - - /* leave space for pointer list */ - p = h->h_aliases; - char **h_aliases = (char **)(buffer + pos); - while(*(p++) != 0) - pos += sizeof(char *); - - /* copy aliases and fill new pointer list */ - for (p = h->h_aliases, q = h_aliases; *p != 0; p++, q++) - { - len = strlen(*p); - if (size <= pos + len) - { - *err = ENOMEM; - return NULL; - } - memcpy(buffer + pos, *p, len); /* copy content */ - buffer[pos + len] = '\0'; - *q = buffer + pos; /* set copied pointer to copied content */ - pos += len + 1; - } - *++q = 0; /* null terminate the pointer list */ - h->h_aliases = h_aliases; /* copy pointer to pointers */ - - return h; -} -#endif - -#if defined(HAVE_GETHOSTBYNAME) && wxUSE_THREADS -static wxMutex nameLock; -#endif -struct hostent * wxGethostbyname_r(const char *hostname, struct hostent *h, - void *buffer, int size, int *err) - -{ - struct hostent *he = NULL; - *err = 0; -#if defined(HAVE_FUNC_GETHOSTBYNAME_R_6) - if (gethostbyname_r(hostname, h, (char*)buffer, size, &he, err)) - he = NULL; -#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5) - he = gethostbyname_r(hostname, h, (char*)buffer, size, err); -#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3) - if (gethostbyname_r(hostname, h, (struct hostent_data*) buffer)) - { - he = NULL; - *err = h_errno; - } - else - he = h; -#elif defined(HAVE_GETHOSTBYNAME) -#if wxUSE_THREADS - wxMutexLocker locker(nameLock); -#endif - he = gethostbyname(hostname); - if (!he) - *err = h_errno; - else - he = deepCopyHostent(h, he, (char*)buffer, size, err); -#endif - return he; -} - -#if defined(HAVE_GETHOSTBYNAME) && wxUSE_THREADS -static wxMutex addrLock; + #include #endif -struct hostent * wxGethostbyaddr_r(const char *addr_buf, int buf_size, - int proto, struct hostent *h, - void *buffer, int size, int *err) -{ - struct hostent *he = NULL; - *err = 0; -#if defined(HAVE_FUNC_GETHOSTBYNAME_R_6) - if (gethostbyaddr_r(addr_buf, buf_size, proto, h, - (char*)buffer, size, &he, err)) - he = NULL; -#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5) - he = gethostbyaddr_r(addr_buf, buf_size, proto, h, (char*)buffer, size, err); -#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3) - if (gethostbyaddr_r(addr_buf, buf_size, proto, h, - (struct hostent_data*) buffer)) - { - he = NULL; - *err = h_errno; - } - else - he = h; -#elif defined(HAVE_GETHOSTBYNAME) -#if wxUSE_THREADS - wxMutexLocker locker(addrLock); -#endif - he = gethostbyaddr(addr_buf, buf_size, proto); - if (!he) - *err = h_errno; - else - he = deepCopyHostent(h, he, (char*)buffer, size, err); -#endif - return he; -} - -#if defined(HAVE_GETSERVBYNAME) -static struct servent * deepCopyServent(struct servent *s, - const struct servent *se, - char *buffer, int size) -{ - /* copy plain old structure */ - memcpy(s, se, sizeof(struct servent)); - - /* copy name */ - int len = strlen(s->s_name); - if (len >= size) - { - return NULL; - } - memcpy(buffer, s->s_name, len); - buffer[len] = '\0'; - s->s_name = buffer; - - /* track position in the buffer */ - int pos = len + 1; - - /* copy protocol */ - len = strlen(s->s_proto); - if (pos + len >= size) - { - return NULL; - } - memcpy(buffer + pos, s->s_proto, len); - buffer[pos + len] = '\0'; - s->s_proto = buffer + pos; - - /* track position in the buffer */ - pos += len + 1; - - /* ensure pointer alignment */ - unsigned int misalign = sizeof(char *) - pos%sizeof(char *); - if(misalign < sizeof(char *)) - pos += misalign; - - /* leave space for pointer list */ - char **p = s->s_aliases, **q; - char **s_aliases = (char **)(buffer + pos); - while(*(p++) != 0) - pos += sizeof(char *); - - /* copy addresses and fill new pointer list */ - for (p = s->s_aliases, q = s_aliases; *p != 0; p++, q++){ - len = strlen(*p); - if (size <= pos + len) - { - return NULL; - } - memcpy(buffer + pos, *p, len); /* copy content */ - buffer[pos + len] = '\0'; - *q = buffer + pos; /* set copied pointer to copied content */ - pos += len + 1; - } - *++q = 0; /* null terminate the pointer list */ - s->s_aliases = s_aliases; /* copy pointer to pointers */ - return s; -} -#endif - -#if defined(HAVE_GETSERVBYNAME) && wxUSE_THREADS -static wxMutex servLock; -#endif -struct servent *wxGetservbyname_r(const char *port, const char *protocol, - struct servent *serv, void *buffer, int size) -{ - struct servent *se = NULL; -#if defined(HAVE_FUNC_GETSERVBYNAME_R_6) - if (getservbyname_r(port, protocol, serv, (char*)buffer, size, &se)) - se = NULL; -#elif defined(HAVE_FUNC_GETSERVBYNAME_R_5) - se = getservbyname_r(port, protocol, serv, (char*)buffer, size); -#elif defined(HAVE_FUNC_GETSERVBYNAME_R_4) - if (getservbyname_r(port, protocol, serv, (struct servent_data*) buffer)) - se = NULL; - else - se = serv; -#elif defined(HAVE_GETSERVBYNAME) -#if wxUSE_THREADS - wxMutexLocker locker(servLock); -#endif - se = getservbyname(port, protocol); - if (se) - se = deepCopyServent(serv, se, (char*)buffer, size); -#endif - return se; -} // ============================================================================ // wxSocketImpl implementation @@ -551,604 +213,4 @@ void wxSocketImplUnix::OnExceptionWaiting() wxFAIL_MSG( "not supposed to be called" ); } -/* - * ------------------------------------------------------------------------- - * GAddress - * ------------------------------------------------------------------------- - */ - -/* CHECK_ADDRESS verifies that the current address family is either - * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it - * initalizes it to be a wxSOCKET_*family*. In other cases, it returns - * an appropiate error code. - * - * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error. - */ -#define CHECK_ADDRESS(address, family) \ -{ \ - if (address->m_family == wxSOCKET_NOFAMILY) \ - if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \ - return address->m_error; \ - if (address->m_family != wxSOCKET_##family) \ - { \ - address->m_error = wxSOCKET_INVADDR; \ - return wxSOCKET_INVADDR; \ - } \ -} - -#define CHECK_ADDRESS_RETVAL(address, family, retval) \ -{ \ - if (address->m_family == wxSOCKET_NOFAMILY) \ - if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \ - return retval; \ - if (address->m_family != wxSOCKET_##family) \ - { \ - address->m_error = wxSOCKET_INVADDR; \ - return retval; \ - } \ -} - - -GAddress *GAddress_new(void) -{ - GAddress *address; - - if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL) - return NULL; - - address->m_family = wxSOCKET_NOFAMILY; - address->m_addr = NULL; - address->m_len = 0; - - return address; -} - -GAddress *GAddress_copy(GAddress *address) -{ - GAddress *addr2; - - assert(address != NULL); - - if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL) - return NULL; - - memcpy(addr2, address, sizeof(GAddress)); - - if (address->m_addr && address->m_len > 0) - { - addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len); - if (addr2->m_addr == NULL) - { - free(addr2); - return NULL; - } - memcpy(addr2->m_addr, address->m_addr, addr2->m_len); - } - - return addr2; -} - -void GAddress_destroy(GAddress *address) -{ - assert(address != NULL); - - if (address->m_addr) - free(address->m_addr); - - 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; -} - -wxSocketError _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 = wxSOCKET_INET; - break; - case AF_UNIX: - address->m_family = wxSOCKET_UNIX; - break; -#if wxUSE_IPV6 - case AF_INET6: - address->m_family = wxSOCKET_INET6; - break; -#endif // wxUSE_IPV6 - default: - { - address->m_error = wxSOCKET_INVOP; - return wxSOCKET_INVOP; - } - } - - if (address->m_addr) - free(address->m_addr); - - address->m_len = len; - address->m_addr = (struct sockaddr *)malloc(len); - - if (address->m_addr == NULL) - { - address->m_error = wxSOCKET_MEMERR; - return wxSOCKET_MEMERR; - } - - memcpy(address->m_addr, addr, len); - - return wxSOCKET_NOERROR; -} - -wxSocketError _GAddress_translate_to(GAddress *address, - struct sockaddr **addr, int *len) -{ - if (!address->m_addr) - { - address->m_error = wxSOCKET_INVADDR; - return wxSOCKET_INVADDR; - } - - *len = address->m_len; - *addr = (struct sockaddr *)malloc(address->m_len); - if (*addr == NULL) - { - address->m_error = wxSOCKET_MEMERR; - return wxSOCKET_MEMERR; - } - - memcpy(*addr, address->m_addr, address->m_len); - return wxSOCKET_NOERROR; -} - -/* - * ------------------------------------------------------------------------- - * Internet address family - * ------------------------------------------------------------------------- - */ - -wxSocketError _GAddress_Init_INET(GAddress *address) -{ - address->m_len = sizeof(struct sockaddr_in); - address->m_addr = (struct sockaddr *) malloc(address->m_len); - if (address->m_addr == NULL) - { - address->m_error = wxSOCKET_MEMERR; - return wxSOCKET_MEMERR; - } - - address->m_family = wxSOCKET_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; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname) -{ - struct hostent *he; - struct in_addr *addr; - - assert(address != NULL); - - CHECK_ADDRESS(address, INET); - - addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr); - - /* If it is a numeric host name, convert it now */ -#if defined(HAVE_INET_ATON) - if (inet_aton(hostname, addr) == 0) - { -#elif defined(HAVE_INET_ADDR) - if ( (addr->s_addr = inet_addr(hostname)) == (unsigned)-1 ) - { -#else - /* Use gethostbyname by default */ -#ifndef __WXMAC__ - int val = 1; /* VA doesn't like constants in conditional expressions */ - if (val) -#endif - { -#endif - struct in_addr *array_addr; - - /* It is a real name, we solve it */ - struct hostent h; -#if defined(HAVE_FUNC_GETHOSTBYNAME_R_3) - struct hostent_data buffer; -#else - char buffer[1024]; -#endif - int err; - he = wxGethostbyname_r(hostname, &h, (void*)&buffer, sizeof(buffer), &err); - if (he == NULL) - { - /* Reset to invalid address */ - addr->s_addr = INADDR_NONE; - address->m_error = wxSOCKET_NOHOST; - return wxSOCKET_NOHOST; - } - - array_addr = (struct in_addr *) *(he->h_addr_list); - addr->s_addr = array_addr[0].s_addr; - } - - return wxSOCKET_NOERROR; -} - - -wxSocketError GAddress_INET_SetBroadcastAddress(GAddress *address) -{ - return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST); -} - -wxSocketError GAddress_INET_SetAnyAddress(GAddress *address) -{ - return GAddress_INET_SetHostAddress(address, INADDR_ANY); -} - -wxSocketError GAddress_INET_SetHostAddress(GAddress *address, - unsigned long hostaddr) -{ - struct in_addr *addr; - - assert(address != NULL); - - CHECK_ADDRESS(address, INET); - - addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr); - addr->s_addr = htonl(hostaddr); - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET_SetPortName(GAddress *address, const char *port, - const char *protocol) -{ - struct servent *se; - struct sockaddr_in *addr; - - assert(address != NULL); - CHECK_ADDRESS(address, INET); - - if (!port) - { - address->m_error = wxSOCKET_INVPORT; - return wxSOCKET_INVPORT; - } - -#if defined(HAVE_FUNC_GETSERVBYNAME_R_4) - struct servent_data buffer; -#else - char buffer[1024]; -#endif - struct servent serv; - se = wxGetservbyname_r(port, protocol, &serv, - (void*)&buffer, sizeof(buffer)); - if (!se) - { - /* the cast to int suppresses compiler warnings about subscript having the - type char */ - if (isdigit((int)port[0])) - { - int port_int; - - port_int = atoi(port); - addr = (struct sockaddr_in *)address->m_addr; - addr->sin_port = htons(port_int); - return wxSOCKET_NOERROR; - } - - address->m_error = wxSOCKET_INVPORT; - return wxSOCKET_INVPORT; - } - - addr = (struct sockaddr_in *)address->m_addr; - addr->sin_port = se->s_port; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port) -{ - struct sockaddr_in *addr; - - assert(address != NULL); - CHECK_ADDRESS(address, INET); - - addr = (struct sockaddr_in *)address->m_addr; - addr->sin_port = htons(port); - - return wxSOCKET_NOERROR; -} - -wxSocketError 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); - - addr = (struct sockaddr_in *)address->m_addr; - addr_buf = (char *)&(addr->sin_addr); - - struct hostent temphost; -#if defined(HAVE_FUNC_GETHOSTBYNAME_R_3) - struct hostent_data buffer; -#else - char buffer[1024]; -#endif - int err; - he = wxGethostbyaddr_r(addr_buf, sizeof(addr->sin_addr), AF_INET, &temphost, - (void*)&buffer, sizeof(buffer), &err); - if (he == NULL) - { - address->m_error = wxSOCKET_NOHOST; - return wxSOCKET_NOHOST; - } - - strncpy(hostname, he->h_name, sbuf); - - return wxSOCKET_NOERROR; -} - -unsigned long GAddress_INET_GetHostAddress(GAddress *address) -{ - struct sockaddr_in *addr; - - assert(address != NULL); - CHECK_ADDRESS_RETVAL(address, INET, 0); - - addr = (struct sockaddr_in *)address->m_addr; - - return ntohl(addr->sin_addr.s_addr); -} - -unsigned short GAddress_INET_GetPort(GAddress *address) -{ - struct sockaddr_in *addr; - - assert(address != NULL); - CHECK_ADDRESS_RETVAL(address, INET, 0); - - addr = (struct sockaddr_in *)address->m_addr; - return ntohs(addr->sin_port); -} - -#if wxUSE_IPV6 -/* - * ------------------------------------------------------------------------- - * Internet IPv6 address family - * ------------------------------------------------------------------------- - */ - -wxSocketError _GAddress_Init_INET6(GAddress *address) -{ - struct in6_addr any_address = IN6ADDR_ANY_INIT; - address->m_len = sizeof(struct sockaddr_in6); - address->m_addr = (struct sockaddr *) malloc(address->m_len); - if (address->m_addr == NULL) - { - address->m_error = wxSOCKET_MEMERR; - return wxSOCKET_MEMERR; - } - memset(address->m_addr,0,address->m_len); - - address->m_family = wxSOCKET_INET6; - address->m_realfamily = AF_INET6; - ((struct sockaddr_in6 *)address->m_addr)->sin6_family = AF_INET6; - ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = any_address; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_SetHostName(GAddress *address, const char *hostname) -{ - assert(address != NULL); - CHECK_ADDRESS(address, INET6); - - addrinfo hints; - memset( & hints, 0, sizeof( hints ) ); - hints.ai_family = AF_INET6; - addrinfo * info = 0; - if ( getaddrinfo( hostname, "0", & hints, & info ) || ! info ) - { - address->m_error = wxSOCKET_NOHOST; - return wxSOCKET_NOHOST; - } - - memcpy( address->m_addr, info->ai_addr, info->ai_addrlen ); - freeaddrinfo( info ); - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_SetAnyAddress(GAddress *address) -{ - assert(address != NULL); - - CHECK_ADDRESS(address, INET6); - - struct in6_addr addr; - memset( & addr, 0, sizeof( addr ) ); - return GAddress_INET6_SetHostAddress(address, addr); -} -wxSocketError GAddress_INET6_SetHostAddress(GAddress *address, - struct in6_addr hostaddr) -{ - assert(address != NULL); - - CHECK_ADDRESS(address, INET6); - - ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = hostaddr; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_SetPortName(GAddress *address, const char *port, - const char *protocol) -{ - struct servent *se; - struct sockaddr_in6 *addr; - - assert(address != NULL); - CHECK_ADDRESS(address, INET6); - - if (!port) - { - address->m_error = wxSOCKET_INVPORT; - return wxSOCKET_INVPORT; - } - - se = getservbyname(port, protocol); - if (!se) - { - if (isdigit(port[0])) - { - int port_int; - - port_int = atoi(port); - addr = (struct sockaddr_in6 *)address->m_addr; - addr->sin6_port = htons((u_short) port_int); - return wxSOCKET_NOERROR; - } - - address->m_error = wxSOCKET_INVPORT; - return wxSOCKET_INVPORT; - } - - addr = (struct sockaddr_in6 *)address->m_addr; - addr->sin6_port = se->s_port; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_SetPort(GAddress *address, unsigned short port) -{ - struct sockaddr_in6 *addr; - - assert(address != NULL); - CHECK_ADDRESS(address, INET6); - - addr = (struct sockaddr_in6 *)address->m_addr; - addr->sin6_port = htons(port); - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_GetHostName(GAddress *address, char *hostname, size_t sbuf) -{ - struct hostent *he; - char *addr_buf; - struct sockaddr_in6 *addr; - - assert(address != NULL); - CHECK_ADDRESS(address, INET6); - - addr = (struct sockaddr_in6 *)address->m_addr; - addr_buf = (char *)&(addr->sin6_addr); - - he = gethostbyaddr(addr_buf, sizeof(addr->sin6_addr), AF_INET6); - if (he == NULL) - { - address->m_error = wxSOCKET_NOHOST; - return wxSOCKET_NOHOST; - } - - strncpy(hostname, he->h_name, sbuf); - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_INET6_GetHostAddress(GAddress *address,struct in6_addr *hostaddr) -{ - assert(address != NULL); - assert(hostaddr != NULL); - CHECK_ADDRESS_RETVAL(address, INET6, wxSOCKET_INVADDR); - *hostaddr = ( (struct sockaddr_in6 *)address->m_addr )->sin6_addr; - return wxSOCKET_NOERROR; -} - -unsigned short GAddress_INET6_GetPort(GAddress *address) -{ - assert(address != NULL); - CHECK_ADDRESS_RETVAL(address, INET6, 0); - - return ntohs( ((struct sockaddr_in6 *)address->m_addr)->sin6_port ); -} - -#endif // wxUSE_IPV6 - -/* - * ------------------------------------------------------------------------- - * Unix address family - * ------------------------------------------------------------------------- - */ - -#ifndef __VISAGECPP__ -wxSocketError _GAddress_Init_UNIX(GAddress *address) -{ - address->m_len = sizeof(struct sockaddr_un); - address->m_addr = (struct sockaddr *)malloc(address->m_len); - if (address->m_addr == NULL) - { - address->m_error = wxSOCKET_MEMERR; - return wxSOCKET_MEMERR; - } - - address->m_family = wxSOCKET_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; - - return wxSOCKET_NOERROR; -} - -#define UNIX_SOCK_PATHLEN (sizeof(addr->sun_path)/sizeof(addr->sun_path[0])) - -wxSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path) -{ - struct sockaddr_un *addr; - - assert(address != NULL); - - CHECK_ADDRESS(address, UNIX); - - addr = ((struct sockaddr_un *)address->m_addr); - strncpy(addr->sun_path, path, UNIX_SOCK_PATHLEN); - addr->sun_path[UNIX_SOCK_PATHLEN - 1] = '\0'; - - return wxSOCKET_NOERROR; -} - -wxSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf) -{ - struct sockaddr_un *addr; - - assert(address != NULL); - CHECK_ADDRESS(address, UNIX); - - addr = (struct sockaddr_un *)address->m_addr; - - strncpy(path, addr->sun_path, sbuf); - - return wxSOCKET_NOERROR; -} -#endif /* !defined(__VISAGECPP__) */ - #endif /* wxUSE_SOCKETS */ -- 2.45.2