/* This little program demonstrates the parsing of IPAddress strings */ int main(int argc, char ** argv) { CompleteSetupSystem css; PrintExampleDescription(); while(1) { printf("Please enter a string representing an IPv4 or IPv6 numeric host-address: "); fflush(stdout); char buf[1024]; (void) fgets(buf, sizeof(buf), stdin); String s = buf; s = s.Trim(); // get rid of newline ugliness IPAddress ip; if (ip.SetFromString(s) == B_NO_ERROR) { printf("I parsed the string [%s] as IPAddress %s\n", s(), ip.ToString()()); printf(" ip.IsValid() returned %i\n", ip.IsValid()); printf(" ip.IsIPv4() returned %i\n", ip.IsIPv4()); printf(" ip.IsMulticast() returned %i\n", ip.IsMulticast()); printf(" ip.IsStandardLoopbackAddress() returned %i\n", ip.IsStandardLoopbackDeviceAddress()); printf("\n"); } else printf("Error, couldn't parse [%s] as an IPAddress!\n", s()); } return 0; }
/** @details The broadcast address can only be calculated on a IPv4 network. While it is * technically possible to calculate an IPv6 broadcast address, the IPv6 protocol has dropped * support for broadcasting. Since broadcasting is not supported in IPv6, this method will result * in an exception given an IPv6 address. * @param ip An IP address on the network. * @param netmask The netmask defining the network range. * @returns The broadcast address. */ _CGUL_EXPORT CGUL::Network::IPAddress CGUL::Network::IPAddress::CalculateBroadcast(const IPAddress& ip, const IPAddress& netmask) { if (ip.GetType() == IPAddressType::IPV6 || netmask.GetType() == IPAddressType::IPV6) { throw NetworkException(NetworkExceptionCode::FAILED_CALCULATE_ADDRESS, NetworkExceptionReason::ADDRESS_INVALID); } if (!ip.IsValid() || ip.GetType() != netmask.GetType()) { throw NetworkException(NetworkExceptionCode::FAILED_CALCULATE_ADDRESS, NetworkExceptionReason::ADDRESS_MISMATCH); } return IPAddress(ip.ToUInt32() | (~netmask.ToUInt32())); }
/** @details A network address defines the "bottom-most" address for a given network. * @param ip An IP address on the network. * @param netmask The netmask defining the network range. * @returns The network address. */ _CGUL_EXPORT CGUL::Network::IPAddress CGUL::Network::IPAddress::CalculateNetwork(const IPAddress& ip, const IPAddress& netmask) { if (!ip.IsValid() || ip.GetType() != netmask.GetType()) { throw NetworkException(NetworkExceptionCode::FAILED_CALCULATE_ADDRESS, NetworkExceptionReason::ADDRESS_MISMATCH); } if (ip.GetType() == IPAddressType::IPV4) { return IPAddress(ip.ToUInt32() & netmask.ToUInt32()); } else { UInt64 network[2]; network[0] = ip.address[0] & netmask.address[0]; network[1] = ip.address[1] & netmask.address[1]; return IPAddress(network); } }
/** @brief Connects to a server on a given ip and port. * @param ip The IP address to connect to. * @param port The port number. */ void Jatta::Network::SocketTCP::Connect(const IPAddress& ip, unsigned short port) { // Check that the IP is valid if (!ip.IsValid()) { throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::ADDRESS_INVALID); } // Create a hints variable used to determine the connection configuration. struct addrinfo hints; memset(&hints, 0, sizeof(addrinfo)); // Check if the IP is an IPv4 or IPv6. if (ip.GetType() == IPAddressType::IPV4) { // Use IPv4. hints.ai_family = AF_INET; } else { // Use IPv6. hints.ai_family = AF_INET6; } // We're setting up a TCP/IP connection, which is a STREAM socket. hints.ai_socktype = SOCK_STREAM; // Convert the port into a string. char portString[6]; # ifdef MSVC sprintf_s(portString, "%d", port); # else sprintf(portString, "%d", port); # endif // Get the address info using the hints. addrinfo* result; if (getaddrinfo(ip.ToString().GetCString(), portString, &hints, &result) != 0) { throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::NO_NETWORK_INTERFACE); } // Create the socket. Because our hints are so strict, we don't have to worry about looping // through the linked list. We should be able to trust that the first result is what we want. sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (sock == INVALID_SOCKET) { freeaddrinfo(result); throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::FAILED_CREATE_SOCKET); } // Make the connection. if (::connect(sock, result->ai_addr, result->ai_addrlen) == SOCKET_ERROR) { freeaddrinfo(result); Close(); throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::FAILED_CONNECT_CALL); } // Make a non-blocking socket. if (!MakeNonBlocking()) { freeaddrinfo(result); Close(); throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::FAILED_NONBLOCKING); } // Turn off the Nagle Algorithm to increase speed. if (!MakeNoDelay()) { freeaddrinfo(result); Close(); throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::FAILED_NO_DELAY); } // Free up the address info linked list. freeaddrinfo(result); }