/////////////////////////////////////////////////////////////////////////////// // 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" #if wxUSE_IPV6 #include #endif #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) */ }; #include #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_