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);
217 Log_warn("Unsupported message %d", msg->messageType);
223 message_t *Msg_create_nopayload(messageType_t messageType)
225 message_t *msg = malloc(sizeof(message_t));
228 Log_fatal("Out of memory");
229 memset(msg, 0, sizeof(message_t));
231 msg->messageType = messageType;
232 init_list_entry(&msg->node);
236 message_t *Msg_create(messageType_t messageType)
238 message_t *msg = Msg_create_nopayload(messageType);
240 switch (messageType) {
242 msg->payload.version = malloc(sizeof(MumbleProto__Version));
243 mumble_proto__version__init(msg->payload.version);
246 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
247 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
250 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
251 mumble_proto__authenticate__init(msg->payload.authenticate);
254 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
255 mumble_proto__ping__init(msg->payload.ping);
258 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
259 mumble_proto__reject__init(msg->payload.reject);
262 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
263 mumble_proto__server_sync__init(msg->payload.serverSync);
266 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
267 mumble_proto__text_message__init(msg->payload.textMessage);
269 case PermissionDenied:
270 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
271 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
274 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
275 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
278 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
279 mumble_proto__user_list__init(msg->payload.userList);
282 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
283 mumble_proto__user_state__init(msg->payload.userState);
286 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
287 mumble_proto__user_remove__init(msg->payload.userRemove);
290 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
291 mumble_proto__voice_target__init(msg->payload.voiceTarget);
294 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
295 mumble_proto__codec_version__init(msg->payload.codecVersion);
298 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
299 mumble_proto__channel_state__init(msg->payload.channelState);
301 case PermissionQuery:
302 msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
303 mumble_proto__permission_query__init(msg->payload.permissionQuery);
307 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
314 void Msg_inc_ref(message_t *msg)
319 void Msg_free(message_t *msg)
321 if (msg->refcount) msg->refcount--;
322 if (msg->refcount > 0)
325 switch (msg->messageType) {
328 mumble_proto__version__free_unpacked(msg->payload.version, NULL);
330 if (msg->payload.version->release)
331 free(msg->payload.version->release);
332 if (msg->payload.version->os)
333 free(msg->payload.version->os);
334 if (msg->payload.version->os_version)
335 free(msg->payload.version->os_version);
336 free(msg->payload.version);
341 mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
343 free(msg->payload.UDPTunnel->packet.data);
344 free(msg->payload.UDPTunnel);
349 mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
351 free(msg->payload.authenticate);
355 mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
357 free(msg->payload.ping);
362 mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
364 free(msg->payload.reject->reason);
365 free(msg->payload.reject);
370 mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
372 free(msg->payload.serverSync->welcome_text);
373 free(msg->payload.serverSync);
378 mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
380 free(msg->payload.textMessage);
383 case PermissionDenied:
385 mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
387 free(msg->payload.permissionDenied->reason);
388 free(msg->payload.permissionDenied);
393 mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
395 free(msg->payload.cryptSetup);
400 mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
402 free(msg->payload.userList);
407 mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
409 free(msg->payload.userState->name);
410 free(msg->payload.userState);
415 mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
417 free(msg->payload.userRemove);
422 mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
424 free(msg->payload.voiceTarget);
429 mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
431 free(msg->payload.codecVersion);
436 mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
438 if (msg->payload.channelState->description)
439 free(msg->payload.channelState->description);
440 free(msg->payload.channelState->name);
441 free(msg->payload.channelState);
444 case PermissionQuery:
446 mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
448 free(msg->payload.permissionQuery);
453 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
459 void dumpmsg(uint8_t *data, int size)
461 int i, r = 0, offset = 0;
464 while (r * 8 + i < size) {
465 for (i = 0; i < 8 && r * 8 + i < size; i++) {
466 offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
468 sprintf(buf + offset, "\n");
476 message_t *Msg_networkToMessage(uint8_t *data, int size)
478 message_t *msg = NULL;
479 uint8_t *msgData = &data[6];
480 int messageType, msgLen;
482 Msg_getPreamble(data, &messageType, &msgLen);
484 Log_debug("Message type %d size %d", messageType, msgLen);
485 //dumpmsg(data, size);
487 switch (messageType) {
490 msg = Msg_create_nopayload(Version);
491 msg->unpacked = true;
492 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
495 case UDPTunnel: /* Non-standard handling of tunneled voice data */
497 msg = Msg_create_nopayload(UDPTunnel);
498 msg->unpacked = false;
499 msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel));
500 if (msg->payload.UDPTunnel == NULL)
501 Log_fatal("Out of memory");
502 msg->payload.UDPTunnel->packet.data = malloc(msgLen);
503 if (msg->payload.UDPTunnel->packet.data == NULL)
504 Log_fatal("Out of memory");
505 memcpy(msg->payload.UDPTunnel->packet.data, msgData, msgLen);
506 msg->payload.UDPTunnel->packet.len = msgLen;
511 msg = Msg_create_nopayload(Authenticate);
512 msg->unpacked = true;
513 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
518 msg = Msg_create_nopayload(Ping);
519 msg->unpacked = true;
520 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
525 msg = Msg_create_nopayload(Reject);
526 msg->unpacked = true;
527 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
532 msg = Msg_create_nopayload(ServerSync);
533 msg->unpacked = true;
534 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
539 msg = Msg_create_nopayload(TextMessage);
540 msg->unpacked = true;
541 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
544 case PermissionDenied:
546 msg = Msg_create_nopayload(PermissionDenied);
547 msg->unpacked = true;
548 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
553 msg = Msg_create_nopayload(CryptSetup);
554 msg->unpacked = true;
555 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
560 msg = Msg_create_nopayload(UserList);
561 msg->unpacked = true;
562 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
567 msg = Msg_create_nopayload(UserState);
568 msg->unpacked = true;
569 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
574 msg = Msg_create_nopayload(VoiceTarget);
575 msg->unpacked = true;
576 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
581 msg = Msg_create_nopayload(CodecVersion);
582 msg->unpacked = true;
583 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
586 case PermissionQuery:
588 msg = Msg_create_nopayload(PermissionQuery);
589 msg->unpacked = true;
590 msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
595 Log_warn("Unsupported message %d", messageType);