summaryrefslogtreecommitdiff
path: root/toxcore/Messenger.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/Messenger.c')
-rw-r--r--toxcore/Messenger.c540
1 files changed, 287 insertions, 253 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. */ 1860static int handle_status(void *object, int i, uint8_t status)
1861void 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; 1882static 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: { 2136static 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. */
2158void 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 }