diff --git a/docs/TCP_Network.txt b/docs/TCP_Network.txt
index b9215943..ce52b8e9 100644
--- a/docs/TCP_Network.txt
+++ b/docs/TCP_Network.txt
@@ -78,6 +78,8 @@ received
client sent the server the public key and the public key we sent to the client,
the next with base nonce + 1...)
+The connection is set to an unconfirmed state until a packet is recieved and
+decrypted correctly using the information in the handshake.
each packet sent to/from the server has an id (the first byte of the plain text
data of the packet.)
diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c
new file mode 100644
index 00000000..2e3f3996
--- /dev/null
+++ b/toxcore/TCP_server.c
@@ -0,0 +1,309 @@
+/*
+* TCP_server.c -- Implementation of the TCP relay server part of Tox.
+*
+* Copyright (C) 2013 Tox project All Rights Reserved.
+*
+* This file is part of Tox.
+*
+* Tox is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Tox is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Tox. If not, see .
+*
+*/
+
+#include "TCP_server.h"
+
+#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
+#include
+#endif
+
+/* return 1 if valid
+ * return 0 if not valid
+ */
+static int sock_valid(sock_t sock)
+{
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+
+ if (sock == INVALID_SOCKET) {
+#else
+
+ if (sock < 0) {
+#endif
+ return 0;
+ }
+
+ return 1;
+}
+
+static void kill_sock(sock_t sock)
+{
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ closesocket(sock);
+#else
+ close(sock);
+#endif
+}
+
+/* return 1 on success
+ * return 0 on failure
+ */
+static int set_nonblock(sock_t sock)
+{
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ u_long mode = 1;
+ return (ioctlsocket(sock, FIONBIO, &mode) == 0);
+#else
+ return (fcntl(sock, F_SETFL, O_NONBLOCK, 1) == 0);
+#endif
+}
+
+/* return 1 on success
+ * return 0 on failure
+ */
+static int set_dualstack(sock_t sock)
+{
+ char ipv6only = 0;
+ socklen_t optsize = sizeof(ipv6only);
+ int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize);
+
+ if ((res == 0) && (ipv6only == 0))
+ return 1;
+
+ ipv6only = 0;
+ return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0);
+}
+
+/* return 1 on success
+ * return 0 on failure
+ */
+static int bind_to_port(sock_t sock, int family, uint16_t port)
+{
+ struct sockaddr_storage addr = {0};
+ size_t addrsize;
+
+ if (family == AF_INET) {
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in);
+ addr4->sin_family = AF_INET;
+ addr4->sin_port = htons(port);
+ } else if (family == AF_INET6) {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in6);
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_port = htons(port);
+ } else {
+ return 0;
+ }
+
+ return (bind(sock, (struct sockaddr *)&addr, addrsize) == 0);
+}
+
+/* return length on success
+ * return 0 if nothing has been read from socket.
+ * return ~0 on failure.
+ */
+static uint16_t read_length(sock_t sock)
+{
+ int count;
+ ioctl(sock, FIONREAD, &count);
+
+ if (count >= sizeof(uint16_t)) {
+ uint16_t length;
+ int len = recv(sock, &length, sizeof(uint16_t), 0);
+
+ if (len != sizeof(uint16_t)) {
+ fprintf(stderr, "FAIL recv packet\n");
+ return 0;
+ }
+
+ length = ntohs(length);
+
+ if (length > MAX_PACKET_SIZE) {
+ return ~0;
+ }
+
+ return length;
+ }
+
+ return 0;
+}
+
+/* return length on success
+ * return -1 on failure
+ */
+static int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length)
+{
+ int count;
+ ioctl(sock, FIONREAD, &count);
+
+ if (count >= length) {
+ int len = recv(sock, data, length, 0);
+
+ if (len != length) {
+ fprintf(stderr, "FAIL recv packet\n");
+ return -1;
+ }
+
+ return length;
+ }
+
+ return -1;
+}
+
+/* return 0 if everything went well.
+ * return -1 if the connection must be killed.
+ */
+static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint16_t length)
+{
+
+}
+
+/* return 0 if everything went well.
+ * return -1 if the connection must be killed.
+ */
+static int read_connection_handshake(TCP_Secure_Connection *con)
+{
+ int ok = 1;
+
+ while (1) {
+ if (con->next_packet_length == 0) {
+ uint16_t len = read_length(con->sock);
+
+ if (len == 0)
+ break;
+
+ if (len != TCP_SERVER_HANDSHAKE_SIZE)
+ return -1;
+
+ con->next_packet_length = len;
+ } else {
+ uint8_t data[con->next_packet_length];
+
+ if (read_TCP_packet(con->sock, data, con->next_packet_length) != -1) {
+ return handle_TCP_handshake(con, data, con->next_packet_length);
+ } else {
+ break;
+ }
+ }
+ }
+}
+
+/* return 1 on success
+ * return 0 on failure
+ */
+static int accept_connection(TCP_Server *TCP_server, sock_t sock)
+{
+ if (!sock_valid(sock))
+ return 0;
+
+ if (!set_nonblock(sock)) {
+ kill_sock(sock);
+ return 0;
+ }//TODO
+
+ printf("accepted %u\n", sock);
+
+ return 1;
+}
+
+static sock_t new_listening_TCP_socket(int family, uint16_t port)
+{
+ sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
+
+ if (!sock_valid(sock)) {
+ return ~0;
+ }
+
+ int ok = set_nonblock(sock);
+
+ if (ok && family == AF_INET6) {
+ ok = set_dualstack(sock);
+ }
+
+ ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0);
+
+ if (!ok) {
+ kill_sock(sock);
+ return ~0;
+ }
+
+ return sock;
+}
+
+TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t *ports)
+{
+ if (num_sockets == 0 || ports == NULL)
+ return NULL;
+
+ TCP_Server *temp = calloc(1, sizeof(Networking_Core));
+
+ 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;
+ }
+ }
+
+ return temp;
+}
+
+void do_TCP_server(TCP_Server *TCP_server)
+{
+ uint32_t i;
+
+ for (i = 0; i < TCP_server->num_listening_socks; ++i) {
+ struct sockaddr_storage addr;
+ int addrlen = sizeof(addr);
+ sock_t sock;
+
+ do {
+ sock = accept(TCP_server->socks_listening[i], (struct sockaddr *)&addr, &addrlen);
+ //TODO
+ } while (accept_connection(TCP_server, sock));
+ }
+}
+
+void kill_TCP_server(TCP_Server *TCP_server)
+{
+ uint32_t i;
+
+ for (i = 0; i < TCP_server->num_listening_socks; ++i) {
+ kill_sock(TCP_server->socks_listening[i]);
+ }
+
+ free(TCP_server->socks_listening);
+ free(TCP_server);
+}
diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h
new file mode 100644
index 00000000..d2c32fda
--- /dev/null
+++ b/toxcore/TCP_server.h
@@ -0,0 +1,68 @@
+/*
+* TCP_server.h -- Implementation of the TCP relay server part of Tox.
+*
+* Copyright (C) 2013 Tox project All Rights Reserved.
+*
+* This file is part of Tox.
+*
+* Tox is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Tox is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Tox. If not, see .
+*
+*/
+
+#include "net_crypto.h"
+
+#define TCP_MAX_BACKLOG 128
+
+#define MAX_PACKET_SIZE 8192
+
+#define MAX_INCOMMING_CONNECTIONS 32
+
+#define TCP_SERVER_HANDSHAKE_SIZE (crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_MACBYTES)
+#define TCP_CLIENT_HANDSHAKE_SIZE (crypto_box_PUBLICKEYBYTES + TCP_SERVER_HANDSHAKE_SIZE)
+
+enum {
+ TCP_STATUS_NO_STATUS,
+ TCP_STATUS_CONNECTED,
+ TCP_STATUS_UNCONFIRMED,
+ TCP_STATUS_CONFIRMED,
+};
+
+typedef struct {
+ uint8_t status;
+ sock_t sock;
+ uint8_t public_key[crypto_box_PUBLICKEYBYTES];
+ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
+ uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */
+ uint8_t shared_key[crypto_box_BEFORENMBYTES];
+ uint16_t next_packet_length;
+} TCP_Secure_Connection;
+
+typedef struct {
+ sock_t *socks_listening;
+ unsigned int num_listening_socks;
+
+ TCP_Secure_Connection incomming_connection_queue[MAX_INCOMMING_CONNECTIONS];
+} TCP_Server;
+
+/* Create new TCP server instance.
+ */
+TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t *ports);
+
+/* Run the TCP_server
+ */
+void do_TCP_server(TCP_Server *TCP_server);
+
+/* Kill the TCP server
+ */
+void kill_TCP_server(TCP_Server *TCP_server);