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;
56 static int iCodecAlpha, iCodecBeta;
57 static bool_t bPreferAlpha;
63 maxBandwidth = getIntConf(MAX_BANDWIDTH) / 8; /* From bits/s -> bytes/s */
71 int Client_getfds(struct pollfd *pollfds)
75 list_iterate(itr, &clients) {
77 c = list_get_entry(itr, client_t, node);
78 pollfds[i].fd = c->tcpfd;
79 pollfds[i].events = POLLIN | POLLHUP | POLLERR;
80 if (c->txsize > 0 || c->readBlockedOnWrite) /* Data waiting to be sent? */
81 pollfds[i].events |= POLLOUT;
90 int bwTop = maxBandwidth + maxBandwidth / 4;
91 list_iterate(itr, &clients) {
93 c = list_get_entry(itr, client_t, node);
94 Log_debug("Client %s BW available %d", c->playerName, c->availableBandwidth);
95 c->availableBandwidth += maxBandwidth;
96 if (c->availableBandwidth > bwTop)
97 c->availableBandwidth = bwTop;
99 if (Timer_isElapsed(&c->lastActivity, 1000000LL * INACTICITY_TIMEOUT)) {
100 /* No activity from client - assume it is lost and close. */
101 Log_info("Session ID %d timeout - closing", c->sessionId);
107 void recheckCodecVersions()
109 int codec_map[MAX_CODECS][2];
111 int i, codecindex, max = 0, version, current_version;
114 memset(codec_map, 0, MAX_CODECS * 2 * sizeof(int));
115 while (Client_iterate(&itr) != NULL) {
116 for (i = 0; i < itr->codec_count; i++) {
117 for (codecindex = 0; codecindex < MAX_CODECS; codecindex++) {
118 if (codec_map[codecindex][0] == 0)
119 codec_map[codecindex][0] = itr->codecs[i];
120 if (itr->codecs[i] == codec_map[codecindex][0])
121 codec_map[codecindex][1]++;
125 if (codec_map[codecindex][0] == 0)
127 for (codecindex = 0; codecindex < MAX_CODECS; codecindex++) {
128 if (codec_map[codecindex][0] == 0)
130 if (codec_map[codecindex][1] > max) {
131 max = codec_map[codecindex][1];
132 version = codec_map[codecindex][0];
135 current_version = bPreferAlpha ? iCodecAlpha : iCodecBeta;
136 if (current_version == version)
138 // If we don't already use the compat bitstream version set
139 // it as alpha and announce it. If another codec now got the
140 // majority set it as the opposite of the currently valid bPreferAlpha
142 if (version == (uint32_t)0x8000000a)
145 bPreferAlpha = ! bPreferAlpha;
148 iCodecAlpha = version;
150 iCodecBeta = version;
152 sendmsg = Msg_create(CodecVersion);
153 sendmsg->payload.codecVersion->alpha = version;
154 sendmsg->payload.codecVersion->beta = version;
155 sendmsg->payload.codecVersion->beta = bPreferAlpha;
156 Client_send_message_except(NULL, sendmsg);
160 int Client_add(int fd, struct sockaddr_in *remote)
165 newclient = malloc(sizeof(client_t));
166 if (newclient == NULL)
167 Log_fatal("Out of memory");
168 memset(newclient, 0, sizeof(client_t));
170 newclient->tcpfd = fd;
171 memcpy(&newclient->remote_tcp, remote, sizeof(struct sockaddr_in));
172 newclient->ssl = SSL_newconnection(newclient->tcpfd, &newclient->SSLready);
173 if (newclient->ssl == NULL) {
174 Log_warn("SSL negotiation failed");
178 newclient->availableBandwidth = maxBandwidth;
179 Timer_init(&newclient->lastActivity);
180 newclient->sessionId = session++; /* XXX - more elaborate? */
182 init_list_entry(&newclient->txMsgQueue);
183 init_list_entry(&newclient->chan_node);
184 init_list_entry(&newclient->node);
186 list_add_tail(&newclient->node, &clients);
189 /* Send version message to client */
190 sendmsg = Msg_create(Version);
191 sendmsg->payload.version->has_version = true;
192 sendmsg->payload.version->version = (1 << 16) | (2 << 8) | 0; /* XXX fix */
193 sendmsg->payload.version->release = strdup("1.2.0");
194 sendmsg->payload.version->os = strdup("Linux/OpenWRT");
196 Client_send_message(newclient, sendmsg);
201 void Client_free(client_t *client)
203 struct dlist *itr, *save;
206 Log_info("Disconnect client ID %d addr %s port %d", client->sessionId,
207 inet_ntoa(client->remote_tcp.sin_addr),
208 ntohs(client->remote_tcp.sin_port));
210 if (client->authenticated) {
211 sendmsg = Msg_create(UserRemove);
212 sendmsg->payload.userRemove->session = client->sessionId;
213 Client_send_message_except(client, sendmsg);
215 list_iterate_safe(itr, save, &client->txMsgQueue) {
216 list_del(&list_get_entry(itr, message_t, node)->node);
217 Msg_free(list_get_entry(itr, message_t, node));
220 list_del(&client->node);
221 list_del(&client->chan_node);
223 SSL_free(client->ssl);
224 close(client->tcpfd);
227 free(client->release);
233 void Client_close(client_t *client)
235 SSL_shutdown(client->ssl);
236 client->shutdown_wait = true;
239 void Client_disconnect_all()
241 struct dlist *itr, *save;
243 list_iterate_safe(itr, save, &clients) {
244 Client_free(list_get_entry(itr, client_t, node));
248 int Client_read_fd(int fd)
251 client_t *client = NULL;
253 list_iterate(itr, &clients) {
254 if(fd == list_get_entry(itr, client_t, node)->tcpfd) {
255 client = list_get_entry(itr, client_t, node);
260 Log_fatal("No client found for fd %d", fd);
262 return Client_read(client);
265 int Client_read(client_t *client)
269 Timer_restart(&client->lastActivity);
271 if (client->writeBlockedOnRead) {
272 client->writeBlockedOnRead = false;
273 Log_debug("Client_read: writeBlockedOnRead == true");
274 return Client_write(client);
277 if (client->shutdown_wait) {
281 if (!client->SSLready) {
283 rc = SSL_nonblockaccept(client->ssl, &client->SSLready);
292 if (!client->msgsize)
293 rc = SSL_read(client->ssl, client->rxbuf, 6 - client->rxcount);
294 else if (client->drainleft > 0)
295 rc = SSL_read(client->ssl, client->rxbuf, client->drainleft > BUFSIZE ? BUFSIZE : client->drainleft);
297 rc = SSL_read(client->ssl, &client->rxbuf[client->rxcount], client->msgsize);
300 if (client->drainleft > 0)
301 client->drainleft -= rc;
303 client->rxcount += rc;
304 if (!client->msgsize && client->rxcount >= 6) {
305 uint32_t *msgLen = (uint32_t *) &client->rxbuf[2];
306 client->msgsize = ntohl(*msgLen);
308 if (client->msgsize > BUFSIZE - 6 && client->drainleft == 0) {
309 Log_warn("Too big message received (%d). Discarding.", client->msgsize);
310 client->rxcount = client->msgsize = 0;
311 client->drainleft = client->msgsize;
313 else if (client->rxcount == client->msgsize + 6) { /* Got all of the message */
314 msg = Msg_networkToMessage(client->rxbuf, client->msgsize + 6);
315 /* pass messsage to handler */
317 Mh_handle_message(client, msg);
318 client->rxcount = client->msgsize = 0;
321 } else /* rc <= 0 */ {
322 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
325 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
326 client->readBlockedOnWrite = true;
329 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_ZERO_RETURN) {
330 Log_warn("Error: Zero return - closing");
331 if (!client->shutdown_wait)
332 Client_close(client);
335 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL) {
336 /* Hmm. This is where we end up when the client closes its connection.
339 Log_info("Connection closed by peer");
342 Log_warn("SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
348 } while (SSL_pending(client->ssl));
352 int Client_write_fd(int fd)
355 client_t *client = NULL;
357 list_iterate(itr, &clients) {
358 if(fd == list_get_entry(itr, client_t, node)->tcpfd) {
359 client = list_get_entry(itr, client_t, node);
364 Log_fatal("No client found for fd %d", fd);
365 Client_write(client);
369 int Client_write(client_t *client)
373 if (client->readBlockedOnWrite) {
374 client->readBlockedOnWrite = false;
375 Log_debug("Client_write: readBlockedOnWrite == true");
376 return Client_read(client);
378 rc = SSL_write(client->ssl, &client->txbuf[client->txcount], client->txsize - client->txcount);
380 client->txcount += rc;
381 if (client->txcount == client->txsize)
382 client->txsize = client->txcount = 0;
385 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
386 client->writeBlockedOnRead = true;
389 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
393 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL)
394 Log_warn("Client_write: Error: %s - Closing connection", strerror(errno));
396 Log_warn("Client_write: SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
401 if (client->txsize == 0 && !list_empty(&client->txMsgQueue)) {
403 msg = list_get_entry(list_get_first(&client->txMsgQueue), message_t, node);
404 list_del(list_get_first(&client->txMsgQueue));
405 client->txQueueCount--;
406 Client_send_message(client, msg);
411 int Client_send_message(client_t *client, message_t *msg)
413 if (!client->authenticated && msg->messageType != Version) {
417 if (client->txsize != 0 || !client->SSLready) {
419 if ((client->txQueueCount > 5 && msg->messageType == UDPTunnel) ||
420 client->txQueueCount > 30) {
424 client->txQueueCount++;
425 list_add_tail(&msg->node, &client->txMsgQueue);
426 Log_debug("Queueing message");
429 memset(client->txbuf, 0, BUFSIZE);
430 len = Msg_messageToNetwork(msg, client->txbuf);
431 doAssert(len < BUFSIZE);
433 client->txsize = len;
435 Client_write(client);
441 client_t *Client_iterate(client_t **client_itr)
443 client_t *c = *client_itr;
445 if (list_empty(&clients))
449 c = list_get_entry(list_get_first(&clients), client_t, node);
451 if (list_get_next(&c->node) == &clients)
454 c = list_get_entry(list_get_next(&c->node), client_t, node);
461 int Client_send_message_except(client_t *client, message_t *msg)
463 client_t *itr = NULL;
466 Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */
467 while (Client_iterate(&itr) != NULL) {
470 Msg_inc_ref(msg); /* One extra reference for each new copy */
471 Log_debug("Msg %d to %s refcount %d", msg->messageType, itr->playerName, msg->refcount);
472 Client_send_message(itr, msg);
475 Msg_free(msg); /* Free our reference to the message */
478 Msg_free(msg); /* If only 1 client is connected then no message is passed
479 * to Client_send_message(). Free it here. */
484 static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t *plain, unsigned int len)
486 if (CryptState_isValid(&client->cryptState) &&
487 CryptState_decrypt(&client->cryptState, encrypted, plain, len))
490 if (Timer_elapsed(&client->cryptState.tLastGood) > 5000000ULL) {
491 if (Timer_elapsed(&client->cryptState.tLastRequest) > 5000000ULL) {
493 Timer_restart(&client->cryptState.tLastRequest);
495 sendmsg = Msg_create(CryptSetup);
496 Log_info("Requesting voice channel crypt resync");
497 Client_send_message(client, sendmsg);
503 #define UDP_PACKET_SIZE 1024
504 int Client_read_udp()
507 struct sockaddr_in from;
508 socklen_t fromlen = sizeof(struct sockaddr_in);
511 UDPMessageType_t msgType;
513 #if defined(__LP64__)
514 uint8_t encbuff[UDP_PACKET_SIZE + 8];
515 uint8_t *encrypted = encbuff + 4;
517 uint8_t encrypted[UDP_PACKET_SIZE];
519 uint8_t buffer[UDP_PACKET_SIZE];
521 len = recvfrom(udpsock, encrypted, UDP_PACKET_SIZE, MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
524 } else if (len < 0) {
526 } else if (len < 5) {
527 // 4 bytes crypt header + type + session
529 } else if (len > UDP_PACKET_SIZE) {
534 if (len == 12 && *encrypted == 0) {
535 uint32_t *ping = (uint32_t *)encrypted;
536 ping[0] = htons(versionBlob);
537 // 1 and 2 will be the timestamp, which we return unmodified.
538 ping[3] = htons((uint32_t)clientcount);
539 ping[4] = htons((uint32_t)getIntConf(MAX_CLIENTS));
540 ping[5] = htons((uint32_t)getIntConf(MAX_BANDWIDTH));
542 sendto(udpsock, encrypted, 6 * sizeof(uint32_t), 0, (struct sockaddr *)&from, fromlen);
546 key = (((uint64_t)from.sin_addr.s_addr) << 16) ^ from.sin_port;
549 while (Client_iterate(&itr) != NULL) {
550 if (itr->key == key) {
551 if (!checkDecrypt(itr, encrypted, buffer, len))
556 if (itr == NULL) { /* Unknown peer */
557 while (Client_iterate(&itr) != NULL) {
558 if (itr->remote_tcp.sin_addr.s_addr == from.sin_addr.s_addr) {
559 if (checkDecrypt(itr, encrypted, buffer, len)) {
561 Log_info("New UDP connection from %s port %d sessionId %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port), itr->sessionId);
562 memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_in));
565 else Log_warn("Bad cryptstate from peer");
573 msgType = (UDPMessageType_t)((buffer[0] >> 5) & 0x7);
576 case UDPVoiceCELTAlpha:
577 case UDPVoiceCELTBeta:
579 Client_voiceMsg(itr, buffer, len);
582 Client_send_udp(itr, buffer, len);
585 Log_debug("Unknown UDP message type from %s port %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
592 /* Handle decrypted voice message */
593 int Client_voiceMsg(client_t *client, uint8_t *data, int len)
595 uint8_t buffer[UDP_PACKET_SIZE];
596 pds_t *pdi = Pds_create(data + 1, len - 1);
597 pds_t *pds = Pds_create(buffer + 1, UDP_PACKET_SIZE - 1);
598 unsigned int type = data[0] & 0xe0;
599 unsigned int target = data[0] & 0x1f;
600 unsigned int poslen, counter;
601 int offset, packetsize;
603 channel_t *ch = (channel_t *)client->channel;
606 if (!client->authenticated || client->mute)
609 packetsize = 20 + 8 + 4 + len;
610 if (client->availableBandwidth - packetsize < 0)
611 goto out; /* Discard */
612 client->availableBandwidth -= packetsize;
614 counter = Pds_get_numval(pdi); /* step past session id */
616 counter = Pds_next8(pdi);
617 offset = Pds_skip(pdi, counter & 0x7f);
618 } while ((counter & 0x80) && offset > 0);
620 poslen = pdi->maxsize - pdi->offset; /* XXX - Add stripping of positional audio */
622 Pds_add_numval(pds, client->sessionId);
623 Pds_append_data_nosize(pds, data + 1, len - 1);
625 if (target & 0x1f) { /* Loopback */
626 buffer[0] = (uint8_t) type;
627 Client_send_udp(client, buffer, pds->offset + 1);
629 else if (target == 0) { /* regular channel speech */
630 buffer[0] = (uint8_t) type;
635 list_iterate(itr, &ch->clients) {
637 c = list_get_entry(itr, client_t, chan_node);
638 if (c != client && !c->deaf) {
639 Client_send_udp(c, buffer, pds->offset + 1);
643 /* XXX - Add targeted whisper here */
652 static int Client_send_udp(client_t *client, uint8_t *data, int len)
656 if (client->remote_udp.sin_port != 0 && CryptState_isValid(&client->cryptState)) {
657 #if defined(__LP64__)
658 buf = mbuf = malloc(len + 4 + 16);
661 mbuf = buf = malloc(len + 4);
664 Log_fatal("Out of memory");
666 CryptState_encrypt(&client->cryptState, data, buf, len);
668 sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, sizeof(struct sockaddr_in));
674 memcpy(buf, data, len);
675 msg = Msg_create(UDPTunnel);
677 msg->payload.UDPTunnel->packet.data = buf;
678 msg->payload.UDPTunnel->packet.len = len;
679 Client_send_message(client, msg);