static void client_handshake_read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) { int n; server_ctx *ctx = (server_ctx *)stream->data; if (nread < 0) { if (buf.len) // If buf is set, we need to free it free(buf.base); HANDLE_CLOSE((uv_handle_t*)stream, handshake_client_close_cb); // Then close the connection return; } else if (!nread) { free(buf.base); return; } memcpy(ctx->handshake_buffer + ctx->buffer_len, buf.base, buf.len); shadow_decrypt(ctx->handshake_buffer + ctx->buffer_len, decrypt_table, buf.len); ctx->buffer_len += nread; if (!ctx->handshake_buffer) { FATAL("Should no call this anmore"); } free(buf.base); if (!ctx->remote_ip) { if (ctx->buffer_len < 2) // Not interpretable return; uint8_t addrtype = ctx->handshake_buffer[0]; if (addrtype == ADDRTYPE_IPV4) { if (ctx->buffer_len < 5) return; ctx->remote_ip = *((uint32_t *)(ctx->handshake_buffer + 1)); SHIFT_BYTE_ARRAY_TO_LEFT(ctx->handshake_buffer, 5, HANDSHAKE_BUFFER_SIZE); ctx->buffer_len -= 5; // TODO: Print out } else if (addrtype == ADDRTYPE_DOMAIN) { uint8_t domain_len = ctx->handshake_buffer[1]; if (!domain_len) { // Domain length is zero LOGE("Domain length is zero"); HANDLE_CLOSE((uv_handle_t*)stream, handshake_client_close_cb); return; } if (ctx->buffer_len < domain_len + 2) return; char domain[domain_len+1]; domain[domain_len] = 0; memcpy(domain, ctx->handshake_buffer+2, domain_len); struct addrinfo hints; hints.ai_family = AF_INET; // IPv4 Only hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = 0; uv_getaddrinfo_t *resolver = (uv_getaddrinfo_t *)malloc(sizeof(uv_getaddrinfo_t)); if (!resolver) { HANDLE_CLOSE((uv_handle_t*)stream, handshake_client_close_cb); FATAL("malloc() failed!"); } resolver->data = ctx; // We need to locate back the stream LOGI("Domain is: %s", domain); n = uv_getaddrinfo(stream->loop, resolver, client_handshake_domain_resolved, domain, NULL, &hints); if (n) { SHOW_UV_ERROR(stream->loop); HANDLE_CLOSE((uv_handle_t*)stream, handshake_client_close_cb); free(resolver); return; } SHIFT_BYTE_ARRAY_TO_LEFT(ctx->handshake_buffer, 2+domain_len, HANDSHAKE_BUFFER_SIZE); ctx->buffer_len -= 2 + domain_len; uv_read_stop(stream); // Pause the reading process, wait for resolve result return; } else { // Unsupported addrtype LOGI("addrtype unknown, closing"); HANDLE_CLOSE((uv_handle_t*)stream, handshake_client_close_cb); return; } } // !ctx->remote_ip if (!ctx->remote_port) { if (ctx->buffer_len < 2) // Not interpretable return; ctx->remote_port = *((uint16_t *)ctx->handshake_buffer); if (!ctx->remote_port) { LOGE("Remote port is zero"); HANDLE_CLOSE((uv_handle_t*)stream, handshake_client_close_cb); return; } SHIFT_BYTE_ARRAY_TO_LEFT(ctx->handshake_buffer, 2, HANDSHAKE_BUFFER_SIZE); ctx->buffer_len -= 2; // Try connect now n = uv_tcp_init(stream->loop, &ctx->remote); if (n) SHOW_UV_ERROR_AND_EXIT(stream->loop); uv_connect_t *req = (uv_connect_t *)malloc(sizeof(uv_connect_t)); if (!req) { HANDLE_CLOSE((uv_handle_t*)stream, handshake_client_close_cb); FATAL("malloc() failed!"); } req->data = ctx; struct sockaddr_in remote_addr; memset(&remote_addr, 0, sizeof(remote_addr)); remote_addr.sin_family = AF_INET; remote_addr.sin_addr.s_addr = ctx->remote_ip; remote_addr.sin_port = ctx->remote_port; n = uv_tcp_connect(req, &ctx->remote, remote_addr, connect_to_remote_cb); if (n) { SHOW_UV_ERROR(stream->loop); HANDLE_CLOSE((uv_handle_t*)stream, handshake_client_close_cb); free(req); return; } uv_read_stop(stream); // We are done handshake } }
static int do_handshake(uv_stream_t *stream) { server_ctx *ctx = (server_ctx *)stream->data; int n; if (!ctx->remote_ip_type) { if (ctx->buffer_len < 2) // Not interpretable return 1; uint8_t addrtype = ctx->handshake_buffer[0]; if (addrtype == ADDRTYPE_IPV4) { if (ctx->buffer_len < 5) return 1; memcpy(ctx->remote_ip, ctx->handshake_buffer + 1, 4); ctx->remote_ip_type = ADDRTYPE_IPV4; SHIFT_BYTE_ARRAY_TO_LEFT(ctx->handshake_buffer, 5, HANDSHAKE_BUFFER_SIZE); ctx->buffer_len -= 5; // TODO: Print out } else if (addrtype == ADDRTYPE_DOMAIN) { uint8_t domain_len = ctx->handshake_buffer[1]; if (!domain_len) { // Domain length is zero LOGE("Domain length is zero"); uv_close((uv_handle_t*)stream, handshake_client_close_cb); return -1; } if (ctx->buffer_len < domain_len + 2) return 1; char domain[domain_len+1]; domain[domain_len] = 0; memcpy(domain, ctx->handshake_buffer+2, domain_len); uv_getaddrinfo_t *resolver = (uv_getaddrinfo_t *)malloc(sizeof(uv_getaddrinfo_t)); if (!resolver) { uv_close((uv_handle_t*)stream, handshake_client_close_cb); FATAL("malloc() failed!"); } resolver->data = ctx; // We need to locate back the stream LOGI("Domain is: %s", domain); n = uv_getaddrinfo(stream->loop, resolver, client_handshake_domain_resolved, domain, NULL, NULL); if (n) { SHOW_UV_ERROR(stream->loop); uv_close((uv_handle_t*)stream, handshake_client_close_cb); free(resolver); return -1; } SHIFT_BYTE_ARRAY_TO_LEFT(ctx->handshake_buffer, 2+domain_len, HANDSHAKE_BUFFER_SIZE); ctx->buffer_len -= 2 + domain_len; uv_read_stop(stream); // Pause the reading process, wait for resolve result return 1; } else { // Unsupported addrtype LOGI("addrtype unknown, closing"); uv_close((uv_handle_t*)stream, handshake_client_close_cb); return -1; } } // !ctx->remote_ip if (!ctx->remote_port) { if (ctx->buffer_len < 2) // Not interpretable return 1; ctx->remote_port = *((uint16_t *)ctx->handshake_buffer); if (!ctx->remote_port) { LOGE("Remote port is zero"); uv_close((uv_handle_t*)stream, handshake_client_close_cb); return -1; } SHIFT_BYTE_ARRAY_TO_LEFT(ctx->handshake_buffer, 2, HANDSHAKE_BUFFER_SIZE); ctx->buffer_len -= 2; // Try connect now n = uv_tcp_init(stream->loop, &ctx->remote); if (n) SHOW_UV_ERROR_AND_EXIT(stream->loop); uv_connect_t *req = (uv_connect_t *)malloc(sizeof(uv_connect_t)); if (!req) { uv_close((uv_handle_t*)stream, handshake_client_close_cb); FATAL("malloc() failed!"); } req->data = ctx; if (ctx->remote_ip_type == ADDRTYPE_IPV4) { struct sockaddr_in remote; memset(&remote, 0, sizeof(remote)); remote.sin_family = AF_INET; memcpy(&remote.sin_addr.s_addr, ctx->remote_ip, 4); remote.sin_port = ctx->remote_port; n = uv_tcp_connect(req, &ctx->remote, remote, connect_to_remote_cb); } else if (ctx->remote_ip_type == ADDRTYPE_IPV6) { struct sockaddr_in6 remote; memset(&remote, 0, sizeof(remote)); remote.sin6_family = AF_INET6; memcpy(&remote.sin6_addr.s6_addr, ctx->remote_ip, 16); remote.sin6_port = ctx->remote_port; n = uv_tcp_connect6(req, &ctx->remote, remote, connect_to_remote_cb); } else { FATAL("addrtype unknown!"); } if (n) { SHOW_UV_ERROR(stream->loop); uv_close((uv_handle_t*)stream, handshake_client_close_cb); free(req); return -1; } } uv_read_stop(stream); return 0; }