TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t *ports, uint8_t *public_key, uint8_t *secret_key, Onion *onion) { if (num_sockets == 0 || ports == NULL) return NULL; if (networking_at_startup() != 0) { return NULL; } TCP_Server *temp = calloc(1, sizeof(TCP_Server)); if (temp == NULL) return NULL; temp->socks_listening = calloc(num_sockets, sizeof(sock_t)); if (temp->socks_listening == NULL) { free(temp); return NULL; } uint8_t family; if (ipv6_enabled) { family = AF_INET6; } else { family = AF_INET; } uint32_t i; for (i = 0; i < num_sockets; ++i) { sock_t sock = new_listening_TCP_socket(family, ports[i]); if (sock_valid(sock)) { temp->socks_listening[temp->num_listening_socks] = sock; ++temp->num_listening_socks; } } if (temp->num_listening_socks == 0) { free(temp); return NULL; } if (onion) { temp->onion = onion; set_callback_handle_recv_1(onion, &handle_onion_recv_1, temp); } memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES); memcpy(temp->secret_key, secret_key, crypto_box_SECRETKEYBYTES); return temp; }
TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *public_key, const uint8_t *secret_key, Onion *onion) { if (num_sockets == 0 || ports == NULL) return NULL; if (networking_at_startup() != 0) { return NULL; } TCP_Server *temp = calloc(1, sizeof(TCP_Server)); if (temp == NULL) return NULL; temp->socks_listening = calloc(num_sockets, sizeof(sock_t)); if (temp->socks_listening == NULL) { free(temp); return NULL; } #ifdef TCP_SERVER_USE_EPOLL temp->efd = epoll_create1(0); if (temp->efd == -1) { free(temp); return NULL; } #endif uint8_t family; if (ipv6_enabled) { family = AF_INET6; } else { family = AF_INET; } uint32_t i; #ifdef TCP_SERVER_USE_EPOLL struct epoll_event ev; #endif for (i = 0; i < num_sockets; ++i) { sock_t sock = new_listening_TCP_socket(family, ports[i]); if (sock_valid(sock)) { #ifdef TCP_SERVER_USE_EPOLL ev.events = EPOLLIN; ev.data.u64 = sock | ((uint64_t)TCP_SOCKET_LISTENING << 32); if (epoll_ctl(temp->efd, EPOLL_CTL_ADD, sock, &ev) == -1) { continue; } #endif temp->socks_listening[temp->num_listening_socks] = sock; ++temp->num_listening_socks; } } if (temp->num_listening_socks == 0) { free(temp); return NULL; } if (onion) { temp->onion = onion; set_callback_handle_recv_1(onion, &handle_onion_recv_1, temp); } memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES); memcpy(temp->secret_key, secret_key, crypto_box_SECRETKEYBYTES); bs_list_init(&temp->accepted_key_list, crypto_box_PUBLICKEYBYTES, 8); return temp; }
/* Create new TCP connection to ip_port/public_key */ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info) { if (networking_at_startup() != 0) { return NULL; } if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) { return NULL; } uint8_t family = ip_port.ip.family; TCP_Proxy_Info default_proxyinfo; if (proxy_info == NULL) { default_proxyinfo.proxy_type = TCP_PROXY_NONE; proxy_info = &default_proxyinfo; } if (proxy_info->proxy_type != TCP_PROXY_NONE) { family = proxy_info->ip_port.ip.family; } Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP); if (!sock_valid(sock)) { return NULL; } if (!set_socket_nosigpipe(sock)) { kill_sock(sock); return 0; } if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) { kill_sock(sock); return NULL; } TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(sizeof(TCP_Client_Connection), 1); if (temp == NULL) { kill_sock(sock); return NULL; } temp->sock = sock; memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE); encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key); temp->ip_port = ip_port; temp->proxy_info = *proxy_info; switch (proxy_info->proxy_type) { case TCP_PROXY_HTTP: temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING; proxy_http_generate_connection_request(temp); break; case TCP_PROXY_SOCKS5: temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING; proxy_socks5_generate_handshake(temp); break; case TCP_PROXY_NONE: temp->status = TCP_CLIENT_CONNECTING; if (generate_handshake(temp) == -1) { kill_sock(sock); free(temp); return NULL; } break; } temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT; return temp; }