/* Handle close-tunnel frame received from the client */ int handle_client_tcp_fin_frame(protocol_frame *rcvd_frame) { tunnel *tun=NULL; int offset = 0; int connid = rcvd_frame->connid; HASH_FIND_INT(by_id, &connid, tun); if(!tun) { log_printf(L_WARNING, "Got TCP FIN frame with unknown tunnel ID %d\n", rcvd_frame->connid); return -1; } if(tun->friendnumber != rcvd_frame->friendnumber) { log_printf(L_WARNING, "Friend #%d tried to close tunnel which belongs to #%d\n", rcvd_frame->friendnumber, tun->friendnumber); return -1; } tunnel_delete(tun); return 0; }
int do_server_loop() { struct timeval tv, tv_start, tv_end; unsigned long long ms_start, ms_end; fd_set fds; unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; tunnel *tun = NULL; tunnel *tmp = NULL; TOX_CONNECTION connected = 0; tox_callback_friend_lossless_packet(tox, parse_lossless_packet, NULL); tv.tv_sec = 0; tv.tv_usec = 20000; FD_ZERO(&master_server_fds); while(1) { TOX_CONNECTION tmp_isconnected = 0; uint32_t tox_do_interval_ms; int select_rv = 0; /* Let tox do its stuff */ tox_iterate(tox); /* Get the desired sleep time, used in select() later */ tox_do_interval_ms = tox_iteration_interval(tox); tv.tv_usec = (tox_do_interval_ms % 1000) * 1000; tv.tv_sec = tox_do_interval_ms / 1000; log_printf(L_DEBUG2, "Iteration interval: %dms\n", tox_do_interval_ms); gettimeofday(&tv_start, NULL); /* Check change in connection state */ tmp_isconnected = connection_status; if(tmp_isconnected != connected) { connected = tmp_isconnected; if(connected) { log_printf(L_DEBUG, "Connected to Tox network\n"); } else { log_printf(L_DEBUG, "Disconnected from Tox network\n"); } } fds = master_server_fds; /* Poll for data from our client connection */ select_rv = select(select_nfds, &fds, NULL, NULL, &tv); if(select_rv == -1 || select_rv == 0) { if(select_rv == -1) { log_printf(L_DEBUG, "Reading from local socket failed: code=%d (%s)\n", errno, strerror(errno)); } else { log_printf(L_DEBUG2, "Nothing to read..."); } } else { HASH_ITER(hh, by_id, tun, tmp) { if(FD_ISSET(tun->sockfd, &fds)) { int nbytes = recv(tun->sockfd, tox_packet_buf+PROTOCOL_BUFFER_OFFSET, READ_BUFFER_SIZE, 0); /* Check if connection closed */ if(nbytes <= 0) { char data[PROTOCOL_BUFFER_OFFSET]; protocol_frame frame_st, *frame; if(nbytes == 0) { log_printf(L_WARNING, "conn closed!\n"); } else { log_printf(L_WARNING, "conn closed, code=%d (%s)\n", errno, strerror(errno)); } frame = &frame_st; memset(frame, 0, sizeof(protocol_frame)); frame->friendnumber = tun->friendnumber; frame->packet_type = PACKET_TYPE_TCP_FIN; frame->connid = tun->connid; frame->data_length = 0; send_frame(frame, data); tunnel_delete(tun); continue; } else { protocol_frame frame_st, *frame; frame = &frame_st; memset(frame, 0, sizeof(protocol_frame)); frame->friendnumber = tun->friendnumber; frame->packet_type = PACKET_TYPE_TCP; frame->connid = tun->connid; frame->data_length = nbytes; send_frame(frame, tox_packet_buf); } } } } gettimeofday(&tv_end, NULL); ms_start = 1000 * tv_start.tv_sec + tv_start.tv_usec/1000; ms_end = 1000 * tv_end.tv_sec + tv_end.tv_usec/1000; if(ms_end - ms_start < tox_do_interval_ms) { /*log_printf(L_DEBUG, "Sleeping for %d ms extra to prevent high CPU usage\n", (tox_do_interval_ms - (ms_end - ms_start)));*/ usleep((tox_do_interval_ms - (ms_end - ms_start)) * 1000); } } }
/* * Call-back from the configuration server; save the configuration state. */ void config_callback(struct http_user_vars_s *vars) { bool should_save; if (http_user_var_lookup(vars, VAR_POST) == NULL) { // This is a GET request -- initialise variables: char buff[32]; http_user_var_insert(vars, VAR_ENABLED, bool_to_string(config.enabled)); http_user_var_insert(vars, VAR_HIDE_TCP, bool_to_string(config.hide_tcp)); http_user_var_insert(vars, VAR_HIDE_TCP_DATA, bool_to_string(config.hide_tcp_data)); http_user_var_insert(vars, VAR_HIDE_TCP_SYN, enum_to_string(config.hide_tcp_syn, flag_def, DEF_SIZE(flag_def))); http_user_var_insert(vars, VAR_HIDE_TCP_ACK, enum_to_string(config.hide_tcp_ack, flag_def, DEF_SIZE(flag_def))); http_user_var_insert(vars, VAR_HIDE_TCP_PSH, enum_to_string(config.hide_tcp_psh, flag_def, DEF_SIZE(flag_def))); http_user_var_insert(vars, VAR_HIDE_TCP_FIN, enum_to_string(config.hide_tcp_fin, flag_def, DEF_SIZE(flag_def))); http_user_var_insert(vars, VAR_HIDE_TCP_RST, enum_to_string(config.hide_tcp_rst, flag_def, DEF_SIZE(flag_def))); http_user_var_insert(vars, VAR_SPLIT_MODE, enum_to_string(config.split, split_def, DEF_SIZE(split_def))); http_user_var_insert(vars, VAR_LOG_LEVEL, enum_to_string((config_enum_t)log_get_level(), log_level_def, DEF_SIZE(log_level_def))); http_user_var_insert(vars, VAR_HIDE_UDP, bool_to_string(config.hide_udp)); http_user_var_insert(vars, VAR_GHOST_MODE, enum_to_string(config.ghost, ghost_def, DEF_SIZE(ghost_def))); http_user_var_insert(vars, VAR_GHOST_CHECK, bool_to_string(config.ghost_check)); http_user_var_insert(vars, VAR_GHOST_SET_TTL, bool_to_string(config.ghost_set_ttl)); snprintf(buff, sizeof(buff)-1, "%u", config.ghost_ttl); http_user_var_insert(vars, VAR_GHOST_TTL, buff); http_user_var_insert(vars, VAR_FRAG_MODE, enum_to_string(config.fragment, frag_def, DEF_SIZE(frag_def))); snprintf(buff, sizeof(buff)-1, "%u", config.tcp_port); http_user_var_insert(vars, VAR_TCP_PORT, buff); http_user_var_insert(vars, VAR_TCP_PROTO, protocol_get_name(config.tcp_proto)); snprintf(buff, sizeof(buff)-1, "%u", config.udp_port); http_user_var_insert(vars, VAR_UDP_PORT, buff); http_user_var_insert(vars, VAR_UDP_PROTO, protocol_get_name(config.udp_proto)); snprintf(buff, sizeof(buff)-1, "%u", config.mtu); http_user_var_insert(vars, VAR_MTU, buff); http_user_var_insert(vars, VAR_LAUNCH_UI, bool_to_string(config.launch_ui)); } else if (http_get_bool_var(vars, VAR_SAVE, &should_save) && should_save) { // This is a POST request that wishes to save a new configuration: struct config_s config_temp; memmove(&config_temp, &config, sizeof(struct config_s)); load_config(vars, &config_temp); // Copy to the global configuration state. thread_lock(&config_lock); memmove(&config, &config_temp, sizeof(struct config_s)); thread_unlock(&config_lock); // Save the new configuration to disk. write_config(&config_temp); // Handle add/del of tunnel URLs const char *url; if (http_get_string_var(vars, VAR_ADD_URL, &url) && url[0] != '\0') { tunnel_add(url); } else if (http_get_string_var(vars, VAR_DEL_URL, &url) && url[0] != '\0') { tunnel_delete(url); } } }