summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/TCP_Network.txt2
-rw-r--r--toxcore/TCP_server.c309
-rw-r--r--toxcore/TCP_server.h68
3 files changed, 379 insertions, 0 deletions
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
78client sent the server the public key and the public key we sent to the client, 78client sent the server the public key and the public key we sent to the client,
79the next with base nonce + 1...) 79the next with base nonce + 1...)
80 80
81The connection is set to an unconfirmed state until a packet is recieved and
82decrypted correctly using the information in the handshake.
81 83
82each packet sent to/from the server has an id (the first byte of the plain text 84each packet sent to/from the server has an id (the first byte of the plain text
83data of the packet.) 85data 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 @@
1/*
2* TCP_server.c -- Implementation of the TCP relay server part of Tox.
3*
4* Copyright (C) 2013 Tox project All Rights Reserved.
5*
6* This file is part of Tox.
7*
8* Tox is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version.
12*
13* Tox is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details.
17*
18* You should have received a copy of the GNU General Public License
19* along with Tox. If not, see <http://www.gnu.org/licenses/>.
20*
21*/
22
23#include "TCP_server.h"
24
25#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
26#include <sys/ioctl.h>
27#endif
28
29/* return 1 if valid
30 * return 0 if not valid
31 */
32static int sock_valid(sock_t sock)
33{
34#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
35
36 if (sock == INVALID_SOCKET) {
37#else
38
39 if (sock < 0) {
40#endif
41 return 0;
42 }
43
44 return 1;
45}
46
47static void kill_sock(sock_t sock)
48{
49#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
50 closesocket(sock);
51#else
52 close(sock);
53#endif
54}
55
56/* return 1 on success
57 * return 0 on failure
58 */
59static int set_nonblock(sock_t sock)
60{
61#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
62 u_long mode = 1;
63 return (ioctlsocket(sock, FIONBIO, &mode) == 0);
64#else
65 return (fcntl(sock, F_SETFL, O_NONBLOCK, 1) == 0);
66#endif
67}
68
69/* return 1 on success
70 * return 0 on failure
71 */
72static int set_dualstack(sock_t sock)
73{
74 char ipv6only = 0;
75 socklen_t optsize = sizeof(ipv6only);
76 int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize);
77
78 if ((res == 0) && (ipv6only == 0))
79 return 1;
80
81 ipv6only = 0;
82 return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0);
83}
84
85/* return 1 on success
86 * return 0 on failure
87 */
88static int bind_to_port(sock_t sock, int family, uint16_t port)
89{
90 struct sockaddr_storage addr = {0};
91 size_t addrsize;
92
93 if (family == AF_INET) {
94 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
95
96 addrsize = sizeof(struct sockaddr_in);
97 addr4->sin_family = AF_INET;
98 addr4->sin_port = htons(port);
99 } else if (family == AF_INET6) {
100 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
101
102 addrsize = sizeof(struct sockaddr_in6);
103 addr6->sin6_family = AF_INET6;
104 addr6->sin6_port = htons(port);
105 } else {
106 return 0;
107 }
108
109 return (bind(sock, (struct sockaddr *)&addr, addrsize) == 0);
110}
111
112/* return length on success
113 * return 0 if nothing has been read from socket.
114 * return ~0 on failure.
115 */
116static uint16_t read_length(sock_t sock)
117{
118 int count;
119 ioctl(sock, FIONREAD, &count);
120
121 if (count >= sizeof(uint16_t)) {
122 uint16_t length;
123 int len = recv(sock, &length, sizeof(uint16_t), 0);
124
125 if (len != sizeof(uint16_t)) {
126 fprintf(stderr, "FAIL recv packet\n");
127 return 0;
128 }
129
130 length = ntohs(length);
131
132 if (length > MAX_PACKET_SIZE) {
133 return ~0;
134 }
135
136 return length;
137 }
138
139 return 0;
140}
141
142/* return length on success
143 * return -1 on failure
144 */
145static int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length)
146{
147 int count;
148 ioctl(sock, FIONREAD, &count);
149
150 if (count >= length) {
151 int len = recv(sock, data, length, 0);
152
153 if (len != length) {
154 fprintf(stderr, "FAIL recv packet\n");
155 return -1;
156 }
157
158 return length;
159 }
160
161 return -1;
162}
163
164/* return 0 if everything went well.
165 * return -1 if the connection must be killed.
166 */
167static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint16_t length)
168{
169
170}
171
172/* return 0 if everything went well.
173 * return -1 if the connection must be killed.
174 */
175static int read_connection_handshake(TCP_Secure_Connection *con)
176{
177 int ok = 1;
178
179 while (1) {
180 if (con->next_packet_length == 0) {
181 uint16_t len = read_length(con->sock);
182
183 if (len == 0)
184 break;
185
186 if (len != TCP_SERVER_HANDSHAKE_SIZE)
187 return -1;
188
189 con->next_packet_length = len;
190 } else {
191 uint8_t data[con->next_packet_length];
192
193 if (read_TCP_packet(con->sock, data, con->next_packet_length) != -1) {
194 return handle_TCP_handshake(con, data, con->next_packet_length);
195 } else {
196 break;
197 }
198 }
199 }
200}
201
202/* return 1 on success
203 * return 0 on failure
204 */
205static int accept_connection(TCP_Server *TCP_server, sock_t sock)
206{
207 if (!sock_valid(sock))
208 return 0;
209
210 if (!set_nonblock(sock)) {
211 kill_sock(sock);
212 return 0;
213 }//TODO
214
215 printf("accepted %u\n", sock);
216
217 return 1;
218}
219
220static sock_t new_listening_TCP_socket(int family, uint16_t port)
221{
222 sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
223
224 if (!sock_valid(sock)) {
225 return ~0;
226 }
227
228 int ok = set_nonblock(sock);
229
230 if (ok && family == AF_INET6) {
231 ok = set_dualstack(sock);
232 }
233
234 ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0);
235
236 if (!ok) {
237 kill_sock(sock);
238 return ~0;
239 }
240
241 return sock;
242}
243
244TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t *ports)
245{
246 if (num_sockets == 0 || ports == NULL)
247 return NULL;
248
249 TCP_Server *temp = calloc(1, sizeof(Networking_Core));
250
251 if (temp == NULL)
252 return NULL;
253
254 temp->socks_listening = calloc(num_sockets, sizeof(sock_t));
255
256 if (temp->socks_listening == NULL) {
257 free(temp);
258 return NULL;
259 }
260
261 uint8_t family;
262
263 if (ipv6_enabled) {
264 family = AF_INET6;
265 } else {
266 family = AF_INET;
267 }
268
269 uint32_t i;
270
271 for (i = 0; i < num_sockets; ++i) {
272 sock_t sock = new_listening_TCP_socket(family, ports[i]);
273
274 if (sock_valid(sock)) {
275 temp->socks_listening[temp->num_listening_socks] = sock;
276 ++temp->num_listening_socks;
277 }
278 }
279
280 return temp;
281}
282
283void do_TCP_server(TCP_Server *TCP_server)
284{
285 uint32_t i;
286
287 for (i = 0; i < TCP_server->num_listening_socks; ++i) {
288 struct sockaddr_storage addr;
289 int addrlen = sizeof(addr);
290 sock_t sock;
291
292 do {
293 sock = accept(TCP_server->socks_listening[i], (struct sockaddr *)&addr, &addrlen);
294 //TODO
295 } while (accept_connection(TCP_server, sock));
296 }
297}
298
299void kill_TCP_server(TCP_Server *TCP_server)
300{
301 uint32_t i;
302
303 for (i = 0; i < TCP_server->num_listening_socks; ++i) {
304 kill_sock(TCP_server->socks_listening[i]);
305 }
306
307 free(TCP_server->socks_listening);
308 free(TCP_server);
309}
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 @@
1/*
2* TCP_server.h -- Implementation of the TCP relay server part of Tox.
3*
4* Copyright (C) 2013 Tox project All Rights Reserved.
5*
6* This file is part of Tox.
7*
8* Tox is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version.
12*
13* Tox is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details.
17*
18* You should have received a copy of the GNU General Public License
19* along with Tox. If not, see <http://www.gnu.org/licenses/>.
20*
21*/
22
23#include "net_crypto.h"
24
25#define TCP_MAX_BACKLOG 128
26
27#define MAX_PACKET_SIZE 8192
28
29#define MAX_INCOMMING_CONNECTIONS 32
30
31#define TCP_SERVER_HANDSHAKE_SIZE (crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_MACBYTES)
32#define TCP_CLIENT_HANDSHAKE_SIZE (crypto_box_PUBLICKEYBYTES + TCP_SERVER_HANDSHAKE_SIZE)
33
34enum {
35 TCP_STATUS_NO_STATUS,
36 TCP_STATUS_CONNECTED,
37 TCP_STATUS_UNCONFIRMED,
38 TCP_STATUS_CONFIRMED,
39};
40
41typedef struct {
42 uint8_t status;
43 sock_t sock;
44 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
45 uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
46 uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */
47 uint8_t shared_key[crypto_box_BEFORENMBYTES];
48 uint16_t next_packet_length;
49} TCP_Secure_Connection;
50
51typedef struct {
52 sock_t *socks_listening;
53 unsigned int num_listening_socks;
54
55 TCP_Secure_Connection incomming_connection_queue[MAX_INCOMMING_CONNECTIONS];
56} TCP_Server;
57
58/* Create new TCP server instance.
59 */
60TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t *ports);
61
62/* Run the TCP_server
63 */
64void do_TCP_server(TCP_Server *TCP_server);
65
66/* Kill the TCP server
67 */
68void kill_TCP_server(TCP_Server *TCP_server);