/* * SRT - Secure, Reliable, Transport * Copyright (c) 2018 Haivision Systems Inc. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * */ /***************************************************************************** written by Haivision Systems Inc. *****************************************************************************/ #ifndef INC__NETINET_ANY_H #define INC__NETINET_ANY_H #include #include "platform_sys.h" // This structure should replace every use of sockaddr and its currently // used specializations, sockaddr_in and sockaddr_in6. This is to simplify // the use of the original BSD API that relies on type-violating type casts. // You can use the instances of sockaddr_any in every place where sockaddr is // required. struct sockaddr_any { union { sockaddr_in sin; sockaddr_in6 sin6; sockaddr sa; }; socklen_t len; sockaddr_any(int domain = AF_INET) { memset(this, 0, sizeof *this); sa.sa_family = domain; len = size(); } socklen_t size() const { switch (sa.sa_family) { case AF_INET: return socklen_t(sizeof sin); case AF_INET6: return socklen_t(sizeof sin6); default: return 0; // fallback, impossible } } int family() const { return sa.sa_family; } // port is in exactly the same location in both sin and sin6 // and has the same size. This is actually yet another common // field, just not mentioned in the sockaddr structure. uint16_t& r_port() { return sin.sin_port; } uint16_t r_port() const { return sin.sin_port; } int hport() const { return ntohs(sin.sin_port); } void hport(int value) { // Port is fortunately located at the same position // in both sockaddr_in and sockaddr_in6 and has the // same size. sin.sin_port = htons(value); } sockaddr* get() { return &sa; } sockaddr* operator&() { return &sa; } const sockaddr* get() const { return &sa; } const sockaddr* operator&() const { return &sa; } template struct TypeMap; template typename TypeMap::type& get(); struct Equal { bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) { return memcmp(&c1, &c2, sizeof(c1)) == 0; } }; struct EqualAddress { bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) { if ( c1.sa.sa_family == AF_INET ) { return c1.sin.sin_addr.s_addr == c2.sin.sin_addr.s_addr; } if ( c1.sa.sa_family == AF_INET6 ) { return memcmp(&c1.sin6.sin6_addr, &c2.sin6.sin6_addr, sizeof (in6_addr)) == 0; } return false; } }; bool equal_address(const sockaddr_any& rhs) const { return EqualAddress()(*this, rhs); } struct Less { bool operator()(const sockaddr_any& c1, const sockaddr_any& c2) { return memcmp(&c1, &c2, sizeof(c1)) < 0; } }; }; template<> struct sockaddr_any::TypeMap { typedef sockaddr_in type; }; template<> struct sockaddr_any::TypeMap { typedef sockaddr_in6 type; }; template <> inline sockaddr_any::TypeMap::type& sockaddr_any::get() { return sin; } template <> inline sockaddr_any::TypeMap::type& sockaddr_any::get() { return sin6; } #endif