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.
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)
48 uint16_t *msgType = (uint16_t *) &buffer[0];
49 uint32_t *msgLen = (uint32_t *) &buffer[2];
51 *msgType = htons(type);
55 static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
57 uint16_t *msgType = (uint16_t *) &buffer[0];
58 uint32_t *msgLen = (uint32_t *) &buffer[2];
60 *type = (int)ntohs(*msgType);
61 *len = (int)ntohl(*msgLen);
64 #define MAX_MSGSIZE (BUFSIZE - 6)
65 int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
68 uint8_t *bufptr = buffer + 6;
70 Log_debug("To net: msg type %d", msg->messageType);
71 switch (msg->messageType) {
73 len = mumble_proto__version__get_packed_size(msg->payload.version);
74 if (len > MAX_MSGSIZE) {
75 Log_warn("Too big tx message. Discarding");
78 Msg_addPreamble(buffer, msg->messageType, len);
79 Log_debug("To net: Version->release: %s Version->os: %s",
80 msg->payload.version->release, msg->payload.version->os);
81 mumble_proto__version__pack(msg->payload.version, bufptr);
83 case UDPTunnel: /* Non-standard handling of tunneled voice traffic. */
84 if (msg->payload.UDPTunnel->packet.len > MAX_MSGSIZE) {
85 Log_warn("Too big tx message. Discarding");
88 Msg_addPreamble(buffer, msg->messageType, msg->payload.UDPTunnel->packet.len);
89 memcpy(bufptr, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
92 len = mumble_proto__authenticate__get_packed_size(msg->payload.authenticate);
93 if (len > MAX_MSGSIZE) {
94 Log_warn("Too big tx message. Discarding");
97 Msg_addPreamble(buffer, msg->messageType, len);
98 mumble_proto__authenticate__pack(msg->payload.authenticate, bufptr);
101 len = mumble_proto__ping__get_packed_size(msg->payload.ping);
102 if (len > MAX_MSGSIZE) {
103 Log_warn("Too big tx message. Discarding");
106 Msg_addPreamble(buffer, msg->messageType, len);
107 mumble_proto__ping__pack(msg->payload.ping, bufptr);
110 len = mumble_proto__reject__get_packed_size(msg->payload.reject);
111 if (len > MAX_MSGSIZE) {
112 Log_warn("Too big tx message. Discarding");
115 Msg_addPreamble(buffer, msg->messageType, len);
116 mumble_proto__reject__pack(msg->payload.reject, bufptr);
119 len = mumble_proto__server_sync__get_packed_size(msg->payload.serverSync);
120 if (len > MAX_MSGSIZE) {
121 Log_warn("Too big tx message. Discarding");
124 Msg_addPreamble(buffer, msg->messageType, len);
125 mumble_proto__server_sync__pack(msg->payload.serverSync, bufptr);
128 len = mumble_proto__text_message__get_packed_size(msg->payload.textMessage);
129 if (len > MAX_MSGSIZE) {
130 Log_warn("Too big tx message. Discarding");
133 Msg_addPreamble(buffer, msg->messageType, len);
134 mumble_proto__text_message__pack(msg->payload.textMessage, bufptr);
136 case PermissionDenied:
137 len = mumble_proto__permission_denied__get_packed_size(msg->payload.permissionDenied);
138 if (len > MAX_MSGSIZE) {
139 Log_warn("Too big tx message. Discarding");
142 Msg_addPreamble(buffer, msg->messageType, len);
143 mumble_proto__permission_denied__pack(msg->payload.permissionDenied, bufptr);
146 len = mumble_proto__crypt_setup__get_packed_size(msg->payload.cryptSetup);
147 if (len > MAX_MSGSIZE) {
148 Log_warn("Too big tx message. Discarding");
151 Msg_addPreamble(buffer, msg->messageType, len);
152 mumble_proto__crypt_setup__pack(msg->payload.cryptSetup, bufptr);
155 len = mumble_proto__user_list__get_packed_size(msg->payload.userList);
156 if (len > MAX_MSGSIZE) {
157 Log_warn("Too big tx message. Discarding");
160 Msg_addPreamble(buffer, msg->messageType, len);
161 mumble_proto__user_list__pack(msg->payload.userList, bufptr);
164 len = mumble_proto__user_state__get_packed_size(msg->payload.userState);
165 if (len > MAX_MSGSIZE) {
166 Log_warn("Too big tx message. Discarding");
169 Msg_addPreamble(buffer, msg->messageType, len);
170 mumble_proto__user_state__pack(msg->payload.userState, bufptr);
173 len = mumble_proto__channel_state__get_packed_size(msg->payload.channelState);
174 if (len > MAX_MSGSIZE) {
175 Log_warn("Too big tx message. Discarding");
178 Msg_addPreamble(buffer, msg->messageType, len);
179 mumble_proto__channel_state__pack(msg->payload.channelState, bufptr);
182 len = mumble_proto__voice_target__get_packed_size(msg->payload.voiceTarget);
183 if (len > MAX_MSGSIZE) {
184 Log_warn("Too big tx message. Discarding");
187 Msg_addPreamble(buffer, msg->messageType, len);
188 mumble_proto__voice_target__pack(msg->payload.voiceTarget, bufptr);
191 len = mumble_proto__codec_version__get_packed_size(msg->payload.codecVersion);
192 if (len > MAX_MSGSIZE) {
193 Log_warn("Too big tx message. Discarding");
196 Msg_addPreamble(buffer, msg->messageType, len);
197 mumble_proto__codec_version__pack(msg->payload.codecVersion, bufptr);
199 case PermissionQuery:
200 len = mumble_proto__permission_query__get_packed_size(msg->payload.permissionQuery);
201 if (len > MAX_MSGSIZE) {
202 Log_warn("Too big tx message. Discarding");
205 Msg_addPreamble(buffer, msg->messageType, len);
206 mumble_proto__permission_query__pack(msg->payload.permissionQuery, bufptr);
210 Log_warn("Unsupported message %d", msg->messageType);
216 message_t *Msg_create_nopayload(messageType_t messageType)
218 message_t *msg = malloc(sizeof(message_t));
221 Log_fatal("Out of memory");
222 memset(msg, 0, sizeof(message_t));
224 msg->messageType = messageType;
225 init_list_entry(&msg->node);
229 message_t *Msg_create(messageType_t messageType)
231 message_t *msg = Msg_create_nopayload(messageType);
233 switch (messageType) {
235 msg->payload.version = malloc(sizeof(MumbleProto__Version));
236 mumble_proto__version__init(msg->payload.version);
239 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
240 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
243 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
244 mumble_proto__authenticate__init(msg->payload.authenticate);
247 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
248 mumble_proto__ping__init(msg->payload.ping);
251 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
252 mumble_proto__reject__init(msg->payload.reject);
255 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
256 mumble_proto__server_sync__init(msg->payload.serverSync);
259 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
260 mumble_proto__text_message__init(msg->payload.textMessage);
262 case PermissionDenied:
263 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
264 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
267 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
268 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
271 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
272 mumble_proto__user_list__init(msg->payload.userList);
275 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
276 mumble_proto__user_state__init(msg->payload.userState);
279 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
280 mumble_proto__user_remove__init(msg->payload.userRemove);
283 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
284 mumble_proto__voice_target__init(msg->payload.voiceTarget);
287 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
288 mumble_proto__codec_version__init(msg->payload.codecVersion);
291 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
292 mumble_proto__channel_state__init(msg->payload.channelState);
294 case PermissionQuery:
295 msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
296 mumble_proto__permission_query__init(msg->payload.permissionQuery);
300 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
307 void Msg_inc_ref(message_t *msg)
312 void Msg_free(message_t *msg)
314 if (msg->refcount) msg->refcount--;
315 if (msg->refcount > 0)
318 switch (msg->messageType) {
321 mumble_proto__version__free_unpacked(msg->payload.version, NULL);
323 if (msg->payload.version->release)
324 free(msg->payload.version->release);
325 if (msg->payload.version->os)
326 free(msg->payload.version->os);
327 if (msg->payload.version->os_version)
328 free(msg->payload.version->os_version);
329 free(msg->payload.version);
334 mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
336 free(msg->payload.UDPTunnel->packet.data);
337 free(msg->payload.UDPTunnel);
342 mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
344 free(msg->payload.authenticate);
348 mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
350 free(msg->payload.ping);
355 mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
357 free(msg->payload.reject->reason);
358 free(msg->payload.reject);
363 mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
365 free(msg->payload.serverSync->welcome_text);
366 free(msg->payload.serverSync);
371 mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
373 free(msg->payload.textMessage);
376 case PermissionDenied:
378 mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
380 free(msg->payload.permissionDenied->reason);
381 free(msg->payload.permissionDenied);
386 mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
388 free(msg->payload.cryptSetup);
393 mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
395 free(msg->payload.userList);
400 mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
402 free(msg->payload.userState->name);
403 free(msg->payload.userState);
408 mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
410 free(msg->payload.userRemove);
415 mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
417 free(msg->payload.voiceTarget);
422 mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
424 free(msg->payload.codecVersion);
429 mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
431 if (msg->payload.channelState->description)
432 free(msg->payload.channelState->description);
433 free(msg->payload.channelState->name);
434 free(msg->payload.channelState);
437 case PermissionQuery:
439 mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
441 free(msg->payload.permissionQuery);
446 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
452 void dumpmsg(uint8_t *data, int size)
454 int i, r = 0, offset = 0;
457 while (r * 8 + i < size) {
458 for (i = 0; i < 8 && r * 8 + i < size; i++) {
459 offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
461 sprintf(buf + offset, "\n");
469 message_t *Msg_networkToMessage(uint8_t *data, int size)
471 message_t *msg = NULL;
472 uint8_t *msgData = &data[6];
473 int messageType, msgLen;
475 Msg_getPreamble(data, &messageType, &msgLen);
477 Log_debug("Message type %d size %d", messageType, msgLen);
478 //dumpmsg(data, size);
480 switch (messageType) {
483 msg = Msg_create_nopayload(Version);
484 msg->unpacked = true;
485 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
488 case UDPTunnel: /* Non-standard handling of tunneled voice data */
490 msg = Msg_create_nopayload(UDPTunnel);
491 msg->unpacked = false;
492 msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel));
493 if (msg->payload.UDPTunnel == NULL)
494 Log_fatal("Out of memory");
495 msg->payload.UDPTunnel->packet.data = malloc(msgLen);
496 if (msg->payload.UDPTunnel->packet.data == NULL)
497 Log_fatal("Out of memory");
498 memcpy(msg->payload.UDPTunnel->packet.data, msgData, msgLen);
499 msg->payload.UDPTunnel->packet.len = msgLen;
504 msg = Msg_create_nopayload(Authenticate);
505 msg->unpacked = true;
506 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
511 msg = Msg_create_nopayload(Ping);
512 msg->unpacked = true;
513 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
518 msg = Msg_create_nopayload(Reject);
519 msg->unpacked = true;
520 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
525 msg = Msg_create_nopayload(ServerSync);
526 msg->unpacked = true;
527 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
532 msg = Msg_create_nopayload(TextMessage);
533 msg->unpacked = true;
534 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
537 case PermissionDenied:
539 msg = Msg_create_nopayload(PermissionDenied);
540 msg->unpacked = true;
541 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
546 msg = Msg_create_nopayload(CryptSetup);
547 msg->unpacked = true;
548 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
553 msg = Msg_create_nopayload(UserList);
554 msg->unpacked = true;
555 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
560 msg = Msg_create_nopayload(UserState);
561 msg->unpacked = true;
562 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
567 msg = Msg_create_nopayload(VoiceTarget);
568 msg->unpacked = true;
569 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
574 msg = Msg_create_nopayload(CodecVersion);
575 msg->unpacked = true;
576 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
579 case PermissionQuery:
581 msg = Msg_create_nopayload(PermissionQuery);
582 msg->unpacked = true;
583 msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
588 Log_warn("Unsupported message %d", messageType);