/** * @file * Declares utility functions for interacting with Winsock */ #pragma once #include #include #include namespace facter { namespace util { namespace windows { /** * Exception thrown when wsa initialization fails. */ struct wsa_exception : std::runtime_error { /** * Constructs a wsa_exception. * @param message The exception message. */ explicit wsa_exception(std::string const& message); }; /** * A class for initiating use of the Winsock DLL, providing wrappers for WSA calls. */ struct wsa { /** * Initializes Winsock. Throws a wsa_exception on failure. */ wsa(); /** * Do WSA cleanup. */ ~wsa(); /** * Use default move constructer. */ wsa(wsa&&) = default; /** * Use default move assignment. * @return Returns this instance. */ wsa& operator=(wsa&&) = default; /** * This wraps calling WSAAddressToString to translate a sockaddr structure to an IPv4 or IPv6 string. * Throws an exception if passed an IPv6 argument on Windows Server 2003 and IPv6 support isn't installed. * See https://social.technet.microsoft.com/Forums/windowsserver/en-US/7166dcbe-d493-4da1-8441-5b5d6aa0d21c/ipv6-and-windows-server-2003 * @param addr The socket address structure. * @return An IPv4 or IPv6 string, or an empty string if addr is uninitialized. */ std::string saddress_to_string(SOCKET_ADDRESS const& addr) const; /** * This adapts sockaddr structs to the SOCKET_ADDRESS wrapper. * @param addr A sockaddr-like structure (sockaddr, sockaddr_in, sockaddr_in6). * @return An IPv4 or IPv6 string. */ template std::string address_to_string(T &addr) const { return saddress_to_string(SOCKET_ADDRESS{reinterpret_cast(&addr), sizeof(T)}); } /** * This wraps calling WSAStringToAddress to translate a an IPv4 or IPv6 string to a sockaddr structure. * @tparam T The expected sockaddr structure, either sockaddr_in or sockaddr_in6. * @tparam ADDRESS_FAMILY The expected address family, either AF_INET or AF_INET6. * @param addr An IPv4 or IPv6 string. * @return A sockaddr structure containing the IPv4 or IPv6 sockaddr data. */ template T string_to_address(std::string const& addr) const { T sock = {ADDRESS_FAMILY}; string_fill_sockaddr(reinterpret_cast(&sock), addr, sizeof(T)); return sock; } private: wsa(wsa const&) = delete; wsa& operator=(wsa const&) = delete; void string_fill_sockaddr(sockaddr *sock, std::string const& addr, int size) const; }; }}} // namespace facter::util::windows