summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Biro <nurupo.contributions@gmail.com>2018-04-07 22:09:42 -0400
committerMaxim Biro <nurupo.contributions@gmail.com>2018-04-17 19:07:50 -0400
commit7d399cedcfd20f0d91a8caf386ae3c63f4dcf285 (patch)
treea0f4134961bb163151532afe3fb5e98927965738
parent2824daf74a6d2bd60ebaf387a30f1b7719b6b67c (diff)
Improve network error reporting on Windows
Windows doesn't report network errors though errno, it has its own facilities.
-rw-r--r--auto_tests/network_test.c17
-rw-r--r--testing/av_test.c1
-rw-r--r--toxav/bwcontroller.c6
-rw-r--r--toxav/rtp.c18
-rw-r--r--toxcore/network.c73
-rw-r--r--toxcore/network.h28
6 files changed, 119 insertions, 24 deletions
diff --git a/auto_tests/network_test.c b/auto_tests/network_test.c
index 15757d4d..6f535ee1 100644
--- a/auto_tests/network_test.c
+++ b/auto_tests/network_test.c
@@ -38,7 +38,10 @@ START_TEST(test_addr_resolv_localhost)
38 38
39 int res = addr_resolve(localhost, &ip, nullptr); 39 int res = addr_resolve(localhost, &ip, nullptr);
40 40
41 ck_assert_msg(res > 0, "Resolver failed: %u, %s", errno, strerror(errno)); 41 int error = net_error();
42 const char *strerror = net_new_strerror(error);
43 ck_assert_msg(res > 0, "Resolver failed: %d, %s", error, strerror);
44 net_kill_strerror(strerror);
42 45
43 char ip_str[IP_NTOA_LEN]; 46 char ip_str[IP_NTOA_LEN];
44 ck_assert_msg(ip.family == TOX_AF_INET, "Expected family TOX_AF_INET, got %u.", ip.family); 47 ck_assert_msg(ip.family == TOX_AF_INET, "Expected family TOX_AF_INET, got %u.", ip.family);
@@ -54,7 +57,10 @@ START_TEST(test_addr_resolv_localhost)
54 localhost_split = 1; 57 localhost_split = 1;
55 } 58 }
56 59
57 ck_assert_msg(res > 0, "Resolver failed: %u, %s", errno, strerror(errno)); 60 error = net_error();
61 strerror = net_new_strerror(error);
62 ck_assert_msg(res > 0, "Resolver failed: %d, %s", error, strerror);
63 net_kill_strerror(strerror);
58 64
59 ck_assert_msg(ip.family == TOX_AF_INET6, "Expected family TOX_AF_INET6 (%u), got %u.", TOX_AF_INET6, ip.family); 65 ck_assert_msg(ip.family == TOX_AF_INET6, "Expected family TOX_AF_INET6 (%u), got %u.", TOX_AF_INET6, ip.family);
60 IP6 ip6_loopback = get_ip6_loopback(); 66 IP6 ip6_loopback = get_ip6_loopback();
@@ -71,7 +77,10 @@ START_TEST(test_addr_resolv_localhost)
71 IP extra; 77 IP extra;
72 ip_reset(&extra); 78 ip_reset(&extra);
73 res = addr_resolve(localhost, &ip, &extra); 79 res = addr_resolve(localhost, &ip, &extra);
74 ck_assert_msg(res > 0, "Resolver failed: %u, %s", errno, strerror(errno)); 80 error = net_error();
81 strerror = net_new_strerror(error);
82 ck_assert_msg(res > 0, "Resolver failed: %d, %s", error, strerror);
83 net_kill_strerror(strerror);
75 84
76#if USE_IPV6 85#if USE_IPV6
77 ck_assert_msg(ip.family == TOX_AF_INET6, "Expected family TOX_AF_INET6 (%u), got %u.", TOX_AF_INET6, ip.family); 86 ck_assert_msg(ip.family == TOX_AF_INET6, "Expected family TOX_AF_INET6 (%u), got %u.", TOX_AF_INET6, ip.family);
@@ -157,6 +166,8 @@ static Suite *network_suite(void)
157{ 166{
158 Suite *s = suite_create("Network"); 167 Suite *s = suite_create("Network");
159 168
169 networking_at_startup();
170
160 DEFTESTCASE(addr_resolv_localhost); 171 DEFTESTCASE(addr_resolv_localhost);
161 DEFTESTCASE(ip_equal); 172 DEFTESTCASE(ip_equal);
162 173
diff --git a/testing/av_test.c b/testing/av_test.c
index 0d61edec..5cc3b5dd 100644
--- a/testing/av_test.c
+++ b/testing/av_test.c
@@ -64,7 +64,6 @@ extern "C" {
64#include <opencv/highgui.h> 64#include <opencv/highgui.h>
65 65
66#include <assert.h> 66#include <assert.h>
67#include <errno.h>
68#include <sched.h> 67#include <sched.h>
69#include <stdio.h> 68#include <stdio.h>
70#include <stdlib.h> 69#include <stdlib.h>
diff --git a/toxav/bwcontroller.c b/toxav/bwcontroller.c
index 5c6782ba..d786080e 100644
--- a/toxav/bwcontroller.c
+++ b/toxav/bwcontroller.c
@@ -145,8 +145,10 @@ void send_update(BWController *bwc)
145 msg->recv = net_htonl(bwc->cycle.recv); 145 msg->recv = net_htonl(bwc->cycle.recv);
146 146
147 if (-1 == m_send_custom_lossy_packet(bwc->m, bwc->friend_number, bwc_packet, sizeof(bwc_packet))) { 147 if (-1 == m_send_custom_lossy_packet(bwc->m, bwc->friend_number, bwc_packet, sizeof(bwc_packet))) {
148 LOGGER_WARNING(bwc->m->log, "BWC send failed (len: %u)! std error: %s", 148 const char *netstrerror = net_new_strerror(net_error());
149 (unsigned)sizeof(bwc_packet), strerror(errno)); 149 LOGGER_WARNING(bwc->m->log, "BWC send failed (len: %u)! std error: %s, net error %s",
150 (unsigned)sizeof(bwc_packet), strerror(errno), netstrerror);
151 net_kill_strerror(netstrerror);
150 } 152 }
151 } 153 }
152 154
diff --git a/toxav/rtp.c b/toxav/rtp.c
index c760d333..a65dbafe 100644
--- a/toxav/rtp.c
+++ b/toxav/rtp.c
@@ -802,8 +802,10 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint32_t length,
802 memcpy(rdata + 1 + RTP_HEADER_SIZE, data, length); 802 memcpy(rdata + 1 + RTP_HEADER_SIZE, data, length);
803 803
804 if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, rdata, SIZEOF_VLA(rdata))) { 804 if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, rdata, SIZEOF_VLA(rdata))) {
805 LOGGER_WARNING(session->m->log, "RTP send failed (len: %u)! std error: %s", 805 const char *netstrerror = net_new_strerror(net_error());
806 (unsigned)SIZEOF_VLA(rdata), strerror(errno)); 806 LOGGER_WARNING(session->m->log, "RTP send failed (len: %u)! std error: %s, net error: %s",
807 (unsigned)SIZEOF_VLA(rdata), strerror(errno), netstrerror);
808 net_kill_strerror(netstrerror);
807 } 809 }
808 } else { 810 } else {
809 /** 811 /**
@@ -819,8 +821,10 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint32_t length,
819 821
820 if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, 822 if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number,
821 rdata, piece + RTP_HEADER_SIZE + 1)) { 823 rdata, piece + RTP_HEADER_SIZE + 1)) {
822 LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s", 824 const char *netstrerror = net_new_strerror(net_error());
823 piece + RTP_HEADER_SIZE + 1, strerror(errno)); 825 LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s, net error: %s",
826 piece + RTP_HEADER_SIZE + 1, strerror(errno), netstrerror);
827 net_kill_strerror(netstrerror);
824 } 828 }
825 829
826 sent += piece; 830 sent += piece;
@@ -837,8 +841,10 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint32_t length,
837 841
838 if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, rdata, 842 if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, rdata,
839 piece + RTP_HEADER_SIZE + 1)) { 843 piece + RTP_HEADER_SIZE + 1)) {
840 LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s", 844 const char *netstrerror = net_new_strerror(net_error());
841 piece + RTP_HEADER_SIZE + 1, strerror(errno)); 845 LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s, net error: %s",
846 piece + RTP_HEADER_SIZE + 1, strerror(errno), netstrerror);
847 net_kill_strerror(netstrerror);
842 } 848 }
843 } 849 }
844 } 850 }
diff --git a/toxcore/network.c b/toxcore/network.c
index d88ba816..984071d4 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -63,15 +63,15 @@
63#include <sys/time.h> 63#include <sys/time.h>
64#include <sys/types.h> 64#include <sys/types.h>
65 65
66#define TOX_EWOULDBLOCK EWOULDBLOCK
67
66#else 68#else
67 69
68#ifndef IPV6_V6ONLY 70#ifndef IPV6_V6ONLY
69#define IPV6_V6ONLY 27 71#define IPV6_V6ONLY 27
70#endif 72#endif
71 73
72#ifndef EWOULDBLOCK 74#define TOX_EWOULDBLOCK WSAEWOULDBLOCK
73#define EWOULDBLOCK WSAEWOULDBLOCK
74#endif
75 75
76static const char *inet_ntop(Family family, const void *addr, char *buf, size_t bufsize) 76static const char *inet_ntop(Family family, const void *addr, char *buf, size_t bufsize)
77{ 77{
@@ -376,10 +376,13 @@ static void loglogdata(Logger *log, const char *message, const uint8_t *buffer,
376 char ip_str[IP_NTOA_LEN]; 376 char ip_str[IP_NTOA_LEN];
377 377
378 if (res < 0) { /* Windows doesn't necessarily know %zu */ 378 if (res < 0) { /* Windows doesn't necessarily know %zu */
379 int error = net_error();
380 const char *strerror = net_new_strerror(error);
379 LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x", 381 LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x",
380 buffer[0], message, (buflen < 999 ? buflen : 999), 'E', 382 buffer[0], message, (buflen < 999 ? buflen : 999), 'E',
381 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), errno, 383 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), error,
382 strerror(errno), data_0(buflen, buffer), data_1(buflen, buffer)); 384 strerror, data_0(buflen, buffer), data_1(buflen, buffer));
385 net_kill_strerror(strerror);
383 } else if ((res > 0) && ((size_t)res <= buflen)) { 386 } else if ((res > 0) && ((size_t)res <= buflen)) {
384 LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x", 387 LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x",
385 buffer[0], message, (res < 999 ? res : 999), ((size_t)res < buflen ? '<' : '='), 388 buffer[0], message, (res < 999 ? res : 999), ((size_t)res < buflen ? '<' : '='),
@@ -498,9 +501,12 @@ static int receivepacket(Logger *log, Socket sock, IP_Port *ip_port, uint8_t *da
498 int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); 501 int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
499 502
500 if (fail_or_len < 0) { 503 if (fail_or_len < 0) {
504 int error = net_error();
501 505
502 if (fail_or_len < 0 && errno != EWOULDBLOCK) { 506 if (fail_or_len < 0 && error != TOX_EWOULDBLOCK) {
503 LOGGER_ERROR(log, "Unexpected error reading from socket: %u, %s", errno, strerror(errno)); 507 const char *strerror = net_new_strerror(error);
508 LOGGER_ERROR(log, "Unexpected error reading from socket: %u, %s", error, strerror);
509 net_kill_strerror(strerror);
504 } 510 }
505 511
506 return -1; /* Nothing received. */ 512 return -1; /* Nothing received. */
@@ -681,7 +687,10 @@ Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint1
681 687
682 /* Check for socket error. */ 688 /* Check for socket error. */
683 if (!sock_valid(temp->sock)) { 689 if (!sock_valid(temp->sock)) {
684 LOGGER_ERROR(log, "Failed to get a socket?! %u, %s", errno, strerror(errno)); 690 int neterror = net_error();
691 const char *strerror = net_new_strerror(neterror);
692 LOGGER_ERROR(log, "Failed to get a socket?! %d, %s", neterror, strerror);
693 net_kill_strerror(strerror);
685 free(temp); 694 free(temp);
686 695
687 if (error) { 696 if (error) {
@@ -769,8 +778,11 @@ Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint1
769 mreq.ipv6mr_interface = 0; 778 mreq.ipv6mr_interface = 0;
770 int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq)); 779 int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq));
771 780
772 LOGGER_DEBUG(log, res < 0 ? "Failed to activate local multicast membership. (%u, %s)" : 781 int neterror = net_error();
773 "Local multicast group FF02::1 joined successfully", errno, strerror(errno)); 782 const char *strerror = net_new_strerror(neterror);
783 LOGGER_DEBUG(log, res < 0 ? "Failed to activate local multicast membership. (%d, %s)" :
784 "Local multicast group FF02::1 joined successfully", neterror, strerror);
785 net_kill_strerror(strerror);
774 } 786 }
775 787
776 /* a hanging program or a different user might block the standard port; 788 /* a hanging program or a different user might block the standard port;
@@ -827,9 +839,11 @@ Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint1
827 } 839 }
828 840
829 char ip_str[IP_NTOA_LEN]; 841 char ip_str[IP_NTOA_LEN];
830 LOGGER_ERROR(log, "Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno), 842 int neterror = net_error();
843 const char *strerror = net_new_strerror(neterror);
844 LOGGER_ERROR(log, "Failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u", neterror, strerror,
831 ip_ntoa(&ip, ip_str, sizeof(ip_str)), port_from, port_to); 845 ip_ntoa(&ip, ip_str, sizeof(ip_str)), port_from, port_to);
832 846 net_kill_strerror(strerror);
833 kill_networking(temp); 847 kill_networking(temp);
834 848
835 if (error) { 849 if (error) {
@@ -1520,3 +1534,38 @@ size_t net_unpack_u64(const uint8_t *bytes, uint64_t *v)
1520 *v = ((uint64_t)hi << 32) | lo; 1534 *v = ((uint64_t)hi << 32) | lo;
1521 return p - bytes; 1535 return p - bytes;
1522} 1536}
1537
1538int net_error(void)
1539{
1540#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
1541 return WSAGetLastError();
1542#else
1543 return errno;
1544#endif
1545}
1546
1547const char *net_new_strerror(int error)
1548{
1549#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
1550 char *str = nullptr;
1551 // Windows API is weird. The 5th function arg is of char* type, but we
1552 // have to pass char** so that it could assign new memory block to our
1553 // pointer, so we have to cast our char** to char* for the compilation
1554 // not to fail (otherwise it would fail to find a variant of this function
1555 // accepting char** as the 5th arg) and Windows inside casts it back
1556 // to char** to do the assignment. So no, this cast you see here, although
1557 // it looks weird, is not a mistake.
1558 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
1559 error, 0, (char *)&str, 0, nullptr);
1560 return str;
1561#else
1562 return strerror(error);
1563#endif
1564}
1565
1566void net_kill_strerror(const char *strerror)
1567{
1568#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
1569 LocalFree((char *)strerror);
1570#endif
1571}
diff --git a/toxcore/network.h b/toxcore/network.h
index 405721b2..10ddef02 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -404,6 +404,34 @@ void net_freeipport(IP_Port *ip_ports);
404 */ 404 */
405int bind_to_port(Socket sock, int family, uint16_t port); 405int bind_to_port(Socket sock, int family, uint16_t port);
406 406
407/* Get the last networking error code.
408 *
409 * Similar to Unix's errno, but cross-platform, as not all platforms use errno
410 * to indicate networking errors.
411 *
412 * Note that different platforms may return different codes for the same error,
413 * so you likely shouldn't be checking the value returned by this function
414 * unless you know what you are doing, you likely just want to use it in
415 * combination with net_new_strerror() to print the error.
416 *
417 * return platform-dependent network error code, if any.
418 */
419int net_error(void);
420
421/* Get a text explanation for the error code from net_error().
422 *
423 * return NULL on failure.
424 * return pointer to a NULL-terminated string describing the error code on
425 * success. The returned string must be freed using net_kill_strerror().
426 */
427const char *net_new_strerror(int error);
428
429/* Frees the string returned by net_new_strerror().
430 * It's valid to pass NULL as the argument, the function does nothing in this
431 * case.
432 */
433void net_kill_strerror(const char *strerror);
434
407/* Initialize networking. 435/* Initialize networking.
408 * bind to ip and port. 436 * bind to ip and port.
409 * ip must be in network order EX: 127.0.0.1 = (7F000001). 437 * ip must be in network order EX: 127.0.0.1 = (7F000001).