<|start_filename|>server.c<|end_filename|>
// Copyright (c) 2012 dndx (idndx.com)

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "config.h"
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <uv.h>
#include "encrypt.h"
#include "utils.h"
#include "server.h"

struct encryptor crypto;

static void established_free_cb(uv_handle_t* handle)
{
	server_ctx *ctx = (server_ctx *)handle->data;
	if (!ctx->encoder.encrypt_table)
		destroy_encryptor(&ctx->encoder);
	free(ctx);
}

// Close remote and free ctx
static void client_established_shutdown_complete(uv_shutdown_t* req, int status)
{
	server_ctx *ctx = (server_ctx *)req->data;
	uv_close((uv_handle_t*)(void *)&ctx->client, established_free_cb);
	free(req);
}

// Close client and free ctx
static void remote_established_shutdown_complete(uv_shutdown_t* req, int status)
{
	server_ctx *ctx = (server_ctx *)req->data;
	uv_close((uv_handle_t*)(void *)&ctx->remote, established_free_cb);
	free(req);
}

// Shutdown client
static void remote_established_close_cb(uv_handle_t* handle)
{
	server_ctx *ctx = (server_ctx *)handle->data;
	uv_read_stop((uv_stream_t *)(void *)&ctx->client);
	uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t));
	req->data = ctx;

	int n = uv_shutdown(req, (uv_stream_t *)(void *)&ctx->client, client_established_shutdown_complete);
	if (n) {
		LOGE("Shutdown client side write stream failed!");
		uv_close((uv_handle_t*)(void *)&ctx->client, established_free_cb);
		free(req);
	}
}

// Close client then close remote
static void client_established_close_cb(uv_handle_t* handle)
{
	server_ctx *ctx = (server_ctx *)handle->data;
	uv_read_stop((uv_stream_t *)(void *)&ctx->remote);
	uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t));
	req->data = ctx;

	int n = uv_shutdown(req, (uv_stream_t *)(void *)&ctx->remote, remote_established_shutdown_complete);
	if (n) {
		LOGE("Shutdown remote side write stream failed!");
		uv_close((uv_handle_t*)(void *)&ctx->remote, established_free_cb);
		free(req);
	}
}

static void remote_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);
		LOGCONN(&ctx->remote, "Remote %s EOF, closing");
		HANDLE_CLOSE((uv_handle_t*)stream, remote_established_close_cb); // Then close the connection
		return;
	} else if (!nread) {
		free(buf.base);
		return;
	}

	shadow_encrypt((uint8_t *)buf.base, &ctx->encoder, nread);

	uv_write_t *req = (uv_write_t *)malloc(sizeof(uv_write_t));
	if (!req) {
		HANDLE_CLOSE((uv_handle_t*)stream, remote_established_close_cb);
		FATAL("malloc() failed!");
	}
	req->data = buf.base;
	buf.len = nread;
	n = uv_write(req, (uv_stream_t *)(void *)&ctx->client, &buf, 1, after_write_cb);
	if (n) {
		LOGE("Write to client failed!");
		free(req);
		free(buf.base);
		HANDLE_CLOSE((uv_handle_t*)(void *)&ctx->client, client_established_close_cb);
		return;
	}
	if (ctx->buffer_len == MAX_PENDING_PER_CONN - 1) { // buffer_len used as pending write request counter
		uv_read_stop(stream);
	}
	ctx->buffer_len++;
}

static void after_write_cb(uv_write_t* req, int status)
{
	server_ctx *ctx = (server_ctx *)req->handle->data;
	if (status) {
		if (uv_last_error(req->handle->loop).code != UV_ECANCELED) {
			if ((uv_tcp_t *)req->handle == &ctx->client) {
				HANDLE_CLOSE((uv_handle_t *)req->handle, client_established_close_cb);
			} else {
				HANDLE_CLOSE((uv_handle_t *)req->handle, remote_established_close_cb);
			}
		}
		free(req->data); // Free buffer
		free(req);
		return;
	}

	if ((uv_tcp_t *)req->handle == &ctx->client && !uv_is_closing((uv_handle_t *)(void *)&ctx->remote)) {
		if (ctx->buffer_len <= MAX_PENDING_PER_CONN) {
			int n = uv_read_start((uv_stream_t *)(void *)&ctx->remote, established_alloc_cb, remote_established_read_cb);
			if (n) {
				SHOW_UV_ERROR(ctx->client.loop);
				HANDLE_CLOSE((uv_handle_t *)(void *)&ctx->remote, remote_established_close_cb);
				free(req->data); // Free buffer
				free(req);
				return;
			}
		}
		ctx->buffer_len--;
	}

	free(req->data); // Free buffer
	free(req);
}

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);
		LOGCONN(&ctx->client, "Client %s 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((uint8_t *)buf.base, &ctx->encoder, 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);
		free(buf.base);
		HANDLE_CLOSE((uv_handle_t*)(void *)&ctx->remote, remote_established_close_cb);
		return;
	}

	// LOGI("Writed to remote");
}

static uv_buf_t established_alloc_cb(uv_handle_t* handle, size_t suggested_size)
{
	#ifdef BUFFER_LIMIT
	void *buf = malloc(BUFFER_LIMIT);
	#else
	void *buf = malloc(suggested_size);
	#endif /* BUFFER_LIMIT */
	if (!buf) {
		FATAL("malloc() failed!");
	}
	#ifdef BUFFER_LIMIT
	return uv_buf_init(buf, BUFFER_LIMIT);
	#else
	return uv_buf_init(buf, suggested_size);
	#endif /* BUFFER_LIMIT */
}

// Failed during handshake
static void handshake_client_close_cb(uv_handle_t* handle)
{
	server_ctx *ctx = (server_ctx *)handle->data;
	if (ctx->handshake_buffer) {
		free(ctx->handshake_buffer);
		ctx->handshake_buffer = NULL;
	}
	if (!ctx->encoder.encrypt_table)
		destroy_encryptor(&ctx->encoder);
	free(ctx);
}

static void connect_to_remote_cb(uv_connect_t* req, int status)
{
	server_ctx *ctx = (server_ctx *)req->data;
	if (status) {
		if (uv_last_error(req->handle->loop).code != UV_ECANCELED) {
			SHOW_UV_ERROR(ctx->client.loop);
			uv_close((uv_handle_t*)(void *)&ctx->remote, remote_established_close_cb);
			free(ctx->handshake_buffer);
			free(req);
		}
		return;
	}

	free(req);

	LOGCONN(&ctx->remote, "Connected to %s");

	uv_buf_t buf;
	buf.base = (char *)ctx->handshake_buffer;
	buf.len = HANDSHAKE_BUFFER_SIZE;

	if (!ctx->buffer_len) {
		free(ctx->handshake_buffer);
	} else {
		uv_write_t *wreq = (uv_write_t *)malloc(sizeof(uv_write_t));
		if (!wreq) {
			uv_close((uv_handle_t*)(void *)&ctx->client, client_established_close_cb);
			FATAL("malloc() failed!");
		}
		wreq->data = buf.base;
		buf.len = ctx->buffer_len;
		int n = uv_write(wreq, (uv_stream_t *)(void *)&ctx->remote, &buf, 1, after_write_cb);
		if (n) {
			LOGE("Write to remote failed!");
			free(wreq);
			uv_close((uv_handle_t*)(void *)&ctx->remote, remote_established_close_cb);
			return;
		}
	}

	ctx->handshake_buffer = NULL;
	ctx->buffer_len = 0;
	
	int n = uv_read_start((uv_stream_t *)(void *)&ctx->client, established_alloc_cb, client_established_read_cb);
	if (n) {
		SHOW_UV_ERROR(ctx->client.loop);
		uv_close((uv_handle_t*)(void *)&ctx->client, client_established_close_cb);
		return;
	}
	n = uv_read_start((uv_stream_t *)(void *)&ctx->remote, established_alloc_cb, remote_established_read_cb);
	if (n) {
		SHOW_UV_ERROR(ctx->client.loop);
		uv_close((uv_handle_t*)(void *)&ctx->remote, remote_established_close_cb);
		return;
	}
}

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;
}

static void client_handshake_domain_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res)
{
	server_ctx *ctx = (server_ctx *)resolver->data;
	if (status) {
		if (uv_last_error(ctx->client.loop).code == UV_ENOENT) {
			LOGI("Resolve error, NXDOMAIN");
		} else {
			SHOW_UV_ERROR(ctx->client.loop);
		}
		uv_close((uv_handle_t*)(void *)&ctx->client, handshake_client_close_cb);
		uv_freeaddrinfo(res);
		free(resolver);
		return;
	}

	if (res->ai_family == AF_INET) { // IPv4
		memcpy(ctx->remote_ip, &((struct sockaddr_in*)(res->ai_addr))->sin_addr.s_addr, 4);
		ctx->remote_ip_type = ADDRTYPE_IPV4;
	} else if (res->ai_family == AF_INET6) {
		memcpy(ctx->remote_ip, &((struct sockaddr_in6*)(res->ai_addr))->sin6_addr.s6_addr, 16);
		ctx->remote_ip_type = ADDRTYPE_IPV6;
	} else {
		FATAL("dns resolve failed!");
	}

	if (do_handshake((uv_stream_t *)(void *)&ctx->client) == 1) {
		int n = uv_read_start((uv_stream_t *)(void *)&ctx->client, client_handshake_alloc_cb, client_handshake_read_cb);
		if (n) {
			uv_close((uv_handle_t*)(void *)&ctx->client, handshake_client_close_cb);
			SHOW_UV_ERROR(ctx->client.loop);
		}
	}

	uv_freeaddrinfo(res);
	free(resolver);
}

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 uv_buf_t client_handshake_alloc_cb(uv_handle_t* handle, size_t suggested_size)
{
	server_ctx *ctx = (server_ctx *)handle->data;
	void *buf = malloc(HANDSHAKE_BUFFER_SIZE - ctx->buffer_len);
	if (!buf) {
		HANDLE_CLOSE(handle, handshake_client_close_cb);
		FATAL("malloc() failed!");
	}
	return uv_buf_init(buf, HANDSHAKE_BUFFER_SIZE - ctx->buffer_len);
}

static void connect_cb(uv_stream_t* listener, int status)
{
	int n;

	if (status) {
		SHOW_UV_ERROR(listener->loop);
		return;
	}

	server_ctx *ctx = calloc(1, sizeof(server_ctx));
	ctx->handshake_buffer = calloc(1, HANDSHAKE_BUFFER_SIZE);

	if (!ctx || !ctx->handshake_buffer)
		FATAL("malloc() failed!");

	ctx->client.data = ctx;
	ctx->remote.data = ctx;
	
	make_encryptor(&crypto, &ctx->encoder, 0, NULL);

	n = uv_tcp_init(listener->loop, &ctx->client);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(listener->loop);

	n = uv_accept(listener, (uv_stream_t *)(void *)&ctx->client);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(listener->loop);

	n = uv_tcp_nodelay(&ctx->client, 1);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(listener->loop);

	#ifdef KEEPALIVE_TIMEOUT
	n = uv_tcp_keepalive(&ctx->client, 1, KEEPALIVE_TIMEOUT);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(listener->loop);
	#endif /* KEEPALIVE_TIMEOUT */

	n = uv_read_start((uv_stream_t *)(void *)&ctx->client, client_handshake_alloc_cb, client_handshake_read_cb);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(listener->loop);

	LOGCONN(&ctx->client, "Accepted connection from %s");
}

int main(int argc, char *argv[])
{
	char **newargv = uv_setup_args(argc, argv);
	char *server_listen = SERVER_LISTEN;
	int server_port = SERVER_PORT;
	uint8_t *password = (<PASSWORD>8_t *)PASSWORD;
	uint8_t crypt_method = CRYPTO_METHOD;
	char *pid_path = PID_FILE;

	char opt;
	while((opt = getopt(argc, newargv, "l:p:k:f:m:")) != -1) { // not portable to windows
		switch(opt) {
			case 'l':
			    server_listen = optarg;
			    break;
			case 'p':
			    server_port = atoi(optarg);
			    break;
			case 'k':
			    password = (<PASSWORD> *)optarg;
			    break;
			case 'f':
			    pid_path = optarg;
			    break;
			case 'm':
			    if (!strcmp("rc4", optarg))
			    	crypt_method = METHOD_RC4;
			    else if (!strcmp("shadow", optarg))
			    	crypt_method = METHOD_SHADOWCRYPT;
			    break;
			default:
				fprintf(stderr, USAGE, newargv[0]);
				abort();
		}
	}

	FILE *pid_file = fopen(pid_path, "wb");
	if (!pid_file)
		FATAL("fopen failed, %s", strerror(errno));
	fprintf(pid_file, "%d", getpid());
	fclose(pid_file);

	char *process_title = malloc(PROCESS_TITLE_LENGTH); // we do not like waste memory
	if (!process_title)
		FATAL("malloc() failed!");
	snprintf(process_title, PROCESS_TITLE_LENGTH, PROCESS_TITLE, server_port);
	uv_set_process_title(process_title);
	free(process_title);

	LOGI(WELCOME_MESSAGE);

	if (crypt_method == METHOD_SHADOWCRYPT)
		LOGI("Using shadowcrypt crypto");
	else if (crypt_method == METHOD_RC4)
		LOGI("Using RC4 crypto");
	else
		FATAL("Crypto unknown!");

	make_encryptor(NULL, &crypto, crypt_method, password);

	LOGI("Crypto ready");
	
	int n;
	uv_loop_t *loop = uv_default_loop();
	uv_tcp_t listener;

	struct sockaddr_in6 addr = uv_ip6_addr(server_listen, server_port);

	n = uv_tcp_init(loop, &listener);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(loop);

	n = uv_tcp_bind6(&listener, addr);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(loop);

	n = uv_listen((uv_stream_t*)(void *)&listener, 5, connect_cb);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(loop);
	LOGI("Listening on %s:%d", server_listen, server_port);

	#ifndef NDEBUG
	setup_signal_handler(loop);
	#endif /* !NDEBUG */

	return uv_run(loop, UV_RUN_DEFAULT);
}


<|start_filename|>utils.h<|end_filename|>
// Copyright (c) 2012 dndx (idndx.com)

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#ifndef UTILS_H_
#define UTILS_H_
#include <stddef.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>

#define STR(x) #x
#define TOSTR(x) STR(x)

#define LOGI(format, ...) do {\
						  time_t now = time(NULL);\
						  char timestr[20];\
						  strftime(timestr, 20, TIME_FORMAT, localtime(&now));\
                          fprintf(stderr, "\e[01;32m %s INFO: \e[0m" format "\n", timestr, ##__VA_ARGS__);}\
                          while(0)
#define LOGE(format, ...) do {\
						  time_t now = time(NULL);\
						  char timestr[20];\
						  strftime(timestr, 20, TIME_FORMAT, localtime(&now));\
                          fprintf(stderr, "\e[01;35m %s ERROR: \e[0m" format " on File: %s Line: %s\n", timestr, ##__VA_ARGS__, __FILE__, TOSTR(__LINE__));}\
                          while(0)
#define LOGCONN(stream, message) do {\
                            struct sockaddr_storage remote_addr;\
                            memset(&remote_addr, 0, sizeof(remote_addr));\
                            int namelen = sizeof(remote_addr);\
                            if (uv_tcp_getpeername((stream), (struct sockaddr *)&remote_addr, &namelen))\
                                break;\
                            char *ip_str = sockaddr_to_str(&remote_addr);\
                            if (!ip_str)\
                              FATAL("unknown address type");\
                            LOGI(message, ip_str);\
                            free(ip_str);\
                        } while (0)
#define FATAL(format, ...) do {\
						  time_t now = time(NULL);\
						  char timestr[20];\
						  strftime(timestr, 20, TIME_FORMAT, localtime(&now));\
                          fprintf(stderr, "\e[01;31m %s FATAL: \e[0m" format " on File: %s Line: %s\n", timestr, ##__VA_ARGS__, __FILE__, TOSTR(__LINE__));exit(1);}\
                          while(0)
#define SHOW_UV_ERROR(loop) do {LOGE("libuv error: %s", uv_strerror(uv_last_error(loop)));} while (0)
#define SHOW_UV_ERROR_AND_EXIT(loop) do {SHOW_UV_ERROR(loop);LOGE("Fatal error, terminating... ");exit(1);} while (0)
//#define POINT_TO_STRUCT(field_ptr, field_name, struct_name) ((struct_name *)((char *)(field_ptr) - offsetof(struct_name, field_name)))
#define SHIFT_BYTE_ARRAY_TO_LEFT(arr, offset, array_size) memmove((arr), (arr) + (offset), (array_size) - (offset))
#define SHOW_BUFFER(buf, len) do {\
                              for (int i=0; i<len; i++)\
                              	putchar(buf[i]);\
                              } while (0)
#define HANDLE_CLOSE(handle, callback) do {\
                                       if (!(uv_is_closing((uv_handle_t *)(void *)&ctx->remote) || uv_is_closing((uv_handle_t *)(void *)&ctx->client)))\
                                       	   uv_close((uv_handle_t *)handle, callback);\
                                       	} while (0)

char *sockaddr_to_str(struct sockaddr_storage *addr);
void setup_signal_handler(uv_loop_t *loop);

#endif /* !UTILS_H_ */


<|start_filename|>tests.c<|end_filename|>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include "encrypt.h"
#include "utils.h"

void encrypt_test()
{
    struct encryptor enc;

	uint8_t target1[2][256] = {
    {60, 53, 84, 138, 217, 94, 88, 23, 39, 242, 219, 35, 12, 157, 165, 181, 255, 143, 83, 247, 162, 16, 31, 209, 190,
     171, 115, 65, 38, 41, 21, 245, 236, 46, 121, 62, 166, 233, 44, 154, 153, 145, 230, 49, 128, 216, 173, 29, 241, 119,
     64, 229, 194, 103, 131, 110, 26, 197, 218, 59, 204, 56, 27, 34, 141, 221, 149, 239, 192, 195, 24, 155, 170, 183, 11
        , 254, 213, 37, 137, 226, 75, 203, 55, 19, 72, 248, 22, 129, 33, 175, 178, 10, 198, 71, 77, 36, 113, 167, 48, 2,
     117, 140, 142, 66, 199, 232, 243, 32, 123, 54, 51, 82, 57, 177, 87, 251, 150, 196, 133, 5, 253, 130, 8, 184, 14,
     152, 231, 3, 186, 159, 76, 89, 228, 205, 156, 96, 163, 146, 18, 91, 132, 85, 80, 109, 172, 176, 105, 13, 50, 235,
     127, 0, 189, 95, 98, 136, 250, 200, 108, 179, 211, 214, 106, 168, 78, 79, 74, 210, 30, 73, 201, 151, 208, 114, 101,
     174, 92, 52, 120, 240, 15, 169, 220, 182, 81, 224, 43, 185, 40, 99, 180, 17, 212, 158, 42, 90, 9, 191, 45, 6, 25, 4
        , 222, 67, 126, 1, 116, 124, 206, 69, 61, 7, 68, 97, 202, 63, 244, 20, 28, 58, 93, 134, 104, 144, 227, 147, 102,
     118, 135, 148, 47, 238, 86, 112, 122, 70, 107, 215, 100, 139, 223, 225, 164, 237, 111, 125, 207, 160, 187, 246, 234
        , 161, 188, 193, 249, 252},
    {151, 205, 99, 127, 201, 119, 199, 211, 122, 196, 91, 74, 12, 147, 124, 180, 21, 191, 138, 83, 217, 30, 86, 7, 70,
     200, 56, 62, 218, 47, 168, 22, 107, 88, 63, 11, 95, 77, 28, 8, 188, 29, 194, 186, 38, 198, 33, 230, 98, 43, 148,
     110, 177, 1, 109, 82, 61, 112, 219, 59, 0, 210, 35, 215, 50, 27, 103, 203, 212, 209, 235, 93, 84, 169, 166, 80, 130
        , 94, 164, 165, 142, 184, 111, 18, 2, 141, 232, 114, 6, 131, 195, 139, 176, 220, 5, 153, 135, 213, 154, 189, 238
        , 174, 226, 53, 222, 146, 162, 236, 158, 143, 55, 244, 233, 96, 173, 26, 206, 100, 227, 49, 178, 34, 234, 108,
     207, 245, 204, 150, 44, 87, 121, 54, 140, 118, 221, 228, 155, 78, 3, 239, 101, 64, 102, 17, 223, 41, 137, 225, 229,
     66, 116, 171, 125, 40, 39, 71, 134, 13, 193, 129, 247, 251, 20, 136, 242, 14, 36, 97, 163, 181, 72, 25, 144, 46,
     175, 89, 145, 113, 90, 159, 190, 15, 183, 73, 123, 187, 128, 248, 252, 152, 24, 197, 68, 253, 52, 69, 117, 57, 92,
     104, 157, 170, 214, 81, 60, 133, 208, 246, 172, 23, 167, 160, 192, 76, 161, 237, 45, 4, 58, 10, 182, 65, 202, 240,
     185, 241, 79, 224, 132, 51, 42, 126, 105, 37, 250, 149, 32, 243, 231, 67, 179, 48, 9, 106, 216, 31, 249, 19, 85,
     254, 156, 115, 255, 120, 75, 16}};

    uint8_t target2[2][256] = {
    {124, 30, 170, 247, 27, 127, 224, 59, 13, 22, 196, 76, 72, 154, 32, 209, 4, 2, 131, 62, 101, 51, 230, 9, 166, 11, 99
        , 80, 208, 112, 36, 248, 81, 102, 130, 88, 218, 38, 168, 15, 241, 228, 167, 117, 158, 41, 10, 180, 194, 50, 204,
     243, 246, 251, 29, 198, 219, 210, 195, 21, 54, 91, 203, 221, 70, 57, 183, 17, 147, 49, 133, 65, 77, 55, 202, 122,
     162, 169, 188, 200, 190, 125, 63, 244, 96, 31, 107, 106, 74, 143, 116, 148, 78, 46, 1, 137, 150, 110, 181, 56, 95,
     139, 58, 3, 231, 66, 165, 142, 242, 43, 192, 157, 89, 175, 109, 220, 128, 0, 178, 42, 255, 20, 214, 185, 83, 160,
     253, 7, 23, 92, 111, 153, 26, 226, 33, 176, 144, 18, 216, 212, 28, 151, 71, 206, 222, 182, 8, 174, 205, 201, 152,
     240, 155, 108, 223, 104, 239, 98, 164, 211, 184, 34, 193, 14, 114, 187, 40, 254, 12, 67, 93, 217, 6, 94, 16, 19, 82
        , 86, 245, 24, 197, 134, 132, 138, 229, 121, 5, 235, 238, 85, 47, 103, 113, 179, 69, 250, 45, 135, 156, 25, 61,
     75, 44, 146, 189, 84, 207, 172, 119, 53, 123, 186, 120, 171, 68, 227, 145, 136, 100, 90, 48, 79, 159, 149, 39, 213,
     236, 126, 52, 60, 225, 199, 105, 73, 233, 252, 118, 215, 35, 115, 64, 37, 97, 129, 161, 177, 87, 237, 141, 173, 191
        , 163, 140, 234, 232, 249},
    {117, 94, 17, 103, 16, 186, 172, 127, 146, 23, 46, 25, 168, 8, 163, 39, 174, 67, 137, 175, 121, 59, 9, 128, 179, 199
        , 132, 4, 140, 54, 1, 85, 14, 134, 161, 238, 30, 241, 37, 224, 166, 45, 119, 109, 202, 196, 93, 190, 220, 69, 49
        , 21, 228, 209, 60, 73, 99, 65, 102, 7, 229, 200, 19, 82, 240, 71, 105, 169, 214, 194, 64, 142, 12, 233, 88, 201
        , 11, 72, 92, 221, 27, 32, 176, 124, 205, 189, 177, 246, 35, 112, 219, 61, 129, 170, 173, 100, 84, 242, 157, 26,
     218, 20, 33, 191, 155, 232, 87, 86, 153, 114, 97, 130, 29, 192, 164, 239, 90, 43, 236, 208, 212, 185, 75, 210, 0,
     81, 227, 5, 116, 243, 34, 18, 182, 70, 181, 197, 217, 95, 183, 101, 252, 248, 107, 89, 136, 216, 203, 68, 91, 223,
     96, 141, 150, 131, 13, 152, 198, 111, 44, 222, 125, 244, 76, 251, 158, 106, 24, 42, 38, 77, 2, 213, 207, 249, 147,
     113, 135, 245, 118, 193, 47, 98, 145, 66, 160, 123, 211, 165, 78, 204, 80, 250, 110, 162, 48, 58, 10, 180, 55, 231,
     79, 149, 74, 62, 50, 148, 143, 206, 28, 15, 57, 159, 139, 225, 122, 237, 138, 171, 36, 56, 115, 63, 144, 154, 6,
     230, 133, 215, 41, 184, 22, 104, 254, 234, 253, 187, 226, 247, 188, 156, 151, 40, 108, 51, 83, 178, 52, 3, 31, 255,
     195, 53, 235, 126, 167, 120}};

     make_encryptor(NULL, &enc, METHOD_SHADOWCRYPT, (uint8_t *)"foobar!");

     for (int i=0; i<256; i++) {
     	assert(target1[0][i] == enc.encrypt_table[i]);
     	assert(target1[1][i] == enc.decrypt_table[i]);
     }

     free(enc.encrypt_table);
     free(enc.decrypt_table);

     make_encryptor(NULL, &enc, METHOD_SHADOWCRYPT, (uint8_t *)"barfoo!");

     for (int i=0; i<256; i++) {
        assert(target2[0][i] == enc.encrypt_table[i]);
        assert(target2[1][i] == enc.decrypt_table[i]);
     }

     free(enc.encrypt_table);
     free(enc.decrypt_table);

     puts("Encryption/Decryption test passed!");

}


int main(void)
{
	encrypt_test();
}


<|start_filename|>encrypt.h<|end_filename|>
// Copyright (c) 2012 dndx (idndx.com)

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#ifndef ENCRYPT_H_
#define ENCRYPT_H_
#include <stdint.h>
#include "rc4.h"

#define TABLE_SIZE 256
#define METHOD_SHADOWCRYPT 0x1
#define METHOD_RC4 0x2
#define MD5_LEN 16

struct encryptor {
	uint8_t *key;
	uint8_t *encrypt_table;
	uint8_t *decrypt_table;
	struct rc4_state *rc4_en;
	struct rc4_state *rc4_de;
};

void md5(const uint8_t *text, uint8_t *message);
void make_tables(const uint8_t *key, uint8_t *encrypt_table, uint8_t *decrypt_table);
void shadow_encrypt(uint8_t *data, struct encryptor *enc, register unsigned int length);
void shadow_decrypt(uint8_t *data, struct encryptor *enc, register unsigned int length);
void make_encryptor(struct encryptor *tpl, struct encryptor *enc, uint8_t method, uint8_t *key);
void destroy_encryptor(struct encryptor *enc);

#endif /* !ENCRYPT_H_ */


<|start_filename|>server.h<|end_filename|>
// Copyright (c) 2012 dndx (idndx.com)

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#ifndef SERVER_H_
#define SERVER_H_

#include <stdint.h>

#define SHADOW_MAJOR_VERSION 0
#define SHADOW_MINOR_VERSION 2
#define WELCOME_MESSAGE "Shadowsocks Version:" TOSTR(SHADOW_MAJOR_VERSION) "." TOSTR(SHADOW_MINOR_VERSION) \
                        " libuv(" TOSTR(UV_VERSION_MAJOR) "." TOSTR(UV_VERSION_MINOR) ")"\
                        " Written by Dndx(idndx.com)"
#define USAGE "Shadowsocks Version:" TOSTR(SHADOW_MAJOR_VERSION) "." TOSTR(SHADOW_MINOR_VERSION) \
                        " libuv(" TOSTR(UV_VERSION_MAJOR) "." TOSTR(UV_VERSION_MINOR) ")"\
                        " Written by Dndx(idndx.com)\n"\
                        "Usage: %s [-l listen] [-p port] [-k keyfile] [-f pidfile] [-m rc4|shadow]\n\n"\
                        "Options:\n"\
                        "  -l : Override the listening IP\n"\
                        "  -p : Override the listening port\n"\
                        "  -k : Override the listening password\n"\
                        "  -f : Override the pidfile path\n"\
                        "  -m : Override the encryption method\n\n"
#define PROCESS_TITLE "shadowsocks on port:%d"
#define PROCESS_TITLE_LENGTH 26
#define ADDRTYPE_IPV4 1
#define ADDRTYPE_DOMAIN 3
#define ADDRTYPE_IPV6 4

typedef struct
{
	uv_tcp_t client;
	uv_tcp_t remote;
	uint8_t remote_ip[16];   // Network order
        uint8_t remote_ip_type;
	uint16_t remote_port; // Network order
        struct encryptor encoder; // En/decoder
	unsigned char *handshake_buffer;
	size_t buffer_len; // Also use as pending cound after handshake
} server_ctx;

static void client_handshake_read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf);
static uv_buf_t client_handshake_alloc_cb(uv_handle_t* handle, size_t suggested_size);
static void after_write_cb(uv_write_t* req, int status);
static uv_buf_t established_alloc_cb(uv_handle_t* handle, size_t suggested_size);
static void client_handshake_domain_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res);

#endif /* !SERVER_H_ */


<|start_filename|>encrypt.c<|end_filename|>
// Copyright (c) 2012 dndx (idndx.com)

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "config.h"
#include <string.h>
#include <openssl/evp.h>
#include <assert.h>
#include "md5.h"
#include "encrypt.h"
#include "utils.h"

#ifdef HIGHFIRST
	uint64_t swap_uint64( uint64_t val )
	{
	    val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
	    val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
	    return (val << 32) | (val >> 32);
	}
#endif /* BIG ENDIAN */

/*
 * message must be uint8_t[16]
 */
void md5(const uint8_t *text, uint8_t *message)
{
	struct MD5Context context;
	MD5Init(&context);
	MD5Update(&context, text, strlen((const char*)text));
	MD5Final(message, &context);
}

static void merge(uint8_t *arr, int start, int end, int mid, int ei, uint64_t keynum)
{
	int asize = mid - start + 1;
	uint8_t a[asize];
	memcpy(a, arr + start, asize);
	uint8_t *b = arr;
	uint8_t *result = arr;

	int i = 0;
	int j = mid + 1;
	int imax = asize;
	int jmax = end + 1;
	int k = start;

	while (i < imax && j < jmax) {
		if (keynum % (a[i] + ei) <= keynum % (b[j] + ei)) {
			result[k] = a[i];
			i++;
			k++;
		} else {
			result[k] = b[j];
			j++;
			k++;
		}
	}

	while (i < imax) {
		result[k] = a[i];
		i++;
		k++;
	}
	while (j < jmax) {
		result[k] = b[j];
		j++;
		k++;
	}
}

static void merge_sort(uint8_t *arr, int start, int end, int ei, uint64_t keynum)
{
	if (end - start <= 0) {
		return;
	}

	int mid = (start + end) / 2;

	merge_sort(arr, start, mid, ei, keynum);
	merge_sort(arr, mid + 1, end, ei, keynum);
	merge(arr, start, end, mid, ei, keynum);
}

static void mergesrt(uint8_t *arr, int length, int ei, uint64_t keynum)
{
	merge_sort(arr, 0, length - 1, ei, keynum);
}

/*
 * encrypt_table and decrypt_table must be uint8_t[TABLE_SIZE]
 */
void make_tables(const uint8_t *key, uint8_t *encrypt_table, uint8_t *decrypt_table)
{
	uint8_t digest[16];
	int ei;
	uint64_t keynum;

	md5(key, digest);
	memcpy(&keynum, digest, 8);
	#ifdef HIGHFIRST
	 	keynum = swap_uint64(keynum);
	#endif /* BIG ENDIAN */
	uint8_t temp_table[TABLE_SIZE];
	for (ei=0; ei<TABLE_SIZE; ei++) {
		temp_table[ei] = ei;
	}
	for (ei=1; ei<1024; ei++) {
		mergesrt(temp_table, TABLE_SIZE, ei, keynum);
	}
	memcpy(encrypt_table, temp_table, TABLE_SIZE);
	for (ei=0; ei<TABLE_SIZE; ei++) {
		decrypt_table[encrypt_table[ei]] = ei;
	}
}

void shadow_encrypt(uint8_t *data, struct encryptor *enc, register unsigned int length)
{
	if (enc->encrypt_table) {
		while (length--) {
			data[length] = enc->encrypt_table[data[length]];
		}
	} else if (enc->rc4_en) {
		rc4_crypt(enc->rc4_en, data, data, length);
	} else {
		FATAL("Crypto unknown!");
	}
	
}

void shadow_decrypt(uint8_t *data, struct encryptor *enc, register unsigned int length)
{
	if (enc->encrypt_table) {
		while (length--) {
			data[length] = enc->decrypt_table[data[length]];
		}
	} else if (enc->rc4_de) {
		rc4_crypt(enc->rc4_de, data, data, length);
	} else {
		FATAL("Crypto unknown!");
	}
}

static int init_rc4_key(struct encryptor *enc)
{
	unsigned char *key = calloc(1, EVP_MAX_IV_LENGTH);
	if (!key)
		FATAL("RC4 Cliper Init Failed");
    unsigned char iv[EVP_MAX_IV_LENGTH];
    int key_len = EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, (uint8_t*) enc->key, strlen((char *)enc->key), 1, key, iv);
    if (!key_len)
    	FATAL("RC4 Cliper Init Failed");

    enc->key = key;

    return key_len;
}

// key should end with \0
void make_encryptor(struct encryptor *tpl, struct encryptor *enc, uint8_t method, uint8_t *key)
{
	memset(enc, 0, sizeof(struct encryptor));

	if (!tpl) {
		if (method == METHOD_SHADOWCRYPT) {
			assert(key);
			enc->key = key;
			enc->encrypt_table = (uint8_t *)calloc(TABLE_SIZE, sizeof(uint8_t));
			enc->decrypt_table = (uint8_t *)calloc(TABLE_SIZE, sizeof(uint8_t));
			if (!(enc->encrypt_table && enc->decrypt_table))
				FATAL("malloc() failed!");
			make_tables(key, enc->encrypt_table, enc->decrypt_table);
		} else if (method == METHOD_RC4) {
			assert(key);
			enc->key = key;
			init_rc4_key(enc);
		}
	} else {
		assert(!method);
		if (tpl->encrypt_table) {
			assert(!key);
			enc->encrypt_table = tpl->encrypt_table;
			enc->decrypt_table = tpl->decrypt_table;
		} else {
			assert(!key);
			assert(tpl->key);
			enc->key = tpl->key;
			enc->rc4_en = (struct rc4_state *)malloc(sizeof(struct rc4_state));
			enc->rc4_de = (struct rc4_state *)malloc(sizeof(struct rc4_state));
			if (!(enc->rc4_en && enc->rc4_de))
				FATAL("malloc() failed!");
			rc4_init(enc->rc4_en, enc->key, MD5_LEN);
			rc4_init(enc->rc4_de, enc->key, MD5_LEN);
		}
	}
}

void destroy_encryptor(struct encryptor *enc)
{
	if (enc->rc4_en) {
		free(enc->rc4_en);
		free(enc->rc4_de);
	}

}


<|start_filename|>config.h<|end_filename|>
#ifndef CONFIG_H_
#define CONFIG_H_
#include "utils.h"
#include "encrypt.h"

// This is the IP address server will be used to accept new connection
// By default, "::0" will listen on both IPv4 and IPv6 stack if your system have a kernel later than Linux 2.4.21 and 2.6
// This have to be an IPv6 address or IPv4-mapped IPv6 address. If you want it listen only on specified IPv4 address, use the format "::ffff:192:168:1:2"
#define SERVER_LISTEN "::0"

// This is the port server will be used to accept new connection
#define SERVER_PORT 8888

// This is the password used for encrypt/decrypt, should be the same as your client
#define PASSWORD "<PASSWORD>!"

// This is the method used for encrypt/decrypt, should be the same as your client
// Available methods:
// METHOD_SHADOWCRYPT : Original Substitute Encryption Method Made By clowwindy
// METHOD_RC4         : RC4 Encryption
#define CRYPTO_METHOD METHOD_SHADOWCRYPT

// This is the path shadowsocks will write it's pid to
#define PID_FILE "/tmp/shadowsocks.pid"

// This is the time format for log, see strftime(3) for more information
#define TIME_FORMAT "%F %T"

// This is the buffer size (in byte) used during handshake, generally you DO NOT need to change this unless you have a good reason to do so
// This buffer will be freed right after handshake is complete
#define HANDSHAKE_BUFFER_SIZE 512

// This is the buffer size (in byte) that will be used during receive data, if you are not sure, just leave it
#define BUFFER_LIMIT 65536

// This is the number of max allowed pending write to client request, if you are running out of memory (which is very unlikely), you may want to decrease this a little
// The max possible memory usage of this program is BUFFER_LIMIT * MAX_PENDING_PER_CONN * Concurrent connection number, but this is kind of situation almost impossible to happen
// In most case, increase this value will better your performance
#define MAX_PENDING_PER_CONN 100

// This is the interval (in seconds) the operation system will be used to check whether the connection is still alive
// If you think you do not need it, you can comment next line to turn it off
#define KEEPALIVE_TIMEOUT 120

#endif /* !CONFIG_H_ */


<|start_filename|>Makefile<|end_filename|>
UNAME := $(shell uname)

RTFLAGS=-lrt
ifeq ($(UNAME), Darwin)
RTFLAGS=-framework CoreServices
endif
OLEVEL=-O2 -DNDEBUG
CFLAGS=-Wall $(OLEVEL) -I libuv/include -std=gnu99
FILES=server.c utils.c encrypt.c md5.c rc4.c
APP=server

all: $(FILES) libuv/libuv.a
	$(CC) $(CFLAGS) -o \
	$(APP) $(FILES) \
	libuv/libuv.a -lpthread -lcrypto -lm $(RTFLAGS)

libuv/libuv.a:
	$(MAKE) -C libuv

valgrind: OLEVEL=-O0 -g
valgrind: all
	valgrind --leak-check=full ./server

debug: OLEVEL=-O0 -g
debug: all

gprof: OLEVEL=-O0 -g -pg
gprof: all

test: OLEVEL=-O0 -g
test: FILES=tests.c encrypt.c md5.c rc4.c
test: APP=test
test: all
	./test
	cd pytest; python test.py

clean:
	$(MAKE) -C libuv clean
	rm -f server
	rm -rf *.dSYM
	rm -rf test


<|start_filename|>utils.c<|end_filename|>
#include "config.h"
#include "utils.h"
#include <signal.h>
#include <uv.h>

// Convert IPv4 or IPv6 sockaddr to string, DO NOT forget to free the buffer after use!
char *sockaddr_to_str(struct sockaddr_storage *addr)
{
	char *result;
	if (addr->ss_family == AF_INET) { // IPv4
		result = (char *)malloc(INET_ADDRSTRLEN);
		if (!result)
			FATAL("malloc() failed!");
		int n = uv_ip4_name((struct sockaddr_in*)addr, result, INET_ADDRSTRLEN);
		if (n) {
			free(result);
			result = NULL;
		}
	} else if (addr->ss_family == AF_INET6) { // IPv4
		result = (char *)malloc(INET6_ADDRSTRLEN);
		if (!result)
			FATAL("malloc() failed!");
		int n = uv_ip6_name((struct sockaddr_in6*)addr, result, INET6_ADDRSTRLEN);
		if (n) {
			free(result);
			result = NULL;
		}
	} else {
		result =  NULL;
	}
	return result;
}

void signal_cb(uv_signal_t* handle, int signum)
{
	extern struct encryptor crypto;

	if (uv_signal_stop(handle))
		SHOW_UV_ERROR_AND_EXIT(handle->loop);
	free(handle);
	LOGI("Ctrl+C Pressed");

	if (crypto.encrypt_table) {
		free(crypto.encrypt_table);
		free(crypto.decrypt_table);
	} else {
		free(crypto.key);
	}

	uv_loop_delete(uv_default_loop()); // Make Valgrind Happy

	exit(0);
}

void setup_signal_handler(uv_loop_t *loop)
{
	signal(SIGPIPE, SIG_IGN);
	
	uv_signal_t *hup = (uv_signal_t *)malloc(sizeof(uv_signal_t));
	if (!hup)
		FATAL("malloc() failed!");

	int n = uv_signal_init(loop, hup);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(loop);

	n = uv_signal_start(hup, signal_cb, SIGINT);
	if (n)
		SHOW_UV_ERROR_AND_EXIT(loop);
}
