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>
43 void dumpmsg(uint8_t *data, int size);
44 static message_t *Msg_create_nopayload(messageType_t messageType);
46 void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
51 buffer[0] = (type) & 0xff;
52 buffer[1] = (type >> 8) & 0xff;
54 buffer[2] = (len) & 0xff;
55 buffer[3] = (len >> 8) & 0xff;
56 buffer[4] = (len >> 16) & 0xff;
57 buffer[5] = (len >> 24) & 0xff;
60 static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
65 msgType = buffer[0] | (buffer[1] << 8);
66 msgLen = buffer[2] | (buffer[3] << 8) | (buffer[4] << 16) | (buffer[5] << 24);
67 *type = (int)ntohs(msgType);
68 *len = (int)ntohl(msgLen);
71 #define MAX_MSGSIZE (BUFSIZE - 6)
72 int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
75 uint8_t *bufptr = buffer + 6;
77 Log_debug("To net: msg type %d", msg->messageType);
78 switch (msg->messageType) {
80 len = mumble_proto__version__get_packed_size(msg->payload.version);
81 if (len > MAX_MSGSIZE) {
82 Log_warn("Too big tx message. Discarding");
85 Msg_addPreamble(buffer, msg->messageType, len);
86 Log_debug("To net: Version->release: %s Version->os: %s",
87 msg->payload.version->release, msg->payload.version->os);
88 mumble_proto__version__pack(msg->payload.version, bufptr);
90 case UDPTunnel: /* Non-standard handling of tunneled voice traffic. */
91 if (msg->payload.UDPTunnel->packet.len > MAX_MSGSIZE) {
92 Log_warn("Too big tx message. Discarding");
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__channel_state__get_packed_size(msg->payload.channelState);
181 if (len > MAX_MSGSIZE) {
182 Log_warn("Too big tx message. Discarding");
185 Msg_addPreamble(buffer, msg->messageType, len);
186 mumble_proto__channel_state__pack(msg->payload.channelState, bufptr);
189 len = mumble_proto__voice_target__get_packed_size(msg->payload.voiceTarget);
190 if (len > MAX_MSGSIZE) {
191 Log_warn("Too big tx message. Discarding");
194 Msg_addPreamble(buffer, msg->messageType, len);
195 mumble_proto__voice_target__pack(msg->payload.voiceTarget, bufptr);
198 len = mumble_proto__codec_version__get_packed_size(msg->payload.codecVersion);
199 if (len > MAX_MSGSIZE) {
200 Log_warn("Too big tx message. Discarding");
203 Msg_addPreamble(buffer, msg->messageType, len);
204 mumble_proto__codec_version__pack(msg->payload.codecVersion, bufptr);
206 case PermissionQuery:
207 len = mumble_proto__permission_query__get_packed_size(msg->payload.permissionQuery);
208 if (len > MAX_MSGSIZE) {
209 Log_warn("Too big tx message. Discarding");
212 Msg_addPreamble(buffer, msg->messageType, len);
213 mumble_proto__permission_query__pack(msg->payload.permissionQuery, bufptr);
216 len = mumble_proto__channel_remove__get_packed_size(msg->payload.channelRemove);
217 if (len > MAX_MSGSIZE) {
218 Log_warn("Too big tx message. Discarding");
221 Msg_addPreamble(buffer, msg->messageType, len);
222 mumble_proto__channel_remove__pack(msg->payload.channelRemove, bufptr);
226 Log_warn("Unsupported message %d", msg->messageType);
232 message_t *Msg_create_nopayload(messageType_t messageType)
234 message_t *msg = malloc(sizeof(message_t));
237 Log_fatal("Out of memory");
238 memset(msg, 0, sizeof(message_t));
240 msg->messageType = messageType;
241 init_list_entry(&msg->node);
245 message_t *Msg_create(messageType_t messageType)
247 message_t *msg = Msg_create_nopayload(messageType);
249 switch (messageType) {
251 msg->payload.version = malloc(sizeof(MumbleProto__Version));
252 mumble_proto__version__init(msg->payload.version);
255 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
256 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
259 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
260 mumble_proto__authenticate__init(msg->payload.authenticate);
263 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
264 mumble_proto__ping__init(msg->payload.ping);
267 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
268 mumble_proto__reject__init(msg->payload.reject);
271 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
272 mumble_proto__server_sync__init(msg->payload.serverSync);
275 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
276 mumble_proto__text_message__init(msg->payload.textMessage);
278 case PermissionDenied:
279 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
280 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
283 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
284 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
287 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
288 mumble_proto__user_list__init(msg->payload.userList);
291 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
292 mumble_proto__user_state__init(msg->payload.userState);
295 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
296 mumble_proto__channel_state__init(msg->payload.channelState);
299 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
300 mumble_proto__user_remove__init(msg->payload.userRemove);
303 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
304 mumble_proto__voice_target__init(msg->payload.voiceTarget);
307 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
308 mumble_proto__codec_version__init(msg->payload.codecVersion);
310 case PermissionQuery:
311 msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
312 mumble_proto__permission_query__init(msg->payload.permissionQuery);
315 msg->payload.channelRemove = malloc(sizeof(MumbleProto__ChannelRemove));
316 mumble_proto__channel_remove__init(msg->payload.channelRemove);
320 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
327 void Msg_inc_ref(message_t *msg)
332 void Msg_free(message_t *msg)
334 if (msg->refcount) msg->refcount--;
335 if (msg->refcount > 0)
338 switch (msg->messageType) {
341 mumble_proto__version__free_unpacked(msg->payload.version, NULL);
343 if (msg->payload.version->release)
344 free(msg->payload.version->release);
345 if (msg->payload.version->os)
346 free(msg->payload.version->os);
347 if (msg->payload.version->os_version)
348 free(msg->payload.version->os_version);
349 free(msg->payload.version);
354 mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
356 free(msg->payload.UDPTunnel->packet.data);
357 free(msg->payload.UDPTunnel);
362 mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
364 free(msg->payload.authenticate);
368 mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
370 free(msg->payload.ping);
375 mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
377 free(msg->payload.reject->reason);
378 free(msg->payload.reject);
383 mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
385 free(msg->payload.serverSync->welcome_text);
386 free(msg->payload.serverSync);
391 mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
393 free(msg->payload.textMessage);
396 case PermissionDenied:
398 mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
400 free(msg->payload.permissionDenied->reason);
401 free(msg->payload.permissionDenied);
406 mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
408 free(msg->payload.cryptSetup);
413 mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
415 free(msg->payload.userList);
420 mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
422 free(msg->payload.userState->name);
423 free(msg->payload.userState);
428 mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
430 free(msg->payload.channelState->name);
431 free(msg->payload.channelState->description);
432 free(msg->payload.channelState);
437 mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
439 free(msg->payload.userRemove);
444 mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
446 free(msg->payload.voiceTarget);
451 mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
453 free(msg->payload.codecVersion);
456 case PermissionQuery:
458 mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
460 free(msg->payload.permissionQuery);
465 mumble_proto__channel_remove__free_unpacked(msg->payload.channelRemove, NULL);
467 free(msg->payload.channelRemove);
472 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
478 void dumpmsg(uint8_t *data, int size)
480 int i, r = 0, offset = 0;
483 while (r * 8 + i < size) {
484 for (i = 0; i < 8 && r * 8 + i < size; i++) {
485 offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
487 sprintf(buf + offset, "\n");
495 message_t *Msg_networkToMessage(uint8_t *data, int size)
497 message_t *msg = NULL;
498 uint8_t *msgData = &data[6];
499 int messageType, msgLen;
501 Msg_getPreamble(data, &messageType, &msgLen);
503 Log_debug("Message type %d size %d", messageType, msgLen);
504 //dumpmsg(data, size);
506 switch (messageType) {
509 msg = Msg_create_nopayload(Version);
510 msg->unpacked = true;
511 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
514 case UDPTunnel: /* Non-standard handling of tunneled voice data */
516 msg = Msg_create_nopayload(UDPTunnel);
517 msg->unpacked = false;
518 msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel));
519 if (msg->payload.UDPTunnel == NULL)
520 Log_fatal("Out of memory");
521 msg->payload.UDPTunnel->packet.data = malloc(msgLen);
522 if (msg->payload.UDPTunnel->packet.data == NULL)
523 Log_fatal("Out of memory");
524 memcpy(msg->payload.UDPTunnel->packet.data, msgData, msgLen);
525 msg->payload.UDPTunnel->packet.len = msgLen;
530 msg = Msg_create_nopayload(Authenticate);
531 msg->unpacked = true;
532 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
537 msg = Msg_create_nopayload(Ping);
538 msg->unpacked = true;
539 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
544 msg = Msg_create_nopayload(Reject);
545 msg->unpacked = true;
546 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
551 msg = Msg_create_nopayload(ServerSync);
552 msg->unpacked = true;
553 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
558 msg = Msg_create_nopayload(TextMessage);
559 msg->unpacked = true;
560 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
563 case PermissionDenied:
565 msg = Msg_create_nopayload(PermissionDenied);
566 msg->unpacked = true;
567 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
572 msg = Msg_create_nopayload(CryptSetup);
573 msg->unpacked = true;
574 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
579 msg = Msg_create_nopayload(UserList);
580 msg->unpacked = true;
581 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
586 msg = Msg_create_nopayload(UserState);
587 msg->unpacked = true;
588 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
593 msg = Msg_create_nopayload(ChannelState);
594 msg->unpacked = true;
595 msg->payload.channelState = mumble_proto__channel_state__unpack(NULL, msgLen, msgData);
600 msg = Msg_create_nopayload(VoiceTarget);
601 msg->unpacked = true;
602 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
607 msg = Msg_create_nopayload(CodecVersion);
608 msg->unpacked = true;
609 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
612 case PermissionQuery:
614 msg = Msg_create_nopayload(PermissionQuery);
615 msg->unpacked = true;
616 msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
621 msg = Msg_create_nopayload(ChannelRemove);
622 msg->unpacked = true;
623 msg->payload.channelRemove = mumble_proto__channel_remove__unpack(NULL, msgLen, msgData);
628 Log_warn("Unsupported message %d", messageType);