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.
35 #include <arpa/inet.h>
42 #define PREAMBLE_SIZE 6
44 static message_t *Msg_create_nopayload(messageType_t messageType);
46 static void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
48 buffer[1] = (type) & 0xff;
49 buffer[0] = (type >> 8) & 0xff;
51 buffer[5] = (len) & 0xff;
52 buffer[4] = (len >> 8) & 0xff;
53 buffer[3] = (len >> 16) & 0xff;
54 buffer[2] = (len >> 24) & 0xff;
57 static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
62 msgType = buffer[1] | (buffer[0] << 8);
63 msgLen = buffer[5] | (buffer[4] << 8) | (buffer[3] << 16) | (buffer[2] << 24);
68 #define MAX_MSGSIZE (BUFSIZE - PREAMBLE_SIZE)
69 int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
72 uint8_t *bufptr = buffer + PREAMBLE_SIZE;
74 Log_debug("To net: msg type %d", msg->messageType);
75 switch (msg->messageType) {
77 len = mumble_proto__version__get_packed_size(msg->payload.version);
78 if (len > MAX_MSGSIZE) {
79 Log_warn("Too big tx message. Discarding");
82 Msg_addPreamble(buffer, msg->messageType, len);
83 mumble_proto__version__pack(msg->payload.version, bufptr);
85 case UDPTunnel: /* Non-standard handling of tunneled voice traffic. */
86 if (msg->payload.UDPTunnel->packet.len > MAX_MSGSIZE) {
87 Log_warn("Too big tx message. Discarding");
90 len = msg->payload.UDPTunnel->packet.len;
91 Msg_addPreamble(buffer, msg->messageType, msg->payload.UDPTunnel->packet.len);
92 memcpy(bufptr, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
95 len = mumble_proto__authenticate__get_packed_size(msg->payload.authenticate);
96 if (len > MAX_MSGSIZE) {
97 Log_warn("Too big tx message. Discarding");
100 Msg_addPreamble(buffer, msg->messageType, len);
101 mumble_proto__authenticate__pack(msg->payload.authenticate, bufptr);
104 len = mumble_proto__ping__get_packed_size(msg->payload.ping);
105 if (len > MAX_MSGSIZE) {
106 Log_warn("Too big tx message. Discarding");
109 Msg_addPreamble(buffer, msg->messageType, len);
110 mumble_proto__ping__pack(msg->payload.ping, bufptr);
113 len = mumble_proto__reject__get_packed_size(msg->payload.reject);
114 if (len > MAX_MSGSIZE) {
115 Log_warn("Too big tx message. Discarding");
118 Msg_addPreamble(buffer, msg->messageType, len);
119 mumble_proto__reject__pack(msg->payload.reject, bufptr);
122 len = mumble_proto__server_sync__get_packed_size(msg->payload.serverSync);
123 if (len > MAX_MSGSIZE) {
124 Log_warn("Too big tx message. Discarding");
127 Msg_addPreamble(buffer, msg->messageType, len);
128 mumble_proto__server_sync__pack(msg->payload.serverSync, bufptr);
131 len = mumble_proto__text_message__get_packed_size(msg->payload.textMessage);
132 if (len > MAX_MSGSIZE) {
133 Log_warn("Too big tx message. Discarding");
136 Msg_addPreamble(buffer, msg->messageType, len);
137 mumble_proto__text_message__pack(msg->payload.textMessage, bufptr);
139 case PermissionDenied:
140 len = mumble_proto__permission_denied__get_packed_size(msg->payload.permissionDenied);
141 if (len > MAX_MSGSIZE) {
142 Log_warn("Too big tx message. Discarding");
145 Msg_addPreamble(buffer, msg->messageType, len);
146 mumble_proto__permission_denied__pack(msg->payload.permissionDenied, bufptr);
149 len = mumble_proto__crypt_setup__get_packed_size(msg->payload.cryptSetup);
150 if (len > MAX_MSGSIZE) {
151 Log_warn("Too big tx message. Discarding");
154 Msg_addPreamble(buffer, msg->messageType, len);
155 mumble_proto__crypt_setup__pack(msg->payload.cryptSetup, bufptr);
158 len = mumble_proto__user_list__get_packed_size(msg->payload.userList);
159 if (len > MAX_MSGSIZE) {
160 Log_warn("Too big tx message. Discarding");
163 Msg_addPreamble(buffer, msg->messageType, len);
164 mumble_proto__user_list__pack(msg->payload.userList, bufptr);
167 len = mumble_proto__user_state__get_packed_size(msg->payload.userState);
168 if (len > MAX_MSGSIZE) {
169 Log_warn("Too big tx message. Discarding");
172 Msg_addPreamble(buffer, msg->messageType, len);
173 mumble_proto__user_state__pack(msg->payload.userState, bufptr);
176 len = mumble_proto__user_remove__get_packed_size(msg->payload.userRemove);
177 if (len > MAX_MSGSIZE) {
178 Log_warn("Too big tx message. Discarding");
181 Msg_addPreamble(buffer, msg->messageType, len);
182 mumble_proto__user_remove__pack(msg->payload.userRemove, bufptr);
185 len = mumble_proto__channel_state__get_packed_size(msg->payload.channelState);
186 if (len > MAX_MSGSIZE) {
187 Log_warn("Too big tx message. Discarding");
190 Msg_addPreamble(buffer, msg->messageType, len);
191 mumble_proto__channel_state__pack(msg->payload.channelState, bufptr);
194 len = mumble_proto__voice_target__get_packed_size(msg->payload.voiceTarget);
195 if (len > MAX_MSGSIZE) {
196 Log_warn("Too big tx message. Discarding");
199 Msg_addPreamble(buffer, msg->messageType, len);
200 mumble_proto__voice_target__pack(msg->payload.voiceTarget, bufptr);
203 len = mumble_proto__codec_version__get_packed_size(msg->payload.codecVersion);
204 if (len > MAX_MSGSIZE) {
205 Log_warn("Too big tx message. Discarding");
208 Msg_addPreamble(buffer, msg->messageType, len);
209 mumble_proto__codec_version__pack(msg->payload.codecVersion, bufptr);
211 case PermissionQuery:
212 len = mumble_proto__permission_query__get_packed_size(msg->payload.permissionQuery);
213 if (len > MAX_MSGSIZE) {
214 Log_warn("Too big tx message. Discarding");
217 Msg_addPreamble(buffer, msg->messageType, len);
218 mumble_proto__permission_query__pack(msg->payload.permissionQuery, bufptr);
221 len = mumble_proto__channel_remove__get_packed_size(msg->payload.channelRemove);
222 if (len > MAX_MSGSIZE) {
223 Log_warn("Too big tx message. Discarding");
226 Msg_addPreamble(buffer, msg->messageType, len);
227 mumble_proto__channel_remove__pack(msg->payload.channelRemove, bufptr);
231 len = mumble_proto__user_stats__get_packed_size(msg->payload.userStats);
232 if (len > MAX_MSGSIZE) {
233 Log_warn("Too big tx message. Discarding");
236 Msg_addPreamble(buffer, msg->messageType, len);
237 mumble_proto__user_stats__pack(msg->payload.userStats, bufptr);
241 len = mumble_proto__server_config__get_packed_size(msg->payload.serverConfig);
242 if (len > MAX_MSGSIZE) {
243 Log_warn("Too big tx message. Discarding");
246 Msg_addPreamble(buffer, msg->messageType, len);
247 mumble_proto__server_config__pack(msg->payload.serverConfig, bufptr);
251 Log_warn("Msg_MessageToNetwork: Unsupported message %d", msg->messageType);
254 return len + PREAMBLE_SIZE;
257 static message_t *Msg_create_nopayload(messageType_t messageType)
259 message_t *msg = malloc(sizeof(message_t));
262 Log_fatal("Out of memory");
263 memset(msg, 0, sizeof(message_t));
265 msg->messageType = messageType;
266 init_list_entry(&msg->node);
270 message_t *Msg_create(messageType_t messageType)
272 message_t *msg = Msg_create_nopayload(messageType);
274 switch (messageType) {
276 msg->payload.version = malloc(sizeof(MumbleProto__Version));
277 mumble_proto__version__init(msg->payload.version);
280 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
281 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
284 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
285 mumble_proto__authenticate__init(msg->payload.authenticate);
288 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
289 mumble_proto__ping__init(msg->payload.ping);
292 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
293 mumble_proto__reject__init(msg->payload.reject);
296 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
297 mumble_proto__server_sync__init(msg->payload.serverSync);
300 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
301 mumble_proto__text_message__init(msg->payload.textMessage);
303 case PermissionDenied:
304 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
305 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
308 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
309 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
312 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
313 mumble_proto__user_list__init(msg->payload.userList);
316 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
317 mumble_proto__user_state__init(msg->payload.userState);
320 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
321 mumble_proto__channel_state__init(msg->payload.channelState);
324 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
325 mumble_proto__user_remove__init(msg->payload.userRemove);
328 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
329 mumble_proto__voice_target__init(msg->payload.voiceTarget);
332 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
333 mumble_proto__codec_version__init(msg->payload.codecVersion);
335 case PermissionQuery:
336 msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
337 mumble_proto__permission_query__init(msg->payload.permissionQuery);
340 msg->payload.channelRemove = malloc(sizeof(MumbleProto__ChannelRemove));
341 mumble_proto__channel_remove__init(msg->payload.channelRemove);
344 msg->payload.userStats = malloc(sizeof(MumbleProto__UserStats));
345 mumble_proto__user_stats__init(msg->payload.userStats);
347 msg->payload.userStats->from_client = malloc(sizeof(MumbleProto__UserStats__Stats));
348 mumble_proto__user_stats__stats__init(msg->payload.userStats->from_client);
350 msg->payload.userStats->from_server = malloc(sizeof(MumbleProto__UserStats__Stats));
351 mumble_proto__user_stats__stats__init(msg->payload.userStats->from_server);
353 msg->payload.userStats->version = malloc(sizeof(MumbleProto__Version));
354 mumble_proto__version__init(msg->payload.userStats->version);
356 if (!msg->payload.userStats || !msg->payload.userStats->from_client ||
357 !msg->payload.userStats->from_server || !msg->payload.userStats->version)
358 Log_fatal("Out of memory");
361 msg->payload.serverConfig = malloc(sizeof(MumbleProto__ServerConfig));
362 mumble_proto__server_config__init(msg->payload.serverConfig);
366 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
373 void Msg_inc_ref(message_t *msg)
378 void Msg_free(message_t *msg)
380 if (msg->refcount) msg->refcount--;
381 if (msg->refcount > 0)
384 switch (msg->messageType) {
387 mumble_proto__version__free_unpacked(msg->payload.version, NULL);
389 if (msg->payload.version->release)
390 free(msg->payload.version->release);
391 if (msg->payload.version->os)
392 free(msg->payload.version->os);
393 if (msg->payload.version->os_version)
394 free(msg->payload.version->os_version);
395 free(msg->payload.version);
400 mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
402 free(msg->payload.UDPTunnel->packet.data);
403 free(msg->payload.UDPTunnel);
408 mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
410 free(msg->payload.authenticate);
414 mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
416 free(msg->payload.ping);
421 mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
423 free(msg->payload.reject->reason);
424 free(msg->payload.reject);
429 mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
431 free(msg->payload.serverSync->welcome_text);
432 free(msg->payload.serverSync);
437 mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
439 if (msg->payload.textMessage->message)
440 free(msg->payload.textMessage->message);
441 if (msg->payload.textMessage->session)
442 free(msg->payload.textMessage->session);
443 if (msg->payload.textMessage->channel_id)
444 free(msg->payload.textMessage->channel_id);
445 if (msg->payload.textMessage->tree_id)
446 free(msg->payload.textMessage->tree_id);
447 free(msg->payload.textMessage);
450 case PermissionDenied:
452 mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
454 free(msg->payload.permissionDenied->reason);
455 free(msg->payload.permissionDenied);
460 mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
462 free(msg->payload.cryptSetup);
467 mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
469 free(msg->payload.userList);
474 mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
476 free(msg->payload.userState->name);
477 free(msg->payload.userState);
482 mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
484 if (msg->payload.channelState->name)
485 free(msg->payload.channelState->name);
486 if (msg->payload.channelState->description)
487 free(msg->payload.channelState->description);
488 if (msg->payload.channelState->links)
489 free(msg->payload.channelState->links);
490 free(msg->payload.channelState);
495 mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
497 free(msg->payload.userRemove);
502 mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
504 free(msg->payload.voiceTarget);
509 mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
511 free(msg->payload.codecVersion);
514 case PermissionQuery:
516 mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
518 free(msg->payload.permissionQuery);
523 mumble_proto__channel_remove__free_unpacked(msg->payload.channelRemove, NULL);
525 free(msg->payload.channelRemove);
530 mumble_proto__user_stats__free_unpacked(msg->payload.userStats, NULL);
532 if (msg->payload.userStats->from_client)
533 free(msg->payload.userStats->from_client);
534 if (msg->payload.userStats->from_server)
535 free(msg->payload.userStats->from_server);
536 if (msg->payload.userStats->version) {
537 if (msg->payload.userStats->version->release)
538 free(msg->payload.userStats->version->release);
539 if (msg->payload.userStats->version->os)
540 free(msg->payload.userStats->version->os);
541 if (msg->payload.userStats->version->os_version)
542 free(msg->payload.userStats->version->os_version);
544 free(msg->payload.userStats->version);
546 if (msg->payload.userStats->celt_versions)
547 free(msg->payload.userStats->celt_versions);
548 if (msg->payload.userStats->certificates) {
549 if (msg->payload.userStats->certificates->data)
550 free(msg->payload.userStats->certificates->data);
551 free(msg->payload.userStats->certificates);
553 if (msg->payload.userStats->address.data)
554 free(msg->payload.userStats->address.data);
556 free(msg->payload.userStats);
561 mumble_proto__server_config__free_unpacked(msg->payload.serverConfig, NULL);
563 free(msg->payload.serverConfig);
568 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
574 message_t *Msg_CreateVoiceMsg(uint8_t *data, int size)
576 message_t *msg = NULL;
578 msg = Msg_create_nopayload(UDPTunnel);
579 msg->unpacked = false;
580 msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel));
581 if (msg->payload.UDPTunnel == NULL)
582 Log_fatal("Out of memory");
583 msg->payload.UDPTunnel->packet.data = malloc(size);
584 if (msg->payload.UDPTunnel->packet.data == NULL)
585 Log_fatal("Out of memory");
586 memcpy(msg->payload.UDPTunnel->packet.data, data, size);
587 msg->payload.UDPTunnel->packet.len = size;
591 message_t *Msg_networkToMessage(uint8_t *data, int size)
593 message_t *msg = NULL;
594 uint8_t *msgData = &data[6];
595 int messageType, msgLen;
597 Msg_getPreamble(data, &messageType, &msgLen);
599 Log_debug("Message type %d size %d", messageType, msgLen);
600 //dumpmsg(data, size);
602 switch (messageType) {
605 msg = Msg_create_nopayload(Version);
606 msg->unpacked = true;
607 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
608 if (msg->payload.version == NULL)
612 case UDPTunnel: /* Non-standard handling of tunneled voice data */
614 msg = Msg_CreateVoiceMsg(msgData, msgLen);
619 msg = Msg_create_nopayload(Authenticate);
620 msg->unpacked = true;
621 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
622 if (msg->payload.authenticate == NULL)
628 msg = Msg_create_nopayload(Ping);
629 msg->unpacked = true;
630 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
631 if (msg->payload.ping == NULL)
637 msg = Msg_create_nopayload(Reject);
638 msg->unpacked = true;
639 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
640 if (msg->payload.reject == NULL)
646 msg = Msg_create_nopayload(ServerSync);
647 msg->unpacked = true;
648 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
649 if (msg->payload.serverSync == NULL)
655 msg = Msg_create_nopayload(TextMessage);
656 msg->unpacked = true;
657 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
658 if (msg->payload.textMessage == NULL)
662 case PermissionDenied:
664 msg = Msg_create_nopayload(PermissionDenied);
665 msg->unpacked = true;
666 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
667 if (msg->payload.permissionDenied == NULL)
673 msg = Msg_create_nopayload(CryptSetup);
674 msg->unpacked = true;
675 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
676 if (msg->payload.cryptSetup == NULL)
682 msg = Msg_create_nopayload(UserList);
683 msg->unpacked = true;
684 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
685 if (msg->payload.userList == NULL)
691 msg = Msg_create_nopayload(UserState);
692 msg->unpacked = true;
693 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
694 if (msg->payload.userState == NULL)
700 msg = Msg_create_nopayload(ChannelState);
701 msg->unpacked = true;
702 msg->payload.channelState = mumble_proto__channel_state__unpack(NULL, msgLen, msgData);
703 if (msg->payload.channelState == NULL)
709 msg = Msg_create_nopayload(VoiceTarget);
710 msg->unpacked = true;
711 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
712 if (msg->payload.voiceTarget == NULL)
718 msg = Msg_create_nopayload(CodecVersion);
719 msg->unpacked = true;
720 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
721 if (msg->payload.codecVersion == NULL)
725 case PermissionQuery:
727 msg = Msg_create_nopayload(PermissionQuery);
728 msg->unpacked = true;
729 msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
730 if (msg->payload.permissionQuery == NULL)
736 msg = Msg_create_nopayload(ChannelRemove);
737 msg->unpacked = true;
738 msg->payload.channelRemove = mumble_proto__channel_remove__unpack(NULL, msgLen, msgData);
739 if (msg->payload.channelRemove == NULL)
745 msg = Msg_create_nopayload(UserStats);
746 msg->unpacked = true;
747 msg->payload.userStats = mumble_proto__user_stats__unpack(NULL, msgLen, msgData);
748 if (msg->payload.userStats == NULL)
754 Log_warn("Unsupported message %d", messageType);