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"
46 static int Client_read(client_t *client);
47 static int Client_write(client_t *client);
48 static int Client_voiceMsg(client_t *client, pds_t *pds);
49 static int Client_send_udp(client_t *client, uint8_t *data, int len);
50 static void Client_voiceMsg_tunnel(client_t *client, message_t *msg);
52 declare_list(clients);
53 static int clientcount; /* = 0 */
54 static int session = 1;
55 static int maxBandwidth;
61 maxBandwidth = getIntConf(MAX_BANDWIDTH);
69 int Client_getfds(struct pollfd *pollfds)
73 list_iterate(itr, &clients) {
75 c = list_get_entry(itr, client_t, node);
76 pollfds[i].fd = c->tcpfd;
77 pollfds[i].events = POLLIN | POLLHUP | POLLERR;
78 if (c->txsize > 0 || c->readBlockedOnWrite) /* Data waiting to be sent? */
79 pollfds[i].events |= POLLOUT;
88 int bwTop = maxBandwidth + maxBandwidth / 4;
89 list_iterate(itr, &clients) {
91 c = list_get_entry(itr, client_t, node);
92 Log_debug("Client %s BW available %d", c->playerName, c->availableBandwidth);
93 c->availableBandwidth += maxBandwidth;
94 if (c->availableBandwidth > bwTop)
95 c->availableBandwidth = bwTop;
97 if (Timer_isElapsed(&c->lastActivity, 1000000LL * INACTICITY_TIMEOUT)) {
98 /* No activity from client - assume it is lost and close. */
99 Log_info("Session ID %d timeout - closing", c->sessionId);
105 int Client_add(int fd, struct sockaddr_in *remote)
109 newclient = malloc(sizeof(client_t));
110 if (newclient == NULL)
111 Log_fatal("Out of memory");
112 memset(newclient, 0, sizeof(client_t));
114 newclient->tcpfd = fd;
115 memcpy(&newclient->remote_tcp, remote, sizeof(struct sockaddr_in));
116 newclient->ssl = SSL_newconnection(newclient->tcpfd, &newclient->SSLready);
117 if (newclient->ssl == NULL) {
118 Log_warn("SSL negotiation failed");
122 newclient->availableBandwidth = maxBandwidth;
123 Timer_init(&newclient->lastActivity);
124 newclient->sessionId = session++; /* XXX - more elaborate? */
126 init_list_entry(&newclient->txMsgQueue);
127 init_list_entry(&newclient->chan_node);
128 init_list_entry(&newclient->node);
130 list_add_tail(&newclient->node, &clients);
135 void Client_free(client_t *client)
137 struct dlist *itr, *save;
140 Log_info("Disconnect client ID %d addr %s port %d", client->sessionId,
141 inet_ntoa(client->remote_tcp.sin_addr),
142 ntohs(client->remote_tcp.sin_port));
144 if (client->authenticated) {
145 sendmsg = Msg_create(ServerLeave);
146 sendmsg->sessionId = client->sessionId;
147 Client_send_message_except(client, sendmsg);
149 list_iterate_safe(itr, save, &client->txMsgQueue) {
150 list_del(&list_get_entry(itr, message_t, node)->node);
151 Msg_free(list_get_entry(itr, message_t, node));
154 list_del(&client->node);
155 list_del(&client->chan_node);
157 SSL_free(client->ssl);
158 close(client->tcpfd);
163 void Client_close(client_t *client)
165 SSL_shutdown(client->ssl);
166 client->shutdown_wait = true;
169 void Client_disconnect_all()
171 struct dlist *itr, *save;
173 list_iterate_safe(itr, save, &clients) {
174 Client_free(list_get_entry(itr, client_t, node));
178 int Client_read_fd(int fd)
181 client_t *client = NULL;
183 list_iterate(itr, &clients) {
184 if(fd == list_get_entry(itr, client_t, node)->tcpfd) {
185 client = list_get_entry(itr, client_t, node);
190 Log_fatal("No client found for fd %d", fd);
192 return Client_read(client);
195 int Client_read(client_t *client)
199 Timer_restart(&client->lastActivity);
201 if (client->writeBlockedOnRead) {
202 client->writeBlockedOnRead = false;
203 Log_debug("Client_read: writeBlockedOnRead == true");
204 return Client_write(client);
207 if (client->shutdown_wait) {
211 if (!client->SSLready) {
213 rc = SSL_nonblockaccept(client->ssl, &client->SSLready);
222 if (!client->msgsize)
223 rc = SSL_read(client->ssl, client->rxbuf, 3 - client->rxcount);
224 else if (client->drainleft > 0)
225 rc = SSL_read(client->ssl, client->rxbuf, client->drainleft > BUFSIZE ? BUFSIZE : client->drainleft);
227 rc = SSL_read(client->ssl, &client->rxbuf[client->rxcount], client->msgsize);
230 if (client->drainleft > 0)
231 client->drainleft -= rc;
233 client->rxcount += rc;
234 if (!client->msgsize && rc >= 3)
235 client->msgsize = ((client->rxbuf[0] & 0xff) << 16) |
236 ((client->rxbuf[1] & 0xff) << 8) |
237 (client->rxbuf[2] & 0xff);
238 if (client->msgsize > BUFSIZE - 3 && client->drainleft == 0) {
239 Log_warn("Too big message received (%d). Discarding.", client->msgsize);
240 client->rxcount = client->msgsize = 0;
241 client->drainleft = client->msgsize;
243 else if (client->rxcount == client->msgsize + 3) { /* Got all of the message */
244 msg = Msg_networkToMessage(&client->rxbuf[3], client->msgsize);
245 /* pass messsage to handler */
247 if (msg->messageType == Speex) /* Tunneled voice message */
248 Client_voiceMsg_tunnel(client, msg);
250 Mh_handle_message(client, msg);
252 client->rxcount = client->msgsize = 0;
255 } else /* rc <= 0 */ {
256 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
259 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
260 client->readBlockedOnWrite = true;
263 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_ZERO_RETURN) {
264 Log_warn("Error: Zero return - closing");
265 if (!client->shutdown_wait)
266 Client_close(client);
269 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL) {
270 /* Hmm. This is where we end up when the client closes its connection.
273 Log_info("Connection closed by peer");
276 Log_warn("SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
282 } while (SSL_pending(client->ssl));
286 int Client_write_fd(int fd)
289 client_t *client = NULL;
291 list_iterate(itr, &clients) {
292 if(fd == list_get_entry(itr, client_t, node)->tcpfd) {
293 client = list_get_entry(itr, client_t, node);
298 Log_fatal("No client found for fd %d", fd);
299 Client_write(client);
303 int Client_write(client_t *client)
307 if (client->readBlockedOnWrite) {
308 client->readBlockedOnWrite = false;
309 Log_debug("Client_write: readBlockedOnWrite == true");
310 return Client_read(client);
312 rc = SSL_write(client->ssl, &client->txbuf[client->txcount], client->txsize - client->txcount);
314 client->txcount += rc;
315 if (client->txcount == client->txsize)
316 client->txsize = client->txcount = 0;
319 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
320 client->writeBlockedOnRead = true;
323 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
327 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL)
328 Log_warn("Client_write: Error: %s - Closing connection", strerror(errno));
330 Log_warn("Client_write: SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
335 if (client->txsize == 0 && !list_empty(&client->txMsgQueue)) {
337 msg = list_get_entry(list_get_first(&client->txMsgQueue), message_t, node);
338 list_del(list_get_first(&client->txMsgQueue));
339 client->txQueueCount--;
340 Client_send_message(client, msg);
345 int Client_send_message(client_t *client, message_t *msg)
347 if (!client->authenticated || !client->SSLready) {
351 if (client->txsize != 0) {
353 if ((client->txQueueCount > 5 && msg->messageType == Speex) ||
354 client->txQueueCount > 30) {
358 client->txQueueCount++;
359 list_add_tail(&msg->node, &client->txMsgQueue);
362 memset(client->txbuf, 0, BUFSIZE);
363 len = Msg_messageToNetwork(msg, &client->txbuf[3], BUFSIZE - 3);
364 doAssert(len < BUFSIZE - 3);
366 client->txbuf[0] = (len >> 16) & 0xff;
367 client->txbuf[1] = (len >> 8) & 0xff;
368 client->txbuf[2] = len & 0xff;
369 client->txsize = len + 3;
371 Client_write(client);
377 client_t *Client_iterate(client_t **client_itr)
379 client_t *c = *client_itr;
381 if (list_empty(&clients))
385 c = list_get_entry(list_get_first(&clients), client_t, node);
387 if (list_get_next(&c->node) == &clients)
390 c = list_get_entry(list_get_next(&c->node), client_t, node);
397 int Client_send_message_except(client_t *client, message_t *msg)
399 client_t *itr = NULL;
402 Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */
403 while (Client_iterate(&itr) != NULL) {
406 Msg_inc_ref(msg); /* One extra reference for each new copy */
407 Log_debug("Msg %d to %s refcount %d", msg->messageType, itr->playerName, msg->refcount);
408 Client_send_message(itr, msg);
411 Msg_free(msg); /* Free our reference to the message */
414 Msg_free(msg); /* If only 1 client is connected then no message is passed
415 * to Client_send_message(). Free it here. */
420 static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t *plain, unsigned int len)
422 if (CryptState_isValid(&client->cryptState) &&
423 CryptState_decrypt(&client->cryptState, encrypted, plain, len))
426 if (Timer_elapsed(&client->cryptState.tLastGood) > 5000000ULL) {
427 if (Timer_elapsed(&client->cryptState.tLastRequest) > 5000000ULL) {
429 Timer_restart(&client->cryptState.tLastRequest);
431 sendmsg = Msg_create(CryptSync);
432 sendmsg->sessionId = client->sessionId;
433 sendmsg->payload.cryptSync.empty = true;
434 Log_info("Requesting voice channel crypt resync");
435 Client_send_message(client, sendmsg);
441 int Client_read_udp()
444 struct sockaddr_in from;
445 socklen_t fromlen = sizeof(struct sockaddr_in);
449 uint32_t sessionId = 0;
452 #if defined(__LP64__)
453 uint8_t encbuff[512 + 8];
454 uint8_t *encrypted = encbuff + 4;
456 uint8_t encrypted[512];
460 len = recvfrom(udpsock, encrypted, 512, MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
463 } else if (len < 0) {
465 } else if (len < 6) {
466 // 4 bytes crypt header + type + session
468 } else if (len > 512) {
472 key = (((uint64_t)from.sin_addr.s_addr) << 16) ^ from.sin_port;
473 pds = Pds_create(buffer, len - 4);
476 while (Client_iterate(&itr) != NULL) {
477 if (itr->key == key) {
478 if (!checkDecrypt(itr, encrypted, buffer, len))
480 msgType = Pds_get_numval(pds);
481 sessionId = Pds_get_numval(pds);
482 if (itr->sessionId != sessionId)
487 if (itr == NULL) { /* Unknown peer */
488 while (Client_iterate(&itr) != NULL) {
490 if (itr->remote_tcp.sin_addr.s_addr == from.sin_addr.s_addr) {
491 if (checkDecrypt(itr, encrypted, buffer, len)) {
492 msgType = Pds_get_numval(pds);
493 sessionId = Pds_get_numval(pds);
494 if (itr->sessionId == sessionId) { /* Found matching client */
496 Log_info("New UDP connection from %s port %d sessionId %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port), sessionId);
497 memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_in));
501 else Log_warn("Bad cryptstate from peer");
509 if (msgType != Speex && msgType != Ping)
512 if (msgType == Ping) {
513 Client_send_udp(itr, buffer, len);
516 Client_voiceMsg(itr, pds);
524 static void Client_voiceMsg_tunnel(client_t *client, message_t *msg)
527 pds_t *pds = Pds_create(buf, 512);
529 Pds_add_numval(pds, msg->messageType);
530 Pds_add_numval(pds, msg->sessionId);
531 Pds_add_numval(pds, msg->payload.speex.seq);
532 Pds_append_data_nosize(pds, msg->payload.speex.data, msg->payload.speex.size);
537 Log_warn("Large Speex message from TCP"); /* XXX - pds resize? */
538 pds->maxsize = pds->offset;
539 Client_voiceMsg(client, pds);
544 static int Client_voiceMsg(client_t *client, pds_t *pds)
546 int seq, flags, msgType, sessionId, packetsize;
547 channel_t *ch = (channel_t *)client->channel;
550 if (!client->authenticated || client->mute)
555 msgType = Pds_get_numval(pds);
556 sessionId = Pds_get_numval(pds);
557 seq = Pds_get_numval(pds);
558 flags = Pds_get_numval(pds);
560 packetsize = 20 + 8 + 4 + pds->maxsize - pds->offset;
561 if (client->availableBandwidth - packetsize < 0)
562 return 0; /* Discard */
564 client->availableBandwidth -= packetsize;
568 if (flags & LoopBack) {
569 Client_send_udp(client, pds->data, pds->maxsize);
575 list_iterate(itr, &ch->clients) {
577 c = list_get_entry(itr, client_t, chan_node);
578 if (c != client && !c->deaf) {
579 Client_send_udp(c, pds->data, pds->maxsize);
586 static int Client_send_udp(client_t *client, uint8_t *data, int len)
591 if (client->remote_udp.sin_port != 0 && CryptState_isValid(&client->cryptState)) {
592 #if defined(__LP64__)
593 buf = mbuf = malloc(len + 4 + 16);
596 mbuf = buf = malloc(len + 4);
599 Log_fatal("Out of memory");
601 CryptState_encrypt(&client->cryptState, data, buf, len);
603 sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, sizeof(struct sockaddr_in));
607 pds_t *pds = Pds_create(data, len);
609 sendmsg = Msg_create(Pds_get_numval(pds));
610 sendmsg->sessionId = Pds_get_numval(pds);
612 if (sendmsg->messageType == Speex || sendmsg->messageType == Ping) {
613 if (sendmsg->messageType == Speex) {
614 sendmsg->payload.speex.seq = Pds_get_numval(pds);
615 sendmsg->payload.speex.size = pds->maxsize - pds->offset;
616 doAssert(pds->maxsize - pds->offset <= SPEEX_DATA_SIZE);
617 memcpy(sendmsg->payload.speex.data, data + pds->offset, pds->maxsize - pds->offset);
619 sendmsg->payload.ping.timestamp = Pds_get_numval(pds);
621 Client_send_message(client, sendmsg);
623 Log_warn("TCP fallback: Unsupported message type %d", sendmsg->messageType);