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 no data received. * return -1 on failure (connection refused). */ static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn) { char success[] = "200"; uint8_t data[16]; // draining works the best if the length is a power of 2 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data) - 1); if (ret == -1) { return 0; } data[sizeof(data) - 1] = 0; if (strstr((char *)data, success)) { // drain all data unsigned int data_left = TCP_socket_data_recv_buffer(TCP_conn->sock); if (data_left) { VLA(uint8_t, temp_data, data_left); read_TCP_packet(TCP_conn->sock, temp_data, data_left); } return 1; } return -1; }
/* 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); }
/* 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; }
/* 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 LLVMValueRef get_prototype(compile_t* c, gentype_t* g, const char *name, ast_t* typeargs, ast_t* fun) { // Behaviours and actor constructors also have sender functions. bool sender = false; switch(ast_id(fun)) { case TK_NEW: sender = g->underlying == TK_ACTOR; break; case TK_BE: sender = true; break; default: {} } // Get a fully qualified name: starts with the type name, followed by the // type arguments, followed by the function name, followed by the function // level type arguments. const char* funname = genname_fun(g->type_name, name, typeargs); // If the function already exists, just return it. LLVMValueRef func = LLVMGetNamedFunction(c->module, funname); if(func != NULL) return func; LLVMTypeRef ftype = get_signature(c, g, fun); if(ftype == NULL) return NULL; // If the function exists now, just return it. func = LLVMGetNamedFunction(c->module, funname); if(func != NULL) return func; if(sender) { // Generate the sender prototype. const char* be_name = genname_be(funname); func = codegen_addfun(c, be_name, ftype); // Change the return type to void for the handler. size_t count = LLVMCountParamTypes(ftype); VLA(LLVMTypeRef, tparams, count); LLVMGetParamTypes(ftype, tparams); ftype = LLVMFunctionType(c->void_type, tparams, (int)count, false); } // Generate the function prototype. return codegen_addfun(c, funname, ftype); }
static LLVMTypeRef send_message(compile_t* c, ast_t* fun, LLVMValueRef to, LLVMValueRef func, uint32_t index) { // Get the parameter types. LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(func)); int count = LLVMCountParamTypes(f_type) + 2; VLA(LLVMTypeRef, f_params, count); LLVMGetParamTypes(f_type, &f_params[2]); // The first one becomes the message size, the second the message ID. f_params[0] = c->i32; f_params[1] = c->i32; f_params[2] = c->void_ptr; LLVMTypeRef msg_type = LLVMStructTypeInContext(c->context, f_params, count, false); LLVMTypeRef msg_type_ptr = LLVMPointerType(msg_type, 0); // Allocate the message, setting its size and ID. size_t msg_size = LLVMABISizeOfType(c->target_data, msg_type); LLVMValueRef args[2]; args[0] = LLVMConstInt(c->i32, pool_index(msg_size), false); args[1] = LLVMConstInt(c->i32, index, false); LLVMValueRef msg = gencall_runtime(c, "pony_alloc_msg", args, 2, ""); LLVMValueRef msg_ptr = LLVMBuildBitCast(c->builder, msg, msg_type_ptr, ""); // Trace while populating the message contents. LLVMValueRef start_trace = gencall_runtime(c, "pony_gc_send", NULL, 0, ""); ast_t* params = ast_childidx(fun, 3); ast_t* param = ast_child(params); bool need_trace = false; for(int i = 3; i < count; i++) { LLVMValueRef arg = LLVMGetParam(func, i - 2); LLVMValueRef arg_ptr = LLVMBuildStructGEP(c->builder, msg_ptr, i, ""); LLVMBuildStore(c->builder, arg, arg_ptr); need_trace |= gentrace(c, arg, ast_type(param)); param = ast_sibling(param); } if(need_trace) gencall_runtime(c, "pony_send_done", NULL, 0, ""); else LLVMInstructionEraseFromParent(start_trace); // Send the message. args[0] = LLVMBuildBitCast(c->builder, to, c->object_ptr, ""); args[1] = msg; gencall_runtime(c, "pony_sendv", args, 2, ""); // Return the type of the message. return msg_type_ptr; }
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); }
static LLVMTypeRef get_signature(compile_t* c, gentype_t* g, ast_t* fun) { // Get a type for the result. ast_t* rtype = ast_childidx(fun, 4); gentype_t rtype_g; if(!gentype(c, rtype, &rtype_g)) { ast_error(rtype, "couldn't generate result type"); return NULL; } // Count the parameters, including the receiver. ast_t* params = ast_childidx(fun, 3); size_t count = ast_childcount(params) + 1; VLA(LLVMTypeRef, tparams, count); count = 0; // Get a type for the receiver. tparams[count++] = g->use_type; // Get a type for each parameter. ast_t* param = ast_child(params); while(param != NULL) { ast_t* ptype = ast_childidx(param, 1); gentype_t ptype_g; if(!gentype(c, ptype, &ptype_g)) { ast_error(ptype, "couldn't generate parameter type"); return NULL; } tparams[count++] = ptype_g.use_type; param = ast_sibling(param); } LLVMTypeRef result = rtype_g.use_type; // Generate the function type. return LLVMFunctionType(result, tparams, (int)count, false); }
static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length, void *user_data) { if (!sendf_ok) { ck_abort_msg("Didn't get resume control"); } if (sending_pos != position) { ck_abort_msg("Bad position %llu", (unsigned long long)position); } if (length == 0) { if (file_sending_done) { ck_abort_msg("File sending already done."); } file_sending_done = 1; return; } if (position + length > max_sending) { if (m_send_reached) { ck_abort_msg("Requested done file transfer."); } length = max_sending - position; m_send_reached = 1; } TOX_ERR_FILE_SEND_CHUNK error; VLA(uint8_t, f_data, length); memset(f_data, sending_num, length); if (tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error)) { ++sending_num; sending_pos += length; } else { ck_abort_msg("Could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length); } if (error != TOX_ERR_FILE_SEND_CHUNK_OK) { ck_abort_msg("Wrong error code"); } }
static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const Mono_Time *mono_time, const uint8_t *comp_public_key) { // Pass comp_public_key to qsort with each Client_data entry, so the // comparison function can use it as the base of comparison. VLA(Cmp_data, cmp_list, length); for (uint32_t i = 0; i < length; ++i) { cmp_list[i].mono_time = mono_time; cmp_list[i].base_public_key = comp_public_key; cmp_list[i].entry = list[i]; } qsort(cmp_list, length, sizeof(Cmp_data), cmp_entry); for (uint32_t i = 0; i < length; ++i) { list[i] = cmp_list[i].entry; } }
static void add_dispatch_case(compile_t* c, gentype_t* g, ast_t* fun, uint32_t index, LLVMValueRef handler, LLVMTypeRef type) { // Add a case to the dispatch function to handle this message. codegen_startfun(c, g->dispatch_fn, false); LLVMBasicBlockRef block = codegen_block(c, "handler"); LLVMValueRef id = LLVMConstInt(c->i32, index, false); LLVMAddCase(g->dispatch_switch, id, block); // Destructure the message. LLVMPositionBuilderAtEnd(c->builder, block); LLVMValueRef msg = LLVMBuildBitCast(c->builder, g->dispatch_msg, type, ""); int count = LLVMCountParams(handler); VLA(LLVMValueRef, args, count); LLVMValueRef this_ptr = LLVMGetParam(g->dispatch_fn, 0); args[0] = LLVMBuildBitCast(c->builder, this_ptr, g->use_type, ""); // Trace the message. LLVMValueRef start_trace = gencall_runtime(c, "pony_gc_recv", NULL, 0, ""); ast_t* params = ast_childidx(fun, 3); ast_t* param = ast_child(params); bool need_trace = false; for(int i = 1; i < count; i++) { LLVMValueRef field = LLVMBuildStructGEP(c->builder, msg, i + 2, ""); args[i] = LLVMBuildLoad(c->builder, field, ""); need_trace |= gentrace(c, args[i], ast_type(param)); param = ast_sibling(param); } if(need_trace) gencall_runtime(c, "pony_recv_done", NULL, 0, ""); else LLVMInstructionEraseFromParent(start_trace); // Call the handler. codegen_call(c, handler, args, count); LLVMBuildRetVoid(c->builder); codegen_finishfun(c); }
/* 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 length of received packet on success. * return 0 if could not read any packet. * return -1 on failure (connection must be killed). */ int read_packet_TCP_secure_connection(Socket sock, uint16_t *next_packet_length, const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, uint16_t max_len) { if (*next_packet_length == 0) { uint16_t len = read_TCP_length(sock); if (len == (uint16_t)~0) { return -1; } if (len == 0) { return 0; } *next_packet_length = len; } if (max_len + CRYPTO_MAC_SIZE < *next_packet_length) { return -1; } VLA(uint8_t, data_encrypted, *next_packet_length); int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length); if (len_packet != *next_packet_length) { return 0; } *next_packet_length = 0; int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); if (len + CRYPTO_MAC_SIZE != len_packet) { return -1; } increment_nonce(recv_nonce); return len; }
static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, size_t length, void *user_data) { if (size_recv != position) { ck_abort_msg("Bad position"); } if (length == 0) { file_recv = 1; return; } VLA(uint8_t, f_data, length); memset(f_data, num, length); ++num; if (memcmp(f_data, data, length) == 0) { size_recv += length; } else { ck_abort_msg("FILE_CORRUPTED"); } }
/* 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; }
int main(int argc, char *argv[]) { Tox *tox1 = tox_new_log(0, 0, 0); Tox *tox2 = tox_new_log(0, 0, 0); struct test_data to_compare = { { 0 } }; uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; tox_self_get_public_key(tox1, public_key); tox_friend_add_norequest(tox2, public_key, NULL); tox_self_get_public_key(tox2, public_key); tox_friend_add_norequest(tox1, public_key, NULL); uint8_t reference_name[TOX_MAX_NAME_LENGTH] = { 0 }; uint8_t reference_status[TOX_MAX_STATUS_MESSAGE_LENGTH] = { 0 }; set_random(tox1, tox_self_set_name, TOX_MAX_NAME_LENGTH); set_random(tox2, tox_self_set_name, TOX_MAX_NAME_LENGTH); set_random(tox1, tox_self_set_status_message, TOX_MAX_STATUS_MESSAGE_LENGTH); set_random(tox2, tox_self_set_status_message, TOX_MAX_STATUS_MESSAGE_LENGTH); tox_self_get_name(tox2, reference_name); tox_self_get_status_message(tox2, reference_status); tox_callback_friend_name(tox1, namechange_callback); tox_callback_friend_status_message(tox1, statuschange_callback); while (true) { if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2) && tox_friend_get_connection_status(tox1, 0, 0) == TOX_CONNECTION_UDP) { printf("Connected.\n"); break; } tox_iterate(tox1, &to_compare); tox_iterate(tox2, NULL); c_sleep(tox_iteration_interval(tox1)); } while (true) { if (to_compare.received_name && to_compare.received_status_message) { printf("Exchanged names and status messages.\n"); break; } tox_iterate(tox1, &to_compare); tox_iterate(tox2, NULL); c_sleep(tox_iteration_interval(tox1)); } size_t save_size = tox_get_savedata_size(tox1); VLA(uint8_t, savedata, save_size); tox_get_savedata(tox1, savedata); struct Tox_Options *options = tox_options_new(NULL); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_data(options, savedata, save_size); Tox *tox_to_compare = tox_new(options, 0); tox_friend_get_name(tox_to_compare, 0, to_compare.name, 0); tox_friend_get_status_message(tox_to_compare, 0, to_compare.status_message, 0); assert(memcmp(reference_name, to_compare.name, TOX_MAX_NAME_LENGTH) == 0); assert(memcmp(reference_status, to_compare.status_message, TOX_MAX_STATUS_MESSAGE_LENGTH) == 0); tox_options_free(options); tox_kill(tox1); tox_kill(tox2); tox_kill(tox_to_compare); return 0; }
static void test_one(void) { uint8_t name[TOX_MAX_NAME_LENGTH]; uint8_t status_message[TOX_MAX_STATUS_MESSAGE_LENGTH]; uint8_t name2[TOX_MAX_NAME_LENGTH]; uint8_t status_message2[TOX_MAX_STATUS_MESSAGE_LENGTH]; uint32_t index[] = { 1, 2 }; Tox *tox1 = tox_new_log(nullptr, nullptr, &index[0]); set_random_name_and_status_message(tox1, name, status_message); Tox *tox2 = tox_new_log(nullptr, nullptr, &index[1]); set_random_name_and_status_message(tox2, name2, status_message2); uint8_t address[TOX_ADDRESS_SIZE]; tox_self_get_address(tox1, address); Tox_Err_Friend_Add error; uint32_t ret = tox_friend_add(tox1, address, (const uint8_t *)"m", 1, &error); ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_OWN_KEY, "Adding own address worked."); tox_self_get_address(tox2, address); uint8_t message[TOX_MAX_FRIEND_REQUEST_LENGTH + 1]; ret = tox_friend_add(tox1, address, nullptr, 0, &error); ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_NULL, "Sending request with no message worked."); ret = tox_friend_add(tox1, address, message, 0, &error); ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_NO_MESSAGE, "Sending request with no message worked."); ret = tox_friend_add(tox1, address, message, sizeof(message), &error); ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_TOO_LONG, "TOX_MAX_FRIEND_REQUEST_LENGTH is too big."); address[0]++; ret = tox_friend_add(tox1, address, (const uint8_t *)"m", 1, &error); ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM, "Adding address with bad checksum worked."); tox_self_get_address(tox2, address); ret = tox_friend_add(tox1, address, message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error); ck_assert_msg(ret == 0 && error == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend."); ret = tox_friend_add(tox1, address, message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error); ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_ALREADY_SENT, "Adding friend twice worked."); tox_self_set_name(tox1, name, sizeof(name), nullptr); ck_assert_msg(tox_self_get_name_size(tox1) == sizeof(name), "Can't set name of TOX_MAX_NAME_LENGTH"); tox_self_set_status_message(tox1, status_message, sizeof(status_message), nullptr); ck_assert_msg(tox_self_get_status_message_size(tox1) == sizeof(status_message), "Can't set status message of TOX_MAX_STATUS_MESSAGE_LENGTH"); tox_self_get_address(tox1, address); size_t save_size = tox_get_savedata_size(tox1); VLA(uint8_t, data, save_size); tox_get_savedata(tox1, data); tox_kill(tox2); Tox_Err_New err_n; struct Tox_Options *options = tox_options_new(nullptr); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_data(options, data, save_size); tox2 = tox_new_log(options, &err_n, &index[1]); ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed"); ck_assert_msg(tox_self_get_name_size(tox2) == sizeof name, "Wrong name size."); ck_assert_msg(tox_self_get_status_message_size(tox2) == sizeof status_message, "Wrong status message size"); uint8_t name_loaded[TOX_MAX_NAME_LENGTH] = { 0 }; tox_self_get_name(tox2, name_loaded); ck_assert_msg(!memcmp(name, name_loaded, sizeof name), "Wrong name."); uint8_t status_message_loaded[TOX_MAX_STATUS_MESSAGE_LENGTH] = { 0 }; tox_self_get_status_message(tox2, status_message_loaded); ck_assert_msg(!memcmp(status_message, status_message_loaded, sizeof status_message_loaded), "Wrong status message."); uint8_t address2[TOX_ADDRESS_SIZE] = { 0 }; tox_self_get_address(tox2, address2); ck_assert_msg(memcmp(address2, address, TOX_ADDRESS_SIZE) == 0, "Wrong address."); uint8_t new_name[TOX_MAX_NAME_LENGTH] = { 0 }; tox_self_get_name(tox2, new_name); ck_assert_msg(memcmp(name, new_name, TOX_MAX_NAME_LENGTH) == 0, "Wrong name"); uint8_t sk[TOX_SECRET_KEY_SIZE]; tox_self_get_secret_key(tox2, sk); tox_kill(tox2); tox_options_default(options); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_SECRET_KEY); tox_options_set_savedata_data(options, sk, sizeof(sk)); tox2 = tox_new_log(options, &err_n, &index[1]); ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed"); uint8_t address3[TOX_ADDRESS_SIZE]; tox_self_get_address(tox2, address3); ck_assert_msg(memcmp(address3, address, TOX_PUBLIC_KEY_SIZE) == 0, "Wrong public key."); uint8_t pk[TOX_PUBLIC_KEY_SIZE]; tox_self_get_public_key(tox2, pk); ck_assert_msg(memcmp(pk, address, TOX_PUBLIC_KEY_SIZE) == 0, "Wrong public key."); tox_options_free(options); tox_kill(tox1); tox_kill(tox2); }
int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); Tox *const tox1 = tox_new_log(nullptr, nullptr, nullptr); Tox *const tox2 = tox_new_log(nullptr, nullptr, nullptr); printf("bootstrapping tox2 off tox1\n"); uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; tox_self_get_dht_id(tox1, dht_key); const uint16_t dht_port = tox_self_get_udp_port(tox1, nullptr); tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr); struct test_data to_compare = {{0}}; uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; tox_self_get_public_key(tox1, public_key); tox_friend_add_norequest(tox2, public_key, nullptr); tox_self_get_public_key(tox2, public_key); tox_friend_add_norequest(tox1, public_key, nullptr); uint8_t reference_name[TOX_MAX_NAME_LENGTH] = { 0 }; uint8_t reference_status[TOX_MAX_STATUS_MESSAGE_LENGTH] = { 0 }; set_random(tox1, tox_self_set_name, TOX_MAX_NAME_LENGTH); set_random(tox2, tox_self_set_name, TOX_MAX_NAME_LENGTH); set_random(tox1, tox_self_set_status_message, TOX_MAX_STATUS_MESSAGE_LENGTH); set_random(tox2, tox_self_set_status_message, TOX_MAX_STATUS_MESSAGE_LENGTH); tox_self_get_name(tox2, reference_name); tox_self_get_status_message(tox2, reference_status); tox_callback_friend_name(tox1, namechange_callback); tox_callback_friend_status_message(tox1, statuschange_callback); while (true) { if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2) && tox_friend_get_connection_status(tox1, 0, nullptr) == TOX_CONNECTION_UDP) { printf("Connected.\n"); break; } tox_iterate(tox1, &to_compare); tox_iterate(tox2, nullptr); c_sleep(tox_iteration_interval(tox1)); } while (true) { if (to_compare.received_name && to_compare.received_status_message) { printf("Exchanged names and status messages.\n"); break; } tox_iterate(tox1, &to_compare); tox_iterate(tox2, nullptr); c_sleep(tox_iteration_interval(tox1)); } size_t save_size = tox_get_savedata_size(tox1); VLA(uint8_t, savedata, save_size); tox_get_savedata(tox1, savedata); struct Tox_Options *const options = tox_options_new(nullptr); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_data(options, savedata, save_size); Tox *const tox_to_compare = tox_new_log(options, nullptr, nullptr); tox_friend_get_name(tox_to_compare, 0, to_compare.name, nullptr); tox_friend_get_status_message(tox_to_compare, 0, to_compare.status_message, nullptr); ck_assert_msg(memcmp(reference_name, to_compare.name, TOX_MAX_NAME_LENGTH) == 0, "incorrect name: should be all zeroes"); ck_assert_msg(memcmp(reference_status, to_compare.status_message, TOX_MAX_STATUS_MESSAGE_LENGTH) == 0, "incorrect status message: should be all zeroes"); tox_options_free(options); tox_kill(tox1); tox_kill(tox2); tox_kill(tox_to_compare); return 0; }
/* return 0 on success * return -1 on failure */ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *data, uint16_t length) { if (length == 0) { return -1; } TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id]; switch (data[0]) { case TCP_PACKET_ROUTING_REQUEST: { if (length != 1 + CRYPTO_PUBLIC_KEY_SIZE) { return -1; } return handle_TCP_routing_req(TCP_server, con_id, data + 1); } case TCP_PACKET_CONNECTION_NOTIFICATION: { if (length != 2) { return -1; } break; } case TCP_PACKET_DISCONNECT_NOTIFICATION: { if (length != 2) { return -1; } return rm_connection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS); } case TCP_PACKET_PING: { if (length != 1 + sizeof(uint64_t)) { return -1; } uint8_t response[1 + sizeof(uint64_t)]; response[0] = TCP_PACKET_PONG; memcpy(response + 1, data + 1, sizeof(uint64_t)); write_packet_TCP_secure_connection(con, response, sizeof(response), 1); return 0; } case TCP_PACKET_PONG: { if (length != 1 + sizeof(uint64_t)) { return -1; } uint64_t ping_id; memcpy(&ping_id, data + 1, sizeof(uint64_t)); if (ping_id) { if (ping_id == con->ping_id) { con->ping_id = 0; } return 0; } return -1; } case TCP_PACKET_OOB_SEND: { if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) { return -1; } return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_PUBLIC_KEY_SIZE)); } case TCP_PACKET_ONION_REQUEST: { if (TCP_server->onion) { if (length <= 1 + CRYPTO_NONCE_SIZE + ONION_SEND_BASE * 2) { return -1; } IP_Port source; source.port = 0; // dummy initialise source.ip.family = TCP_ONION_FAMILY; source.ip.ip6.uint32[0] = con_id; source.ip.ip6.uint32[1] = 0; source.ip.ip6.uint64[1] = con->identifier; onion_send_1(TCP_server->onion, data + 1 + CRYPTO_NONCE_SIZE, length - (1 + CRYPTO_NONCE_SIZE), source, data + 1); } return 0; } case TCP_PACKET_ONION_RESPONSE: { return -1; } default: { if (data[0] < NUM_RESERVED_PORTS) { return -1; } uint8_t c_id = data[0] - NUM_RESERVED_PORTS; if (c_id >= NUM_CLIENT_CONNECTIONS) { return -1; } if (con->connections[c_id].status == 0) { return -1; } if (con->connections[c_id].status != 2) { return 0; } uint32_t index = con->connections[c_id].index; uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS; VLA(uint8_t, new_data, length); memcpy(new_data, data, length); new_data[0] = other_c_id; int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length, 0); if (ret == -1) { return -1; } return 0; } } return 0; }