static void client_handshake_read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) { 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); uv_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, nread); shadow_decrypt(ctx->handshake_buffer + ctx->buffer_len, &ctx->encoder, nread); ctx->buffer_len += nread; if (!ctx->handshake_buffer) { FATAL("Should not call this anymore"); } free(buf.base); do_handshake(stream); }
static void client_established_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) { // EOF if (buf.len) // If buf is set, we need to free it free(buf.base); LOGI("Client EOF, Closing"); HANDLE_CLOSE((uv_handle_t*)stream, client_established_close_cb); // Then close the connection return; } else if (!nread) { free(buf.base); return; } shadow_decrypt((unsigned char *)buf.base, decrypt_table, nread); uv_write_t *req = (uv_write_t *)malloc(sizeof(uv_write_t)); if (!req) { HANDLE_CLOSE((uv_handle_t*)stream, client_established_close_cb); FATAL("malloc() failed!"); } req->data = buf.base; buf.len = nread; n = uv_write(req, (uv_stream_t *)(void *)&ctx->remote, &buf, 1, after_write_cb); if (n) { LOGE("Write to remote failed!"); free(req); HANDLE_CLOSE((uv_handle_t*)stream, client_established_close_cb); return; } // LOGI("Writed to remote"); }
inline static int crypt_recv(int fd, void *buf, size_t len) { int size = recv(fd, buf, len, 0); if (size > 0) { shadow_decrypt(buf, &chd_crypto, (size_t)size); } return size; }
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 } }