diff options
-rw-r--r-- | toxcore/Messenger.c | 540 | ||||
-rw-r--r-- | toxcore/net_crypto.c | 141 | ||||
-rw-r--r-- | toxcore/net_crypto.h | 74 | ||||
-rw-r--r-- | toxcore/onion_client.c | 31 | ||||
-rw-r--r-- | toxcore/onion_client.h | 7 |
5 files changed, 493 insertions, 300 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 7fdae8f0..9889d666 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -1857,347 +1857,381 @@ static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t) | |||
1857 | } | 1857 | } |
1858 | } | 1858 | } |
1859 | 1859 | ||
1860 | /* TODO: Make this function not suck. */ | 1860 | static int handle_status(void *object, int i, uint8_t status) |
1861 | void do_friends(Messenger *m) | ||
1862 | { | 1861 | { |
1863 | uint32_t i; | ||
1864 | int len; | ||
1865 | uint8_t temp[MAX_CRYPTO_DATA_SIZE]; | ||
1866 | uint64_t temp_time = unix_time(); | 1862 | uint64_t temp_time = unix_time(); |
1863 | Messenger *m = object; | ||
1867 | 1864 | ||
1868 | for (i = 0; i < m->numfriends; ++i) { | 1865 | if (status) { /* Went online. */ |
1869 | if (m->friendlist[i].status == FRIEND_ADDED) { | 1866 | set_friend_status(m, i, FRIEND_ONLINE); |
1870 | int fr = send_friendrequest(m->onion_c, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, | 1867 | m->friendlist[i].name_sent = 0; |
1871 | m->friendlist[i].info, | 1868 | m->friendlist[i].userstatus_sent = 0; |
1872 | m->friendlist[i].info_size); | 1869 | m->friendlist[i].statusmessage_sent = 0; |
1870 | m->friendlist[i].ping_lastrecv = temp_time; | ||
1871 | } else { /* Went offline. */ | ||
1872 | m->friendlist[i].crypt_connection_id = -1; | ||
1873 | 1873 | ||
1874 | if (fr >= 0) { | 1874 | if (m->friendlist[i].status == FRIEND_ONLINE) { |
1875 | set_friend_status(m, i, FRIEND_REQUESTED); | 1875 | set_friend_status(m, i, FRIEND_CONFIRMED); |
1876 | m->friendlist[i].friendrequest_lastsent = temp_time; | ||
1877 | } | ||
1878 | } | 1876 | } |
1877 | } | ||
1879 | 1878 | ||
1880 | if (m->friendlist[i].status == FRIEND_REQUESTED | 1879 | return 0; |
1881 | || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */ | 1880 | } |
1882 | if (m->friendlist[i].status == FRIEND_REQUESTED) { | ||
1883 | /* If we didn't connect to friend after successfully sending him a friend request the request is deemed | ||
1884 | * unsuccessful so we set the status back to FRIEND_ADDED and try again. | ||
1885 | */ | ||
1886 | check_friend_request_timed_out(m, i, temp_time); | ||
1887 | } | ||
1888 | 1881 | ||
1889 | IP_Port friendip; | 1882 | static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) |
1890 | int friendok = onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip); | 1883 | { |
1884 | if (len == 0) | ||
1885 | return -1; | ||
1891 | 1886 | ||
1892 | switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { | 1887 | Messenger *m = object; |
1893 | case CRYPTO_CONN_NO_CONNECTION: | 1888 | uint64_t temp_time = unix_time(); |
1894 | if (friendok == 1) | 1889 | uint8_t packet_id = temp[0]; |
1895 | m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); | 1890 | uint8_t *data = temp + 1; |
1891 | uint32_t data_length = len - 1; | ||
1896 | 1892 | ||
1897 | break; | 1893 | if (m->friendlist[i].status != FRIEND_ONLINE) |
1894 | return -1; | ||
1898 | 1895 | ||
1899 | case CRYPTO_CONN_ESTABLISHED: /* Connection is established. */ | 1896 | switch (packet_id) { |
1900 | set_friend_status(m, i, FRIEND_ONLINE); | 1897 | case PACKET_ID_ALIVE: { |
1901 | m->friendlist[i].name_sent = 0; | 1898 | m->friendlist[i].ping_lastrecv = temp_time; |
1902 | m->friendlist[i].userstatus_sent = 0; | 1899 | break; |
1903 | m->friendlist[i].statusmessage_sent = 0; | 1900 | } |
1904 | m->friendlist[i].ping_lastrecv = temp_time; | ||
1905 | break; | ||
1906 | 1901 | ||
1907 | case CRYPTO_CONN_TIMED_OUT: | 1902 | case PACKET_ID_NICKNAME: { |
1908 | crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); | 1903 | if (data_length > MAX_NAME_LENGTH || data_length == 0) |
1909 | m->friendlist[i].crypt_connection_id = -1; | 1904 | break; |
1910 | break; | ||
1911 | 1905 | ||
1912 | default: | 1906 | /* Make sure the NULL terminator is present. */ |
1913 | break; | 1907 | uint8_t data_terminated[data_length + 1]; |
1914 | } | 1908 | memcpy(data_terminated, data, data_length); |
1909 | data_terminated[data_length] = 0; | ||
1910 | |||
1911 | /* inform of namechange before we overwrite the old name */ | ||
1912 | if (m->friend_namechange) | ||
1913 | m->friend_namechange(m, i, data_terminated, data_length, m->friend_namechange_userdata); | ||
1914 | |||
1915 | memcpy(m->friendlist[i].name, data_terminated, data_length); | ||
1916 | m->friendlist[i].name_length = data_length; | ||
1917 | |||
1918 | break; | ||
1915 | } | 1919 | } |
1916 | 1920 | ||
1917 | while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ | 1921 | case PACKET_ID_STATUSMESSAGE: { |
1918 | if (m->friendlist[i].name_sent == 0) { | 1922 | if (data_length == 0 || data_length > MAX_STATUSMESSAGE_LENGTH) |
1919 | if (m_sendname(m, i, m->name, m->name_length)) | 1923 | break; |
1920 | m->friendlist[i].name_sent = 1; | ||
1921 | } | ||
1922 | 1924 | ||
1923 | if (m->friendlist[i].statusmessage_sent == 0) { | 1925 | /* Make sure the NULL terminator is present. */ |
1924 | if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) | 1926 | uint8_t data_terminated[data_length + 1]; |
1925 | m->friendlist[i].statusmessage_sent = 1; | 1927 | memcpy(data_terminated, data, data_length); |
1926 | } | 1928 | data_terminated[data_length] = 0; |
1927 | 1929 | ||
1928 | if (m->friendlist[i].userstatus_sent == 0) { | 1930 | if (m->friend_statusmessagechange) |
1929 | if (send_userstatus(m, i, m->userstatus)) | 1931 | m->friend_statusmessagechange(m, i, data_terminated, data_length, |
1930 | m->friendlist[i].userstatus_sent = 1; | 1932 | m->friend_statuschange_userdata); |
1931 | } | ||
1932 | 1933 | ||
1933 | if (m->friendlist[i].user_istyping_sent == 0) { | 1934 | set_friend_statusmessage(m, i, data_terminated, data_length); |
1934 | if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) | 1935 | break; |
1935 | m->friendlist[i].user_istyping_sent = 1; | 1936 | } |
1936 | } | ||
1937 | 1937 | ||
1938 | if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { | 1938 | case PACKET_ID_USERSTATUS: { |
1939 | send_ping(m, i); | 1939 | if (data_length != 1) |
1940 | } | 1940 | break; |
1941 | |||
1942 | USERSTATUS status = data[0]; | ||
1941 | 1943 | ||
1942 | len = read_cryptpacket(m->net_crypto, m->friendlist[i].crypt_connection_id, temp); | 1944 | if (status >= USERSTATUS_INVALID) |
1945 | break; | ||
1943 | 1946 | ||
1944 | if (len > 0) { | 1947 | if (m->friend_userstatuschange) |
1945 | uint8_t packet_id = temp[0]; | 1948 | m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); |
1946 | uint8_t *data = temp + 1; | ||
1947 | uint32_t data_length = len - 1; | ||
1948 | 1949 | ||
1949 | switch (packet_id) { | 1950 | set_friend_userstatus(m, i, status); |
1950 | case PACKET_ID_ALIVE: { | 1951 | break; |
1951 | m->friendlist[i].ping_lastrecv = temp_time; | 1952 | } |
1952 | break; | ||
1953 | } | ||
1954 | 1953 | ||
1955 | case PACKET_ID_NICKNAME: { | 1954 | case PACKET_ID_TYPING: { |
1956 | if (data_length > MAX_NAME_LENGTH || data_length == 0) | 1955 | if (data_length != 1) |
1957 | break; | 1956 | break; |
1958 | 1957 | ||
1959 | /* Make sure the NULL terminator is present. */ | 1958 | uint8_t typing = data[0]; |
1960 | uint8_t data_terminated[data_length + 1]; | ||
1961 | memcpy(data_terminated, data, data_length); | ||
1962 | data_terminated[data_length] = 0; | ||
1963 | 1959 | ||
1964 | /* inform of namechange before we overwrite the old name */ | 1960 | set_friend_typing(m, i, typing); |
1965 | if (m->friend_namechange) | ||
1966 | m->friend_namechange(m, i, data_terminated, data_length, m->friend_namechange_userdata); | ||
1967 | 1961 | ||
1968 | memcpy(m->friendlist[i].name, data_terminated, data_length); | 1962 | if (m->friend_typingchange) |
1969 | m->friendlist[i].name_length = data_length; | 1963 | m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata); |
1970 | 1964 | ||
1971 | break; | 1965 | break; |
1972 | } | 1966 | } |
1973 | 1967 | ||
1974 | case PACKET_ID_STATUSMESSAGE: { | 1968 | case PACKET_ID_MESSAGE: { |
1975 | if (data_length == 0 || data_length > MAX_STATUSMESSAGE_LENGTH) | 1969 | uint8_t *message_id = data; |
1976 | break; | 1970 | uint8_t message_id_length = 4; |
1977 | 1971 | ||
1978 | /* Make sure the NULL terminator is present. */ | 1972 | if (data_length <= message_id_length) |
1979 | uint8_t data_terminated[data_length + 1]; | 1973 | break; |
1980 | memcpy(data_terminated, data, data_length); | ||
1981 | data_terminated[data_length] = 0; | ||
1982 | 1974 | ||
1983 | if (m->friend_statusmessagechange) | 1975 | uint8_t *message = data + message_id_length; |
1984 | m->friend_statusmessagechange(m, i, data_terminated, data_length, | 1976 | uint16_t message_length = data_length - message_id_length; |
1985 | m->friend_statuschange_userdata); | ||
1986 | 1977 | ||
1987 | set_friend_statusmessage(m, i, data_terminated, data_length); | 1978 | /* Make sure the NULL terminator is present. */ |
1988 | break; | 1979 | uint8_t message_terminated[message_length + 1]; |
1989 | } | 1980 | memcpy(message_terminated, message, message_length); |
1981 | message_terminated[message_length] = 0; | ||
1990 | 1982 | ||
1991 | case PACKET_ID_USERSTATUS: { | 1983 | if (m->friendlist[i].receives_read_receipts) { |
1992 | if (data_length != 1) | 1984 | write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); |
1993 | break; | 1985 | } |
1994 | 1986 | ||
1995 | USERSTATUS status = data[0]; | 1987 | if (m->friend_message) |
1988 | (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); | ||
1996 | 1989 | ||
1997 | if (status >= USERSTATUS_INVALID) | 1990 | break; |
1998 | break; | 1991 | } |
1999 | 1992 | ||
2000 | if (m->friend_userstatuschange) | 1993 | case PACKET_ID_ACTION: { |
2001 | m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); | 1994 | uint8_t *message_id = data; |
1995 | uint8_t message_id_length = 4; | ||
2002 | 1996 | ||
2003 | set_friend_userstatus(m, i, status); | 1997 | if (data_length <= message_id_length) |
2004 | break; | 1998 | break; |
2005 | } | ||
2006 | 1999 | ||
2007 | case PACKET_ID_TYPING: { | 2000 | uint8_t *action = data + message_id_length; |
2008 | if (data_length != 1) | 2001 | uint16_t action_length = data_length - message_id_length; |
2009 | break; | ||
2010 | 2002 | ||
2011 | uint8_t typing = data[0]; | 2003 | /* Make sure the NULL terminator is present. */ |
2004 | uint8_t action_terminated[action_length + 1]; | ||
2005 | memcpy(action_terminated, action, action_length); | ||
2006 | action_terminated[action_length] = 0; | ||
2012 | 2007 | ||
2013 | set_friend_typing(m, i, typing); | 2008 | if (m->friendlist[i].receives_read_receipts) { |
2009 | write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); | ||
2010 | } | ||
2014 | 2011 | ||
2015 | if (m->friend_typingchange) | 2012 | if (m->friend_action) |
2016 | m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata); | 2013 | (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); |
2017 | 2014 | ||
2018 | break; | 2015 | break; |
2019 | } | 2016 | } |
2017 | |||
2018 | case PACKET_ID_RECEIPT: { | ||
2019 | uint32_t msgid; | ||
2020 | 2020 | ||
2021 | case PACKET_ID_MESSAGE: { | 2021 | if (data_length < sizeof(msgid)) |
2022 | uint8_t *message_id = data; | 2022 | break; |
2023 | uint8_t message_id_length = 4; | ||
2024 | 2023 | ||
2025 | if (data_length <= message_id_length) | 2024 | memcpy(&msgid, data, sizeof(msgid)); |
2026 | break; | 2025 | msgid = ntohl(msgid); |
2027 | 2026 | ||
2028 | uint8_t *message = data + message_id_length; | 2027 | if (m->read_receipt) |
2029 | uint16_t message_length = data_length - message_id_length; | 2028 | (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); |
2030 | 2029 | ||
2031 | /* Make sure the NULL terminator is present. */ | 2030 | break; |
2032 | uint8_t message_terminated[message_length + 1]; | 2031 | } |
2033 | memcpy(message_terminated, message, message_length); | ||
2034 | message_terminated[message_length] = 0; | ||
2035 | 2032 | ||
2036 | if (m->friendlist[i].receives_read_receipts) { | 2033 | case PACKET_ID_INVITE_GROUPCHAT: { |
2037 | write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); | 2034 | if (data_length != crypto_box_PUBLICKEYBYTES) |
2038 | } | 2035 | break; |
2039 | 2036 | ||
2040 | if (m->friend_message) | 2037 | if (m->group_invite) |
2041 | (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); | 2038 | (*m->group_invite)(m, i, data, m->group_invite_userdata); |
2042 | 2039 | ||
2043 | break; | 2040 | break; |
2044 | } | 2041 | } |
2045 | 2042 | ||
2046 | case PACKET_ID_ACTION: { | 2043 | case PACKET_ID_JOIN_GROUPCHAT: { |
2047 | uint8_t *message_id = data; | 2044 | if (data_length != crypto_box_PUBLICKEYBYTES * 2) |
2048 | uint8_t message_id_length = 4; | 2045 | break; |
2049 | 2046 | ||
2050 | if (data_length <= message_id_length) | 2047 | int groupnum = group_num(m, data); |
2051 | break; | ||
2052 | 2048 | ||
2053 | uint8_t *action = data + message_id_length; | 2049 | if (groupnum == -1) |
2054 | uint16_t action_length = data_length - message_id_length; | 2050 | break; |
2055 | 2051 | ||
2056 | /* Make sure the NULL terminator is present. */ | 2052 | if (!group_invited(m, i, groupnum)) |
2057 | uint8_t action_terminated[action_length + 1]; | 2053 | break; |
2058 | memcpy(action_terminated, action, action_length); | ||
2059 | action_terminated[action_length] = 0; | ||
2060 | 2054 | ||
2061 | if (m->friendlist[i].receives_read_receipts) { | 2055 | group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); |
2062 | write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); | 2056 | /* This is just there to speedup joining. */ |
2063 | } | 2057 | chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES); |
2058 | break; | ||
2059 | } | ||
2064 | 2060 | ||
2065 | if (m->friend_action) | 2061 | case PACKET_ID_FILE_SENDREQUEST: { |
2066 | (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); | 2062 | if (data_length < 1 + sizeof(uint64_t) + 1) |
2063 | break; | ||
2067 | 2064 | ||
2068 | break; | 2065 | uint8_t filenumber = data[0]; |
2069 | } | 2066 | uint64_t filesize; |
2067 | net_to_host(data + 1, sizeof(filesize)); | ||
2068 | memcpy(&filesize, data + 1, sizeof(filesize)); | ||
2069 | m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; | ||
2070 | m->friendlist[i].file_receiving[filenumber].size = filesize; | ||
2071 | m->friendlist[i].file_receiving[filenumber].transferred = 0; | ||
2070 | 2072 | ||
2071 | case PACKET_ID_RECEIPT: { | 2073 | /* Force NULL terminate file name. */ |
2072 | uint32_t msgid; | 2074 | uint8_t filename_terminated[data_length - 1 - sizeof(uint64_t) + 1]; |
2075 | memcpy(filename_terminated, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t)); | ||
2076 | filename_terminated[data_length - 1 - sizeof(uint64_t)] = 0; | ||
2073 | 2077 | ||
2074 | if (data_length < sizeof(msgid)) | 2078 | if (m->file_sendrequest) |
2075 | break; | 2079 | (*m->file_sendrequest)(m, i, filenumber, filesize, filename_terminated, data_length - 1 - sizeof(uint64_t), |
2080 | m->file_sendrequest_userdata); | ||
2076 | 2081 | ||
2077 | memcpy(&msgid, data, sizeof(msgid)); | 2082 | break; |
2078 | msgid = ntohl(msgid); | 2083 | } |
2079 | 2084 | ||
2080 | if (m->read_receipt) | 2085 | case PACKET_ID_FILE_CONTROL: { |
2081 | (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); | 2086 | if (data_length < 3) |
2087 | break; | ||
2082 | 2088 | ||
2083 | break; | 2089 | uint8_t send_receive = data[0]; |
2084 | } | 2090 | uint8_t filenumber = data[1]; |
2091 | uint8_t control_type = data[2]; | ||
2085 | 2092 | ||
2086 | case PACKET_ID_INVITE_GROUPCHAT: { | 2093 | if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1) |
2087 | if (data_length != crypto_box_PUBLICKEYBYTES) | 2094 | break; |
2088 | break; | ||
2089 | 2095 | ||
2090 | if (m->group_invite) | 2096 | if (m->file_filecontrol) |
2091 | (*m->group_invite)(m, i, data, m->group_invite_userdata); | 2097 | (*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, |
2098 | m->file_filecontrol_userdata); | ||
2092 | 2099 | ||
2093 | break; | 2100 | break; |
2094 | } | 2101 | } |
2095 | 2102 | ||
2096 | case PACKET_ID_JOIN_GROUPCHAT: { | 2103 | case PACKET_ID_FILE_DATA: { |
2097 | if (data_length != crypto_box_PUBLICKEYBYTES * 2) | 2104 | if (data_length < 2) |
2098 | break; | 2105 | break; |
2099 | 2106 | ||
2100 | int groupnum = group_num(m, data); | 2107 | uint8_t filenumber = data[0]; |
2101 | 2108 | ||
2102 | if (groupnum == -1) | 2109 | if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE) |
2103 | break; | 2110 | break; |
2104 | 2111 | ||
2105 | if (!group_invited(m, i, groupnum)) | 2112 | m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1); |
2106 | break; | ||
2107 | 2113 | ||
2108 | group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); | 2114 | if (m->file_filedata) |
2109 | /* This is just there to speedup joining. */ | 2115 | (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); |
2110 | chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES); | ||
2111 | break; | ||
2112 | } | ||
2113 | 2116 | ||
2114 | case PACKET_ID_FILE_SENDREQUEST: { | 2117 | break; |
2115 | if (data_length < 1 + sizeof(uint64_t) + 1) | 2118 | } |
2116 | break; | ||
2117 | 2119 | ||
2118 | uint8_t filenumber = data[0]; | 2120 | case PACKET_ID_MSI: { |
2119 | uint64_t filesize; | 2121 | if (data_length == 0) |
2120 | net_to_host(data + 1, sizeof(filesize)); | 2122 | break; |
2121 | memcpy(&filesize, data + 1, sizeof(filesize)); | ||
2122 | m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; | ||
2123 | m->friendlist[i].file_receiving[filenumber].size = filesize; | ||
2124 | m->friendlist[i].file_receiving[filenumber].transferred = 0; | ||
2125 | 2123 | ||
2126 | /* Force NULL terminate file name. */ | 2124 | if (m->msi_packet) |
2127 | uint8_t filename_terminated[data_length - 1 - sizeof(uint64_t) + 1]; | 2125 | (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata); |
2128 | memcpy(filename_terminated, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t)); | 2126 | } |
2129 | filename_terminated[data_length - 1 - sizeof(uint64_t)] = 0; | ||
2130 | 2127 | ||
2131 | if (m->file_sendrequest) | 2128 | default: { |
2132 | (*m->file_sendrequest)(m, i, filenumber, filesize, filename_terminated, data_length - 1 - sizeof(uint64_t), | 2129 | break; |
2133 | m->file_sendrequest_userdata); | 2130 | } |
2131 | } | ||
2134 | 2132 | ||
2135 | break; | 2133 | return 0; |
2136 | } | 2134 | } |
2137 | 2135 | ||
2138 | case PACKET_ID_FILE_CONTROL: { | 2136 | static int friend_new_connection(Messenger *m, int32_t friendnumber, uint8_t *real_public_key) |
2139 | if (data_length < 3) | 2137 | { |
2140 | break; | 2138 | if (friend_not_valid(m, friendnumber)) |
2139 | return -1; | ||
2141 | 2140 | ||
2142 | uint8_t send_receive = data[0]; | 2141 | if (m->friendlist[friendnumber].crypt_connection_id != -1) { |
2143 | uint8_t filenumber = data[1]; | 2142 | return -1; |
2144 | uint8_t control_type = data[2]; | 2143 | } |
2145 | 2144 | ||
2146 | if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1) | 2145 | int id = new_crypto_connection(m->net_crypto, real_public_key); |
2147 | break; | ||
2148 | 2146 | ||
2149 | if (m->file_filecontrol) | 2147 | if (id == -1) |
2150 | (*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, | 2148 | return -1; |
2151 | m->file_filecontrol_userdata); | ||
2152 | 2149 | ||
2153 | break; | 2150 | m->friendlist[friendnumber].crypt_connection_id = id; |
2154 | } | 2151 | connection_status_handler(m->net_crypto, id, &handle_status, m, friendnumber); |
2152 | connection_data_handler(m->net_crypto, id, &handle_packet, m, friendnumber); | ||
2153 | return 0; | ||
2155 | 2154 | ||
2156 | case PACKET_ID_FILE_DATA: { | 2155 | } |
2157 | if (data_length < 2) | ||
2158 | break; | ||
2159 | 2156 | ||
2160 | uint8_t filenumber = data[0]; | 2157 | /* TODO: Make this function not suck. */ |
2158 | void do_friends(Messenger *m) | ||
2159 | { | ||
2160 | uint32_t i; | ||
2161 | uint64_t temp_time = unix_time(); | ||
2161 | 2162 | ||
2162 | if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE) | 2163 | for (i = 0; i < m->numfriends; ++i) { |
2163 | break; | 2164 | if (m->friendlist[i].status == FRIEND_ADDED) { |
2165 | int fr = send_friendrequest(m->onion_c, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, | ||
2166 | m->friendlist[i].info, | ||
2167 | m->friendlist[i].info_size); | ||
2164 | 2168 | ||
2165 | m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1); | 2169 | if (fr >= 0) { |
2170 | set_friend_status(m, i, FRIEND_REQUESTED); | ||
2171 | m->friendlist[i].friendrequest_lastsent = temp_time; | ||
2172 | } | ||
2173 | } | ||
2166 | 2174 | ||
2167 | if (m->file_filedata) | 2175 | if (m->friendlist[i].status == FRIEND_REQUESTED |
2168 | (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); | 2176 | || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */ |
2177 | if (m->friendlist[i].status == FRIEND_REQUESTED) { | ||
2178 | /* If we didn't connect to friend after successfully sending him a friend request the request is deemed | ||
2179 | * unsuccessful so we set the status back to FRIEND_ADDED and try again. | ||
2180 | */ | ||
2181 | check_friend_request_timed_out(m, i, temp_time); | ||
2182 | } | ||
2169 | 2183 | ||
2170 | break; | 2184 | friend_new_connection(m, i, m->friendlist[i].client_id); |
2171 | } | 2185 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; |
2172 | 2186 | ||
2173 | case PACKET_ID_MSI: { | 2187 | if (onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key) == 0) { |
2174 | if (data_length == 0) | 2188 | set_conection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key); |
2175 | break; | 2189 | } |
2176 | 2190 | ||
2177 | if (m->msi_packet) | 2191 | IP_Port friendip; |
2178 | (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata); | ||
2179 | } | ||
2180 | 2192 | ||
2181 | default: { | 2193 | if (onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip) == 1) { |
2182 | break; | 2194 | set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, friendip); |
2183 | } | 2195 | } |
2184 | } | 2196 | } |
2185 | } else { | ||
2186 | if (is_cryptoconnected(m->net_crypto, | ||
2187 | m->friendlist[i].crypt_connection_id) == CRYPTO_CONN_TIMED_OUT) { /* If the connection timed out, kill it. */ | ||
2188 | crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); | ||
2189 | m->friendlist[i].crypt_connection_id = -1; | ||
2190 | set_friend_status(m, i, FRIEND_CONFIRMED); | ||
2191 | } | ||
2192 | 2197 | ||
2193 | if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { | 2198 | if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ |
2194 | /* If we stopped recieving ping packets, kill it. */ | 2199 | if (m->friendlist[i].name_sent == 0) { |
2195 | crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); | 2200 | if (m_sendname(m, i, m->name, m->name_length)) |
2196 | m->friendlist[i].crypt_connection_id = -1; | 2201 | m->friendlist[i].name_sent = 1; |
2197 | set_friend_status(m, i, FRIEND_CONFIRMED); | 2202 | } |
2198 | } | ||
2199 | 2203 | ||
2200 | break; | 2204 | if (m->friendlist[i].statusmessage_sent == 0) { |
2205 | if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) | ||
2206 | m->friendlist[i].statusmessage_sent = 1; | ||
2207 | } | ||
2208 | |||
2209 | if (m->friendlist[i].userstatus_sent == 0) { | ||
2210 | if (send_userstatus(m, i, m->userstatus)) | ||
2211 | m->friendlist[i].userstatus_sent = 1; | ||
2212 | } | ||
2213 | |||
2214 | if (m->friendlist[i].user_istyping_sent == 0) { | ||
2215 | if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) | ||
2216 | m->friendlist[i].user_istyping_sent = 1; | ||
2217 | } | ||
2218 | |||
2219 | if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { | ||
2220 | send_ping(m, i); | ||
2221 | } | ||
2222 | |||
2223 | if (is_cryptoconnected(m->net_crypto, | ||
2224 | m->friendlist[i].crypt_connection_id) == CRYPTO_CONN_TIMED_OUT) { /* If the connection timed out, kill it. */ | ||
2225 | crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); | ||
2226 | m->friendlist[i].crypt_connection_id = -1; | ||
2227 | set_friend_status(m, i, FRIEND_CONFIRMED); | ||
2228 | } | ||
2229 | |||
2230 | if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { | ||
2231 | /* If we stopped recieving ping packets, kill it. */ | ||
2232 | crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); | ||
2233 | m->friendlist[i].crypt_connection_id = -1; | ||
2234 | set_friend_status(m, i, FRIEND_CONFIRMED); | ||
2201 | } | 2235 | } |
2202 | } | 2236 | } |
2203 | } | 2237 | } |
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index a0a913d2..9425afba 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c | |||
@@ -379,6 +379,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *dat | |||
379 | return -1; | 379 | return -1; |
380 | 380 | ||
381 | increment_nonce(conn->sent_nonce); | 381 | increment_nonce(conn->sent_nonce); |
382 | conn->last_data_packet_sent = current_time(); //TODO remove this. | ||
382 | return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); | 383 | return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); |
383 | } | 384 | } |
384 | 385 | ||
@@ -459,6 +460,7 @@ static int new_temp_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *pack | |||
459 | conn->temp_packet = temp_packet; | 460 | conn->temp_packet = temp_packet; |
460 | conn->temp_packet_length = length; | 461 | conn->temp_packet_length = length; |
461 | conn->temp_packet_sent_time = 0; | 462 | conn->temp_packet_sent_time = 0; |
463 | conn->temp_packet_num_sent = 0; | ||
462 | return 0; | 464 | return 0; |
463 | } | 465 | } |
464 | 466 | ||
@@ -480,6 +482,7 @@ static int clear_temp_packet(Net_Crypto *c, int crypt_connection_id) | |||
480 | conn->temp_packet = 0; | 482 | conn->temp_packet = 0; |
481 | conn->temp_packet_length = 0; | 483 | conn->temp_packet_length = 0; |
482 | conn->temp_packet_sent_time = 0; | 484 | conn->temp_packet_sent_time = 0; |
485 | conn->temp_packet_num_sent = 0; | ||
483 | return 0; | 486 | return 0; |
484 | } | 487 | } |
485 | 488 | ||
@@ -503,6 +506,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) | |||
503 | return -1; | 506 | return -1; |
504 | 507 | ||
505 | conn->temp_packet_sent_time = current_time(); | 508 | conn->temp_packet_sent_time = current_time(); |
509 | ++conn->temp_packet_num_sent; | ||
506 | return 0; | 510 | return 0; |
507 | } | 511 | } |
508 | 512 | ||
@@ -594,7 +598,24 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint | |||
594 | 598 | ||
595 | case NET_PACKET_CRYPTO_DATA: { | 599 | case NET_PACKET_CRYPTO_DATA: { |
596 | if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) { | 600 | if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) { |
597 | //TODO | 601 | uint8_t data[MAX_DATA_DATA_PACKET_SIZE]; |
602 | int len = handle_data_packet(c, crypt_connection_id, data, packet, length); | ||
603 | |||
604 | if (len == -1) | ||
605 | return -1; | ||
606 | |||
607 | if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) { | ||
608 | if (conn->connection_status_callback) | ||
609 | conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1); | ||
610 | |||
611 | clear_temp_packet(c, crypt_connection_id); | ||
612 | conn->status = CRYPTO_CONN_ESTABLISHED; | ||
613 | } | ||
614 | |||
615 | if (conn->connection_data_callback) | ||
616 | conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, data, len); | ||
617 | |||
618 | //TODO add buffers and packet requesting. | ||
598 | } else { | 619 | } else { |
599 | return -1; | 620 | return -1; |
600 | } | 621 | } |
@@ -870,6 +891,9 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t | |||
870 | if (conn == 0) | 891 | if (conn == 0) |
871 | return -1; | 892 | return -1; |
872 | 893 | ||
894 | if (conn->dht_public_key_set == 1 && memcmp(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
895 | return -1; | ||
896 | |||
873 | memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); | 897 | memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); |
874 | conn->dht_public_key_set = 1; | 898 | conn->dht_public_key_set = 1; |
875 | 899 | ||
@@ -908,6 +932,52 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) | |||
908 | return 0; | 932 | return 0; |
909 | } | 933 | } |
910 | 934 | ||
935 | /* Set function to be called when connection with crypt_connection_id goes connects/disconnects. | ||
936 | * | ||
937 | * The set function should return -1 on failure and 0 on success. | ||
938 | * Note that if this function is set, the connection will clear itself on disconnect. | ||
939 | * Object and id will be passed to this function untouched. | ||
940 | * status is 1 if the connection is going online, 0 if it is going offline. | ||
941 | * | ||
942 | * return -1 on failure. | ||
943 | * return 0 on success. | ||
944 | */ | ||
945 | int connection_status_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_status_callback)(void *object, | ||
946 | int id, uint8_t status), void *object, int id) | ||
947 | { | ||
948 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
949 | |||
950 | if (conn == 0) | ||
951 | return -1; | ||
952 | |||
953 | conn->connection_status_callback = connection_status_callback; | ||
954 | conn->connection_status_callback_object = object; | ||
955 | conn->connection_status_callback_id = id; | ||
956 | return 0; | ||
957 | } | ||
958 | |||
959 | /* Set function to be called when connection with crypt_connection_id receives a data packet of length. | ||
960 | * | ||
961 | * The set function should return -1 on failure and 0 on success. | ||
962 | * Object and id will be passed to this function untouched. | ||
963 | * | ||
964 | * return -1 on failure. | ||
965 | * return 0 on success. | ||
966 | */ | ||
967 | int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, | ||
968 | int id, uint8_t *data, uint16_t length), void *object, int id) | ||
969 | { | ||
970 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
971 | |||
972 | if (conn == 0) | ||
973 | return -1; | ||
974 | |||
975 | conn->connection_data_callback = connection_data_callback; | ||
976 | conn->connection_data_callback_object = object; | ||
977 | conn->connection_data_callback_id = id; | ||
978 | return 0; | ||
979 | } | ||
980 | |||
911 | /* Get the crypto connection id from the ip_port. | 981 | /* Get the crypto connection id from the ip_port. |
912 | * | 982 | * |
913 | * return -1 on failure. | 983 | * return -1 on failure. |
@@ -977,27 +1047,26 @@ static void send_crypto_packets(Net_Crypto *c) | |||
977 | if (conn == 0) | 1047 | if (conn == 0) |
978 | return; | 1048 | return; |
979 | 1049 | ||
980 | if ((CRYPTO_SEND_PACKET_INTERVAL * 1000UL) + conn->temp_packet_sent_time < temp_time) { | 1050 | if ((CRYPTO_SEND_PACKET_INTERVAL * 1000ULL) + conn->temp_packet_sent_time < temp_time) { |
981 | send_temp_packet(c, i); | 1051 | send_temp_packet(c, i); |
982 | } | 1052 | } |
1053 | |||
1054 | if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED | ||
1055 | && (500ULL * 1000ULL) + conn->last_data_packet_sent < temp_time) {//TODO remove this. | ||
1056 | uint8_t data[4] = {}; | ||
1057 | send_data_packet(c, i, data, 4); | ||
1058 | } | ||
983 | } | 1059 | } |
984 | } | 1060 | } |
985 | 1061 | ||
986 | /* return 0 if there is no received data in the buffer. | ||
987 | * return -1 if the packet was discarded. | ||
988 | * return length of received data if successful. | ||
989 | */ | ||
990 | int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) | ||
991 | { | ||
992 | |||
993 | } | ||
994 | 1062 | ||
995 | /* returns the number of packet slots left in the sendbuffer. | 1063 | /* returns the number of packet slots left in the sendbuffer. |
996 | * return 0 if failure. | 1064 | * return 0 if failure. |
997 | */ | 1065 | */ |
998 | uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) | 1066 | uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) |
999 | { | 1067 | { |
1000 | 1068 | //TODO | |
1069 | return 0; | ||
1001 | } | 1070 | } |
1002 | 1071 | ||
1003 | /* return 0 if data could not be put in packet queue. | 1072 | /* return 0 if data could not be put in packet queue. |
@@ -1005,28 +1074,22 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) | |||
1005 | */ | 1074 | */ |
1006 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) | 1075 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) |
1007 | { | 1076 | { |
1077 | //TODO | ||
1078 | if (send_data_packet(c, crypt_connection_id, data, length) == 0) | ||
1079 | return 1; | ||
1008 | 1080 | ||
1009 | } | 1081 | return 0; |
1010 | |||
1011 | |||
1012 | /* Start a secure connection with other peer who has public_key and ip_port. | ||
1013 | * | ||
1014 | * return -1 if failure. | ||
1015 | * return crypt_connection_id of the initialized connection if everything went well. | ||
1016 | */ | ||
1017 | int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) | ||
1018 | { | ||
1019 | |||
1020 | } | 1082 | } |
1021 | 1083 | ||
1022 | /* Kill a crypto connection. | 1084 | /* Kill a crypto connection. |
1023 | * | 1085 | * |
1024 | * return 0 if killed successfully. | 1086 | * return -1 on failure. |
1025 | * return 1 if there was a problem. | 1087 | * return 0 on success. |
1026 | */ | 1088 | */ |
1027 | int crypto_kill(Net_Crypto *c, int crypt_connection_id) | 1089 | int crypto_kill(Net_Crypto *c, int crypt_connection_id) |
1028 | { | 1090 | { |
1029 | 1091 | //TODO | |
1092 | return wipe_crypto_connection(c, crypt_connection_id); | ||
1030 | } | 1093 | } |
1031 | 1094 | ||
1032 | /* return 0 if no connection. | 1095 | /* return 0 if no connection. |
@@ -1096,9 +1159,35 @@ Net_Crypto *new_net_crypto(DHT *dht) | |||
1096 | static void kill_timedout(Net_Crypto *c) | 1159 | static void kill_timedout(Net_Crypto *c) |
1097 | { | 1160 | { |
1098 | uint32_t i; | 1161 | uint32_t i; |
1162 | uint64_t temp_time = current_time(); | ||
1099 | 1163 | ||
1100 | for (i = 0; i < c->crypto_connections_length; ++i) { | 1164 | for (i = 0; i < c->crypto_connections_length; ++i) { |
1101 | //TODO | 1165 | Crypto_Connection *conn = get_crypto_connection(c, i); |
1166 | |||
1167 | if (conn == 0) | ||
1168 | return; | ||
1169 | |||
1170 | if (conn->status == CRYPTO_CONN_NO_CONNECTION || conn->status == CRYPTO_CONN_TIMED_OUT) | ||
1171 | continue; | ||
1172 | |||
1173 | if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT | ||
1174 | || conn->status == CRYPTO_CONN_NOT_CONFIRMED) { | ||
1175 | if (conn->temp_packet_num_sent < MAX_NUM_SENDPACKET_TRIES) | ||
1176 | continue; | ||
1177 | |||
1178 | if (conn->connection_status_callback) { | ||
1179 | conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0); | ||
1180 | crypto_kill(c, i); | ||
1181 | continue; | ||
1182 | } | ||
1183 | |||
1184 | conn->status = CRYPTO_CONN_TIMED_OUT; | ||
1185 | continue; | ||
1186 | } | ||
1187 | |||
1188 | if (conn->status == CRYPTO_CONN_ESTABLISHED) { | ||
1189 | //TODO: add a timeout here? | ||
1190 | } | ||
1102 | } | 1191 | } |
1103 | } | 1192 | } |
1104 | 1193 | ||
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 3d58e5c1..5d4ff35b 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h | |||
@@ -44,6 +44,9 @@ | |||
44 | 44 | ||
45 | /* Interval in ms between sending cookie request/handshake packets. */ | 45 | /* Interval in ms between sending cookie request/handshake packets. */ |
46 | #define CRYPTO_SEND_PACKET_INTERVAL 500 | 46 | #define CRYPTO_SEND_PACKET_INTERVAL 500 |
47 | /* The maximum number of times we try to send the cookie request and handshake | ||
48 | before giving up. */ | ||
49 | #define MAX_NUM_SENDPACKET_TRIES 10 | ||
47 | 50 | ||
48 | typedef struct { | 51 | typedef struct { |
49 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ | 52 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ |
@@ -59,8 +62,6 @@ typedef struct { | |||
59 | * 4 if the connection is established. | 62 | * 4 if the connection is established. |
60 | * 5 if the connection is timed out. | 63 | * 5 if the connection is timed out. |
61 | */ | 64 | */ |
62 | uint64_t timeout; | ||
63 | |||
64 | uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ | 65 | uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ |
65 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ | 66 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ |
66 | uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */ | 67 | uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */ |
@@ -68,9 +69,20 @@ typedef struct { | |||
68 | uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ | 69 | uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ |
69 | uint16_t temp_packet_length; | 70 | uint16_t temp_packet_length; |
70 | uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ | 71 | uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ |
72 | uint32_t temp_packet_num_sent; | ||
71 | 73 | ||
72 | IP_Port ip_port; /* The ip and port to contact this guy directly.*/ | 74 | IP_Port ip_port; /* The ip and port to contact this guy directly.*/ |
73 | uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ | 75 | uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ |
76 | |||
77 | int (*connection_status_callback)(void *object, int id, uint8_t status); | ||
78 | void *connection_status_callback_object; | ||
79 | int connection_status_callback_id; | ||
80 | |||
81 | int (*connection_data_callback)(void *object, int id, uint8_t *data, uint16_t length); | ||
82 | void *connection_data_callback_object; | ||
83 | int connection_data_callback_id; | ||
84 | |||
85 | uint64_t last_data_packet_sent; | ||
74 | } Crypto_Connection; | 86 | } Crypto_Connection; |
75 | 87 | ||
76 | typedef struct { | 88 | typedef struct { |
@@ -117,12 +129,52 @@ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void * | |||
117 | */ | 129 | */ |
118 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); | 130 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); |
119 | 131 | ||
132 | /* Create a crypto connection. | ||
133 | * If one to that real public key already exists, return it. | ||
134 | * | ||
135 | * return -1 on failure. | ||
136 | * return connection id on success. | ||
137 | */ | ||
138 | int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key); | ||
139 | |||
140 | /* Set the DHT public key of the crypto connection. | ||
141 | * | ||
142 | * return -1 on failure. | ||
143 | * return 0 on success. | ||
144 | */ | ||
145 | int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key); | ||
146 | |||
147 | /* Set the direct ip of the crypto connection. | ||
148 | * | ||
149 | * return -1 on failure. | ||
150 | * return 0 on success. | ||
151 | */ | ||
152 | int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port); | ||
153 | |||
154 | /* Set function to be called when connection with crypt_connection_id goes connects/disconnects. | ||
155 | * | ||
156 | * The set function should return -1 on failure and 0 on success. | ||
157 | * Note that if this function is set, the connection will clear itself on disconnect. | ||
158 | * Object and id will be passed to this function untouched. | ||
159 | * status is 1 if the connection is going online, 0 if it is going offline. | ||
160 | * | ||
161 | * return -1 on failure. | ||
162 | * return 0 on success. | ||
163 | */ | ||
164 | int connection_status_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_status_callback)(void *object, | ||
165 | int id, uint8_t status), void *object, int id); | ||
120 | 166 | ||
121 | /* return 0 if there is no received data in the buffer. | 167 | /* Set function to be called when connection with crypt_connection_id receives a data packet of length. |
122 | * return -1 if the packet was discarded. | 168 | * |
123 | * return length of received data if successful. | 169 | * The set function should return -1 on failure and 0 on success. |
170 | * Object and id will be passed to this function untouched. | ||
171 | * | ||
172 | * return -1 on failure. | ||
173 | * return 0 on success. | ||
124 | */ | 174 | */ |
125 | int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data); | 175 | int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, |
176 | int id, uint8_t *data, uint16_t length), void *object, int id); | ||
177 | |||
126 | 178 | ||
127 | /* returns the number of packet slots left in the sendbuffer. | 179 | /* returns the number of packet slots left in the sendbuffer. |
128 | * return 0 if failure. | 180 | * return 0 if failure. |
@@ -134,17 +186,11 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) | |||
134 | */ | 186 | */ |
135 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); | 187 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); |
136 | 188 | ||
137 | /* Start a secure connection with other peer who has public_key and ip_port. | ||
138 | * | ||
139 | * return -1 if failure. | ||
140 | * return crypt_connection_id of the initialized connection if everything went well. | ||
141 | */ | ||
142 | int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port); | ||
143 | 189 | ||
144 | /* Kill a crypto connection. | 190 | /* Kill a crypto connection. |
145 | * | 191 | * |
146 | * return 0 if killed successfully. | 192 | * return -1 on failure. |
147 | * return 1 if there was a problem. | 193 | * return 0 on success. |
148 | */ | 194 | */ |
149 | int crypto_kill(Net_Crypto *c, int crypt_connection_id); | 195 | int crypto_kill(Net_Crypto *c, int crypt_connection_id); |
150 | 196 | ||
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index c7ebcd15..ca92ee42 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c | |||
@@ -796,14 +796,12 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) | |||
796 | return friend_num; | 796 | return friend_num; |
797 | } | 797 | } |
798 | 798 | ||
799 | /* Get the ip of friend friendnum and put it in ip_port | 799 | /* Copy friends DHT public key into dht_key. |
800 | * | ||
801 | * return -1, -- if client_id does NOT refer to a friend | ||
802 | * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) | ||
803 | * return 1, ip if client_id refers to a friend and we found him | ||
804 | * | 800 | * |
801 | * return -1 on failure (no key copied). | ||
802 | * return 0 on success (key copied). | ||
805 | */ | 803 | */ |
806 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) | 804 | int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key) |
807 | { | 805 | { |
808 | if ((uint32_t)friend_num >= onion_c->num_friends) | 806 | if ((uint32_t)friend_num >= onion_c->num_friends) |
809 | return -1; | 807 | return -1; |
@@ -814,9 +812,28 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) | |||
814 | if (!onion_c->friends_list[friend_num].is_fake_clientid) | 812 | if (!onion_c->friends_list[friend_num].is_fake_clientid) |
815 | return -1; | 813 | return -1; |
816 | 814 | ||
817 | return DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port); | 815 | memcpy(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES); |
816 | return 0; | ||
817 | } | ||
818 | |||
819 | /* Get the ip of friend friendnum and put it in ip_port | ||
820 | * | ||
821 | * return -1, -- if client_id does NOT refer to a friend | ||
822 | * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) | ||
823 | * return 1, ip if client_id refers to a friend and we found him | ||
824 | * | ||
825 | */ | ||
826 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) | ||
827 | { | ||
828 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; | ||
829 | |||
830 | if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) != 0) | ||
831 | return -1; | ||
832 | |||
833 | return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port); | ||
818 | } | 834 | } |
819 | 835 | ||
836 | |||
820 | /* Set if friend is online or not. | 837 | /* Set if friend is online or not. |
821 | * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online. | 838 | * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online. |
822 | * | 839 | * |
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 6b960e40..4affcc6a 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h | |||
@@ -172,6 +172,13 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on | |||
172 | */ | 172 | */ |
173 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); | 173 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); |
174 | 174 | ||
175 | /* Copy friends DHT public key into dht_key. | ||
176 | * | ||
177 | * return -1 on failure (no key copied). | ||
178 | * return 0 on success (key copied). | ||
179 | */ | ||
180 | int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key); | ||
181 | |||
175 | #define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) | 182 | #define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) |
176 | #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) | 183 | #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) |
177 | 184 | ||