Panda3D
Loading...
Searching...
No Matches
socket_address.cxx
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file socket_address.h
10 * @author rdb
11 * @date 2016-06-17
12 */
13
14#include "socket_address.h"
15#include "config_downloader.h"
16
17/**
18 * This function will take a port and string-based TCP address and initialize
19 * the address with this information. Returns true on success; on failure, it
20 * returns false and the address may be undefined.
21 */
23set_host(const std::string &hostname, unsigned short port) {
24 // hmm inet_addr4 does not resolve 255.255.255.255 on ME98 ?? * HACK * ??
25 if (hostname == "255.255.255.255") {
26 return set_broadcast(port);
27 }
28
29 struct addrinfo hints, *res = nullptr;
30 memset(&hints, 0, sizeof(hints));
31 hints.ai_flags = AI_ADDRCONFIG;
32 hints.ai_family = support_ipv6 ? AF_UNSPEC : AF_INET;
33
34 if (getaddrinfo(hostname.c_str(), nullptr, &hints, &res)) {
35 return false;
36 }
37
38 nassertr(res->ai_addrlen <= sizeof(_storage), false);
39 memcpy(&_storage, res->ai_addr, res->ai_addrlen);
40 freeaddrinfo(res);
41
42 _addr4.sin_port = htons(port);
43 return true;
44}
45
46/**
47 * Initializes the address from a string specifying both the address and port,
48 * separated by a colon. An IPv6 address must be enclosed in brackets.
49 */
51set_host(const std::string &hostname) {
52 std::string::size_type pos = hostname.rfind(':');
53 if (pos == std::string::npos) {
54 return false;
55 }
56
57 std::string::size_type host_begin = 0;
58 std::string::size_type host_end = pos;
59
60 // Strip spaces.
61 while (host_begin < host_end && isspace(hostname[host_begin])) {
62 ++host_begin;
63 }
64
65 while (host_begin < host_end && isspace(hostname[host_end - 1])) {
66 --host_end;
67 }
68
69 if (host_begin < host_end && hostname[host_begin] == '[') {
70 // Looks like an IPv6 address; extract from the brackets.
71 host_begin += 1;
72 if (hostname[host_end - 1] == ']') {
73 host_end -= 1;
74 } else {
75 return false;
76 }
77 }
78
79 std::string host = hostname.substr(host_begin, host_end - host_begin);
80 std::string port = hostname.substr(pos + 1, 100);
81
82 unsigned short port_dig = (unsigned short)atoi(port.c_str());
83 return set_host(host, port_dig);
84}
85
86/**
87 * Return the IP address portion in dot notation string.
88 */
90get_ip() const {
91 char buf[48];
92 buf[0] = 0;
93
94 if (_storage.ss_family == AF_INET) {
95 getnameinfo(&_addr, sizeof(sockaddr_in), buf, sizeof(buf), nullptr, 0, NI_NUMERICHOST);
96
97 } else if (_storage.ss_family == AF_INET6) {
98 getnameinfo(&_addr, sizeof(sockaddr_in6), buf, sizeof(buf), nullptr, 0, NI_NUMERICHOST);
99
100 } else {
101 nassert_raise("unsupported address family");
102 }
103
104 return std::string(buf);
105}
106
107/**
108 * Return the ip address/port in dot notation string. If this is an IPv6
109 * address, it will be enclosed in square brackets.
110 */
112get_ip_port() const {
113 char buf[100]; // 100 is more than enough for any ip address:port combo..
114 buf[0] = 0;
115
116 if (_storage.ss_family == AF_INET) {
117 getnameinfo(&_addr, sizeof(sockaddr_in), buf, sizeof(buf), nullptr, 0, NI_NUMERICHOST);
118 sprintf(buf + strlen(buf), ":%hu", get_port());
119
120 } else if (_storage.ss_family == AF_INET6) {
121 // Protect the IPv6 address within square brackets.
122 buf[0] = '[';
123 getnameinfo(&_addr, sizeof(sockaddr_in6), buf + 1, sizeof(buf) - 1, nullptr, 0, NI_NUMERICHOST);
124 sprintf(buf + strlen(buf), "]:%hu", get_port());
125
126 } else {
127 nassert_raise("unsupported address family");
128 }
129
130 return std::string(buf);
131}
132
133/**
134 * Returns a raw 32-bit unsigned integer representing the IPv4 address.
135 * @deprecated Does not work with IPv6 addresses.
136 */
137unsigned long Socket_Address::
138GetIPAddressRaw() const {
139 if (_addr.sa_family == AF_INET) {
140 return _addr4.sin_addr.s_addr;
141 }
142 if (_addr.sa_family == AF_INET6) {
143 // Okay, if we got here, something probably went wrong, but let's see if
144 // we can offer a meaningful translation for mapped addresses.
145 uint32_t *parts = (uint32_t *)&_addr6.sin6_addr;
146 if (parts[0] == 0 && parts[1] == 0 && (parts[2] == 0 || parts[2] == htonl(0xffff))) {
147 if (parts[2] == 0 && parts[3] == htonl(1)) {
148 // Special exception for localhost.
149 return 0x1000007f;
150 } else {
151 return parts[3];
152 }
153 }
154 }
155 nassert_raise("GetIPAddressRaw() can only be called on an IPv4 address");
156 return 0;
157}
bool set_host(const std::string &hostname, unsigned short port)
This function will take a port and string-based TCP address and initialize the address with this info...
bool set_broadcast(unsigned short port)
Set to the broadcast address and a specified port.
std::string get_ip() const
Return the IP address portion in dot notation string.
unsigned long GetIPAddressRaw() const
Returns a raw 32-bit unsigned integer representing the IPv4 address.
std::string get_ip_port() const
Return the ip address/port in dot notation string.
unsigned short get_port() const
Get the port portion as an integer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.