1 /* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2010, 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 #include "voicetarget.h"
45 extern char system_string[], version_string[];
47 static int Client_read(client_t *client);
48 static int Client_write(client_t *client);
49 static int Client_send_udp(client_t *client, uint8_t *data, int len);
50 void Client_free(client_t *client);
52 declare_list(clients);
53 static int clientcount; /* = 0 */
54 static int session = 1;
55 static int maxBandwidth;
57 int iCodecAlpha, iCodecBeta;
64 maxBandwidth = getIntConf(MAX_BANDWIDTH) / 8; /* From bits/s -> bytes/s */
72 int Client_getfds(struct pollfd *pollfds)
76 list_iterate(itr, &clients) {
78 c = list_get_entry(itr, client_t, node);
79 pollfds[i].fd = c->tcpfd;
80 pollfds[i].events = POLLIN | POLLHUP | POLLERR;
81 if (c->txsize > 0 || c->readBlockedOnWrite) /* Data waiting to be sent? */
82 pollfds[i].events |= POLLOUT;
91 int bwTop = maxBandwidth + maxBandwidth / 4;
92 list_iterate(itr, &clients) {
94 c = list_get_entry(itr, client_t, node);
95 Log_debug("Client %s BW available %d", c->playerName, c->availableBandwidth);
96 c->availableBandwidth += maxBandwidth;
97 if (c->availableBandwidth > bwTop)
98 c->availableBandwidth = bwTop;
100 if (Timer_isElapsed(&c->lastActivity, 1000000LL * INACTICITY_TIMEOUT)) {
101 /* No activity from client - assume it is lost and close. */
102 Log_info("Timeout, closing session %d - %s@%s:%d",
105 inet_ntoa(c->remote_tcp.sin_addr),
106 ntohs(c->remote_tcp.sin_port));
112 void recheckCodecVersions()
114 int codec_map[MAX_CODECS][2];
115 client_t *itr = NULL;
116 int i, codecindex, max = 0, version, current_version;
119 memset(codec_map, 0, MAX_CODECS * 2 * sizeof(int));
120 while (Client_iterate(&itr) != NULL) {
121 for (i = 0; i < itr->codec_count; i++) {
122 for (codecindex = 0; codecindex < MAX_CODECS; codecindex++) {
123 if (codec_map[codecindex][0] == 0) {
124 codec_map[codecindex][0] = itr->codecs[i];
125 codec_map[codecindex][1] = 1;
128 if (itr->codecs[i] == codec_map[codecindex][0])
129 codec_map[codecindex][1]++;
133 for (codecindex = 0; codecindex < MAX_CODECS; codecindex++) {
134 if (codec_map[codecindex][0] == 0)
136 if (codec_map[codecindex][1] > max) {
137 max = codec_map[codecindex][1];
138 version = codec_map[codecindex][0];
141 current_version = bPreferAlpha ? iCodecAlpha : iCodecBeta;
142 if (current_version == version)
144 // If we don't already use the compat bitstream version set
145 // it as alpha and announce it. If another codec now got the
146 // majority set it as the opposite of the currently valid bPreferAlpha
148 if (version == (uint32_t)0x8000000a)
151 bPreferAlpha = ! bPreferAlpha;
154 iCodecAlpha = version;
156 iCodecBeta = version;
158 sendmsg = Msg_create(CodecVersion);
159 sendmsg->payload.codecVersion->alpha = version;
160 sendmsg->payload.codecVersion->beta = version;
161 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
162 Client_send_message_except(NULL, sendmsg);
164 Log_info("CELT codec switch 0x%x 0x%x (prefer 0x%x)", iCodecAlpha, iCodecBeta,
165 bPreferAlpha ? iCodecAlpha : iCodecBeta);
169 int Client_add(int fd, struct sockaddr_in *remote)
174 newclient = malloc(sizeof(client_t));
175 if (newclient == NULL)
176 Log_fatal("Out of memory");
177 memset(newclient, 0, sizeof(client_t));
179 newclient->tcpfd = fd;
180 memcpy(&newclient->remote_tcp, remote, sizeof(struct sockaddr_in));
181 newclient->ssl = SSL_newconnection(newclient->tcpfd, &newclient->SSLready);
182 if (newclient->ssl == NULL) {
183 Log_warn("SSL negotiation failed");
187 newclient->availableBandwidth = maxBandwidth;
188 Timer_init(&newclient->lastActivity);
189 newclient->sessionId = session++; /* XXX - more elaborate? */
191 init_list_entry(&newclient->txMsgQueue);
192 init_list_entry(&newclient->chan_node);
193 init_list_entry(&newclient->node);
194 init_list_entry(&newclient->voicetargets);
196 list_add_tail(&newclient->node, &clients);
199 /* Send version message to client */
200 sendmsg = Msg_create(Version);
201 sendmsg->payload.version->has_version = true;
202 sendmsg->payload.version->version = PROTOCOL_VERSION;
203 sendmsg->payload.version->release = strdup(UMURMUR_VERSION);
204 sendmsg->payload.version->os = strdup(system_string);
205 sendmsg->payload.version->os_version = strdup(version_string);
206 Client_send_message(newclient, sendmsg);
211 void Client_free(client_t *client)
213 struct dlist *itr, *save;
216 Log_info("Disconnect session %d - %s@%s:%d",
219 inet_ntoa(client->remote_tcp.sin_addr),
220 ntohs(client->remote_tcp.sin_port));
222 if (client->authenticated) {
223 sendmsg = Msg_create(UserRemove);
224 sendmsg->payload.userRemove->session = client->sessionId;
225 Client_send_message_except(client, sendmsg);
227 list_iterate_safe(itr, save, &client->txMsgQueue) {
228 list_del(&list_get_entry(itr, message_t, node)->node);
229 Msg_free(list_get_entry(itr, message_t, node));
231 Voicetarget_free_all(client);
233 list_del(&client->node);
234 list_del(&client->chan_node);
236 SSL_free(client->ssl);
237 close(client->tcpfd);
240 free(client->release);
243 if (client->playerName)
244 free(client->playerName);
246 free(client->context);
250 void Client_close(client_t *client)
252 SSL_shutdown(client->ssl);
253 client->shutdown_wait = true;
256 void Client_disconnect_all()
258 struct dlist *itr, *save;
260 list_iterate_safe(itr, save, &clients) {
261 Client_free(list_get_entry(itr, client_t, node));
265 int Client_read_fd(int fd)
268 client_t *client = NULL;
270 list_iterate(itr, &clients) {
271 if (fd == list_get_entry(itr, client_t, node)->tcpfd) {
272 client = list_get_entry(itr, client_t, node);
277 Log_fatal("No client found for fd %d", fd);
279 return Client_read(client);
282 int Client_read(client_t *client)
286 Timer_restart(&client->lastActivity);
288 if (client->writeBlockedOnRead) {
289 client->writeBlockedOnRead = false;
290 Log_debug("Client_read: writeBlockedOnRead == true");
291 return Client_write(client);
294 if (client->shutdown_wait) {
298 if (!client->SSLready) {
300 rc = SSL_nonblockaccept(client->ssl, &client->SSLready);
309 if (!client->msgsize)
310 rc = SSL_read(client->ssl, &client->rxbuf[client->rxcount], 6 - client->rxcount);
311 else if (client->drainleft > 0)
312 rc = SSL_read(client->ssl, client->rxbuf, client->drainleft > BUFSIZE ? BUFSIZE : client->drainleft);
314 rc = SSL_read(client->ssl, &client->rxbuf[client->rxcount], client->msgsize);
317 if (client->drainleft > 0)
318 client->drainleft -= rc;
320 client->rxcount += rc;
321 if (!client->msgsize && client->rxcount >= 6) {
323 memcpy(&msgLen, &client->rxbuf[2], sizeof(uint32_t));
324 client->msgsize = ntohl(msgLen);
326 if (client->msgsize > BUFSIZE - 6 && client->drainleft == 0) {
327 Log_warn("Too big message received (%d). Discarding.", client->msgsize);
328 client->rxcount = client->msgsize = 0;
329 client->drainleft = client->msgsize;
331 else if (client->rxcount == client->msgsize + 6) { /* Got all of the message */
332 msg = Msg_networkToMessage(client->rxbuf, client->msgsize + 6);
333 /* pass messsage to handler */
335 Mh_handle_message(client, msg);
336 client->rxcount = client->msgsize = 0;
339 } else /* rc <= 0 */ {
340 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
343 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
344 client->readBlockedOnWrite = true;
347 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_ZERO_RETURN) {
348 Log_warn("Error: Zero return - closing");
349 if (!client->shutdown_wait)
350 Client_close(client);
353 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL) {
354 /* Hmm. This is where we end up when the client closes its connection.
357 Log_info("Connection closed by peer. Session %d - %s@%s:%d",
360 inet_ntoa(client->remote_tcp.sin_addr),
361 ntohs(client->remote_tcp.sin_port));
364 Log_warn("SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
370 } while (SSL_pending(client->ssl));
374 int Client_write_fd(int fd)
377 client_t *client = NULL;
379 list_iterate(itr, &clients) {
380 if(fd == list_get_entry(itr, client_t, node)->tcpfd) {
381 client = list_get_entry(itr, client_t, node);
386 Log_fatal("No client found for fd %d", fd);
387 Client_write(client);
391 int Client_write(client_t *client)
395 if (client->readBlockedOnWrite) {
396 client->readBlockedOnWrite = false;
397 Log_debug("Client_write: readBlockedOnWrite == true");
398 return Client_read(client);
400 rc = SSL_write(client->ssl, &client->txbuf[client->txcount], client->txsize - client->txcount);
402 client->txcount += rc;
403 if (client->txcount == client->txsize)
404 client->txsize = client->txcount = 0;
407 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_READ) {
408 client->writeBlockedOnRead = true;
411 else if (SSL_get_error(client->ssl, rc) == SSL_ERROR_WANT_WRITE) {
415 if (SSL_get_error(client->ssl, rc) == SSL_ERROR_SYSCALL)
416 Log_warn("Client_write: Error: %s - Closing connection", strerror(errno));
418 Log_warn("Client_write: SSL error: %d - Closing connection.", SSL_get_error(client->ssl, rc));
423 if (client->txsize == 0 && !list_empty(&client->txMsgQueue)) {
425 msg = list_get_entry(list_get_first(&client->txMsgQueue), message_t, node);
426 list_del(list_get_first(&client->txMsgQueue));
427 client->txQueueCount--;
428 Client_send_message(client, msg);
433 int Client_send_message(client_t *client, message_t *msg)
435 if (!client->authenticated && msg->messageType != Version) {
439 if (client->txsize != 0 || !client->SSLready) {
441 if ((client->txQueueCount > 5 && msg->messageType == UDPTunnel) ||
442 client->txQueueCount > 30) {
446 client->txQueueCount++;
447 list_add_tail(&msg->node, &client->txMsgQueue);
448 Log_debug("Queueing message");
451 memset(client->txbuf, 0, BUFSIZE);
452 len = Msg_messageToNetwork(msg, client->txbuf);
453 doAssert(len < BUFSIZE);
455 client->txsize = len;
457 Client_write(client);
463 client_t *Client_iterate(client_t **client_itr)
465 client_t *c = *client_itr;
467 if (list_empty(&clients))
471 c = list_get_entry(list_get_first(&clients), client_t, node);
473 if (list_get_next(&c->node) == &clients)
476 c = list_get_entry(list_get_next(&c->node), client_t, node);
483 int Client_send_message_except(client_t *client, message_t *msg)
485 client_t *itr = NULL;
488 Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */
489 while (Client_iterate(&itr) != NULL) {
492 Msg_inc_ref(msg); /* One extra reference for each new copy */
493 Log_debug("Msg %d to %s refcount %d", msg->messageType, itr->playerName, msg->refcount);
494 Client_send_message(itr, msg);
497 Msg_free(msg); /* Free our reference to the message */
500 Msg_free(msg); /* If only 1 client is connected then no message is passed
501 * to Client_send_message(). Free it here. */
506 static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t *plain, unsigned int len)
508 if (CryptState_isValid(&client->cryptState) &&
509 CryptState_decrypt(&client->cryptState, encrypted, plain, len))
512 if (Timer_elapsed(&client->cryptState.tLastGood) > 5000000ULL) {
513 if (Timer_elapsed(&client->cryptState.tLastRequest) > 5000000ULL) {
515 Timer_restart(&client->cryptState.tLastRequest);
517 sendmsg = Msg_create(CryptSetup);
518 Log_info("Requesting voice channel crypt resync. Session %d - %s@%s:%d",
521 inet_ntoa(client->remote_tcp.sin_addr),
522 ntohs(client->remote_tcp.sin_port));
524 Client_send_message(client, sendmsg);
530 #define UDP_PACKET_SIZE 1024
531 int Client_read_udp()
534 struct sockaddr_in from;
535 socklen_t fromlen = sizeof(struct sockaddr_in);
538 UDPMessageType_t msgType;
540 #if defined(__LP64__)
541 uint8_t encbuff[UDP_PACKET_SIZE + 8];
542 uint8_t *encrypted = encbuff + 4;
544 uint8_t encrypted[UDP_PACKET_SIZE];
546 uint8_t buffer[UDP_PACKET_SIZE];
548 len = recvfrom(udpsock, encrypted, UDP_PACKET_SIZE, MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
551 } else if (len < 0) {
553 } else if (len < 5) {
554 // 4 bytes crypt header + type + session
556 } else if (len > UDP_PACKET_SIZE) {
561 if (len == 12 && *encrypted == 0) {
562 uint32_t *ping = (uint32_t *)encrypted;
563 ping[0] = htonl((uint32_t)PROTOCOL_VERSION);
564 // 1 and 2 will be the timestamp, which we return unmodified.
565 ping[3] = htonl((uint32_t)clientcount);
566 ping[4] = htonl((uint32_t)getIntConf(MAX_CLIENTS));
567 ping[5] = htonl((uint32_t)getIntConf(MAX_BANDWIDTH));
569 sendto(udpsock, encrypted, 6 * sizeof(uint32_t), 0, (struct sockaddr *)&from, fromlen);
573 key = (((uint64_t)from.sin_addr.s_addr) << 16) ^ from.sin_port;
576 while (Client_iterate(&itr) != NULL) {
577 if (itr->key == key) {
578 if (!checkDecrypt(itr, encrypted, buffer, len))
583 if (itr == NULL) { /* Unknown peer */
584 while (Client_iterate(&itr) != NULL) {
585 if (itr->remote_tcp.sin_addr.s_addr == from.sin_addr.s_addr) {
586 if (checkDecrypt(itr, encrypted, buffer, len)) {
588 Log_info("New UDP connection from session %d - %s@%s:%d",
591 inet_ntoa(from.sin_addr),
592 ntohs(from.sin_port));
593 memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_in));
596 else Log_warn("Bad cryptstate from peer");
604 msgType = (UDPMessageType_t)((buffer[0] >> 5) & 0x7);
607 case UDPVoiceCELTAlpha:
608 case UDPVoiceCELTBeta:
610 Client_voiceMsg(itr, buffer, len);
613 Log_debug("UDP Ping reply len %d", len);
614 Client_send_udp(itr, buffer, len);
617 Log_debug("Unknown UDP message type from %s port %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
624 static inline void Client_send_voice(client_t *src, client_t *dst, uint8_t *data, int len, int poslen)
626 if (IS_AUTH(dst) && dst != src && !dst->deaf) {
627 if (poslen > 0 && strcmp(src->context, dst->context) == 0)
628 Client_send_udp(dst, data, len);
630 Client_send_udp(dst, data, len - poslen);
634 /* Handle decrypted voice message */
635 int Client_voiceMsg(client_t *client, uint8_t *data, int len)
637 uint8_t buffer[UDP_PACKET_SIZE];
638 pds_t *pdi = Pds_create(data + 1, len - 1);
639 pds_t *pds = Pds_create(buffer + 1, UDP_PACKET_SIZE - 1);
640 unsigned int type = data[0] & 0xe0;
641 unsigned int target = data[0] & 0x1f;
642 unsigned int poslen, counter;
643 int offset, packetsize;
646 channel_t *ch = (channel_t *)client->channel;
649 if (!client->authenticated || client->mute)
652 packetsize = 20 + 8 + 4 + len;
653 if (client->availableBandwidth - packetsize < 0)
654 goto out; /* Discard */
655 client->availableBandwidth -= packetsize;
657 counter = Pds_get_numval(pdi); /* step past session id */
659 counter = Pds_next8(pdi);
660 offset = Pds_skip(pdi, counter & 0x7f);
661 } while ((counter & 0x80) && offset > 0);
663 poslen = pdi->maxsize - pdi->offset; /* For stripping of positional info */
665 Pds_add_numval(pds, client->sessionId);
666 Pds_append_data_nosize(pds, data + 1, len - 1);
668 if (target == 0x1f) { /* Loopback */
669 buffer[0] = (uint8_t) type;
670 Client_send_udp(client, buffer, pds->offset + 1);
672 else if (target == 0) { /* regular channel speech */
673 buffer[0] = (uint8_t) type;
678 list_iterate(itr, &ch->clients) {
680 c = list_get_entry(itr, client_t, chan_node);
681 Client_send_voice(client, c, buffer, pds->offset + 1, poslen);
684 if (!list_empty(&ch->channel_links)) {
685 struct dlist *ch_itr;
686 list_iterate(ch_itr, &ch->channel_links) {
688 ch_link = list_get_entry(ch_itr, channel_t, link_node);
689 list_iterate(itr, &ch_link->clients) {
691 c = list_get_entry(itr, client_t, chan_node);
692 Log_debug("Linked voice from %s -> %s", ch->name, ch_link->name);
693 Client_send_voice(client, c, buffer, pds->offset + 1, poslen);
697 } else if ((vt = Voicetarget_get_id(client, target)) != NULL) { /* Targeted whisper */
701 for (i = 0; i < TARGET_MAX_CHANNELS && vt->channels[i] != -1; i++) {
702 Log_debug("Whisper channel %d", vt->channels[i]);
703 ch = Chan_fromId(vt->channels[i]);
706 list_iterate(itr, &ch->clients) {
708 c = list_get_entry(itr, client_t, chan_node);
709 Client_send_voice(client, c, buffer, pds->offset + 1, poslen);
713 for (i = 0; i < TARGET_MAX_SESSIONS && vt->sessions[i] != -1; i++) {
715 Log_debug("Whisper session %d", vt->sessions[i]);
716 while (Client_iterate(&c) != NULL) {
717 if (c->sessionId == vt->sessions[i]) {
718 Client_send_voice(client, c, buffer, pds->offset + 1, poslen);
732 static int Client_send_udp(client_t *client, uint8_t *data, int len)
736 if (client->remote_udp.sin_port != 0 && CryptState_isValid(&client->cryptState)) {
737 #if defined(__LP64__)
738 buf = mbuf = malloc(len + 4 + 16);
741 mbuf = buf = malloc(len + 4);
744 Log_fatal("Out of memory");
746 CryptState_encrypt(&client->cryptState, data, buf, len);
748 sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, sizeof(struct sockaddr_in));
754 memcpy(buf, data, len);
755 msg = Msg_create(UDPTunnel);
757 msg->payload.UDPTunnel->packet.data = buf;
758 msg->payload.UDPTunnel->packet.len = len;
759 Client_send_message(client, msg);