IPAddress::IPAddress(const std::string& addr) { IPv4AddressImpl empty4 = IPv4AddressImpl(); if (addr.empty() || trim(addr) == "0.0.0.0") { newIPv4(empty4.addr()); return; } IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); if (addr4 != empty4) { newIPv4(addr4.addr()); return; } #if defined(POCO_HAVE_IPv6) IPv6AddressImpl empty6 = IPv6AddressImpl(); if (addr.empty() || trim(addr) == "::") { newIPv6(empty6.addr()); return; } IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); if (addr6 != IPv6AddressImpl()) { newIPv6(addr6.addr(), addr6.scope()); return; } #endif throw InvalidAddressException(addr); }
/** * `Socket` Constructor. * * Constructs a `Socket` object given a listening address/port and begins * listening for clients. * * @param addr `std::string` object containing the listen address * @param port `int` containing the port number to listen on */ Socket::Socket(const std::string& addr, int port) { // Ensure the validity of the provided port if (port < 1 || port > 65535) throw InvalidArgument{"The provided port number is out of range."}; // Fetch a finalized sockaddr_storage for the given address struct sockaddr_storage address = parseAddress(addr); // Use the appropriate setup helper depending on the address family if (address.ss_family == AF_INET || address.ss_family == AF_INET6) { // Assign the appropriate address family to describe the `Connection` this->family = (address.ss_family == AF_INET ? SocketFamily::IPv4 : SocketFamily::IPv6); // Determine the appropriate pointer type for the remote address auto addrPtr = (address.ss_family == AF_INET ? addr4(address) : addr6(address)); // Store a text-based representation of the remote address char addressString[INET6_ADDRSTRLEN + 1] = {}; this->host = inet_ntop(address.ss_family, addrPtr, addressString, INET6_ADDRSTRLEN); // Assign the port to the sockaddr struct *(this->family == SocketFamily::IPv4 ? port4(address) : port6(address)) = htons(this->port = port); } else { // Remote address has an unexpected address family throw InvalidArgument{"The remote address has an unexpected address " "family."}; } // Setup the socket using the appropriate address family and type this->socket = ::socket(address.ss_family, SOCK_STREAM, 0); // Attempt to bind the socket to the listening address if (bind(this->socket, addr_(address), this->family == SocketFamily::IPv4 ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) < 0) { // A problem occurred, close the socket and throw an exception close(this->socket); throw UnexpectedError{"Couldn't bind to [" + this->host + "]:" + std::to_string(this->port)}; } else { // Allow reusing the socket int reuse = 1; setsockopt(this->socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)); // Listen with a backlog of 16 clients listen(this->socket, 16); } }
IPAddress::IPAddress(const std::string& addr, Family family) { if (family == IPv4) { IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); newIPv4(addr4.addr()); return; } #if defined(POCO_HAVE_IPv6) else if (family == IPv6) { IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); newIPv6(addr6.addr(), addr6.scope()); return; } #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); }
/** * Accepts an incoming client and creates a `Connection` object for it. * * This method blocks execution until a client is accepted. * * @return `Connection` object representing the accepted client. */ std::shared_ptr<Connection> Socket::accept() const { // Create storage to accept and capture the client's remote address std::string raddress{}; struct sockaddr_storage cli_addr = {}; socklen_t cli_addr_len = sizeof(struct sockaddr); int cli_fd = -1; // Check if the Socket is valid if (this->valid()) { // Accept an incoming client cli_fd = ::accept(this->socket, (struct sockaddr*)&cli_addr, &cli_addr_len); // Store a text-based representation of the remote address if (cli_addr.ss_family == AF_INET || cli_addr.ss_family == AF_INET6) { // Determine the appropriate pointer type for the remote address auto addrPtr = (cli_addr.ss_family == AF_INET ? addr4(cli_addr) : addr6(cli_addr)); // Assign the resulting address to the raddress string char addressString[INET6_ADDRSTRLEN + 1] = {}; raddress = inet_ntop(cli_addr.ss_family, addrPtr, addressString, INET6_ADDRSTRLEN); } // If cli_fd is negative, an error occurred if (cli_fd < 0) { throw UnexpectedError{"Couldn't accept client on [" + this->host + "]:" + std::to_string(this->port) + " - Invalid client file " "descriptor"}; } } else { // Cannot accept a client on an invalid Socket throw UnexpectedError{"Couldn't accept client on [" + this->host + "]:" + std::to_string(this->port) + " - Invalid socket"}; } // Return a shared_ptr to the newly created Connection object return std::shared_ptr<Connection>{ new Connection{this->host, raddress, this->port, cli_fd} }; }
void test() { namespace ip = std::experimental::net::ip; try { std::error_code ec; std::string string_value; // address constructors. ip::address addr1; const ip::address_v4 const_addr_v4; ip::address addr2(const_addr_v4); const ip::address_v6 const_addr_v6; ip::address addr3(const_addr_v6); ip::address addr4("127.0.0.1"); ip::address addr5("127.0.0.1", ec); ip::address addr6(string_value); ip::address addr7(string_value, ec); // address functions. bool b = addr1.is_v4(); (void)b; b = addr1.is_v6(); (void)b; b = addr1.is_loopback(); (void)b; b = addr1.is_unspecified(); (void)b; b = addr1.is_multicast(); (void)b; ip::address_v4 addr_v4_value = ip::address_cast<ip::address_v4>(addr1); (void)addr_v4_value; ip::address_v6 addr_v6_value = ip::address_cast<ip::address_v6>(addr1); (void)addr_v6_value; string_value = addr1.to_string(); string_value = addr1.to_string(ec); // address comparisons. b = (addr1 == addr2); (void)b; b = (addr1 != addr2); (void)b; b = (addr1 < addr2); (void)b; b = (addr1 > addr2); (void)b; b = (addr1 <= addr2); (void)b; b = (addr1 >= addr2); (void)b; // address creation functions. addr1 = ip::make_address("127.0.0.1"); addr1 = ip::make_address("127.0.0.1", ec); addr1 = ip::make_address(string_value); addr1 = ip::make_address(string_value, ec); // address I/O. std::ostringstream os; os << addr1; std::wostringstream wos; wos << addr1; } catch (std::exception&) { } }