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 void dumpmsg(uint8_t *data, int size);
45 static message_t *Msg_create_nopayload(messageType_t messageType);
47 static void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
52 buffer[0] = (type) & 0xff;
53 buffer[1] = (type >> 8) & 0xff;
55 buffer[2] = (len) & 0xff;
56 buffer[3] = (len >> 8) & 0xff;
57 buffer[4] = (len >> 16) & 0xff;
58 buffer[5] = (len >> 24) & 0xff;
61 static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
66 msgType = buffer[0] | (buffer[1] << 8);
67 msgLen = buffer[2] | (buffer[3] << 8) | (buffer[4] << 16) | (buffer[5] << 24);
68 *type = (int)ntohs(msgType);
69 *len = (int)ntohl(msgLen);
72 #define MAX_MSGSIZE (BUFSIZE - PREAMBLE_SIZE)
73 int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
76 uint8_t *bufptr = buffer + PREAMBLE_SIZE;
78 Log_debug("To net: msg type %d", msg->messageType);
79 switch (msg->messageType) {
81 len = mumble_proto__version__get_packed_size(msg->payload.version);
82 if (len > MAX_MSGSIZE) {
83 Log_warn("Too big tx message. Discarding");
86 Msg_addPreamble(buffer, msg->messageType, len);
87 mumble_proto__version__pack(msg->payload.version, bufptr);
89 case UDPTunnel: /* Non-standard handling of tunneled voice traffic. */
90 if (msg->payload.UDPTunnel->packet.len > MAX_MSGSIZE) {
91 Log_warn("Too big tx message. Discarding");
94 len = msg->payload.UDPTunnel->packet.len;
95 Msg_addPreamble(buffer, msg->messageType, msg->payload.UDPTunnel->packet.len);
96 memcpy(bufptr, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
99 len = mumble_proto__authenticate__get_packed_size(msg->payload.authenticate);
100 if (len > MAX_MSGSIZE) {
101 Log_warn("Too big tx message. Discarding");
104 Msg_addPreamble(buffer, msg->messageType, len);
105 mumble_proto__authenticate__pack(msg->payload.authenticate, bufptr);
108 len = mumble_proto__ping__get_packed_size(msg->payload.ping);
109 if (len > MAX_MSGSIZE) {
110 Log_warn("Too big tx message. Discarding");
113 Msg_addPreamble(buffer, msg->messageType, len);
114 mumble_proto__ping__pack(msg->payload.ping, bufptr);
117 len = mumble_proto__reject__get_packed_size(msg->payload.reject);
118 if (len > MAX_MSGSIZE) {
119 Log_warn("Too big tx message. Discarding");
122 Msg_addPreamble(buffer, msg->messageType, len);
123 mumble_proto__reject__pack(msg->payload.reject, bufptr);
126 len = mumble_proto__server_sync__get_packed_size(msg->payload.serverSync);
127 if (len > MAX_MSGSIZE) {
128 Log_warn("Too big tx message. Discarding");
131 Msg_addPreamble(buffer, msg->messageType, len);
132 mumble_proto__server_sync__pack(msg->payload.serverSync, bufptr);
135 len = mumble_proto__text_message__get_packed_size(msg->payload.textMessage);
136 if (len > MAX_MSGSIZE) {
137 Log_warn("Too big tx message. Discarding");
140 Msg_addPreamble(buffer, msg->messageType, len);
141 mumble_proto__text_message__pack(msg->payload.textMessage, bufptr);
143 case PermissionDenied:
144 len = mumble_proto__permission_denied__get_packed_size(msg->payload.permissionDenied);
145 if (len > MAX_MSGSIZE) {
146 Log_warn("Too big tx message. Discarding");
149 Msg_addPreamble(buffer, msg->messageType, len);
150 mumble_proto__permission_denied__pack(msg->payload.permissionDenied, bufptr);
153 len = mumble_proto__crypt_setup__get_packed_size(msg->payload.cryptSetup);
154 if (len > MAX_MSGSIZE) {
155 Log_warn("Too big tx message. Discarding");
158 Msg_addPreamble(buffer, msg->messageType, len);
159 mumble_proto__crypt_setup__pack(msg->payload.cryptSetup, bufptr);
162 len = mumble_proto__user_list__get_packed_size(msg->payload.userList);
163 if (len > MAX_MSGSIZE) {
164 Log_warn("Too big tx message. Discarding");
167 Msg_addPreamble(buffer, msg->messageType, len);
168 mumble_proto__user_list__pack(msg->payload.userList, bufptr);
171 len = mumble_proto__user_state__get_packed_size(msg->payload.userState);
172 if (len > MAX_MSGSIZE) {
173 Log_warn("Too big tx message. Discarding");
176 Msg_addPreamble(buffer, msg->messageType, len);
177 mumble_proto__user_state__pack(msg->payload.userState, bufptr);
180 len = mumble_proto__user_remove__get_packed_size(msg->payload.userRemove);
181 if (len > MAX_MSGSIZE) {
182 Log_warn("Too big tx message. Discarding");
185 Msg_addPreamble(buffer, msg->messageType, len);
186 mumble_proto__user_remove__pack(msg->payload.userRemove, bufptr);
189 len = mumble_proto__channel_state__get_packed_size(msg->payload.channelState);
190 if (len > MAX_MSGSIZE) {
191 Log_warn("Too big tx message. Discarding");
194 Msg_addPreamble(buffer, msg->messageType, len);
195 mumble_proto__channel_state__pack(msg->payload.channelState, bufptr);
198 len = mumble_proto__voice_target__get_packed_size(msg->payload.voiceTarget);
199 if (len > MAX_MSGSIZE) {
200 Log_warn("Too big tx message. Discarding");
203 Msg_addPreamble(buffer, msg->messageType, len);
204 mumble_proto__voice_target__pack(msg->payload.voiceTarget, bufptr);
207 len = mumble_proto__codec_version__get_packed_size(msg->payload.codecVersion);
208 if (len > MAX_MSGSIZE) {
209 Log_warn("Too big tx message. Discarding");
212 Msg_addPreamble(buffer, msg->messageType, len);
213 mumble_proto__codec_version__pack(msg->payload.codecVersion, bufptr);
215 case PermissionQuery:
216 len = mumble_proto__permission_query__get_packed_size(msg->payload.permissionQuery);
217 if (len > MAX_MSGSIZE) {
218 Log_warn("Too big tx message. Discarding");
221 Msg_addPreamble(buffer, msg->messageType, len);
222 mumble_proto__permission_query__pack(msg->payload.permissionQuery, bufptr);
225 len = mumble_proto__channel_remove__get_packed_size(msg->payload.channelRemove);
226 if (len > MAX_MSGSIZE) {
227 Log_warn("Too big tx message. Discarding");
230 Msg_addPreamble(buffer, msg->messageType, len);
231 mumble_proto__channel_remove__pack(msg->payload.channelRemove, bufptr);
235 Log_warn("Msg_MessageToNetwork: Unsupported message %d", msg->messageType);
238 return len + PREAMBLE_SIZE;
241 static message_t *Msg_create_nopayload(messageType_t messageType)
243 message_t *msg = malloc(sizeof(message_t));
246 Log_fatal("Out of memory");
247 memset(msg, 0, sizeof(message_t));
249 msg->messageType = messageType;
250 init_list_entry(&msg->node);
254 message_t *Msg_create(messageType_t messageType)
256 message_t *msg = Msg_create_nopayload(messageType);
258 switch (messageType) {
260 msg->payload.version = malloc(sizeof(MumbleProto__Version));
261 mumble_proto__version__init(msg->payload.version);
264 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
265 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
268 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
269 mumble_proto__authenticate__init(msg->payload.authenticate);
272 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
273 mumble_proto__ping__init(msg->payload.ping);
276 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
277 mumble_proto__reject__init(msg->payload.reject);
280 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
281 mumble_proto__server_sync__init(msg->payload.serverSync);
284 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
285 mumble_proto__text_message__init(msg->payload.textMessage);
287 case PermissionDenied:
288 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
289 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
292 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
293 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
296 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
297 mumble_proto__user_list__init(msg->payload.userList);
300 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
301 mumble_proto__user_state__init(msg->payload.userState);
304 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
305 mumble_proto__channel_state__init(msg->payload.channelState);
308 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
309 mumble_proto__user_remove__init(msg->payload.userRemove);
312 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
313 mumble_proto__voice_target__init(msg->payload.voiceTarget);
316 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
317 mumble_proto__codec_version__init(msg->payload.codecVersion);
319 case PermissionQuery:
320 msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
321 mumble_proto__permission_query__init(msg->payload.permissionQuery);
324 msg->payload.channelRemove = malloc(sizeof(MumbleProto__ChannelRemove));
325 mumble_proto__channel_remove__init(msg->payload.channelRemove);
329 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
336 void Msg_inc_ref(message_t *msg)
341 void Msg_free(message_t *msg)
343 if (msg->refcount) msg->refcount--;
344 if (msg->refcount > 0)
347 switch (msg->messageType) {
350 mumble_proto__version__free_unpacked(msg->payload.version, NULL);
352 if (msg->payload.version->release)
353 free(msg->payload.version->release);
354 if (msg->payload.version->os)
355 free(msg->payload.version->os);
356 if (msg->payload.version->os_version)
357 free(msg->payload.version->os_version);
358 free(msg->payload.version);
363 mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
365 free(msg->payload.UDPTunnel->packet.data);
366 free(msg->payload.UDPTunnel);
371 mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
373 free(msg->payload.authenticate);
377 mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
379 free(msg->payload.ping);
384 mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
386 free(msg->payload.reject->reason);
387 free(msg->payload.reject);
392 mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
394 free(msg->payload.serverSync->welcome_text);
395 free(msg->payload.serverSync);
400 mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
402 free(msg->payload.textMessage);
405 case PermissionDenied:
407 mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
409 free(msg->payload.permissionDenied->reason);
410 free(msg->payload.permissionDenied);
415 mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
417 free(msg->payload.cryptSetup);
422 mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
424 free(msg->payload.userList);
429 mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
431 free(msg->payload.userState->name);
432 free(msg->payload.userState);
437 mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
439 if (msg->payload.channelState->name)
440 free(msg->payload.channelState->name);
441 if (msg->payload.channelState->description)
442 free(msg->payload.channelState->description);
443 if (msg->payload.channelState->links)
444 free(msg->payload.channelState->links);
445 free(msg->payload.channelState);
450 mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
452 free(msg->payload.userRemove);
457 mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
459 free(msg->payload.voiceTarget);
464 mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
466 free(msg->payload.codecVersion);
469 case PermissionQuery:
471 mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
473 free(msg->payload.permissionQuery);
478 mumble_proto__channel_remove__free_unpacked(msg->payload.channelRemove, NULL);
480 free(msg->payload.channelRemove);
485 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
491 void dumpmsg(uint8_t *data, int size)
493 int i, r = 0, offset = 0;
496 while (r * 8 + i < size) {
497 for (i = 0; i < 8 && r * 8 + i < size; i++) {
498 offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
500 sprintf(buf + offset, "\n");
508 message_t *Msg_CreateVoiceMsg(uint8_t *data, int size)
510 message_t *msg = NULL;
512 msg = Msg_create_nopayload(UDPTunnel);
513 msg->unpacked = false;
514 msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel));
515 if (msg->payload.UDPTunnel == NULL)
516 Log_fatal("Out of memory");
517 msg->payload.UDPTunnel->packet.data = malloc(size);
518 if (msg->payload.UDPTunnel->packet.data == NULL)
519 Log_fatal("Out of memory");
520 memcpy(msg->payload.UDPTunnel->packet.data, data, size);
521 msg->payload.UDPTunnel->packet.len = size;
525 message_t *Msg_networkToMessage(uint8_t *data, int size)
527 message_t *msg = NULL;
528 uint8_t *msgData = &data[6];
529 int messageType, msgLen;
531 Msg_getPreamble(data, &messageType, &msgLen);
533 Log_debug("Message type %d size %d", messageType, msgLen);
534 //dumpmsg(data, size);
536 switch (messageType) {
539 msg = Msg_create_nopayload(Version);
540 msg->unpacked = true;
541 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
542 if (msg->payload.version == NULL)
546 case UDPTunnel: /* Non-standard handling of tunneled voice data */
548 msg = Msg_CreateVoiceMsg(msgData, msgLen);
553 msg = Msg_create_nopayload(Authenticate);
554 msg->unpacked = true;
555 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
556 if (msg->payload.authenticate == NULL)
562 msg = Msg_create_nopayload(Ping);
563 msg->unpacked = true;
564 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
565 if (msg->payload.ping == NULL)
571 msg = Msg_create_nopayload(Reject);
572 msg->unpacked = true;
573 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
574 if (msg->payload.reject == NULL)
580 msg = Msg_create_nopayload(ServerSync);
581 msg->unpacked = true;
582 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
583 if (msg->payload.serverSync == NULL)
589 msg = Msg_create_nopayload(TextMessage);
590 msg->unpacked = true;
591 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
592 if (msg->payload.textMessage == NULL)
596 case PermissionDenied:
598 msg = Msg_create_nopayload(PermissionDenied);
599 msg->unpacked = true;
600 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
601 if (msg->payload.permissionDenied == NULL)
607 msg = Msg_create_nopayload(CryptSetup);
608 msg->unpacked = true;
609 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
610 if (msg->payload.cryptSetup == NULL)
616 msg = Msg_create_nopayload(UserList);
617 msg->unpacked = true;
618 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
619 if (msg->payload.userList == NULL)
625 msg = Msg_create_nopayload(UserState);
626 msg->unpacked = true;
627 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
628 if (msg->payload.userState == NULL)
634 msg = Msg_create_nopayload(ChannelState);
635 msg->unpacked = true;
636 msg->payload.channelState = mumble_proto__channel_state__unpack(NULL, msgLen, msgData);
637 if (msg->payload.channelState == NULL)
643 msg = Msg_create_nopayload(VoiceTarget);
644 msg->unpacked = true;
645 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
646 if (msg->payload.voiceTarget == NULL)
652 msg = Msg_create_nopayload(CodecVersion);
653 msg->unpacked = true;
654 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
655 if (msg->payload.codecVersion == NULL)
659 case PermissionQuery:
661 msg = Msg_create_nopayload(PermissionQuery);
662 msg->unpacked = true;
663 msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
664 if (msg->payload.permissionQuery == NULL)
670 msg = Msg_create_nopayload(ChannelRemove);
671 msg->unpacked = true;
672 msg->payload.channelRemove = mumble_proto__channel_remove__unpack(NULL, msgLen, msgData);
673 if (msg->payload.channelRemove == NULL)
679 Log_warn("Unsupported message %d", messageType);