diff options
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/LAN_discovery.c | 75 | ||||
-rw-r--r-- | toxcore/Messenger.c | 9 | ||||
-rw-r--r-- | toxcore/TCP_client.c | 178 | ||||
-rw-r--r-- | toxcore/TCP_client.h | 5 | ||||
-rw-r--r-- | toxcore/TCP_server.c | 125 | ||||
-rw-r--r-- | toxcore/TCP_server.h | 10 | ||||
-rw-r--r-- | toxcore/group_chats.c | 11 | ||||
-rw-r--r-- | toxcore/net_crypto.c | 70 | ||||
-rw-r--r-- | toxcore/net_crypto.h | 4 | ||||
-rw-r--r-- | toxcore/network.c | 26 | ||||
-rw-r--r-- | toxcore/network.h | 15 | ||||
-rw-r--r-- | toxcore/onion_client.c | 2 | ||||
-rw-r--r-- | toxcore/ping_array.c | 2 | ||||
-rw-r--r-- | toxcore/tox.h | 14 |
14 files changed, 422 insertions, 124 deletions
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index e1b8534c..420c490d 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c | |||
@@ -30,11 +30,72 @@ | |||
30 | 30 | ||
31 | #define MAX_INTERFACES 16 | 31 | #define MAX_INTERFACES 16 |
32 | 32 | ||
33 | #ifdef __linux | ||
34 | 33 | ||
35 | static int broadcast_count = -1; | 34 | static int broadcast_count = -1; |
36 | static IP_Port broadcast_ip_port[MAX_INTERFACES]; | 35 | static IP_Port broadcast_ip_port[MAX_INTERFACES]; |
37 | 36 | ||
37 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | ||
38 | |||
39 | #include <iphlpapi.h> | ||
40 | |||
41 | static void fetch_broadcast_info(uint16_t port) | ||
42 | { | ||
43 | broadcast_count = 0; | ||
44 | |||
45 | IP_ADAPTER_INFO *pAdapterInfo = malloc(sizeof(pAdapterInfo)); | ||
46 | unsigned long ulOutBufLen = sizeof(pAdapterInfo); | ||
47 | |||
48 | if (pAdapterInfo == NULL) { | ||
49 | printf("Error allocating memory for pAdapterInfo\n"); | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { | ||
54 | free(pAdapterInfo); | ||
55 | pAdapterInfo = malloc(ulOutBufLen); | ||
56 | |||
57 | if (pAdapterInfo == NULL) { | ||
58 | printf("Error allocating memory needed to call GetAdaptersinfo\n"); | ||
59 | return; | ||
60 | } | ||
61 | } | ||
62 | |||
63 | int ret; | ||
64 | |||
65 | if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { | ||
66 | IP_ADAPTER_INFO *pAdapter = pAdapterInfo; | ||
67 | |||
68 | while (pAdapter) { | ||
69 | IP gateway = {0}, subnet_mask = {0}; | ||
70 | |||
71 | if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask) | ||
72 | && addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) { | ||
73 | if (gateway.family == AF_INET && subnet_mask.family == AF_INET) { | ||
74 | IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; | ||
75 | ip_port->ip.family = AF_INET; | ||
76 | uint32_t gateway_ip = ntohl(gateway.ip4.uint32), subnet_ip = ntohl(subnet_mask.ip4.uint32); | ||
77 | uint32_t broadcast_ip = gateway_ip + ~subnet_ip - 1; | ||
78 | ip_port->ip.ip4.uint32 = htonl(broadcast_ip); | ||
79 | ip_port->port = port; | ||
80 | broadcast_count++; | ||
81 | printf("broadcast ip: %s\n", ip_ntoa(&ip_port->ip)); | ||
82 | |||
83 | if (broadcast_count >= MAX_INTERFACES) { | ||
84 | return; | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | pAdapter = pAdapter->Next; | ||
90 | } | ||
91 | } else { | ||
92 | printf("Fetching adapter info failed %i\n", ret); | ||
93 | } | ||
94 | |||
95 | } | ||
96 | |||
97 | #elif defined(__linux__) | ||
98 | |||
38 | static void fetch_broadcast_info(uint16_t port) | 99 | static void fetch_broadcast_info(uint16_t port) |
39 | { | 100 | { |
40 | /* Not sure how many platforms this will run on, | 101 | /* Not sure how many platforms this will run on, |
@@ -93,6 +154,14 @@ static void fetch_broadcast_info(uint16_t port) | |||
93 | close(sock); | 154 | close(sock); |
94 | } | 155 | } |
95 | 156 | ||
157 | #else //TODO: Other platforms? | ||
158 | |||
159 | static void fetch_broadcast_info(uint16_t port) | ||
160 | { | ||
161 | broadcast_count = 0; | ||
162 | } | ||
163 | |||
164 | #endif | ||
96 | /* Send packet to all IPv4 broadcast addresses | 165 | /* Send packet to all IPv4 broadcast addresses |
97 | * | 166 | * |
98 | * return 1 if sent to at least one broadcast target. | 167 | * return 1 if sent to at least one broadcast target. |
@@ -115,7 +184,6 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, const uint8 | |||
115 | 184 | ||
116 | return 1; | 185 | return 1; |
117 | } | 186 | } |
118 | #endif /* __linux */ | ||
119 | 187 | ||
120 | /* Return the broadcast ip. */ | 188 | /* Return the broadcast ip. */ |
121 | static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast) | 189 | static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast) |
@@ -228,9 +296,8 @@ int send_LANdiscovery(uint16_t port, DHT *dht) | |||
228 | data[0] = NET_PACKET_LAN_DISCOVERY; | 296 | data[0] = NET_PACKET_LAN_DISCOVERY; |
229 | id_copy(data + 1, dht->self_public_key); | 297 | id_copy(data + 1, dht->self_public_key); |
230 | 298 | ||
231 | #ifdef __linux | ||
232 | send_broadcasts(dht->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); | 299 | send_broadcasts(dht->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); |
233 | #endif | 300 | |
234 | int res = -1; | 301 | int res = -1; |
235 | IP_Port ip_port; | 302 | IP_Port ip_port; |
236 | ip_port.port = port; | 303 | ip_port.port = port; |
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 4344fdcb..b65f09ae 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -1206,8 +1206,10 @@ int join_groupchat(Messenger *m, int32_t friendnumber, const uint8_t *friend_gro | |||
1206 | 1206 | ||
1207 | IP_Port friend_ip = get_friend_ipport(m, friendnumber); | 1207 | IP_Port friend_ip = get_friend_ipport(m, friendnumber); |
1208 | 1208 | ||
1209 | if (friend_ip.ip.family == 0) | 1209 | if (friend_ip.ip.family == 0) { |
1210 | del_groupchat(m, groupnum); | ||
1210 | return -1; | 1211 | return -1; |
1212 | } | ||
1211 | 1213 | ||
1212 | id_copy(data, friend_group_public_key); | 1214 | id_copy(data, friend_group_public_key); |
1213 | id_copy(data + crypto_box_PUBLICKEYBYTES, m->chats[groupnum]->self_public_key); | 1215 | id_copy(data + crypto_box_PUBLICKEYBYTES, m->chats[groupnum]->self_public_key); |
@@ -1218,6 +1220,7 @@ int join_groupchat(Messenger *m, int32_t friendnumber, const uint8_t *friend_gro | |||
1218 | return groupnum; | 1220 | return groupnum; |
1219 | } | 1221 | } |
1220 | 1222 | ||
1223 | del_groupchat(m, groupnum); | ||
1221 | return -1; | 1224 | return -1; |
1222 | } | 1225 | } |
1223 | 1226 | ||
@@ -2598,6 +2601,10 @@ static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length) | |||
2598 | 2601 | ||
2599 | if (temp.status >= 3) { | 2602 | if (temp.status >= 3) { |
2600 | int fnum = m_addfriend_norequest(m, temp.client_id); | 2603 | int fnum = m_addfriend_norequest(m, temp.client_id); |
2604 | |||
2605 | if (fnum < 0) | ||
2606 | continue; | ||
2607 | |||
2601 | setfriendname(m, fnum, temp.name, ntohs(temp.name_length)); | 2608 | setfriendname(m, fnum, temp.name, ntohs(temp.name_length)); |
2602 | set_friend_statusmessage(m, fnum, temp.statusmessage, ntohs(temp.statusmessage_length)); | 2609 | set_friend_statusmessage(m, fnum, temp.statusmessage, ntohs(temp.statusmessage_length)); |
2603 | set_friend_userstatus(m, fnum, temp.userstatus); | 2610 | set_friend_userstatus(m, fnum, temp.userstatus); |
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 087188f7..45220538 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c | |||
@@ -109,7 +109,7 @@ static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data | |||
109 | /* return 0 if pending data was sent completely | 109 | /* return 0 if pending data was sent completely |
110 | * return -1 if it wasn't | 110 | * return -1 if it wasn't |
111 | */ | 111 | */ |
112 | static int send_pending_data(TCP_Client_Connection *con) | 112 | static int send_pending_data_nonpriority(TCP_Client_Connection *con) |
113 | { | 113 | { |
114 | if (con->last_packet_length == 0) { | 114 | if (con->last_packet_length == 0) { |
115 | return 0; | 115 | return 0; |
@@ -127,24 +127,95 @@ static int send_pending_data(TCP_Client_Connection *con) | |||
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | if (len > left) | 130 | con->last_packet_sent += len; |
131 | return -1; | ||
132 | } | ||
133 | |||
134 | /* return 0 if pending data was sent completely | ||
135 | * return -1 if it wasn't | ||
136 | */ | ||
137 | static int send_pending_data(TCP_Client_Connection *con) | ||
138 | { | ||
139 | /* finish sending current non-priority packet */ | ||
140 | if (send_pending_data_nonpriority(con) == -1) { | ||
131 | return -1; | 141 | return -1; |
142 | } | ||
143 | |||
144 | TCP_Priority_List *p = con->priority_queue_start; | ||
145 | |||
146 | while (p) { | ||
147 | uint16_t left = p->size - p->sent; | ||
148 | int len = send(con->sock, p->data + p->sent, left, MSG_NOSIGNAL); | ||
149 | |||
150 | if (len != left) { | ||
151 | if (len > 0) { | ||
152 | p->sent += len; | ||
153 | } | ||
154 | |||
155 | break; | ||
156 | } | ||
157 | |||
158 | TCP_Priority_List *pp = p; | ||
159 | p = p->next; | ||
160 | free(pp); | ||
161 | } | ||
162 | |||
163 | con->priority_queue_start = p; | ||
164 | |||
165 | if (!p) { | ||
166 | con->priority_queue_end = NULL; | ||
167 | return 0; | ||
168 | } | ||
132 | 169 | ||
133 | con->last_packet_sent += len; | ||
134 | return -1; | 170 | return -1; |
135 | } | 171 | } |
136 | 172 | ||
173 | /* return 0 on failure (only if malloc fails) | ||
174 | * return 1 on success | ||
175 | */ | ||
176 | static _Bool add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) | ||
177 | { | ||
178 | TCP_Priority_List *p = con->priority_queue_end, *new; | ||
179 | new = malloc(sizeof(TCP_Priority_List) + size); | ||
180 | |||
181 | if (!new) { | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | new->next = NULL; | ||
186 | new->size = size; | ||
187 | new->sent = sent; | ||
188 | memcpy(new->data, packet, size); | ||
189 | |||
190 | if (p) { | ||
191 | p->next = new; | ||
192 | } else { | ||
193 | con->priority_queue_start = new; | ||
194 | } | ||
195 | |||
196 | con->priority_queue_end = new; | ||
197 | return 1; | ||
198 | } | ||
199 | |||
137 | /* return 1 on success. | 200 | /* return 1 on success. |
138 | * return 0 if could not send packet. | 201 | * return 0 if could not send packet. |
139 | * return -1 on failure (connection must be killed). | 202 | * return -1 on failure (connection must be killed). |
140 | */ | 203 | */ |
141 | static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length) | 204 | static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length, |
205 | _Bool priority) | ||
142 | { | 206 | { |
143 | if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) | 207 | if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) |
144 | return -1; | 208 | return -1; |
145 | 209 | ||
146 | if (send_pending_data(con) == -1) | 210 | _Bool sendpriority = 1; |
147 | return 0; | 211 | |
212 | if (send_pending_data(con) == -1) { | ||
213 | if (priority) { | ||
214 | sendpriority = 0; | ||
215 | } else { | ||
216 | return 0; | ||
217 | } | ||
218 | } | ||
148 | 219 | ||
149 | uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; | 220 | uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; |
150 | 221 | ||
@@ -155,17 +226,33 @@ static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const | |||
155 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) | 226 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) |
156 | return -1; | 227 | return -1; |
157 | 228 | ||
158 | increment_nonce(con->sent_nonce); | 229 | if (priority) { |
230 | len = sendpriority ? send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL) : 0; | ||
159 | 231 | ||
160 | len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); | 232 | if (len <= 0) { |
233 | len = 0; | ||
234 | } | ||
161 | 235 | ||
162 | if ((unsigned int)len == sizeof(packet)) | 236 | increment_nonce(con->sent_nonce); |
163 | return 1; | 237 | |
238 | if (len == sizeof(packet)) { | ||
239 | return 1; | ||
240 | } | ||
241 | |||
242 | return add_priority(con, packet, sizeof(packet), len); | ||
243 | } | ||
244 | |||
245 | len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); | ||
164 | 246 | ||
165 | if (len <= 0) | 247 | if (len <= 0) |
166 | return 0; | 248 | return 0; |
167 | 249 | ||
168 | memcpy(con->last_packet, packet, length); | 250 | increment_nonce(con->sent_nonce); |
251 | |||
252 | if ((unsigned int)len == sizeof(packet)) | ||
253 | return 1; | ||
254 | |||
255 | memcpy(con->last_packet, packet, sizeof(packet)); | ||
169 | con->last_packet_length = sizeof(packet); | 256 | con->last_packet_length = sizeof(packet); |
170 | con->last_packet_sent = len; | 257 | con->last_packet_sent = len; |
171 | return 1; | 258 | return 1; |
@@ -180,7 +267,7 @@ int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) | |||
180 | uint8_t packet[1 + crypto_box_PUBLICKEYBYTES]; | 267 | uint8_t packet[1 + crypto_box_PUBLICKEYBYTES]; |
181 | packet[0] = TCP_PACKET_ROUTING_REQUEST; | 268 | packet[0] = TCP_PACKET_ROUTING_REQUEST; |
182 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); | 269 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); |
183 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 270 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1); |
184 | } | 271 | } |
185 | 272 | ||
186 | void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, | 273 | void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, |
@@ -197,6 +284,9 @@ void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(v | |||
197 | con->status_callback_object = object; | 284 | con->status_callback_object = object; |
198 | } | 285 | } |
199 | 286 | ||
287 | static int send_ping_response(TCP_Client_Connection *con); | ||
288 | static int send_ping_request(TCP_Client_Connection *con); | ||
289 | |||
200 | /* return 1 on success. | 290 | /* return 1 on success. |
201 | * return 0 if could not send packet. | 291 | * return 0 if could not send packet. |
202 | * return -1 on failure. | 292 | * return -1 on failure. |
@@ -209,10 +299,13 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, u | |||
209 | if (con->connections[con_id].status != 2) | 299 | if (con->connections[con_id].status != 2) |
210 | return -1; | 300 | return -1; |
211 | 301 | ||
302 | if (send_ping_response(con) == 0 || send_ping_request(con) == 0) | ||
303 | return 0; | ||
304 | |||
212 | uint8_t packet[1 + length]; | 305 | uint8_t packet[1 + length]; |
213 | packet[0] = con_id + NUM_RESERVED_PORTS; | 306 | packet[0] = con_id + NUM_RESERVED_PORTS; |
214 | memcpy(packet + 1, data, length); | 307 | memcpy(packet + 1, data, length); |
215 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 308 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0); |
216 | } | 309 | } |
217 | 310 | ||
218 | /* return 1 on success. | 311 | /* return 1 on success. |
@@ -228,7 +321,7 @@ int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const | |||
228 | packet[0] = TCP_PACKET_OOB_SEND; | 321 | packet[0] = TCP_PACKET_OOB_SEND; |
229 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); | 322 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); |
230 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); | 323 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); |
231 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 324 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0); |
232 | } | 325 | } |
233 | 326 | ||
234 | 327 | ||
@@ -274,31 +367,49 @@ static int send_disconnect_notification(TCP_Client_Connection *con, uint8_t id) | |||
274 | uint8_t packet[1 + 1]; | 367 | uint8_t packet[1 + 1]; |
275 | packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; | 368 | packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; |
276 | packet[1] = id; | 369 | packet[1] = id; |
277 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 370 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1); |
278 | } | 371 | } |
279 | 372 | ||
280 | /* return 1 on success. | 373 | /* return 1 on success. |
281 | * return 0 if could not send packet. | 374 | * return 0 if could not send packet. |
282 | * return -1 on failure (connection must be killed). | 375 | * return -1 on failure (connection must be killed). |
283 | */ | 376 | */ |
284 | static int send_ping_request(TCP_Client_Connection *con, uint64_t ping_id) | 377 | static int send_ping_request(TCP_Client_Connection *con) |
285 | { | 378 | { |
379 | if (!con->ping_request_id) | ||
380 | return 1; | ||
381 | |||
286 | uint8_t packet[1 + sizeof(uint64_t)]; | 382 | uint8_t packet[1 + sizeof(uint64_t)]; |
287 | packet[0] = TCP_PACKET_PING; | 383 | packet[0] = TCP_PACKET_PING; |
288 | memcpy(packet + 1, &ping_id, sizeof(uint64_t)); | 384 | memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t)); |
289 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 385 | int ret; |
386 | |||
387 | if ((ret = write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1)) == 1) { | ||
388 | con->ping_request_id = 0; | ||
389 | } | ||
390 | |||
391 | return ret; | ||
290 | } | 392 | } |
291 | 393 | ||
292 | /* return 1 on success. | 394 | /* return 1 on success. |
293 | * return 0 if could not send packet. | 395 | * return 0 if could not send packet. |
294 | * return -1 on failure (connection must be killed). | 396 | * return -1 on failure (connection must be killed). |
295 | */ | 397 | */ |
296 | static int send_ping_response(TCP_Client_Connection *con, uint64_t ping_id) | 398 | static int send_ping_response(TCP_Client_Connection *con) |
297 | { | 399 | { |
400 | if (!con->ping_response_id) | ||
401 | return 1; | ||
402 | |||
298 | uint8_t packet[1 + sizeof(uint64_t)]; | 403 | uint8_t packet[1 + sizeof(uint64_t)]; |
299 | packet[0] = TCP_PACKET_PONG; | 404 | packet[0] = TCP_PACKET_PONG; |
300 | memcpy(packet + 1, &ping_id, sizeof(uint64_t)); | 405 | memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t)); |
301 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 406 | int ret; |
407 | |||
408 | if ((ret = write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1)) == 1) { | ||
409 | con->ping_response_id = 0; | ||
410 | } | ||
411 | |||
412 | return ret; | ||
302 | } | 413 | } |
303 | 414 | ||
304 | /* return 1 on success. | 415 | /* return 1 on success. |
@@ -324,7 +435,7 @@ int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t | |||
324 | uint8_t packet[1 + length]; | 435 | uint8_t packet[1 + length]; |
325 | packet[0] = TCP_PACKET_ONION_REQUEST; | 436 | packet[0] = TCP_PACKET_ONION_REQUEST; |
326 | memcpy(packet + 1, data, length); | 437 | memcpy(packet + 1, data, length); |
327 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 438 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0); |
328 | } | 439 | } |
329 | 440 | ||
330 | void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data, | 441 | void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data, |
@@ -427,7 +538,7 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u | |||
427 | uint8_t con_id = data[1] - NUM_RESERVED_PORTS; | 538 | uint8_t con_id = data[1] - NUM_RESERVED_PORTS; |
428 | 539 | ||
429 | if (conn->connections[con_id].status != 1) | 540 | if (conn->connections[con_id].status != 1) |
430 | return -1; | 541 | return 0; |
431 | 542 | ||
432 | conn->connections[con_id].status = 2; | 543 | conn->connections[con_id].status = 2; |
433 | 544 | ||
@@ -451,7 +562,7 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u | |||
451 | return 0; | 562 | return 0; |
452 | 563 | ||
453 | if (conn->connections[con_id].status != 2) | 564 | if (conn->connections[con_id].status != 2) |
454 | return -1; | 565 | return 0; |
455 | 566 | ||
456 | conn->connections[con_id].status = 1; | 567 | conn->connections[con_id].status = 1; |
457 | 568 | ||
@@ -468,7 +579,8 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u | |||
468 | 579 | ||
469 | uint64_t ping_id; | 580 | uint64_t ping_id; |
470 | memcpy(&ping_id, data + 1, sizeof(uint64_t)); | 581 | memcpy(&ping_id, data + 1, sizeof(uint64_t)); |
471 | send_ping_response(conn, ping_id); | 582 | conn->ping_response_id = ping_id; |
583 | send_ping_response(conn); | ||
472 | return 0; | 584 | return 0; |
473 | } | 585 | } |
474 | 586 | ||
@@ -523,6 +635,9 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u | |||
523 | static int do_confirmed_TCP(TCP_Client_Connection *conn) | 635 | static int do_confirmed_TCP(TCP_Client_Connection *conn) |
524 | { | 636 | { |
525 | send_pending_data(conn); | 637 | send_pending_data(conn); |
638 | send_ping_response(conn); | ||
639 | send_ping_request(conn); | ||
640 | |||
526 | uint8_t packet[MAX_PACKET_SIZE]; | 641 | uint8_t packet[MAX_PACKET_SIZE]; |
527 | int len; | 642 | int len; |
528 | 643 | ||
@@ -532,16 +647,9 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn) | |||
532 | if (!ping_id) | 647 | if (!ping_id) |
533 | ++ping_id; | 648 | ++ping_id; |
534 | 649 | ||
535 | int ret = send_ping_request(conn, ping_id); | 650 | conn->ping_request_id = conn->ping_id = ping_id; |
536 | 651 | send_ping_request(conn); | |
537 | if (ret == 1) { | 652 | conn->last_pinged = unix_time(); |
538 | conn->last_pinged = unix_time(); | ||
539 | conn->ping_id = ping_id; | ||
540 | } else { | ||
541 | if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { | ||
542 | conn->status = TCP_CLIENT_DISCONNECTED; | ||
543 | } | ||
544 | } | ||
545 | } | 653 | } |
546 | 654 | ||
547 | if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { | 655 | if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { |
diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index 2622b4f7..9998d20c 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h | |||
@@ -52,11 +52,16 @@ typedef struct { | |||
52 | uint16_t last_packet_length; | 52 | uint16_t last_packet_length; |
53 | uint16_t last_packet_sent; | 53 | uint16_t last_packet_sent; |
54 | 54 | ||
55 | TCP_Priority_List *priority_queue_start, *priority_queue_end; | ||
56 | |||
55 | uint64_t kill_at; | 57 | uint64_t kill_at; |
56 | 58 | ||
57 | uint64_t last_pinged; | 59 | uint64_t last_pinged; |
58 | uint64_t ping_id; | 60 | uint64_t ping_id; |
59 | 61 | ||
62 | uint64_t ping_response_id; | ||
63 | uint64_t ping_request_id; | ||
64 | |||
60 | void *net_crypto_pointer; | 65 | void *net_crypto_pointer; |
61 | uint32_t net_crypto_location; | 66 | uint32_t net_crypto_location; |
62 | struct { | 67 | struct { |
diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 7487ad4f..47e2ff27 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c | |||
@@ -288,7 +288,7 @@ int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, | |||
288 | /* return 0 if pending data was sent completely | 288 | /* return 0 if pending data was sent completely |
289 | * return -1 if it wasn't | 289 | * return -1 if it wasn't |
290 | */ | 290 | */ |
291 | static int send_pending_data(TCP_Secure_Connection *con) | 291 | static int send_pending_data_nonpriority(TCP_Secure_Connection *con) |
292 | { | 292 | { |
293 | if (con->last_packet_length == 0) { | 293 | if (con->last_packet_length == 0) { |
294 | return 0; | 294 | return 0; |
@@ -306,25 +306,96 @@ static int send_pending_data(TCP_Secure_Connection *con) | |||
306 | return 0; | 306 | return 0; |
307 | } | 307 | } |
308 | 308 | ||
309 | if (len > left) | 309 | con->last_packet_sent += len; |
310 | return -1; | ||
311 | |||
312 | } | ||
313 | |||
314 | /* return 0 if pending data was sent completely | ||
315 | * return -1 if it wasn't | ||
316 | */ | ||
317 | static int send_pending_data(TCP_Secure_Connection *con) | ||
318 | { | ||
319 | /* finish sending current non-priority packet */ | ||
320 | if (send_pending_data_nonpriority(con) == -1) { | ||
310 | return -1; | 321 | return -1; |
322 | } | ||
323 | |||
324 | TCP_Priority_List *p = con->priority_queue_start; | ||
325 | |||
326 | while (p) { | ||
327 | uint16_t left = p->size - p->sent; | ||
328 | int len = send(con->sock, p->data + p->sent, left, MSG_NOSIGNAL); | ||
329 | |||
330 | if (len != left) { | ||
331 | if (len > 0) { | ||
332 | p->sent += len; | ||
333 | } | ||
334 | |||
335 | break; | ||
336 | } | ||
337 | |||
338 | TCP_Priority_List *pp = p; | ||
339 | p = p->next; | ||
340 | free(pp); | ||
341 | } | ||
342 | |||
343 | con->priority_queue_start = p; | ||
344 | |||
345 | if (!p) { | ||
346 | con->priority_queue_end = NULL; | ||
347 | return 0; | ||
348 | } | ||
311 | 349 | ||
312 | con->last_packet_sent += len; | ||
313 | return -1; | 350 | return -1; |
351 | } | ||
352 | |||
353 | /* return 0 on failure (only if malloc fails) | ||
354 | * return 1 on success | ||
355 | */ | ||
356 | static _Bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) | ||
357 | { | ||
358 | TCP_Priority_List *p = con->priority_queue_end, *new; | ||
359 | new = malloc(sizeof(TCP_Priority_List) + size); | ||
314 | 360 | ||
361 | if (!new) { | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | new->next = NULL; | ||
366 | new->size = size; | ||
367 | new->sent = sent; | ||
368 | memcpy(new->data, packet, size); | ||
369 | |||
370 | if (p) { | ||
371 | p->next = new; | ||
372 | } else { | ||
373 | con->priority_queue_start = new; | ||
374 | } | ||
375 | |||
376 | con->priority_queue_end = new; | ||
377 | return 1; | ||
315 | } | 378 | } |
316 | 379 | ||
317 | /* return 1 on success. | 380 | /* return 1 on success. |
318 | * return 0 if could not send packet. | 381 | * return 0 if could not send packet. |
319 | * return -1 on failure (connection must be killed). | 382 | * return -1 on failure (connection must be killed). |
320 | */ | 383 | */ |
321 | static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length) | 384 | static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, |
385 | _Bool priority) | ||
322 | { | 386 | { |
323 | if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) | 387 | if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) |
324 | return -1; | 388 | return -1; |
325 | 389 | ||
326 | if (send_pending_data(con) == -1) | 390 | _Bool sendpriority = 1; |
327 | return 0; | 391 | |
392 | if (send_pending_data(con) == -1) { | ||
393 | if (priority) { | ||
394 | sendpriority = 0; | ||
395 | } else { | ||
396 | return 0; | ||
397 | } | ||
398 | } | ||
328 | 399 | ||
329 | uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; | 400 | uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; |
330 | 401 | ||
@@ -335,17 +406,33 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const | |||
335 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) | 406 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) |
336 | return -1; | 407 | return -1; |
337 | 408 | ||
338 | increment_nonce(con->sent_nonce); | 409 | if (priority) { |
410 | len = sendpriority ? send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL) : 0; | ||
339 | 411 | ||
340 | len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); | 412 | if (len <= 0) { |
413 | len = 0; | ||
414 | } | ||
341 | 415 | ||
342 | if ((unsigned int)len == sizeof(packet)) | 416 | increment_nonce(con->sent_nonce); |
343 | return 1; | 417 | |
418 | if (len == sizeof(packet)) { | ||
419 | return 1; | ||
420 | } | ||
421 | |||
422 | return add_priority(con, packet, sizeof(packet), len); | ||
423 | } | ||
424 | |||
425 | len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); | ||
344 | 426 | ||
345 | if (len <= 0) | 427 | if (len <= 0) |
346 | return 0; | 428 | return 0; |
347 | 429 | ||
348 | memcpy(con->last_packet, packet, length); | 430 | increment_nonce(con->sent_nonce); |
431 | |||
432 | if ((unsigned int)len == sizeof(packet)) | ||
433 | return 1; | ||
434 | |||
435 | memcpy(con->last_packet, packet, sizeof(packet)); | ||
349 | con->last_packet_length = sizeof(packet); | 436 | con->last_packet_length = sizeof(packet); |
350 | con->last_packet_sent = len; | 437 | con->last_packet_sent = len; |
351 | return 1; | 438 | return 1; |
@@ -459,7 +546,7 @@ static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const | |||
459 | data[1] = rpid; | 546 | data[1] = rpid; |
460 | memcpy(data + 2, public_key, crypto_box_PUBLICKEYBYTES); | 547 | memcpy(data + 2, public_key, crypto_box_PUBLICKEYBYTES); |
461 | 548 | ||
462 | return write_packet_TCP_secure_connection(con, data, sizeof(data)); | 549 | return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); |
463 | } | 550 | } |
464 | 551 | ||
465 | /* return 1 on success. | 552 | /* return 1 on success. |
@@ -469,7 +556,7 @@ static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const | |||
469 | static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) | 556 | static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) |
470 | { | 557 | { |
471 | uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, id + NUM_RESERVED_PORTS}; | 558 | uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, id + NUM_RESERVED_PORTS}; |
472 | return write_packet_TCP_secure_connection(con, data, sizeof(data)); | 559 | return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); |
473 | } | 560 | } |
474 | 561 | ||
475 | /* return 1 on success. | 562 | /* return 1 on success. |
@@ -479,7 +566,7 @@ static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) | |||
479 | static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id) | 566 | static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id) |
480 | { | 567 | { |
481 | uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, id + NUM_RESERVED_PORTS}; | 568 | uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, id + NUM_RESERVED_PORTS}; |
482 | return write_packet_TCP_secure_connection(con, data, sizeof(data)); | 569 | return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); |
483 | } | 570 | } |
484 | 571 | ||
485 | /* return 0 on success. | 572 | /* return 0 on success. |
@@ -579,7 +666,7 @@ static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, const ui | |||
579 | memcpy(resp_packet + 1, con->public_key, crypto_box_PUBLICKEYBYTES); | 666 | memcpy(resp_packet + 1, con->public_key, crypto_box_PUBLICKEYBYTES); |
580 | memcpy(resp_packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); | 667 | memcpy(resp_packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); |
581 | write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet, | 668 | write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet, |
582 | sizeof(resp_packet)); | 669 | sizeof(resp_packet), 0); |
583 | } | 670 | } |
584 | 671 | ||
585 | return 0; | 672 | return 0; |
@@ -637,7 +724,7 @@ static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, | |||
637 | memcpy(packet + 1, data, length); | 724 | memcpy(packet + 1, data, length); |
638 | packet[0] = TCP_PACKET_ONION_RESPONSE; | 725 | packet[0] = TCP_PACKET_ONION_RESPONSE; |
639 | 726 | ||
640 | if (write_packet_TCP_secure_connection(con, packet, sizeof(packet)) != 1) | 727 | if (write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0) != 1) |
641 | return 1; | 728 | return 1; |
642 | 729 | ||
643 | return 0; | 730 | return 0; |
@@ -682,7 +769,7 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint | |||
682 | uint8_t response[1 + sizeof(uint64_t)]; | 769 | uint8_t response[1 + sizeof(uint64_t)]; |
683 | response[0] = TCP_PACKET_PONG; | 770 | response[0] = TCP_PACKET_PONG; |
684 | memcpy(response + 1, data + 1, sizeof(uint64_t)); | 771 | memcpy(response + 1, data + 1, sizeof(uint64_t)); |
685 | write_packet_TCP_secure_connection(con, response, sizeof(response)); | 772 | write_packet_TCP_secure_connection(con, response, sizeof(response), 1); |
686 | return 0; | 773 | return 0; |
687 | } | 774 | } |
688 | 775 | ||
@@ -752,7 +839,7 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint | |||
752 | uint8_t new_data[length]; | 839 | uint8_t new_data[length]; |
753 | memcpy(new_data, data, length); | 840 | memcpy(new_data, data, length); |
754 | new_data[0] = other_c_id; | 841 | new_data[0] = other_c_id; |
755 | int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length); | 842 | int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length, 0); |
756 | 843 | ||
757 | if (ret == -1) | 844 | if (ret == -1) |
758 | return -1; | 845 | return -1; |
@@ -1058,7 +1145,7 @@ static void do_TCP_confirmed(TCP_Server *TCP_server) | |||
1058 | ++ping_id; | 1145 | ++ping_id; |
1059 | 1146 | ||
1060 | memcpy(ping + 1, &ping_id, sizeof(uint64_t)); | 1147 | memcpy(ping + 1, &ping_id, sizeof(uint64_t)); |
1061 | int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping)); | 1148 | int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1); |
1062 | 1149 | ||
1063 | if (ret == 1) { | 1150 | if (ret == 1) { |
1064 | conn->last_pinged = unix_time(); | 1151 | conn->last_pinged = unix_time(); |
diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index def0a978..81507acb 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h | |||
@@ -80,6 +80,14 @@ enum { | |||
80 | TCP_STATUS_CONFIRMED, | 80 | TCP_STATUS_CONFIRMED, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | typedef struct TCP_Priority_List TCP_Priority_List; | ||
84 | |||
85 | struct TCP_Priority_List { | ||
86 | TCP_Priority_List *next; | ||
87 | uint16_t size, sent; | ||
88 | uint8_t data[0]; | ||
89 | }; | ||
90 | |||
83 | typedef struct TCP_Secure_Connection { | 91 | typedef struct TCP_Secure_Connection { |
84 | uint8_t status; | 92 | uint8_t status; |
85 | sock_t sock; | 93 | sock_t sock; |
@@ -98,6 +106,8 @@ typedef struct TCP_Secure_Connection { | |||
98 | uint16_t last_packet_length; | 106 | uint16_t last_packet_length; |
99 | uint16_t last_packet_sent; | 107 | uint16_t last_packet_sent; |
100 | 108 | ||
109 | TCP_Priority_List *priority_queue_start, *priority_queue_end; | ||
110 | |||
101 | uint64_t identifier; | 111 | uint64_t identifier; |
102 | 112 | ||
103 | uint64_t last_pinged; | 113 | uint64_t last_pinged; |
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index 1f76878b..77fa6acd 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c | |||
@@ -471,16 +471,6 @@ static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, const | |||
471 | 471 | ||
472 | int ok = add_closepeer(chat, chat->group[peernum].client_id, source); | 472 | int ok = add_closepeer(chat, chat->group[peernum].client_id, source); |
473 | 473 | ||
474 | if (chat->assoc) { | ||
475 | ippts_send.ip_port = chat->group[peernum].ping_via; | ||
476 | ippts_send.timestamp = chat->group[peernum].last_pinged; | ||
477 | |||
478 | IP_Port ipp_recv; | ||
479 | ipp_recv = source; | ||
480 | |||
481 | Assoc_add_entry(chat->assoc, contents.nodes[i].client_id, &ippts_send, &ipp_recv, ok == 0 ? 1 : 0); | ||
482 | } | ||
483 | |||
484 | return 0; | 474 | return 0; |
485 | } | 475 | } |
486 | 476 | ||
@@ -830,6 +820,7 @@ void do_groupchat(Group_Chat *chat) | |||
830 | void kill_groupchat(Group_Chat *chat) | 820 | void kill_groupchat(Group_Chat *chat) |
831 | { | 821 | { |
832 | send_data(chat, 0, 0, GROUP_CHAT_QUIT); | 822 | send_data(chat, 0, 0, GROUP_CHAT_QUIT); |
823 | kill_Assoc(chat->assoc); | ||
833 | free(chat->group); | 824 | free(chat->group); |
834 | free(chat); | 825 | free(chat); |
835 | } | 826 | } |
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index e0319f34..ac2359ee 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c | |||
@@ -37,21 +37,6 @@ static uint8_t crypt_connection_id_not_valid(const Net_Crypto *c, int crypt_conn | |||
37 | return (uint32_t)crypt_connection_id >= c->crypto_connections_length; | 37 | return (uint32_t)crypt_connection_id >= c->crypto_connections_length; |
38 | } | 38 | } |
39 | 39 | ||
40 | /* return 0 if connection is dead. | ||
41 | * return 1 if connection is alive. | ||
42 | */ | ||
43 | static int is_alive(uint8_t status) | ||
44 | { | ||
45 | if (status == CRYPTO_CONN_COOKIE_REQUESTING || | ||
46 | status == CRYPTO_CONN_HANDSHAKE_SENT || | ||
47 | status == CRYPTO_CONN_NOT_CONFIRMED || | ||
48 | status == CRYPTO_CONN_ESTABLISHED) { | ||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | /* cookie timeout in seconds */ | 40 | /* cookie timeout in seconds */ |
56 | #define COOKIE_TIMEOUT 10 | 41 | #define COOKIE_TIMEOUT 10 |
57 | #define COOKIE_DATA_LENGTH (crypto_box_PUBLICKEYBYTES * 2) | 42 | #define COOKIE_DATA_LENGTH (crypto_box_PUBLICKEYBYTES * 2) |
@@ -426,19 +411,22 @@ static int send_packet_to(const Net_Crypto *c, int crypt_connection_id, const ui | |||
426 | 411 | ||
427 | } | 412 | } |
428 | 413 | ||
429 | //TODO: spread packets over many relays, detect and kill bad relays. | 414 | //TODO: detect and kill bad relays. |
430 | uint32_t i; | 415 | uint32_t i; |
431 | 416 | ||
417 | unsigned int r = rand(); | ||
418 | |||
432 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | 419 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { |
433 | if (conn->status_tcp[i] == STATUS_TCP_ONLINE) {/* friend is connected to this relay. */ | 420 | if (conn->status_tcp[(i + r) % MAX_TCP_CONNECTIONS] == STATUS_TCP_ONLINE) {/* friend is connected to this relay. */ |
434 | if (send_data(c->tcp_connections[i], conn->con_number_tcp[i], data, length) == 1) | 421 | if (send_data(c->tcp_connections[(i + r) % MAX_TCP_CONNECTIONS], conn->con_number_tcp[(i + r) % MAX_TCP_CONNECTIONS], |
422 | data, length) == 1) | ||
435 | return 0; | 423 | return 0; |
436 | } | 424 | } |
437 | } | 425 | } |
438 | 426 | ||
439 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | 427 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { |
440 | if (conn->status_tcp[i] == STATUS_TCP_INVISIBLE) { | 428 | if (conn->status_tcp[(i + r) % MAX_TCP_CONNECTIONS] == STATUS_TCP_INVISIBLE) { |
441 | if (send_oob_packet(c->tcp_connections[i], conn->dht_public_key, data, length) == 1) | 429 | if (send_oob_packet(c->tcp_connections[(i + r) % MAX_TCP_CONNECTIONS], conn->dht_public_key, data, length) == 1) |
442 | return 0; | 430 | return 0; |
443 | } | 431 | } |
444 | } | 432 | } |
@@ -1106,6 +1094,14 @@ static int handle_data_packet_helper(const Net_Crypto *c, int crypt_connection_i | |||
1106 | return -1; | 1094 | return -1; |
1107 | } | 1095 | } |
1108 | 1096 | ||
1097 | if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) { | ||
1098 | clear_temp_packet(c, crypt_connection_id); | ||
1099 | conn->status = CRYPTO_CONN_ESTABLISHED; | ||
1100 | |||
1101 | if (conn->connection_status_callback) | ||
1102 | conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1); | ||
1103 | } | ||
1104 | |||
1109 | if (real_data[0] == PACKET_ID_REQUEST) { | 1105 | if (real_data[0] == PACKET_ID_REQUEST) { |
1110 | int requested = handle_request_packet(&conn->send_array, real_data, real_length); | 1106 | int requested = handle_request_packet(&conn->send_array, real_data, real_length); |
1111 | 1107 | ||
@@ -1148,14 +1144,6 @@ static int handle_data_packet_helper(const Net_Crypto *c, int crypt_connection_i | |||
1148 | return -1; | 1144 | return -1; |
1149 | } | 1145 | } |
1150 | 1146 | ||
1151 | if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) { | ||
1152 | if (conn->connection_status_callback) | ||
1153 | conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1); | ||
1154 | |||
1155 | clear_temp_packet(c, crypt_connection_id); | ||
1156 | conn->status = CRYPTO_CONN_ESTABLISHED; | ||
1157 | } | ||
1158 | |||
1159 | return 0; | 1147 | return 0; |
1160 | } | 1148 | } |
1161 | 1149 | ||
@@ -1485,6 +1473,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) | |||
1485 | /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ | 1473 | /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ |
1486 | set_connection_dht_public_key(c, crypt_connection_id, n_c->dht_public_key, current_time_monotonic()); | 1474 | set_connection_dht_public_key(c, crypt_connection_id, n_c->dht_public_key, current_time_monotonic()); |
1487 | conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; | 1475 | conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; |
1476 | conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH; | ||
1488 | crypto_connection_add_source(c, crypt_connection_id, n_c->source); | 1477 | crypto_connection_add_source(c, crypt_connection_id, n_c->source); |
1489 | return crypt_connection_id; | 1478 | return crypt_connection_id; |
1490 | } | 1479 | } |
@@ -1517,6 +1506,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key) | |||
1517 | crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); | 1506 | crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); |
1518 | conn->status = CRYPTO_CONN_COOKIE_REQUESTING; | 1507 | conn->status = CRYPTO_CONN_COOKIE_REQUESTING; |
1519 | conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; | 1508 | conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; |
1509 | conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH; | ||
1520 | return crypt_connection_id; | 1510 | return crypt_connection_id; |
1521 | } | 1511 | } |
1522 | 1512 | ||
@@ -2250,6 +2240,15 @@ static void send_crypto_packets(Net_Crypto *c) | |||
2250 | notes: needs improvement but seems to work fine for packet loss <1% | 2240 | notes: needs improvement but seems to work fine for packet loss <1% |
2251 | */ | 2241 | */ |
2252 | 2242 | ||
2243 | /* additional step: adjust the send rate based on the size change of the send queue */ | ||
2244 | uint32_t queue_size = num_packets_array(&conn->send_array); | ||
2245 | |||
2246 | if (queue_size > conn->packet_send_rate && queue_size > conn->last_queue_size) { | ||
2247 | conn->rate_increase = 0; | ||
2248 | conn->packets_resent = conn->packets_sent; | ||
2249 | } | ||
2250 | |||
2251 | |||
2253 | //hack to prevent 1 packet lost from affecting calculations at low send rates | 2252 | //hack to prevent 1 packet lost from affecting calculations at low send rates |
2254 | if (conn->packets_resent == 1) { | 2253 | if (conn->packets_resent == 1) { |
2255 | conn->packets_resent = 0; | 2254 | conn->packets_resent = 0; |
@@ -2300,18 +2299,27 @@ static void send_crypto_packets(Net_Crypto *c) | |||
2300 | double linear_increase = realrate * 0.0025 + 1.0; | 2299 | double linear_increase = realrate * 0.0025 + 1.0; |
2301 | 2300 | ||
2302 | //final send rate: average of "real" and previous send rates + increases | 2301 | //final send rate: average of "real" and previous send rates + increases |
2303 | conn->packet_send_rate = (realrate + conn->packet_send_rate) / 2.0 + conn->rate_increase + linear_increase; | 2302 | double newrate = (realrate + conn->packet_send_rate) / 2.0 + conn->rate_increase + linear_increase; |
2303 | conn->last_send_rate = conn->packet_send_rate; | ||
2304 | conn->packet_send_rate = newrate; | ||
2304 | 2305 | ||
2305 | 2306 | ||
2306 | conn->dropped = dropped; | 2307 | conn->dropped = dropped; |
2307 | conn->drop_ignore = drop_ignore_new; | 2308 | conn->drop_ignore = drop_ignore_new; |
2308 | conn->packets_resent = 0; | 2309 | conn->packets_resent = 0; |
2310 | conn->last_queue_size = queue_size; | ||
2309 | 2311 | ||
2310 | if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE || !conn->sending) { | 2312 | if (!conn->sending || !conn->packets_sent) { |
2311 | conn->rate_increase = 0; | 2313 | conn->rate_increase = 0; |
2314 | conn->packet_send_rate /= 2; | ||
2315 | } | ||
2316 | |||
2317 | if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE) { | ||
2312 | conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; | 2318 | conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; |
2313 | } | 2319 | } |
2314 | 2320 | ||
2321 | conn->packets_sent = 0; | ||
2322 | |||
2315 | if (conn->sending != 0 && num_packets_array(&conn->send_array) < CRYPTO_MIN_QUEUE_LENGTH / 2) { | 2323 | if (conn->sending != 0 && num_packets_array(&conn->send_array) < CRYPTO_MIN_QUEUE_LENGTH / 2) { |
2316 | --conn->sending; | 2324 | --conn->sending; |
2317 | } | 2325 | } |
@@ -2342,6 +2350,7 @@ static void send_crypto_packets(Net_Crypto *c) | |||
2342 | 2350 | ||
2343 | conn->packets_resent += ret; | 2351 | conn->packets_resent += ret; |
2344 | conn->packets_left -= ret; | 2352 | conn->packets_left -= ret; |
2353 | conn->packets_sent += ret; | ||
2345 | } | 2354 | } |
2346 | 2355 | ||
2347 | if (conn->packet_send_rate > CRYPTO_PACKET_MIN_RATE * 1.5) { | 2356 | if (conn->packet_send_rate > CRYPTO_PACKET_MIN_RATE * 1.5) { |
@@ -2421,6 +2430,7 @@ int64_t write_cryptpacket(const Net_Crypto *c, int crypt_connection_id, const ui | |||
2421 | return -1; | 2430 | return -1; |
2422 | 2431 | ||
2423 | --conn->packets_left; | 2432 | --conn->packets_left; |
2433 | conn->packets_sent++; | ||
2424 | conn->sending = CONN_SENDING_VALUE; | 2434 | conn->sending = CONN_SENDING_VALUE; |
2425 | return ret; | 2435 | return ret; |
2426 | } | 2436 | } |
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 4fed0000..2bc9a716 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h | |||
@@ -143,9 +143,9 @@ typedef struct { | |||
143 | uint32_t packets_left; | 143 | uint32_t packets_left; |
144 | uint64_t last_packets_left_set; | 144 | uint64_t last_packets_left_set; |
145 | 145 | ||
146 | double dropped, drop_ignore, rate_increase; | 146 | double dropped, drop_ignore, rate_increase, last_send_rate; |
147 | uint64_t drop_ignore_start, rate_increase_stop_start; | 147 | uint64_t drop_ignore_start, rate_increase_stop_start; |
148 | uint32_t packets_resent; | 148 | uint32_t packets_resent, last_queue_size, packets_sent, last_packets_sent; |
149 | 149 | ||
150 | uint8_t sending; /* indicates if data is being sent or not. */ | 150 | uint8_t sending; /* indicates if data is being sent or not. */ |
151 | 151 | ||
diff --git a/toxcore/network.c b/toxcore/network.c index 0009a558..373fef9e 100644 --- a/toxcore/network.c +++ b/toxcore/network.c | |||
@@ -671,7 +671,7 @@ int ip_equal(const IP *a, const IP *b) | |||
671 | } | 671 | } |
672 | 672 | ||
673 | return 0; | 673 | return 0; |
674 | }; | 674 | } |
675 | 675 | ||
676 | /* ipport_equal | 676 | /* ipport_equal |
677 | * compares two IPAny_Port structures | 677 | * compares two IPAny_Port structures |
@@ -688,7 +688,7 @@ int ipport_equal(const IP_Port *a, const IP_Port *b) | |||
688 | return 0; | 688 | return 0; |
689 | 689 | ||
690 | return ip_equal(&a->ip, &b->ip); | 690 | return ip_equal(&a->ip, &b->ip); |
691 | }; | 691 | } |
692 | 692 | ||
693 | /* nulls out ip */ | 693 | /* nulls out ip */ |
694 | void ip_reset(IP *ip) | 694 | void ip_reset(IP *ip) |
@@ -697,7 +697,7 @@ void ip_reset(IP *ip) | |||
697 | return; | 697 | return; |
698 | 698 | ||
699 | memset(ip, 0, sizeof(IP)); | 699 | memset(ip, 0, sizeof(IP)); |
700 | }; | 700 | } |
701 | 701 | ||
702 | /* nulls out ip, sets family according to flag */ | 702 | /* nulls out ip, sets family according to flag */ |
703 | void ip_init(IP *ip, uint8_t ipv6enabled) | 703 | void ip_init(IP *ip, uint8_t ipv6enabled) |
@@ -707,7 +707,7 @@ void ip_init(IP *ip, uint8_t ipv6enabled) | |||
707 | 707 | ||
708 | memset(ip, 0, sizeof(IP)); | 708 | memset(ip, 0, sizeof(IP)); |
709 | ip->family = ipv6enabled ? AF_INET6 : AF_INET; | 709 | ip->family = ipv6enabled ? AF_INET6 : AF_INET; |
710 | }; | 710 | } |
711 | 711 | ||
712 | /* checks if ip is valid */ | 712 | /* checks if ip is valid */ |
713 | int ip_isset(const IP *ip) | 713 | int ip_isset(const IP *ip) |
@@ -716,7 +716,7 @@ int ip_isset(const IP *ip) | |||
716 | return 0; | 716 | return 0; |
717 | 717 | ||
718 | return (ip->family != 0); | 718 | return (ip->family != 0); |
719 | }; | 719 | } |
720 | 720 | ||
721 | /* checks if ip is valid */ | 721 | /* checks if ip is valid */ |
722 | int ipport_isset(const IP_Port *ipport) | 722 | int ipport_isset(const IP_Port *ipport) |
@@ -728,7 +728,7 @@ int ipport_isset(const IP_Port *ipport) | |||
728 | return 0; | 728 | return 0; |
729 | 729 | ||
730 | return ip_isset(&ipport->ip); | 730 | return ip_isset(&ipport->ip); |
731 | }; | 731 | } |
732 | 732 | ||
733 | /* copies an ip structure (careful about direction!) */ | 733 | /* copies an ip structure (careful about direction!) */ |
734 | void ip_copy(IP *target, const IP *source) | 734 | void ip_copy(IP *target, const IP *source) |
@@ -737,7 +737,7 @@ void ip_copy(IP *target, const IP *source) | |||
737 | return; | 737 | return; |
738 | 738 | ||
739 | memcpy(target, source, sizeof(IP)); | 739 | memcpy(target, source, sizeof(IP)); |
740 | }; | 740 | } |
741 | 741 | ||
742 | /* copies an ip_port structure (careful about direction!) */ | 742 | /* copies an ip_port structure (careful about direction!) */ |
743 | void ipport_copy(IP_Port *target, const IP_Port *source) | 743 | void ipport_copy(IP_Port *target, const IP_Port *source) |
@@ -805,7 +805,7 @@ const char *ip_ntoa(const IP *ip) | |||
805 | /* brute force protection against lacking termination */ | 805 | /* brute force protection against lacking termination */ |
806 | addresstext[sizeof(addresstext) - 1] = 0; | 806 | addresstext[sizeof(addresstext) - 1] = 0; |
807 | return addresstext; | 807 | return addresstext; |
808 | }; | 808 | } |
809 | 809 | ||
810 | /* | 810 | /* |
811 | * addr_parse_ip | 811 | * addr_parse_ip |
@@ -820,7 +820,6 @@ const char *ip_ntoa(const IP *ip) | |||
820 | * | 820 | * |
821 | * returns 1 on success, 0 on failure | 821 | * returns 1 on success, 0 on failure |
822 | */ | 822 | */ |
823 | |||
824 | int addr_parse_ip(const char *address, IP *to) | 823 | int addr_parse_ip(const char *address, IP *to) |
825 | { | 824 | { |
826 | if (!address || !to) | 825 | if (!address || !to) |
@@ -832,7 +831,7 @@ int addr_parse_ip(const char *address, IP *to) | |||
832 | to->family = AF_INET; | 831 | to->family = AF_INET; |
833 | to->ip4.in_addr = addr4; | 832 | to->ip4.in_addr = addr4; |
834 | return 1; | 833 | return 1; |
835 | }; | 834 | } |
836 | 835 | ||
837 | struct in6_addr addr6; | 836 | struct in6_addr addr6; |
838 | 837 | ||
@@ -840,10 +839,10 @@ int addr_parse_ip(const char *address, IP *to) | |||
840 | to->family = AF_INET6; | 839 | to->family = AF_INET6; |
841 | to->ip6.in6_addr = addr6; | 840 | to->ip6.in6_addr = addr6; |
842 | return 1; | 841 | return 1; |
843 | }; | 842 | } |
844 | 843 | ||
845 | return 0; | 844 | return 0; |
846 | }; | 845 | } |
847 | 846 | ||
848 | /* | 847 | /* |
849 | * addr_resolve(): | 848 | * addr_resolve(): |
@@ -862,7 +861,6 @@ int addr_parse_ip(const char *address, IP *to) | |||
862 | * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6 | 861 | * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6 |
863 | * returns 0 on failure | 862 | * returns 0 on failure |
864 | */ | 863 | */ |
865 | |||
866 | int addr_resolve(const char *address, IP *to, IP *extra) | 864 | int addr_resolve(const char *address, IP *to, IP *extra) |
867 | { | 865 | { |
868 | if (!address || !to) | 866 | if (!address || !to) |
@@ -970,4 +968,4 @@ int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra) | |||
970 | return 0; | 968 | return 0; |
971 | 969 | ||
972 | return 1; | 970 | return 1; |
973 | }; | 971 | } |
diff --git a/toxcore/network.h b/toxcore/network.h index 359d26c8..b902a487 100644 --- a/toxcore/network.h +++ b/toxcore/network.h | |||
@@ -191,6 +191,21 @@ IP_Port; | |||
191 | */ | 191 | */ |
192 | const char *ip_ntoa(const IP *ip); | 192 | const char *ip_ntoa(const IP *ip); |
193 | 193 | ||
194 | /* | ||
195 | * addr_parse_ip | ||
196 | * directly parses the input into an IP structure | ||
197 | * tries IPv4 first, then IPv6 | ||
198 | * | ||
199 | * input | ||
200 | * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6) | ||
201 | * | ||
202 | * output | ||
203 | * IP: family and the value is set on success | ||
204 | * | ||
205 | * returns 1 on success, 0 on failure | ||
206 | */ | ||
207 | int addr_parse_ip(const char *address, IP *to); | ||
208 | |||
194 | /* ip_equal | 209 | /* ip_equal |
195 | * compares two IPAny structures | 210 | * compares two IPAny structures |
196 | * unset means unequal | 211 | * unset means unequal |
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 7d0efc79..42982ea8 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c | |||
@@ -831,7 +831,7 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) | |||
831 | uint32_t i; | 831 | uint32_t i; |
832 | 832 | ||
833 | for (i = onion_c->num_friends; i != 0; --i) { | 833 | for (i = onion_c->num_friends; i != 0; --i) { |
834 | if (onion_c->friends_list[i].status != 0) | 834 | if (onion_c->friends_list[i - 1].status != 0) |
835 | break; | 835 | break; |
836 | } | 836 | } |
837 | 837 | ||
diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c index 5c92527e..93dade05 100644 --- a/toxcore/ping_array.c +++ b/toxcore/ping_array.c | |||
@@ -135,7 +135,7 @@ int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout) | |||
135 | if (size == 0 || timeout == 0 || empty_array == NULL) | 135 | if (size == 0 || timeout == 0 || empty_array == NULL) |
136 | return -1; | 136 | return -1; |
137 | 137 | ||
138 | empty_array->entries = calloc(size * sizeof(Ping_Array_Entry), 1); | 138 | empty_array->entries = calloc(size, sizeof(Ping_Array_Entry)); |
139 | 139 | ||
140 | if (empty_array->entries == NULL) | 140 | if (empty_array->entries == NULL) |
141 | return -1; | 141 | return -1; |
diff --git a/toxcore/tox.h b/toxcore/tox.h index 5418b03e..14426f31 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h | |||
@@ -90,7 +90,7 @@ void tox_get_address(const Tox *tox, uint8_t *address); | |||
90 | * data is the data and length is the length. | 90 | * data is the data and length is the length. |
91 | * | 91 | * |
92 | * return the friend number if success. | 92 | * return the friend number if success. |
93 | * return TOX_FA_TOOLONG if message length is too long. | 93 | * return TOX_FAERR_TOOLONG if message length is too long. |
94 | * return TOX_FAERR_NOMESSAGE if no message (message length must be >= 1 byte). | 94 | * return TOX_FAERR_NOMESSAGE if no message (message length must be >= 1 byte). |
95 | * return TOX_FAERR_OWNKEY if user's own key. | 95 | * return TOX_FAERR_OWNKEY if user's own key. |
96 | * return TOX_FAERR_ALREADYSENT if friend request already sent or already a friend. | 96 | * return TOX_FAERR_ALREADYSENT if friend request already sent or already a friend. |
@@ -294,13 +294,13 @@ void tox_callback_friend_request(Tox *tox, void (*function)(Tox *tox, const uint | |||
294 | void *), void *userdata); | 294 | void *), void *userdata); |
295 | 295 | ||
296 | /* Set the function that will be executed when a message from a friend is received. | 296 | /* Set the function that will be executed when a message from a friend is received. |
297 | * Function format is: function(Tox *tox, int32_t friendnumber, uint8_t * message, uint32_t length, void *userdata) | 297 | * Function format is: function(Tox *tox, int32_t friendnumber, uint8_t * message, uint16_t length, void *userdata) |
298 | */ | 298 | */ |
299 | void tox_callback_friend_message(Tox *tox, void (*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), | 299 | void tox_callback_friend_message(Tox *tox, void (*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), |
300 | void *userdata); | 300 | void *userdata); |
301 | 301 | ||
302 | /* Set the function that will be executed when an action from a friend is received. | 302 | /* Set the function that will be executed when an action from a friend is received. |
303 | * Function format is: function(Tox *tox, int32_t friendnumber, uint8_t * action, uint32_t length, void *userdata) | 303 | * Function format is: function(Tox *tox, int32_t friendnumber, uint8_t * action, uint16_t length, void *userdata) |
304 | */ | 304 | */ |
305 | void tox_callback_friend_action(Tox *tox, void (*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), | 305 | void tox_callback_friend_action(Tox *tox, void (*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), |
306 | void *userdata); | 306 | void *userdata); |
@@ -495,20 +495,20 @@ uint32_t tox_get_chatlist(const Tox *tox, int *out_list, uint32_t list_size); | |||
495 | * tox_file_data_remaining(...) can be used to know how many bytes are left to send/receive. | 495 | * tox_file_data_remaining(...) can be used to know how many bytes are left to send/receive. |
496 | * | 496 | * |
497 | * If the connection breaks during file sending (The other person goes offline without pausing the sending and then comes back) | 497 | * If the connection breaks during file sending (The other person goes offline without pausing the sending and then comes back) |
498 | * the receiver must send a control packet with receive_send == 0 message_id = TOX_FILECONTROL_RESUME_BROKEN and the data being | 498 | * the receiver must send a control packet with send_receive == 1 message_id = TOX_FILECONTROL_RESUME_BROKEN and the data being |
499 | * a uint64_t (in host byte order) containing the number of bytes received. | 499 | * a uint64_t (in host byte order) containing the number of bytes received. |
500 | * | 500 | * |
501 | * If the sender receives this packet, he must send a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT | 501 | * If the sender receives this packet, he must send a control packet with send_receive == 0 and control_type == TOX_FILECONTROL_ACCEPT |
502 | * then he must start sending file data from the position (data , uint64_t in host byte order) received in the TOX_FILECONTROL_RESUME_BROKEN packet. | 502 | * then he must start sending file data from the position (data , uint64_t in host byte order) received in the TOX_FILECONTROL_RESUME_BROKEN packet. |
503 | * | 503 | * |
504 | * To pause a file transfer send a control packet with control_type == TOX_FILECONTROL_PAUSE. | 504 | * To pause a file transfer send a control packet with control_type == TOX_FILECONTROL_PAUSE. |
505 | * To unpause a file transfer send a control packet with control_type == TOX_FILECONTROL_ACCEPT. | 505 | * To unpause a file transfer send a control packet with control_type == TOX_FILECONTROL_ACCEPT. |
506 | * | 506 | * |
507 | * If you receive a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_PAUSE, you must stop sending filenumber until the other | 507 | * If you receive a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_PAUSE, you must stop sending filenumber until the other |
508 | * person sends a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT with the filenumber being a paused filenumber. | 508 | * person sends a control packet with send_receive == 0 and control_type == TOX_FILECONTROL_ACCEPT with the filenumber being a paused filenumber. |
509 | * | 509 | * |
510 | * If you receive a control packet with receive_send == 0 and control_type == TOX_FILECONTROL_PAUSE, it means the sender of filenumber has paused the | 510 | * If you receive a control packet with receive_send == 0 and control_type == TOX_FILECONTROL_PAUSE, it means the sender of filenumber has paused the |
511 | * transfer and will resume it later with a control packet with receive_send == 0 and control_type == TOX_FILECONTROL_ACCEPT for that file number. | 511 | * transfer and will resume it later with a control packet with send_receive == 1 and control_type == TOX_FILECONTROL_ACCEPT for that file number. |
512 | * | 512 | * |
513 | * More to come... | 513 | * More to come... |
514 | */ | 514 | */ |