static void accept_cb(EV_P_ ev_io *w, int revents) { listen_ctx_t *listener = (listen_ctx_t *)w; struct sockaddr_storage destaddr; int err; int serverfd = accept(listener->fd, NULL, NULL); if (serverfd == -1) { ERROR("accept"); return; } err = getdestaddr(serverfd, &destaddr); if (err) { ERROR("getdestaddr"); return; } setnonblocking(serverfd); int opt = 1; setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif int index = rand() % listener->remote_num; struct sockaddr *remote_addr = listener->remote_addr[index]; int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP); if (remotefd < 0) { ERROR("socket"); return; } setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif // Setup setnonblocking(remotefd); server_t *server = new_server(serverfd, listener->method); remote_t *remote = new_remote(remotefd, listener->timeout); server->remote = remote; remote->server = server; server->destaddr = destaddr; connect(remotefd, remote_addr, get_sockaddr_len(remote_addr)); // listen to remote connected event ev_io_start(EV_A_ & remote->send_ctx->io); ev_io_start(EV_A_ & server->recv_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); }
static void accept_cb(EV_P_ ev_io *w, int revents) { listen_ctx_t *listener = (listen_ctx_t *)w; struct sockaddr_storage destaddr; int err; int serverfd = accept(listener->fd, NULL, NULL); if (serverfd == -1) { ERROR("accept"); return; } err = getdestaddr(serverfd, &destaddr); if (err) { ERROR("getdestaddr"); return; } setnonblocking(serverfd); int opt = 1; setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif int index = rand() % listener->remote_num; struct sockaddr *remote_addr = listener->remote_addr[index]; int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP); if (remotefd == -1) { ERROR("socket"); return; } // Set flags setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif // Enable TCP keepalive feature int keepAlive = 1; int keepIdle = 40; int keepInterval = 20; int keepCount = 5; setsockopt(remotefd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive)); setsockopt(remotefd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle)); setsockopt(remotefd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval)); setsockopt(remotefd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount)); // Set non blocking setnonblocking(remotefd); // Enable MPTCP if (listener->mptcp == 1) { int err = setsockopt(remotefd, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt)); if (err == -1) { ERROR("failed to enable multipath TCP"); } } server_t *server = new_server(serverfd, listener->method); remote_t *remote = new_remote(remotefd, listener->timeout); server->remote = remote; remote->server = server; server->destaddr = destaddr; int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr)); if (r == -1 && errno != CONNECT_IN_PROGRESS) { ERROR("connect"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } // listen to remote connected event ev_io_start(EV_A_ & remote->send_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); ev_io_start(EV_A_ & server->recv_ctx->io); }
static void poll_cb(uv_poll_t *watcher, int status, int events) { char buffer[1024] = {0}; char control_buffer[64] = {0}; struct iovec iov[1]; struct msghdr msg; struct sockaddr client_addr; struct server_context *server = container_of(watcher, struct server_context, watcher); if (status >= 0) { msg.msg_name = &client_addr; msg.msg_namelen = sizeof(client_addr); msg.msg_control = control_buffer; msg.msg_controllen = sizeof(control_buffer); iov[0].iov_base = buffer; iov[0].iov_len = sizeof(buffer); msg.msg_iov = iov; msg.msg_iovlen = 1; int msglen = recvmsg(watcher->io_watcher.fd, &msg, 0); if (msglen <= 0) { logger_stderr("receive from client error: %s", strerror(errno)); } struct sockaddr dest_addr; if (getdestaddr(&msg, &dest_addr)) { logger_stderr("can not get destination address"); } int addrlen = dest_addr.sa_family == AF_INET ? IPV4_HEADER_LEN : IPV6_HEADER_LEN; int mlen = addrlen + msglen; int clen = PRIMITIVE_BYTES + mlen; uint8_t *c = malloc(clen); uint8_t *m = c + PRIMITIVE_BYTES; /* * * xsocks UDP Request * +------+----------+----------+----------+ * | ATYP | DST.ADDR | DST.PORT | DATA | * +------+----------+----------+----------+ * | 1 | Variable | 2 | Variable | * +------+----------+----------+----------+ * */ if (dest_addr.sa_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)&dest_addr; m[0] = ATYP_IPV4; memcpy(m + 1, &addr->sin_addr, 4); memcpy(m + 1 + 4, &addr->sin_port, 2); } else { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&dest_addr; m[0] = ATYP_IPV6; memcpy(m + 1, &addr->sin6_addr, 16); memcpy(m + 1 + 16, &addr->sin6_port, 2); } memcpy(m + addrlen, buffer, msglen); int rc = crypto_encrypt(c, m, mlen); if (!rc) { char key[KEY_BYTES + 1] = {0}; crypto_generickey((uint8_t *)key, sizeof(key) -1, (uint8_t *)&client_addr, sizeof(client_addr), NULL, 0); struct client_context *client = NULL; uv_mutex_lock(&mutex); cache_lookup(cache, key, (void *)&client); uv_mutex_unlock(&mutex); if (client == NULL) { client = new_client(); client->addr = client_addr; memcpy(client->key, key, sizeof(key)); uv_timer_init(watcher->loop, client->timer); uv_udp_init(watcher->loop, &client->server_handle); client->server_handle.data = client; uv_udp_recv_start(&client->server_handle, server_alloc_cb, server_recv_cb); uv_mutex_lock(&mutex); cache_insert(cache, client->key, (void *)client); uv_mutex_unlock(&mutex); } reset_timer(client); forward_to_server(server->server_addr, client, c, clen); } } }
static void accept_cb(EV_P_ ev_io *w, int revents) { struct listen_ctx *listener = (struct listen_ctx *)w; struct sockaddr_storage destaddr; int err; int clientfd = accept(listener->fd, NULL, NULL); if (clientfd == -1) { ERROR("accept"); return; } err = getdestaddr(clientfd, &destaddr); if (err) { ERROR("getdestaddr"); return; } setnonblocking(clientfd); #ifdef SO_NOSIGPIPE int opt = 1; setsockopt(clientfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif struct addrinfo hints, *res; int sockfd; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; int index = rand() % listener->remote_num; err = getaddrinfo(listener->remote_addr[index].host, listener->remote_addr[index].port, &hints, &res); if (err) { ERROR("getaddrinfo"); return; } sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sockfd < 0) { ERROR("socket"); freeaddrinfo(res); return; } #ifdef SO_NOSIGPIPE setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif // Setup setnonblocking(sockfd); struct server *server = new_server(clientfd, listener->method); struct remote *remote = new_remote(sockfd, listener->timeout); server->remote = remote; remote->server = server; server->destaddr = destaddr; connect(sockfd, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); // listen to remote connected event ev_io_start(EV_A_ & remote->send_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); }