diff options
-rw-r--r-- | toxcore/network.c | 178 | ||||
-rw-r--r-- | toxcore/network.h | 22 |
2 files changed, 198 insertions, 2 deletions
diff --git a/toxcore/network.c b/toxcore/network.c index 622a4b17..f504401e 100644 --- a/toxcore/network.c +++ b/toxcore/network.c | |||
@@ -234,3 +234,181 @@ void kill_networking(Networking_Core *net) | |||
234 | free(net); | 234 | free(net); |
235 | return; | 235 | return; |
236 | } | 236 | } |
237 | |||
238 | /* | ||
239 | * addr_parse_ip | ||
240 | * directly parses the input into an IP structure | ||
241 | * tries IPv4 first, then IPv6 | ||
242 | * | ||
243 | * input | ||
244 | * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6) | ||
245 | * | ||
246 | * output | ||
247 | * IP: family and the value is set on success | ||
248 | * | ||
249 | * returns 1 on success, 0 on failure | ||
250 | */ | ||
251 | |||
252 | int addr_parse_ip(const char *address, IPAny *to) | ||
253 | { | ||
254 | struct in_addr addr4; | ||
255 | if (1 == inet_pton(AF_INET, address, &addr4)) | ||
256 | { | ||
257 | to->family = AF_INET; | ||
258 | to->ip4.in_addr = addr4; | ||
259 | return 1; | ||
260 | }; | ||
261 | |||
262 | struct in6_addr addr6; | ||
263 | if (1 == inet_pton(AF_INET6, address, &addr6)) | ||
264 | { | ||
265 | to->family = AF_INET6; | ||
266 | to->ip6 = addr6; | ||
267 | return 1; | ||
268 | }; | ||
269 | |||
270 | return 0; | ||
271 | }; | ||
272 | |||
273 | /* | ||
274 | * addr_resolve(): | ||
275 | * uses getaddrinfo to resolve an address into an IP address | ||
276 | * uses the first IPv4/IPv6 addresses returned by getaddrinfo | ||
277 | * | ||
278 | * input | ||
279 | * address: a hostname (or something parseable to an IP address) | ||
280 | * ip: ip.family MUST be initialized, either set to a specific IP version | ||
281 | * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both | ||
282 | * IP versions are acceptable | ||
283 | * | ||
284 | * returns in ip a valid IPAny (v4/v6), | ||
285 | * prefers v6 if ip.family was AF_UNSPEC and both available | ||
286 | * returns 0 on failure | ||
287 | */ | ||
288 | |||
289 | int addr_resolve(const char *address, IPAny *ip) | ||
290 | { | ||
291 | struct addrinfo *server = NULL; | ||
292 | struct addrinfo *walker = NULL; | ||
293 | struct addrinfo hints; | ||
294 | int rc; | ||
295 | |||
296 | memset(&hints, 0, sizeof(hints)); | ||
297 | hints.ai_family = ip->family; | ||
298 | hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses. | ||
299 | |||
300 | #ifdef __WIN32__ | ||
301 | WSADATA wsa_data; | ||
302 | |||
303 | /* CLEANUP: really not the best place to put this */ | ||
304 | rc = WSAStartup(MAKEWORD(2, 2), &wsa_data); | ||
305 | |||
306 | if (rc != 0) { | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | #endif | ||
311 | |||
312 | rc = getaddrinfo(address, NULL, &hints, &server); | ||
313 | // Lookup failed. | ||
314 | if (rc != 0) { | ||
315 | #ifdef __WIN32__ | ||
316 | WSACleanup(); | ||
317 | #endif | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | IP4 ip4; | ||
322 | memset(&ip4, 0, sizeof(ip4)); | ||
323 | IP6 ip6; | ||
324 | memset(&ip6, 0, sizeof(ip6)); | ||
325 | |||
326 | walker = server; | ||
327 | while (walker && (rc != 3)) | ||
328 | { | ||
329 | if (ip->family != AF_UNSPEC) | ||
330 | { | ||
331 | if (walker->ai_family == ip->family) { | ||
332 | if (ip->family == AF_INET) | ||
333 | { | ||
334 | if (walker->ai_addrlen == sizeof(struct sockaddr_in)) | ||
335 | { | ||
336 | struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; | ||
337 | ip->ip4.in_addr = addr->sin_addr; | ||
338 | rc = 3; | ||
339 | } | ||
340 | } | ||
341 | else if (ip->family == AF_INET6) | ||
342 | { | ||
343 | if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) | ||
344 | { | ||
345 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; | ||
346 | ip->ip6 = addr->sin6_addr; | ||
347 | rc = 3; | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | if (walker->ai_family == AF_INET) | ||
355 | { | ||
356 | if (walker->ai_addrlen == sizeof(struct sockaddr_in)) | ||
357 | { | ||
358 | struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; | ||
359 | ip4.in_addr = addr->sin_addr; | ||
360 | rc |= 1; | ||
361 | } | ||
362 | } | ||
363 | else if (walker->ai_family == AF_INET6) | ||
364 | { | ||
365 | if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) | ||
366 | { | ||
367 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; | ||
368 | ip6 = addr->sin6_addr; | ||
369 | rc |= 2; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | |||
374 | walker = walker->ai_next; | ||
375 | } | ||
376 | |||
377 | if (ip->family == AF_UNSPEC) | ||
378 | { | ||
379 | if (rc & 2) | ||
380 | { | ||
381 | ip->family = AF_INET6; | ||
382 | ip->ip6 = ip6; | ||
383 | } else if (rc & 1) | ||
384 | { | ||
385 | ip->family = AF_INET; | ||
386 | ip->ip4 = ip4; | ||
387 | } | ||
388 | else | ||
389 | rc = 0; | ||
390 | } | ||
391 | |||
392 | |||
393 | freeaddrinfo(server); | ||
394 | #ifdef __WIN32__ | ||
395 | WSACleanup(); | ||
396 | #endif | ||
397 | return rc; | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | * addr_resolve_or_parse_ip | ||
402 | * resolves string into an IP address | ||
403 | * | ||
404 | * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6) | ||
405 | * returns 1 on success, 0 on failure | ||
406 | */ | ||
407 | int addr_resolve_or_parse_ip(const char *address, IPAny *to) | ||
408 | { | ||
409 | if (!addr_resolve(address, to)) | ||
410 | if (!addr_parse_ip(address, to)) | ||
411 | return 0; | ||
412 | |||
413 | return 1; | ||
414 | }; | ||
diff --git a/toxcore/network.h b/toxcore/network.h index 9991c4a4..2a0b5560 100644 --- a/toxcore/network.h +++ b/toxcore/network.h | |||
@@ -86,9 +86,19 @@ typedef union { | |||
86 | uint8_t uint8[4]; | 86 | uint8_t uint8[4]; |
87 | uint16_t uint16[2]; | 87 | uint16_t uint16[2]; |
88 | uint32_t uint32; | 88 | uint32_t uint32; |
89 | in_addr_t in_addr; | 89 | struct in_addr in_addr; |
90 | } IP4; | 90 | } IP4; |
91 | 91 | ||
92 | typedef struct in6_addr IP6; | ||
93 | |||
94 | typedef struct { | ||
95 | sa_family_t family; | ||
96 | union { | ||
97 | IP4 ip4; | ||
98 | IP6 ip6; | ||
99 | }; | ||
100 | } IPAny; | ||
101 | |||
92 | typedef union { | 102 | typedef union { |
93 | struct { | 103 | struct { |
94 | IP4 ip; | 104 | IP4 ip; |
@@ -109,6 +119,15 @@ typedef struct { | |||
109 | #endif | 119 | #endif |
110 | } ADDR; | 120 | } ADDR; |
111 | 121 | ||
122 | /* | ||
123 | * addr_resolve_or_parse_ip | ||
124 | * resolves string into an IP address | ||
125 | * | ||
126 | * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6) | ||
127 | * returns 1 on success, 0 on failure | ||
128 | */ | ||
129 | int addr_resolve_or_parse_ip(const char *address, IPAny *to); | ||
130 | |||
112 | /* Function to receive data, ip and port of sender is put into ip_port. | 131 | /* Function to receive data, ip and port of sender is put into ip_port. |
113 | * Packet data is put into data. | 132 | * Packet data is put into data. |
114 | * Packet length is put into length. | 133 | * Packet length is put into length. |
@@ -161,5 +180,4 @@ Networking_Core *new_networking(IP4 ip, uint16_t port); | |||
161 | /* Function to cleanup networking stuff (doesn't do much right now). */ | 180 | /* Function to cleanup networking stuff (doesn't do much right now). */ |
162 | void kill_networking(Networking_Core *net); | 181 | void kill_networking(Networking_Core *net); |
163 | 182 | ||
164 | |||
165 | #endif | 183 | #endif |