1 /* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 - Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 - Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15 - Neither the name of the Developers nor the names of its contributors may
16 be used to endorse or promote products derived from this software without
17 specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/socket.h>
39 #include "messagehandler.h"
43 /* Version 0.2.0 XXX fixme */
44 const uint32_t versionBlob = 1<<16 | 2<<8 | 0;
46 static int Client_read(client_t *client);
47 static int Client_write(client_t *client);
48 static int Client_send_udp(client_t *client, uint8_t *data, int len);
49 void Client_free(client_t *client);
51 declare_list(clients);
52 static int clientcount; /* = 0 */
53 static int session = 1;
54 static int maxBandwidth;
60 maxBandwidth = getIntConf(MAX_BANDWIDTH);
68 int Client_getfds(struct pollfd *pollfds)
72 list_iterate(itr, &clients) {
74 c = list_get_entry(itr, client_t, node);
75 pollfds[i].fd = c->tcpfd;
76 pollfds[i].events = POLLIN | POLLHUP | POLLERR;
77 if (c->txsize > 0 || c->readBlockedOnWrite) /* Data waiting to be sent? */
78 pollfds[i].events |= POLLOUT;
87 int bwTop = maxBandwidth + maxBandwidth / 4;
88 list_iterate(itr, &clients) {
90 c = list_get_entry(itr, client_t, node);
91 Log_debug("Client %s BW available %d", c->playerName, c->availableBandwidth);
92 c->availableBandwidth += maxBandwidth;
93 if (c->availableBandwidth > bwTop)
94 c->availableBandwidth = bwTop;
96 if (Timer_isElapsed(&c->lastActivity, 1000000LL * INACTICITY_TIMEOUT)) {
97 /* No activity from client - assume it is lost and close. */
98 Log_info("Session ID %d timeout - closing", c->sessionId);
104 int Client_add(int fd, struct sockaddr_in *remote)
108 newclient = malloc(sizeof(client_t));
109 if (newclient == NULL)
110 Log_fatal("Out of memory");
111 memset(newclient, 0, sizeof(client_t));
113 newclient->tcpfd = fd;
114 memcpy(&newclient->remote_tcp, remote, sizeof(struct sockaddr_in));
115 newclient->ssl = SSL_newconnection(newclient->tcpfd, &newclient->SSLready);
116 if (newclient->ssl == NULL) {
117 Log_warn("SSL negotiation failed");
121 newclient->availableBandwidth = maxBandwidth;
122 Timer_init(&newclient->lastActivity);
123 newclient->sessionId = session++; /* XXX - more elaborate? */
125 init_list_entry(&newclient->txMsgQueue);
126 init_list_entry(&newclient->chan_node);
127 init_list_entry(&newclient->node);
129 list_add_tail(&newclient->node, &clients);
134 void Client_free(client_t *client)
136 struct dlist *itr, *save;
139 Log_info("Disconnect client ID %d addr %s port %d", client->sessionId,
140 inet_ntoa(client->remote_tcp.sin_addr),
141 ntohs(client->remote_tcp.sin_port));
143 if (client->authenticated) {
144 sendmsg = Msg_create(UserRemove);
145 sendmsg->payload.userRemove->session = client->sessionId;
146 Client_send_message_except(client, sendmsg);
148 list_iterate_safe(itr, save, &client->txMsgQueue) {
149 list_del(&list_get_entry(itr, message_t, node)->node);
150 Msg_free(list_get_entry(itr, message_t, node));
153 list_del(&client->node);
154 list_del(&client->chan_node);
156 SSL_free(client->ssl);
157 close(client->tcpfd);
162 void Client_close(client_t *client)
164 SSL_shutdown(client->ssl);
165 client->shutdown_wait = true;
168 void Client_disconnect_all()
170 struct dlist *itr, *save;
172 list_iterate_safe(itr, save, &clients) {
173 Client_free(list_get_entry(itr, client_t, node));
177 int Client_read_fd(int fd)
180 client_t *client = NULL;
182 list_iterate(itr, &clients) {
183 if(fd == list_get_entry(itr, client_t, node)->tcpfd) {
184 client = list_get_entry(itr, client_t, node);
189 Log_fatal("No client found for fd %d", fd);
191 return Client_read(client);
194 int Client_read(client_t *client)
198 Timer_restart(&client->lastActivity);
200 if (client->writeBlockedOnRead) {
201 client->writeBlockedOnRead = false;
202 Log_debug("Client_read: writeBlockedOnRead == true");
203 return Client_write(client);
206 if (client->shutdown_wait) {
210 if (!client->SSLready) {
212 rc = SSL_nonblockaccept(client->ssl, &client->SSLready);
221 if (!client->msgsize)
222 rc = SSL_read(client->ssl, client->rxbuf, 6 - client->rxcount);
223 else if (client->drainleft > 0)
224 rc = SSL_read(client->ssl, client->rxbuf, client->drainleft > BUFSIZE ? BUFSIZE : client->drainleft);
226 rc = SSL_read(client->ssl, &client->rxbuf[client->rxcount], client->msgsize);
229 if (client->drainleft > 0)
230 client->drainleft -= rc;
232 client->rxcount += rc;
233 if (!client->msgsize && client->rxcount >= 6) {
234 uint32_t *msgLen = (uint32_t *) &client->rxbuf[2];
235 client->msgsize = ntohl(*msgLen);
237 if (client->msgsize > BUFSIZE - 6 && client->drainleft == 0) {
238 Log_warn("Too big message received (%d). Discarding.", client->msgsize);
239 client->rxcount = client->msgsize = 0;
240 client->drainleft = client->msgsize;
242 else if (client->rxcount == client->msgsize + 6) { /* Got all of the message */
243 msg = Msg_networkToMessage(client->rxbuf, client->msgsize + 6);
244 /* pass messsage to handler */
246 Mh_handle_message(client, msg);
247 client->rxcount = client->msgsize = 0;
250 } else /* rc <= 0 */ {
251 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
254 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
255 client->readBlockedOnWrite = true;
258 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_ZERO_RETURN) {
259 Log_warn("Error: Zero return - closing");
260 if (!client->shutdown_wait)
261 Client_close(client);
264 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL) {
265 /* Hmm. This is where we end up when the client closes its connection.
268 Log_info("Connection closed by peer");
271 Log_warn("SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
277 } while (SSL_pending(client->ssl));
281 int Client_write_fd(int fd)
284 client_t *client = NULL;
286 list_iterate(itr, &clients) {
287 if(fd == list_get_entry(itr, client_t, node)->tcpfd) {
288 client = list_get_entry(itr, client_t, node);
293 Log_fatal("No client found for fd %d", fd);
294 Client_write(client);
298 int Client_write(client_t *client)
302 if (client->readBlockedOnWrite) {
303 client->readBlockedOnWrite = false;
304 Log_debug("Client_write: readBlockedOnWrite == true");
305 return Client_read(client);
307 rc = SSL_write(client->ssl, &client->txbuf[client->txcount], client->txsize - client->txcount);
309 client->txcount += rc;
310 if (client->txcount == client->txsize)
311 client->txsize = client->txcount = 0;
314 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
315 client->writeBlockedOnRead = true;
318 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
322 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL)
323 Log_warn("Client_write: Error: %s - Closing connection", strerror(errno));
325 Log_warn("Client_write: SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
330 if (client->txsize == 0 && !list_empty(&client->txMsgQueue)) {
332 msg = list_get_entry(list_get_first(&client->txMsgQueue), message_t, node);
333 list_del(list_get_first(&client->txMsgQueue));
334 client->txQueueCount--;
335 Client_send_message(client, msg);
340 int Client_send_message(client_t *client, message_t *msg)
342 if (!client->authenticated || !client->SSLready) {
346 if (client->txsize != 0) {
348 if ((client->txQueueCount > 5 && msg->messageType == UDPTunnel) ||
349 client->txQueueCount > 30) {
353 client->txQueueCount++;
354 list_add_tail(&msg->node, &client->txMsgQueue);
355 Log_debug("Queueing message");
358 memset(client->txbuf, 0, BUFSIZE);
359 len = Msg_messageToNetwork(msg, client->txbuf);
360 doAssert(len < BUFSIZE);
362 client->txsize = len;
364 Client_write(client);
370 client_t *Client_iterate(client_t **client_itr)
372 client_t *c = *client_itr;
374 if (list_empty(&clients))
378 c = list_get_entry(list_get_first(&clients), client_t, node);
380 if (list_get_next(&c->node) == &clients)
383 c = list_get_entry(list_get_next(&c->node), client_t, node);
390 int Client_send_message_except(client_t *client, message_t *msg)
392 client_t *itr = NULL;
395 Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */
396 while (Client_iterate(&itr) != NULL) {
399 Msg_inc_ref(msg); /* One extra reference for each new copy */
400 Log_debug("Msg %d to %s refcount %d", msg->messageType, itr->playerName, msg->refcount);
401 Client_send_message(itr, msg);
404 Msg_free(msg); /* Free our reference to the message */
407 Msg_free(msg); /* If only 1 client is connected then no message is passed
408 * to Client_send_message(). Free it here. */
413 static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t *plain, unsigned int len)
415 if (CryptState_isValid(&client->cryptState) &&
416 CryptState_decrypt(&client->cryptState, encrypted, plain, len))
419 if (Timer_elapsed(&client->cryptState.tLastGood) > 5000000ULL) {
420 if (Timer_elapsed(&client->cryptState.tLastRequest) > 5000000ULL) {
422 Timer_restart(&client->cryptState.tLastRequest);
424 sendmsg = Msg_create(CryptSetup);
425 Log_info("Requesting voice channel crypt resync");
426 Client_send_message(client, sendmsg);
432 #define UDP_PACKET_SIZE 1024
433 int Client_read_udp()
436 struct sockaddr_in from;
437 socklen_t fromlen = sizeof(struct sockaddr_in);
440 UDPMessageType_t msgType;
442 #if defined(__LP64__)
443 uint8_t encbuff[UDP_PACKET_SIZE + 8];
444 uint8_t *encrypted = encbuff + 4;
446 uint8_t encrypted[UDP_PACKET_SIZE];
448 uint8_t buffer[UDP_PACKET_SIZE];
450 len = recvfrom(udpsock, encrypted, UDP_PACKET_SIZE, MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
453 } else if (len < 0) {
455 } else if (len < 5) {
456 // 4 bytes crypt header + type + session
458 } else if (len > UDP_PACKET_SIZE) {
463 if (len == 12 && *encrypted == 0) {
464 uint32_t *ping = (uint32_t *)encrypted;
465 ping[0] = htons(versionBlob);
466 // 1 and 2 will be the timestamp, which we return unmodified.
467 ping[3] = htons((uint32_t)clientcount);
468 ping[4] = htons((uint32_t)getIntConf(MAX_CLIENTS));
469 ping[5] = htons((uint32_t)getIntConf(MAX_BANDWIDTH));
471 sendto(udpsock, encrypted, 6 * sizeof(uint32_t), 0, (struct sockaddr *)&from, fromlen);
475 key = (((uint64_t)from.sin_addr.s_addr) << 16) ^ from.sin_port;
478 while (Client_iterate(&itr) != NULL) {
479 if (itr->key == key) {
480 if (!checkDecrypt(itr, encrypted, buffer, len))
485 if (itr == NULL) { /* Unknown peer */
486 while (Client_iterate(&itr) != NULL) {
487 if (itr->remote_tcp.sin_addr.s_addr == from.sin_addr.s_addr) {
488 if (checkDecrypt(itr, encrypted, buffer, len)) {
490 Log_info("New UDP connection from %s port %d sessionId %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port), itr->sessionId);
491 memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_in));
494 else Log_warn("Bad cryptstate from peer");
502 msgType = (UDPMessageType_t)((buffer[0] >> 5) & 0x7);
505 case UDPVoiceCELTAlpha:
506 case UDPVoiceCELTBeta:
508 Client_voiceMsg(itr, buffer, len);
511 Client_send_udp(itr, buffer, len);
514 Log_debug("Unknown UDP message type from %s port %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
521 /* Handle decrypted voice message */
522 int Client_voiceMsg(client_t *client, uint8_t *data, int len)
524 uint8_t buffer[UDP_PACKET_SIZE];
525 pds_t *pdi = Pds_create(data + 1, len - 1);
526 pds_t *pds = Pds_create(buffer + 1, UDP_PACKET_SIZE - 1);
527 unsigned int type = data[0] & 0xe0;
528 unsigned int target = data[0] & 0x1f;
529 unsigned int poslen, counter;
530 int offset, packetsize;
532 channel_t *ch = (channel_t *)client->channel;
535 if (!client->authenticated || client->mute)
538 packetsize = 20 + 8 + 4 + len;
539 if (client->availableBandwidth - packetsize < 0)
540 return 0; /* Discard */
541 client->availableBandwidth -= packetsize;
543 counter = Pds_get_numval(pdi); /* Seems like this... */
545 counter = Pds_next8(pdi);
546 offset = Pds_skip(pdi, counter & 0x7f);
547 } while ((counter & 0x80) && offset > 0);
549 poslen = pdi->maxsize - pdi->offset; /* XXX - Add stripping of positional audio */
551 Pds_add_numval(pds, client->sessionId);
552 Pds_append_data_nosize(pds, data + 1, len - 1);
554 if (target & 0x1f) { /* Loopback */
555 buffer[0] = (uint8_t) type;
556 Client_send_udp(client, buffer, pds->offset + 1);
558 else if (target == 0) { /* regular channel speech */
559 buffer[0] = (uint8_t) type;
564 list_iterate(itr, &ch->clients) {
566 c = list_get_entry(itr, client_t, chan_node);
567 if (c != client && !c->deaf) {
568 Client_send_udp(c, buffer, pds->offset + 1);
572 /* XXX - Add targeted whisper here */
580 static int Client_send_udp(client_t *client, uint8_t *data, int len)
584 if (client->remote_udp.sin_port != 0 && CryptState_isValid(&client->cryptState)) {
585 #if defined(__LP64__)
586 buf = mbuf = malloc(len + 4 + 16);
589 mbuf = buf = malloc(len + 4);
592 Log_fatal("Out of memory");
594 CryptState_encrypt(&client->cryptState, data, buf, len);
596 sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, sizeof(struct sockaddr_in));
602 memcpy(buf, data, len);
603 msg = Msg_create(UDPTunnel);
605 msg->payload.UDPTunnel->packet.data = buf;
606 msg->payload.UDPTunnel->packet.len = len;
607 Client_send_message(client, msg);