diff options
-rw-r--r-- | toxav/bwcontroller.c | 4 | ||||
-rw-r--r-- | toxav/bwcontroller.h | 4 | ||||
-rw-r--r-- | toxav/toxav.c | 2 | ||||
-rw-r--r-- | toxcore/net_crypto.c | 174 | ||||
-rw-r--r-- | toxcore/net_crypto.h | 8 |
5 files changed, 142 insertions, 50 deletions
diff --git a/toxav/bwcontroller.c b/toxav/bwcontroller.c index 503627c1..1725e193 100644 --- a/toxav/bwcontroller.c +++ b/toxav/bwcontroller.c | |||
@@ -63,8 +63,8 @@ int bwc_handle_data(Messenger *m, uint32_t friendnumber, const uint8_t *data, ui | |||
63 | void send_update(BWController *bwc); | 63 | void send_update(BWController *bwc); |
64 | 64 | ||
65 | BWController *bwc_new(Messenger *m, uint32_t friendnumber, | 65 | BWController *bwc_new(Messenger *m, uint32_t friendnumber, |
66 | void (*mcb) (BWController *, uint32_t, float, void *), | 66 | void (*mcb) (BWController *, uint32_t, float, void *), |
67 | void *udata) | 67 | void *udata) |
68 | { | 68 | { |
69 | BWController *retu = calloc(sizeof(struct BWController_s), 1); | 69 | BWController *retu = calloc(sizeof(struct BWController_s), 1); |
70 | 70 | ||
diff --git a/toxav/bwcontroller.h b/toxav/bwcontroller.h index 48472dff..5e7ae9df 100644 --- a/toxav/bwcontroller.h +++ b/toxav/bwcontroller.h | |||
@@ -26,8 +26,8 @@ | |||
26 | typedef struct BWController_s BWController; | 26 | typedef struct BWController_s BWController; |
27 | 27 | ||
28 | BWController *bwc_new(Messenger *m, uint32_t friendnumber, | 28 | BWController *bwc_new(Messenger *m, uint32_t friendnumber, |
29 | void (*mcb) (BWController *, uint32_t, float, void *), | 29 | void (*mcb) (BWController *, uint32_t, float, void *), |
30 | void *udata); | 30 | void *udata); |
31 | void bwc_kill(BWController *bwc); | 31 | void bwc_kill(BWController *bwc); |
32 | 32 | ||
33 | void bwc_feed_avg(BWController *bwc, uint32_t bytes); | 33 | void bwc_feed_avg(BWController *bwc, uint32_t bytes); |
diff --git a/toxav/toxav.c b/toxav/toxav.c index a3aadcfa..3d4004cf 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -513,7 +513,7 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
513 | goto END; | 513 | goto END; |
514 | } | 514 | } |
515 | 515 | ||
516 | rtp_allow_receiving(call->audio.first); | 516 | rtp_allow_receiving(call->video.first); |
517 | } else { | 517 | } else { |
518 | rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; | 518 | rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; |
519 | goto END; | 519 | goto END; |
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 4d76e659..b4640c61 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c | |||
@@ -384,6 +384,78 @@ static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_c | |||
384 | } | 384 | } |
385 | 385 | ||
386 | 386 | ||
387 | /* Associate an ip_port to a connection. | ||
388 | * | ||
389 | * return -1 on failure. | ||
390 | * return 0 on success. | ||
391 | */ | ||
392 | static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) | ||
393 | { | ||
394 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
395 | |||
396 | if (conn == 0) | ||
397 | return -1; | ||
398 | |||
399 | if (ip_port.ip.family == AF_INET) { | ||
400 | if (!ipport_equal(&ip_port, &conn->ip_portv4) && LAN_ip(conn->ip_portv4.ip) != 0) { | ||
401 | if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) | ||
402 | return -1; | ||
403 | |||
404 | bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id); | ||
405 | conn->ip_portv4 = ip_port; | ||
406 | return 0; | ||
407 | } | ||
408 | } else if (ip_port.ip.family == AF_INET6) { | ||
409 | if (!ipport_equal(&ip_port, &conn->ip_portv6)) { | ||
410 | if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) | ||
411 | return -1; | ||
412 | |||
413 | bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id); | ||
414 | conn->ip_portv6 = ip_port; | ||
415 | return 0; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | return -1; | ||
420 | } | ||
421 | |||
422 | /* Return the IP_Port that should be used to send packets to the other peer. | ||
423 | * | ||
424 | * return IP_Port with family 0 on failure. | ||
425 | * return IP_Port on success. | ||
426 | */ | ||
427 | IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id) | ||
428 | { | ||
429 | IP_Port empty; | ||
430 | empty.ip.family = 0; | ||
431 | |||
432 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
433 | |||
434 | if (conn == 0) | ||
435 | return empty; | ||
436 | |||
437 | uint64_t current_time = unix_time(); | ||
438 | _Bool v6 = 0, v4 = 0; | ||
439 | |||
440 | if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) { | ||
441 | v4 = 1; | ||
442 | } | ||
443 | |||
444 | if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) { | ||
445 | v6 = 1; | ||
446 | } | ||
447 | |||
448 | if (v4 && LAN_ip(conn->ip_portv4.ip) == 0) { | ||
449 | return conn->ip_portv4; | ||
450 | } else if (v6 && conn->ip_portv6.ip.family == AF_INET6) { | ||
451 | return conn->ip_portv6; | ||
452 | } else if (conn->ip_portv4.ip.family == AF_INET) { | ||
453 | return conn->ip_portv4; | ||
454 | } else { | ||
455 | return empty; | ||
456 | } | ||
457 | } | ||
458 | |||
387 | /* Sends a packet to the peer using the fastest route. | 459 | /* Sends a packet to the peer using the fastest route. |
388 | * | 460 | * |
389 | * return -1 on failure. | 461 | * return -1 on failure. |
@@ -400,14 +472,15 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t | |||
400 | int direct_send_attempt = 0; | 472 | int direct_send_attempt = 0; |
401 | 473 | ||
402 | pthread_mutex_lock(&conn->mutex); | 474 | pthread_mutex_lock(&conn->mutex); |
475 | IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id); | ||
403 | 476 | ||
404 | //TODO: on bad networks, direct connections might not last indefinitely. | 477 | //TODO: on bad networks, direct connections might not last indefinitely. |
405 | if (conn->ip_port.ip.family != 0) { | 478 | if (ip_port.ip.family != 0) { |
406 | _Bool direct_connected = 0; | 479 | _Bool direct_connected = 0; |
407 | crypto_connection_status(c, crypt_connection_id, &direct_connected, NULL); | 480 | crypto_connection_status(c, crypt_connection_id, &direct_connected, NULL); |
408 | 481 | ||
409 | if (direct_connected) { | 482 | if (direct_connected) { |
410 | if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) { | 483 | if ((uint32_t)sendpacket(c->dht->net, ip_port, data, length) == length) { |
411 | pthread_mutex_unlock(&conn->mutex); | 484 | pthread_mutex_unlock(&conn->mutex); |
412 | return 0; | 485 | return 0; |
413 | } else { | 486 | } else { |
@@ -418,7 +491,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t | |||
418 | 491 | ||
419 | //TODO: a better way of sending packets directly to confirm the others ip. | 492 | //TODO: a better way of sending packets directly to confirm the others ip. |
420 | if (length < 96 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { | 493 | if (length < 96 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { |
421 | if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) | 494 | if ((uint32_t)sendpacket(c->dht->net, ip_port, data, length) == length) |
422 | direct_send_attempt = 1; | 495 | direct_send_attempt = 1; |
423 | } | 496 | } |
424 | } | 497 | } |
@@ -1474,15 +1547,15 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, | |||
1474 | return -1; | 1547 | return -1; |
1475 | 1548 | ||
1476 | if (source.ip.family == AF_INET || source.ip.family == AF_INET6) { | 1549 | if (source.ip.family == AF_INET || source.ip.family == AF_INET6) { |
1477 | if (!ipport_equal(&source, &conn->ip_port)) { | 1550 | if (add_ip_port_connection(c, crypt_connection_id, source) != 0) |
1478 | if (!bs_list_add(&c->ip_port_list, (uint8_t *)&source, crypt_connection_id)) | 1551 | return -1; |
1479 | return -1; | ||
1480 | 1552 | ||
1481 | bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_port, crypt_connection_id); | 1553 | if (source.ip.family == AF_INET) { |
1482 | conn->ip_port = source; | 1554 | conn->direct_lastrecv_timev4 = unix_time(); |
1555 | } else { | ||
1556 | conn->direct_lastrecv_timev6 = unix_time(); | ||
1483 | } | 1557 | } |
1484 | 1558 | ||
1485 | conn->direct_lastrecv_time = unix_time(); | ||
1486 | return 0; | 1559 | return 0; |
1487 | } else if (source.ip.family == TCP_FAMILY) { | 1560 | } else if (source.ip.family == TCP_FAMILY) { |
1488 | if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, source.ip.ip6.uint32[0]) == 0) | 1561 | if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, source.ip.ip6.uint32[0]) == 0) |
@@ -1684,32 +1757,22 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, | |||
1684 | if (conn == 0) | 1757 | if (conn == 0) |
1685 | return -1; | 1758 | return -1; |
1686 | 1759 | ||
1687 | if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) | 1760 | if (add_ip_port_connection(c, crypt_connection_id, ip_port) == 0) { |
1688 | return -1; | 1761 | if (connected) { |
1689 | 1762 | if (ip_port.ip.family == AF_INET) { | |
1690 | if (!ipport_equal(&ip_port, &conn->ip_port)) { | 1763 | conn->direct_lastrecv_timev4 = unix_time(); |
1691 | if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_time) > unix_time()) { | ||
1692 | /* We already know a LAN ip, no need to switch. */ | ||
1693 | if (LAN_ip(conn->ip_port.ip) == 0) | ||
1694 | return -1; | ||
1695 | |||
1696 | /* Prefer ipv6. */ | ||
1697 | if (conn->ip_port.ip.family == AF_INET6 && ip_port.ip.family == AF_INET) | ||
1698 | return -1; | ||
1699 | } | ||
1700 | |||
1701 | if (bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) { | ||
1702 | bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_port, crypt_connection_id); | ||
1703 | conn->ip_port = ip_port; | ||
1704 | |||
1705 | if (connected) { | ||
1706 | conn->direct_lastrecv_time = unix_time(); | ||
1707 | } else { | 1764 | } else { |
1708 | conn->direct_lastrecv_time = 0; | 1765 | conn->direct_lastrecv_timev6 = unix_time(); |
1766 | } | ||
1767 | } else { | ||
1768 | if (ip_port.ip.family == AF_INET) { | ||
1769 | conn->direct_lastrecv_timev4 = 0; | ||
1770 | } else { | ||
1771 | conn->direct_lastrecv_timev6 = 0; | ||
1709 | } | 1772 | } |
1710 | |||
1711 | return 0; | ||
1712 | } | 1773 | } |
1774 | |||
1775 | return 0; | ||
1713 | } | 1776 | } |
1714 | 1777 | ||
1715 | return -1; | 1778 | return -1; |
@@ -2019,7 +2082,13 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet | |||
2019 | return -1; | 2082 | return -1; |
2020 | 2083 | ||
2021 | pthread_mutex_lock(&conn->mutex); | 2084 | pthread_mutex_lock(&conn->mutex); |
2022 | conn->direct_lastrecv_time = unix_time(); | 2085 | |
2086 | if (source.ip.family == AF_INET) { | ||
2087 | conn->direct_lastrecv_timev4 = unix_time(); | ||
2088 | } else { | ||
2089 | conn->direct_lastrecv_timev6 = unix_time(); | ||
2090 | } | ||
2091 | |||
2023 | pthread_mutex_unlock(&conn->mutex); | 2092 | pthread_mutex_unlock(&conn->mutex); |
2024 | return 0; | 2093 | return 0; |
2025 | } | 2094 | } |
@@ -2033,12 +2102,15 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet | |||
2033 | */ | 2102 | */ |
2034 | #define REQUEST_PACKETS_COMPARE_CONSTANT (0.125 * 100.0) | 2103 | #define REQUEST_PACKETS_COMPARE_CONSTANT (0.125 * 100.0) |
2035 | 2104 | ||
2036 | /* Multiplier for maximum allowed resends. */ | ||
2037 | #define PACKET_RESEND_MULTIPLIER 3.5 | ||
2038 | |||
2039 | /* Timeout for increasing speed after congestion event (in ms). */ | 2105 | /* Timeout for increasing speed after congestion event (in ms). */ |
2040 | #define CONGESTION_EVENT_TIMEOUT 1000 | 2106 | #define CONGESTION_EVENT_TIMEOUT 1000 |
2041 | 2107 | ||
2108 | /* If the send queue is SEND_QUEUE_RATIO times larger than the | ||
2109 | * calculated link speed the packet send speed will be reduced | ||
2110 | * by a value depending on this number. | ||
2111 | */ | ||
2112 | #define SEND_QUEUE_RATIO 2.0 | ||
2113 | |||
2042 | static void send_crypto_packets(Net_Crypto *c) | 2114 | static void send_crypto_packets(Net_Crypto *c) |
2043 | { | 2115 | { |
2044 | uint32_t i; | 2116 | uint32_t i; |
@@ -2057,7 +2129,7 @@ static void send_crypto_packets(Net_Crypto *c) | |||
2057 | } | 2129 | } |
2058 | 2130 | ||
2059 | if ((conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) | 2131 | if ((conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) |
2060 | && ((CRYPTO_SEND_PACKET_INTERVAL / 4) + conn->last_request_packet_sent) < temp_time) { | 2132 | && ((CRYPTO_SEND_PACKET_INTERVAL) + conn->last_request_packet_sent) < temp_time) { |
2061 | if (send_request_packet(c, i) == 0) { | 2133 | if (send_request_packet(c, i) == 0) { |
2062 | conn->last_request_packet_sent = temp_time; | 2134 | conn->last_request_packet_sent = temp_time; |
2063 | } | 2135 | } |
@@ -2069,6 +2141,18 @@ static void send_crypto_packets(Net_Crypto *c) | |||
2069 | double request_packet_interval = (REQUEST_PACKETS_COMPARE_CONSTANT / (((double)num_packets_array( | 2141 | double request_packet_interval = (REQUEST_PACKETS_COMPARE_CONSTANT / (((double)num_packets_array( |
2070 | &conn->recv_array) + 1.0) / (conn->packet_recv_rate + 1.0))); | 2142 | &conn->recv_array) + 1.0) / (conn->packet_recv_rate + 1.0))); |
2071 | 2143 | ||
2144 | double request_packet_interval2 = ((CRYPTO_PACKET_MIN_RATE / conn->packet_recv_rate) * | ||
2145 | (double)CRYPTO_SEND_PACKET_INTERVAL) + (double)PACKET_COUNTER_AVERAGE_INTERVAL; | ||
2146 | |||
2147 | if (request_packet_interval2 < request_packet_interval) | ||
2148 | request_packet_interval = request_packet_interval2; | ||
2149 | |||
2150 | if (request_packet_interval < PACKET_COUNTER_AVERAGE_INTERVAL) | ||
2151 | request_packet_interval = PACKET_COUNTER_AVERAGE_INTERVAL; | ||
2152 | |||
2153 | if (request_packet_interval > CRYPTO_SEND_PACKET_INTERVAL) | ||
2154 | request_packet_interval = CRYPTO_SEND_PACKET_INTERVAL; | ||
2155 | |||
2072 | if (temp_time - conn->last_request_packet_sent > (uint64_t)request_packet_interval) { | 2156 | if (temp_time - conn->last_request_packet_sent > (uint64_t)request_packet_interval) { |
2073 | if (send_request_packet(c, i) == 0) { | 2157 | if (send_request_packet(c, i) == 0) { |
2074 | conn->last_request_packet_sent = temp_time; | 2158 | conn->last_request_packet_sent = temp_time; |
@@ -2130,8 +2214,8 @@ static void send_crypto_packets(Net_Crypto *c) | |||
2130 | double send_array_ratio = (((double)npackets) / min_speed); | 2214 | double send_array_ratio = (((double)npackets) / min_speed); |
2131 | 2215 | ||
2132 | //TODO: Improve formula? | 2216 | //TODO: Improve formula? |
2133 | if (send_array_ratio > 2.0 && CRYPTO_MIN_QUEUE_LENGTH * 3 < npackets) { | 2217 | if (send_array_ratio > SEND_QUEUE_RATIO && CRYPTO_MIN_QUEUE_LENGTH < npackets) { |
2134 | conn->packet_send_rate = min_speed * (1.0 / (send_array_ratio / 2.0)); | 2218 | conn->packet_send_rate = min_speed * (1.0 / (send_array_ratio / SEND_QUEUE_RATIO)); |
2135 | } else if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) { | 2219 | } else if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) { |
2136 | conn->packet_send_rate = min_speed * 1.2; | 2220 | conn->packet_send_rate = min_speed * 1.2; |
2137 | } else { | 2221 | } else { |
@@ -2163,7 +2247,7 @@ static void send_crypto_packets(Net_Crypto *c) | |||
2163 | conn->last_packets_left_set = temp_time - adj; | 2247 | conn->last_packets_left_set = temp_time - adj; |
2164 | } | 2248 | } |
2165 | 2249 | ||
2166 | int ret = send_requested_packets(c, i, conn->packets_left * PACKET_RESEND_MULTIPLIER); | 2250 | int ret = send_requested_packets(c, i, conn->packets_left); |
2167 | 2251 | ||
2168 | if (ret != -1) { | 2252 | if (ret != -1) { |
2169 | if ((unsigned int)ret < conn->packets_left) { | 2253 | if ((unsigned int)ret < conn->packets_left) { |
@@ -2364,7 +2448,8 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id) | |||
2364 | kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); | 2448 | kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); |
2365 | pthread_mutex_unlock(&c->tcp_mutex); | 2449 | pthread_mutex_unlock(&c->tcp_mutex); |
2366 | 2450 | ||
2367 | bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_port, crypt_connection_id); | 2451 | bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id); |
2452 | bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id); | ||
2368 | clear_temp_packet(c, crypt_connection_id); | 2453 | clear_temp_packet(c, crypt_connection_id); |
2369 | clear_buffer(&conn->send_array); | 2454 | clear_buffer(&conn->send_array); |
2370 | clear_buffer(&conn->recv_array); | 2455 | clear_buffer(&conn->recv_array); |
@@ -2392,7 +2477,12 @@ unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_ | |||
2392 | if (direct_connected) { | 2477 | if (direct_connected) { |
2393 | *direct_connected = 0; | 2478 | *direct_connected = 0; |
2394 | 2479 | ||
2395 | if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_time) > unix_time()) | 2480 | uint64_t current_time = unix_time(); |
2481 | |||
2482 | if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) | ||
2483 | *direct_connected = 1; | ||
2484 | |||
2485 | if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) | ||
2396 | *direct_connected = 1; | 2486 | *direct_connected = 1; |
2397 | } | 2487 | } |
2398 | 2488 | ||
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index e5484e1e..cfeeaca5 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h | |||
@@ -39,7 +39,7 @@ | |||
39 | #define CRYPTO_PACKET_BUFFER_SIZE 16384 /* Must be a power of 2 */ | 39 | #define CRYPTO_PACKET_BUFFER_SIZE 16384 /* Must be a power of 2 */ |
40 | 40 | ||
41 | /* Minimum packet rate per second. */ | 41 | /* Minimum packet rate per second. */ |
42 | #define CRYPTO_PACKET_MIN_RATE 8.0 | 42 | #define CRYPTO_PACKET_MIN_RATE 4.0 |
43 | 43 | ||
44 | /* Minimum packet queue max length. */ | 44 | /* Minimum packet queue max length. */ |
45 | #define CRYPTO_MIN_QUEUE_LENGTH 64 | 45 | #define CRYPTO_MIN_QUEUE_LENGTH 64 |
@@ -119,8 +119,10 @@ typedef struct { | |||
119 | uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ | 119 | uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ |
120 | uint32_t temp_packet_num_sent; | 120 | uint32_t temp_packet_num_sent; |
121 | 121 | ||
122 | IP_Port ip_port; /* The ip and port to contact this guy directly.*/ | 122 | IP_Port ip_portv4; /* The ip and port to contact this guy directly.*/ |
123 | uint64_t direct_lastrecv_time; /* The Time at which we last received a direct packet in ms. */ | 123 | IP_Port ip_portv6; |
124 | uint64_t direct_lastrecv_timev4; /* The Time at which we last received a direct packet in ms. */ | ||
125 | uint64_t direct_lastrecv_timev6; | ||
124 | 126 | ||
125 | Packets_Array send_array; | 127 | Packets_Array send_array; |
126 | Packets_Array recv_array; | 128 | Packets_Array recv_array; |