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 (c == NULL && !list_empty(&clients)) {
382 c = list_get_entry(list_get_first(&clients), client_t, node);
384 if (list_get_next(&c->node) == &clients)
387 c = list_get_entry(list_get_next(&c->node), client_t, node);
394 int Client_send_message_except(client_t *client, message_t *msg)
396 client_t *itr = NULL;
399 Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */
400 while (Client_iterate(&itr) != NULL) {
403 Msg_inc_ref(msg); /* One extra reference for each new copy */
404 Log_debug("Msg %d to %s refcount %d", msg->messageType, itr->playerName, msg->refcount);
405 Client_send_message(itr, msg);
408 Msg_free(msg); /* Free our reference to the message */
411 Msg_free(msg); /* If only 1 client is connected then no message is passed
412 * to Client_send_message(). Free it here. */
417 static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t *plain, unsigned int len)
419 if (CryptState_isValid(&client->cryptState) &&
420 CryptState_decrypt(&client->cryptState, encrypted, plain, len))
423 if (Timer_elapsed(&client->cryptState.tLastGood) > 5000000ULL) {
424 if (Timer_elapsed(&client->cryptState.tLastRequest) > 5000000ULL) {
426 Timer_restart(&client->cryptState.tLastRequest);
428 sendmsg = Msg_create(CryptSync);
429 sendmsg->sessionId = client->sessionId;
430 sendmsg->payload.cryptSync.empty = true;
431 Log_info("Requesting voice channel crypt resync");
432 Client_send_message(client, sendmsg);
438 int Client_read_udp()
441 struct sockaddr_in from;
442 socklen_t fromlen = sizeof(struct sockaddr_in);
446 uint32_t sessionId = 0;
449 #if defined(__LP64__)
450 uint8_t encbuff[512 + 8];
451 uint8_t *encrypted = encbuff + 4;
453 uint8_t encrypted[512];
457 len = recvfrom(udpsock, encrypted, 512, MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
460 } else if (len < 0) {
462 } else if (len < 6) {
463 // 4 bytes crypt header + type + session
465 } else if (len > 512) {
469 key = (((uint64_t)from.sin_addr.s_addr) << 16) ^ from.sin_port;
470 pds = Pds_create(buffer, len - 4);
473 while (Client_iterate(&itr) != NULL) {
474 if (itr->key == key) {
475 if (!checkDecrypt(itr, encrypted, buffer, len))
477 msgType = Pds_get_numval(pds);
478 sessionId = Pds_get_numval(pds);
479 if (itr->sessionId != sessionId)
484 if (itr == NULL) { /* Unknown peer */
485 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)) {
489 msgType = Pds_get_numval(pds);
490 sessionId = Pds_get_numval(pds);
491 if (itr->sessionId == sessionId) { /* Found matching client */
493 Log_info("New UDP connection from %s port %d sessionId %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port), sessionId);
494 memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_in));
498 else Log_warn("Bad cryptstate from peer");
506 if (msgType != Speex && msgType != Ping)
509 if (msgType == Ping) {
510 Client_send_udp(itr, buffer, len);
513 Client_voiceMsg(itr, pds);
521 static void Client_voiceMsg_tunnel(client_t *client, message_t *msg)
524 pds_t *pds = Pds_create(buf, 512);
526 Pds_add_numval(pds, msg->messageType);
527 Pds_add_numval(pds, msg->sessionId);
528 Pds_add_numval(pds, msg->payload.speex.seq);
529 Pds_append_data_nosize(pds, msg->payload.speex.data, msg->payload.speex.size);
531 Log_warn("Large Speex message from TCP"); /* XXX - pds resize? */
532 pds->maxsize = pds->offset;
533 Client_voiceMsg(client, pds);
537 static int Client_voiceMsg(client_t *client, pds_t *pds)
539 int seq, flags, msgType, sessionId, packetsize;
540 channel_t *ch = (channel_t *)client->channel;
543 if (!client->authenticated || client->mute)
548 msgType = Pds_get_numval(pds);
549 sessionId = Pds_get_numval(pds);
550 seq = Pds_get_numval(pds);
551 flags = Pds_get_numval(pds);
553 packetsize = 20 + 8 + 4 + pds->maxsize - pds->offset;
554 if (client->availableBandwidth - packetsize < 0)
555 return 0; /* Discard */
557 client->availableBandwidth -= packetsize;
561 if (flags & LoopBack) {
562 Client_send_udp(client, pds->data, pds->maxsize);
568 list_iterate(itr, &ch->clients) {
570 c = list_get_entry(itr, client_t, chan_node);
571 if (c != client && !c->deaf) {
572 Client_send_udp(c, pds->data, pds->maxsize);
579 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));
600 pds_t *pds = Pds_create(data, len);
602 sendmsg = Msg_create(Pds_get_numval(pds));
603 sendmsg->sessionId = Pds_get_numval(pds);
605 if (sendmsg->messageType == Speex || sendmsg->messageType == Ping) {
606 if (sendmsg->messageType == Speex) {
607 sendmsg->payload.speex.seq = Pds_get_numval(pds);
608 sendmsg->payload.speex.size = pds->maxsize - pds->offset;
609 doAssert(pds->maxsize - pds->offset <= SPEEX_DATA_SIZE);
610 memcpy(sendmsg->payload.speex.data, data + pds->offset, pds->maxsize - pds->offset);
612 sendmsg->payload.ping.timestamp = Pds_get_numval(pds);
614 Client_send_message(client, sendmsg);
616 Log_warn("TCP fallback: Unsupported message type %d", sendmsg->messageType);