/* return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, bool priority) { if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { return -1; } bool sendpriority = 1; if (send_pending_data(con) == -1) { if (priority) { sendpriority = 0; } else { return 0; } } VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); memcpy(packet, &c_length, sizeof(uint16_t)); int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) { return -1; } if (priority) { len = sendpriority ? send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL) : 0; if (len <= 0) { len = 0; } increment_nonce(con->sent_nonce); if ((unsigned int)len == SIZEOF_VLA(packet)) { return 1; } return add_priority(con, packet, SIZEOF_VLA(packet), len); } len = send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL); if (len <= 0) { return 0; } increment_nonce(con->sent_nonce); if ((unsigned int)len == SIZEOF_VLA(packet)) { return 1; } memcpy(con->last_packet, packet, SIZEOF_VLA(packet)); con->last_packet_length = SIZEOF_VLA(packet); con->last_packet_sent = len; return 1; }
static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, uint16_t length) { TCP_Server *TCP_server = (TCP_Server *)object; uint32_t index = dest.ip.ip6.uint32[0]; if (index >= TCP_server->size_accepted_connections) { return 1; } TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[index]; if (con->identifier != dest.ip.ip6.uint64[1]) { return 1; } VLA(uint8_t, packet, 1 + length); memcpy(packet + 1, data, length); packet[0] = TCP_PACKET_ONION_RESPONSE; if (write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0) != 1) { return 1; } return 0; }
static int handle_data_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) { Onion_Announce *onion_a = (Onion_Announce *)object; if (length <= DATA_REQUEST_MIN_SIZE_RECV) { return 1; } if (length > ONION_MAX_PACKET_SIZE) { return 1; } int index = in_entries(onion_a, packet + 1); if (index == -1) { return 1; } VLA(uint8_t, data, length - (CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3)); data[0] = NET_PACKET_ONION_DATA_RESPONSE; memcpy(data + 1, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3)); if (send_onion_response(onion_a->net, onion_a->entries[index].ret_ip_port, data, SIZEOF_VLA(data), onion_a->entries[index].ret) == -1) { return 1; } return 0; }
/* return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length) { VLA(uint8_t, packet, 1 + length); packet[0] = TCP_PACKET_ONION_REQUEST; memcpy(packet + 1, data, length); return write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0); }
static void set_random(Tox *m, bool (*setter)(Tox *, const uint8_t *, size_t, Tox_Err_Set_Info *), size_t length) { VLA(uint8_t, text, length); uint32_t i; for (i = 0; i < length; ++i) { text[i] = random_u08(); } setter(m, text, SIZEOF_VLA(text), nullptr); }
static void set_random(Tox *m, bool (*setter)(Tox *, const uint8_t *, size_t, TOX_ERR_SET_INFO *), size_t length) { VLA(uint8_t, text, length); uint32_t i; for (i = 0; i < length; ++i) { text[i] = rand(); } setter(m, text, SIZEOF_VLA(text), 0); }
/* return 1 on success. * return 0 if could not send packet. * return -1 on failure. */ int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length) { if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) { return -1; } VLA(uint8_t, packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length); packet[0] = TCP_PACKET_OOB_SEND; memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length); return write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0); }
/* return 1 on success. * return 0 if could not send packet. * return -1 on failure. */ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length) { if (con_id >= NUM_CLIENT_CONNECTIONS) { return -1; } if (con->connections[con_id].status != 2) { return -1; } if (send_ping_response(con) == 0 || send_ping_request(con) == 0) { return 0; } VLA(uint8_t, packet, 1 + length); packet[0] = con_id + NUM_RESERVED_PORTS; memcpy(packet + 1, data, length); return write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0); }
/* return 0 on success. * return -1 on failure (connection must be killed). */ static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *public_key, const uint8_t *data, uint16_t length) { if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) { return -1; } TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id]; int other_index = get_TCP_connection_index(TCP_server, public_key); if (other_index != -1) { VLA(uint8_t, resp_packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length); resp_packet[0] = TCP_PACKET_OOB_RECV; memcpy(resp_packet + 1, con->public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(resp_packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length); write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet, SIZEOF_VLA(resp_packet), 0); } return 0; }
/* Send a Friend request packet. * * return -1 if failure. * return 0 if it sent the friend request directly to the friend. * return the number of peers it was routed through if it did not send it directly. */ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data, uint16_t length) { if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) { return -1; } const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id); if (!friend_con) { return -1; } VLA(uint8_t, packet, 1 + sizeof(nospam_num) + length); memcpy(packet + 1, &nospam_num, sizeof(nospam_num)); memcpy(packet + 1 + sizeof(nospam_num), data, length); if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) { packet[0] = PACKET_ID_FRIEND_REQUESTS; return write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, packet, SIZEOF_VLA(packet), 0) != -1; } packet[0] = CRYPTO_PACKET_FRIEND_REQ; const int num = send_onion_data(fr_c->onion_c, friend_con->onion_friendnum, packet, SIZEOF_VLA(packet)); if (num <= 0) { return -1; } return num; }