diff options
Diffstat (limited to 'toxcore/net_crypto.c')
-rw-r--r-- | toxcore/net_crypto.c | 375 |
1 files changed, 372 insertions, 3 deletions
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 41efc1b1..56ff1bdd 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c | |||
@@ -210,6 +210,28 @@ static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *pack | |||
210 | return 0; | 210 | return 0; |
211 | } | 211 | } |
212 | 212 | ||
213 | /* Handle the cookie request packet (for TCP) | ||
214 | */ | ||
215 | static int tcp_handle_cookie_request(Net_Crypto *c, TCP_Client_Connection *TCP_con, uint8_t conn_id, uint8_t *packet, | ||
216 | uint32_t length) | ||
217 | { | ||
218 | uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; | ||
219 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | ||
220 | |||
221 | if (handle_cookie_request(c, request_plain, shared_key, packet, length) != 0) | ||
222 | return -1; | ||
223 | |||
224 | uint8_t data[COOKIE_RESPONSE_LENGTH]; | ||
225 | |||
226 | if (create_cookie_response(c, data, request_plain, shared_key) != sizeof(data)) | ||
227 | return -1; | ||
228 | |||
229 | if ((uint32_t)send_data(TCP_con, conn_id, data, sizeof(data)) != 1) | ||
230 | return -1; | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
213 | /* Handle a cookie response packet of length encrypted with shared_key. | 235 | /* Handle a cookie response packet of length encrypted with shared_key. |
214 | * put the cookie in the response in cookie | 236 | * put the cookie in the response in cookie |
215 | * | 237 | * |
@@ -352,10 +374,23 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, | |||
352 | if (conn == 0) | 374 | if (conn == 0) |
353 | return -1; | 375 | return -1; |
354 | 376 | ||
355 | if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) != length) | 377 | //TODO: on bad networks, direct connections might not last indefinitely. |
356 | return -1; | 378 | if (conn->ip_port.ip.family != 0) { |
379 | if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) | ||
380 | return 0; | ||
381 | } | ||
357 | 382 | ||
358 | return 0; | 383 | //TODO: spread packets over many relays, detect and kill bad relays. |
384 | uint32_t i; | ||
385 | |||
386 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
387 | if (conn->status_tcp[i] == 2) {/* friend is connected to this relay. */ | ||
388 | if (send_data(c->tcp_connections[i], conn->con_number_tcp[i], data, length) == 1) | ||
389 | return 0; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | return -1; | ||
359 | } | 394 | } |
360 | 395 | ||
361 | /** START: Array Related functions **/ | 396 | /** START: Array Related functions **/ |
@@ -1187,6 +1222,24 @@ static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) | |||
1187 | return -1; | 1222 | return -1; |
1188 | } | 1223 | } |
1189 | 1224 | ||
1225 | /* Get crypto connection id from public key of peer. | ||
1226 | * | ||
1227 | * return -1 if there are no connections like we are looking for. | ||
1228 | * return id if it found it. | ||
1229 | */ | ||
1230 | static int getcryptconnection_id_dht_pubkey(Net_Crypto *c, uint8_t *dht_public_key) | ||
1231 | { | ||
1232 | uint32_t i; | ||
1233 | |||
1234 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
1235 | if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION && c->crypto_connections[i].dht_public_key_set) | ||
1236 | if (memcmp(dht_public_key, c->crypto_connections[i].dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
1237 | return i; | ||
1238 | } | ||
1239 | |||
1240 | return -1; | ||
1241 | } | ||
1242 | |||
1190 | /* Add a source to the crypto connection. | 1243 | /* Add a source to the crypto connection. |
1191 | * This is to be used only when we have recieved a packet from that source. | 1244 | * This is to be used only when we have recieved a packet from that source. |
1192 | * | 1245 | * |
@@ -1346,6 +1399,56 @@ int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key) | |||
1346 | return crypt_connection_id; | 1399 | return crypt_connection_id; |
1347 | } | 1400 | } |
1348 | 1401 | ||
1402 | /* Disconnect peer from all associated TCP connections. | ||
1403 | * | ||
1404 | * return -1 on failure. | ||
1405 | * return 0 on success. | ||
1406 | */ | ||
1407 | static int disconnect_peer_tcp(Net_Crypto *c, int crypt_connection_id) | ||
1408 | { | ||
1409 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1410 | |||
1411 | if (conn == 0) | ||
1412 | return -1; | ||
1413 | |||
1414 | uint32_t i; | ||
1415 | |||
1416 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1417 | if (conn->status_tcp[i]) { | ||
1418 | send_disconnect_request(c->tcp_connections[i], conn->con_number_tcp[i]); | ||
1419 | conn->status_tcp[i] = 0; | ||
1420 | conn->con_number_tcp[i] = 0; | ||
1421 | } | ||
1422 | } | ||
1423 | |||
1424 | return 0; | ||
1425 | } | ||
1426 | |||
1427 | /* Connect peer to all associated TCP connections. | ||
1428 | * | ||
1429 | * return -1 on failure. | ||
1430 | * return 0 on success. | ||
1431 | */ | ||
1432 | static int connect_peer_tcp(Net_Crypto *c, int crypt_connection_id) | ||
1433 | { | ||
1434 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1435 | |||
1436 | if (conn == 0) | ||
1437 | return -1; | ||
1438 | |||
1439 | uint32_t i; | ||
1440 | |||
1441 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1442 | if (c->tcp_connections[i] == NULL) | ||
1443 | continue; | ||
1444 | |||
1445 | //TODO check function return? | ||
1446 | send_routing_request(c->tcp_connections[i], conn->dht_public_key); | ||
1447 | } | ||
1448 | |||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1349 | /* Set the DHT public key of the crypto connection. | 1452 | /* Set the DHT public key of the crypto connection. |
1350 | * | 1453 | * |
1351 | * return -1 on failure. | 1454 | * return -1 on failure. |
@@ -1361,6 +1464,10 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t | |||
1361 | if (conn->dht_public_key_set == 1 && memcmp(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) | 1464 | if (conn->dht_public_key_set == 1 && memcmp(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) |
1362 | return -1; | 1465 | return -1; |
1363 | 1466 | ||
1467 | if (conn->dht_public_key_set == 1) { | ||
1468 | disconnect_peer_tcp(c, crypt_connection_id); | ||
1469 | } | ||
1470 | |||
1364 | memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); | 1471 | memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); |
1365 | conn->dht_public_key_set = 1; | 1472 | conn->dht_public_key_set = 1; |
1366 | 1473 | ||
@@ -1376,6 +1483,7 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t | |||
1376 | return -1; | 1483 | return -1; |
1377 | }//TODO | 1484 | }//TODO |
1378 | 1485 | ||
1486 | connect_peer_tcp(c, crypt_connection_id); | ||
1379 | return 0; | 1487 | return 0; |
1380 | } | 1488 | } |
1381 | 1489 | ||
@@ -1399,6 +1507,264 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) | |||
1399 | return 0; | 1507 | return 0; |
1400 | } | 1508 | } |
1401 | 1509 | ||
1510 | static int tcp_response_callback(void *object, uint8_t connection_id, uint8_t *public_key) | ||
1511 | { | ||
1512 | TCP_Client_Connection *TCP_con = object; | ||
1513 | Net_Crypto *c = TCP_con->net_crypto_pointer; | ||
1514 | |||
1515 | int crypt_connection_id = getcryptconnection_id_dht_pubkey(c, public_key); | ||
1516 | |||
1517 | if (crypt_connection_id == -1) | ||
1518 | return -1; | ||
1519 | |||
1520 | set_tcp_connection_number(TCP_con, connection_id, crypt_connection_id); | ||
1521 | |||
1522 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1523 | |||
1524 | if (conn == 0) | ||
1525 | return -1; | ||
1526 | |||
1527 | uint32_t location = TCP_con->net_crypto_location; | ||
1528 | |||
1529 | if (location >= MAX_TCP_CONNECTIONS) | ||
1530 | return -1; | ||
1531 | |||
1532 | if (c->tcp_connections[location] != TCP_con) | ||
1533 | return -1; | ||
1534 | |||
1535 | conn->status_tcp[location] = 1; | ||
1536 | conn->con_number_tcp[location] = connection_id; | ||
1537 | return 0; | ||
1538 | } | ||
1539 | |||
1540 | static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status) | ||
1541 | { | ||
1542 | TCP_Client_Connection *TCP_con = object; | ||
1543 | Net_Crypto *c = TCP_con->net_crypto_pointer; | ||
1544 | |||
1545 | Crypto_Connection *conn = get_crypto_connection(c, number); | ||
1546 | |||
1547 | if (conn == 0) | ||
1548 | return -1; | ||
1549 | |||
1550 | uint32_t location = TCP_con->net_crypto_location; | ||
1551 | |||
1552 | if (location >= MAX_TCP_CONNECTIONS) | ||
1553 | return -1; | ||
1554 | |||
1555 | if (c->tcp_connections[location] != TCP_con) | ||
1556 | return -1; | ||
1557 | |||
1558 | conn->status_tcp[location] = status; | ||
1559 | conn->con_number_tcp[location] = connection_id; | ||
1560 | return 0; | ||
1561 | } | ||
1562 | |||
1563 | static int tcp_data_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length) | ||
1564 | { | ||
1565 | if (length == 0) | ||
1566 | return -1; | ||
1567 | |||
1568 | TCP_Client_Connection *TCP_con = object; | ||
1569 | Net_Crypto *c = TCP_con->net_crypto_pointer; | ||
1570 | |||
1571 | if (data[0] == NET_PACKET_COOKIE_REQUEST) { | ||
1572 | return tcp_handle_cookie_request(c, TCP_con, connection_id, data, length); | ||
1573 | } | ||
1574 | |||
1575 | Crypto_Connection *conn = get_crypto_connection(c, number); | ||
1576 | |||
1577 | if (conn == 0) | ||
1578 | return -1; | ||
1579 | |||
1580 | if (handle_packet_connection(c, number, data, length) != 0) | ||
1581 | return -1; | ||
1582 | |||
1583 | //TODO detect and kill bad TCP connections. | ||
1584 | return 0; | ||
1585 | } | ||
1586 | |||
1587 | /* Check if tcp connection to public key can be created. | ||
1588 | * | ||
1589 | * return -1 if it can't. | ||
1590 | * return 0 if it can. | ||
1591 | */ | ||
1592 | static int tcp_connection_check(Net_Crypto *c, uint8_t *public_key) | ||
1593 | { | ||
1594 | uint32_t i; | ||
1595 | |||
1596 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1597 | if (c->tcp_connections_new[i] == NULL) | ||
1598 | continue; | ||
1599 | |||
1600 | if (memcmp(c->tcp_connections_new[i]->public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
1601 | return -1; | ||
1602 | } | ||
1603 | |||
1604 | uint32_t num = 0; | ||
1605 | |||
1606 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1607 | if (c->tcp_connections[i] == NULL) | ||
1608 | continue; | ||
1609 | |||
1610 | if (memcmp(c->tcp_connections[i]->public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
1611 | return -1; | ||
1612 | |||
1613 | ++num; | ||
1614 | } | ||
1615 | |||
1616 | if (num == MAX_TCP_CONNECTIONS) | ||
1617 | return -1; | ||
1618 | |||
1619 | return 0; | ||
1620 | } | ||
1621 | |||
1622 | /* Add a tcp relay to the array. | ||
1623 | * | ||
1624 | * return 0 if it was added. | ||
1625 | * return -1 if it wasn't. | ||
1626 | */ | ||
1627 | int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, uint8_t *public_key) | ||
1628 | { | ||
1629 | if (tcp_connection_check(c, public_key) != 0) | ||
1630 | return -1; | ||
1631 | |||
1632 | uint32_t i; | ||
1633 | |||
1634 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1635 | if (c->tcp_connections_new[i] == NULL) { | ||
1636 | c->tcp_connections_new[i] = new_TCP_connection(ip_port, public_key, c->dht->self_public_key, c->dht->self_secret_key); | ||
1637 | return 0; | ||
1638 | } | ||
1639 | } | ||
1640 | |||
1641 | return -1; | ||
1642 | } | ||
1643 | |||
1644 | /* Add a connected tcp connection to the tcp_connections array. | ||
1645 | * | ||
1646 | * return 0 if it was added. | ||
1647 | * return -1 if it wasn't. | ||
1648 | */ | ||
1649 | static int add_tcp_connected(Net_Crypto *c, TCP_Client_Connection *tcp_con) | ||
1650 | { | ||
1651 | uint32_t i; | ||
1652 | |||
1653 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1654 | if (c->tcp_connections[i] == NULL) | ||
1655 | break; | ||
1656 | } | ||
1657 | |||
1658 | if (i == MAX_TCP_CONNECTIONS) | ||
1659 | return -1; | ||
1660 | |||
1661 | uint32_t tcp_num = i; | ||
1662 | |||
1663 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
1664 | Crypto_Connection *conn = get_crypto_connection(c, i); | ||
1665 | |||
1666 | if (conn == 0) | ||
1667 | return -1; | ||
1668 | |||
1669 | if (conn->status == CRYPTO_CONN_NO_CONNECTION) | ||
1670 | continue; | ||
1671 | |||
1672 | if (conn->status == CRYPTO_CONN_TIMED_OUT) | ||
1673 | continue; | ||
1674 | |||
1675 | if (conn->dht_public_key_set) | ||
1676 | if (send_routing_request(tcp_con, conn->dht_public_key) != 1) | ||
1677 | return -1; | ||
1678 | |||
1679 | } | ||
1680 | |||
1681 | tcp_con->net_crypto_pointer = c; | ||
1682 | tcp_con->net_crypto_location = tcp_num; | ||
1683 | routing_response_handler(tcp_con, tcp_response_callback, tcp_con); | ||
1684 | routing_status_handler(tcp_con, tcp_status_callback, tcp_con); | ||
1685 | routing_data_handler(tcp_con, tcp_data_callback, tcp_con); | ||
1686 | c->tcp_connections[tcp_num] = tcp_con; | ||
1687 | return 0; | ||
1688 | } | ||
1689 | |||
1690 | static void do_tcp(Net_Crypto *c) | ||
1691 | { | ||
1692 | uint32_t i; | ||
1693 | |||
1694 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1695 | if (c->tcp_connections_new[i] == NULL) | ||
1696 | continue; | ||
1697 | |||
1698 | do_TCP_connection(c->tcp_connections_new[i]); | ||
1699 | |||
1700 | if (c->tcp_connections_new[i]->status == TCP_CLIENT_CONFIRMED) { | ||
1701 | if (add_tcp_connected(c, c->tcp_connections_new[i]) == 0) { | ||
1702 | c->tcp_connections_new[i] = NULL; | ||
1703 | } else { | ||
1704 | kill_TCP_connection(c->tcp_connections_new[i]); | ||
1705 | c->tcp_connections_new[i] = NULL; | ||
1706 | } | ||
1707 | } | ||
1708 | } | ||
1709 | |||
1710 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1711 | if (c->tcp_connections[i] == NULL) | ||
1712 | continue; | ||
1713 | |||
1714 | do_TCP_connection(c->tcp_connections[i]); | ||
1715 | } | ||
1716 | } | ||
1717 | |||
1718 | static void clear_disconnected_tcp_peer(Crypto_Connection *conn, uint32_t number) | ||
1719 | { | ||
1720 | if (conn->status == CRYPTO_CONN_NO_CONNECTION) | ||
1721 | return; | ||
1722 | |||
1723 | if (number >= MAX_TCP_CONNECTIONS) | ||
1724 | return; | ||
1725 | |||
1726 | conn->status_tcp[number] = 0; | ||
1727 | conn->con_number_tcp[number] = 0; | ||
1728 | } | ||
1729 | |||
1730 | static void clear_disconnected_tcp(Net_Crypto *c) | ||
1731 | { | ||
1732 | uint32_t i, j; | ||
1733 | |||
1734 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1735 | if (c->tcp_connections_new[i] == NULL) | ||
1736 | continue; | ||
1737 | |||
1738 | if (c->tcp_connections_new[i]->status != TCP_CLIENT_DISCONNECTED) | ||
1739 | continue; | ||
1740 | |||
1741 | kill_TCP_connection(c->tcp_connections_new[i]); | ||
1742 | c->tcp_connections_new[i] = NULL; | ||
1743 | } | ||
1744 | |||
1745 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1746 | if (c->tcp_connections[i] == NULL) | ||
1747 | continue; | ||
1748 | |||
1749 | TCP_Client_Connection *tcp_con = c->tcp_connections[i]; | ||
1750 | |||
1751 | if (tcp_con->status != TCP_CLIENT_DISCONNECTED) | ||
1752 | continue; | ||
1753 | |||
1754 | c->tcp_connections[i] = NULL; | ||
1755 | kill_TCP_connection(tcp_con); | ||
1756 | |||
1757 | for (j = 0; j < c->crypto_connections_length; ++j) { | ||
1758 | Crypto_Connection *conn = get_crypto_connection(c, j); | ||
1759 | |||
1760 | if (conn == 0) | ||
1761 | return; | ||
1762 | |||
1763 | clear_disconnected_tcp_peer(conn, i); | ||
1764 | } | ||
1765 | } | ||
1766 | } | ||
1767 | |||
1402 | /* Set function to be called when connection with crypt_connection_id goes connects/disconnects. | 1768 | /* Set function to be called when connection with crypt_connection_id goes connects/disconnects. |
1403 | * | 1769 | * |
1404 | * The set function should return -1 on failure and 0 on success. | 1770 | * The set function should return -1 on failure and 0 on success. |
@@ -1647,6 +2013,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id) | |||
1647 | { | 2013 | { |
1648 | //TODO | 2014 | //TODO |
1649 | send_kill_packet(c, crypt_connection_id); | 2015 | send_kill_packet(c, crypt_connection_id); |
2016 | disconnect_peer_tcp(c, crypt_connection_id); | ||
1650 | return wipe_crypto_connection(c, crypt_connection_id); | 2017 | return wipe_crypto_connection(c, crypt_connection_id); |
1651 | } | 2018 | } |
1652 | 2019 | ||
@@ -1764,6 +2131,8 @@ void do_net_crypto(Net_Crypto *c) | |||
1764 | { | 2131 | { |
1765 | unix_time_update(); | 2132 | unix_time_update(); |
1766 | kill_timedout(c); | 2133 | kill_timedout(c); |
2134 | do_tcp(c); | ||
2135 | clear_disconnected_tcp(c); | ||
1767 | send_crypto_packets(c); | 2136 | send_crypto_packets(c); |
1768 | } | 2137 | } |
1769 | 2138 | ||