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);
45 void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
47 uint16_t *msgType = (uint16_t *) &buffer[0];
48 uint32_t *msgLen = (uint32_t *) &buffer[2];
50 *msgType = htons(type);
54 static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
56 uint16_t *msgType = (uint16_t *) &buffer[0];
57 uint32_t *msgLen = (uint32_t *) &buffer[2];
59 *type = (int)ntohs(*msgType);
60 *len = (int)ntohl(*msgLen);
63 #define MAX_MSGSIZE (BUFSIZE - 6)
64 int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
67 uint8_t *bufptr = buffer + 6;
69 Log_debug("To net: msg type %d", msg->messageType);
70 switch (msg->messageType) {
72 len = mumble_proto__version__get_packed_size(msg->payload.version);
73 if (len > MAX_MSGSIZE) {
74 Log_warn("Too big tx message. Discarding");
77 Msg_addPreamble(buffer, msg->messageType, len);
78 Log_debug("To net: Version->release: %s Version->os: %s",
79 msg->payload.version->release, msg->payload.version->os);
80 mumble_proto__version__pack(msg->payload.version, bufptr);
82 case UDPTunnel: /* Non-standard handling of tunneled voice traffic. */
83 if (msg->payload.UDPTunnel->packet.len > MAX_MSGSIZE) {
84 Log_warn("Too big tx message. Discarding");
87 Msg_addPreamble(buffer, msg->messageType, msg->payload.UDPTunnel->packet.len);
88 memcpy(bufptr, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
91 len = mumble_proto__authenticate__get_packed_size(msg->payload.authenticate);
92 if (len > MAX_MSGSIZE) {
93 Log_warn("Too big tx message. Discarding");
96 Msg_addPreamble(buffer, msg->messageType, len);
97 mumble_proto__authenticate__pack(msg->payload.authenticate, bufptr);
100 len = mumble_proto__ping__get_packed_size(msg->payload.ping);
101 if (len > MAX_MSGSIZE) {
102 Log_warn("Too big tx message. Discarding");
105 Msg_addPreamble(buffer, msg->messageType, len);
106 mumble_proto__ping__pack(msg->payload.ping, bufptr);
109 len = mumble_proto__reject__get_packed_size(msg->payload.reject);
110 if (len > MAX_MSGSIZE) {
111 Log_warn("Too big tx message. Discarding");
114 Msg_addPreamble(buffer, msg->messageType, len);
115 mumble_proto__reject__pack(msg->payload.reject, bufptr);
118 len = mumble_proto__server_sync__get_packed_size(msg->payload.serverSync);
119 if (len > MAX_MSGSIZE) {
120 Log_warn("Too big tx message. Discarding");
123 Msg_addPreamble(buffer, msg->messageType, len);
124 mumble_proto__server_sync__pack(msg->payload.serverSync, bufptr);
127 len = mumble_proto__text_message__get_packed_size(msg->payload.textMessage);
128 if (len > MAX_MSGSIZE) {
129 Log_warn("Too big tx message. Discarding");
132 Msg_addPreamble(buffer, msg->messageType, len);
133 mumble_proto__text_message__pack(msg->payload.textMessage, bufptr);
135 case PermissionDenied:
136 len = mumble_proto__permission_denied__get_packed_size(msg->payload.permissionDenied);
137 if (len > MAX_MSGSIZE) {
138 Log_warn("Too big tx message. Discarding");
141 Msg_addPreamble(buffer, msg->messageType, len);
142 mumble_proto__permission_denied__pack(msg->payload.permissionDenied, bufptr);
145 len = mumble_proto__crypt_setup__get_packed_size(msg->payload.cryptSetup);
146 if (len > MAX_MSGSIZE) {
147 Log_warn("Too big tx message. Discarding");
150 Msg_addPreamble(buffer, msg->messageType, len);
151 mumble_proto__crypt_setup__pack(msg->payload.cryptSetup, bufptr);
154 len = mumble_proto__user_list__get_packed_size(msg->payload.userList);
155 if (len > MAX_MSGSIZE) {
156 Log_warn("Too big tx message. Discarding");
159 Msg_addPreamble(buffer, msg->messageType, len);
160 mumble_proto__user_list__pack(msg->payload.userList, bufptr);
163 len = mumble_proto__user_state__get_packed_size(msg->payload.userState);
164 if (len > MAX_MSGSIZE) {
165 Log_warn("Too big tx message. Discarding");
168 Msg_addPreamble(buffer, msg->messageType, len);
169 mumble_proto__user_state__pack(msg->payload.userState, bufptr);
172 len = mumble_proto__channel_state__get_packed_size(msg->payload.channelState);
173 if (len > MAX_MSGSIZE) {
174 Log_warn("Too big tx message. Discarding");
177 Msg_addPreamble(buffer, msg->messageType, len);
178 mumble_proto__channel_state__pack(msg->payload.channelState, bufptr);
181 len = mumble_proto__voice_target__get_packed_size(msg->payload.voiceTarget);
182 if (len > MAX_MSGSIZE) {
183 Log_warn("Too big tx message. Discarding");
186 Msg_addPreamble(buffer, msg->messageType, len);
187 mumble_proto__voice_target__pack(msg->payload.voiceTarget, bufptr);
190 len = mumble_proto__codec_version__get_packed_size(msg->payload.codecVersion);
191 if (len > MAX_MSGSIZE) {
192 Log_warn("Too big tx message. Discarding");
195 Msg_addPreamble(buffer, msg->messageType, len);
196 mumble_proto__codec_version__pack(msg->payload.codecVersion, bufptr);
198 case PermissionQuery:
199 len = mumble_proto__permission_query__get_packed_size(msg->payload.permissionQuery);
200 if (len > MAX_MSGSIZE) {
201 Log_warn("Too big tx message. Discarding");
204 Msg_addPreamble(buffer, msg->messageType, len);
205 mumble_proto__permission_query__pack(msg->payload.permissionQuery, bufptr);
209 Log_warn("Unsupported message %d", msg->messageType);
215 message_t *Msg_create(messageType_t messageType)
217 message_t *msg = malloc(sizeof(message_t));
220 Log_fatal("Out of memory");
221 memset(msg, 0, sizeof(message_t));
223 msg->messageType = messageType;
224 init_list_entry(&msg->node);
226 switch (messageType) {
228 msg->payload.version = malloc(sizeof(MumbleProto__Version));
229 mumble_proto__version__init(msg->payload.version);
232 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
233 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
236 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
237 mumble_proto__authenticate__init(msg->payload.authenticate);
240 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
241 mumble_proto__ping__init(msg->payload.ping);
244 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
245 mumble_proto__reject__init(msg->payload.reject);
248 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
249 mumble_proto__server_sync__init(msg->payload.serverSync);
252 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
253 mumble_proto__text_message__init(msg->payload.textMessage);
255 case PermissionDenied:
256 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
257 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
260 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
261 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
264 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
265 mumble_proto__user_list__init(msg->payload.userList);
268 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
269 mumble_proto__user_state__init(msg->payload.userState);
272 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
273 mumble_proto__user_remove__init(msg->payload.userRemove);
276 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
277 mumble_proto__voice_target__init(msg->payload.voiceTarget);
280 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
281 mumble_proto__codec_version__init(msg->payload.codecVersion);
284 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
285 mumble_proto__channel_state__init(msg->payload.channelState);
287 case PermissionQuery:
288 msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
289 mumble_proto__permission_query__init(msg->payload.permissionQuery);
293 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
300 void Msg_inc_ref(message_t *msg)
305 void Msg_free(message_t *msg)
307 if (msg->refcount) msg->refcount--;
308 if (msg->refcount > 0)
311 switch (msg->messageType) {
314 mumble_proto__version__free_unpacked(msg->payload.version, NULL);
316 if (msg->payload.version->release)
317 free(msg->payload.version->release);
318 if (msg->payload.version->os)
319 free(msg->payload.version->os);
320 if (msg->payload.version->os_version)
321 free(msg->payload.version->os_version);
322 free(msg->payload.version);
327 mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
329 free(msg->payload.UDPTunnel->packet.data);
330 free(msg->payload.UDPTunnel);
335 mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
339 mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
341 free(msg->payload.ping);
346 mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
348 free(msg->payload.reject->reason);
349 free(msg->payload.reject);
354 mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
356 free(msg->payload.serverSync->welcome_text);
357 free(msg->payload.serverSync);
362 mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
364 free(msg->payload.textMessage);
367 case PermissionDenied:
369 mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
371 free(msg->payload.permissionDenied->reason);
372 free(msg->payload.permissionDenied);
377 mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
379 free(msg->payload.cryptSetup);
384 mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
386 free(msg->payload.userList);
391 mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
393 free(msg->payload.userState->name);
394 free(msg->payload.userState);
399 mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
401 free(msg->payload.userRemove);
406 mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
408 free(msg->payload.voiceTarget);
413 mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
415 free(msg->payload.codecVersion);
420 mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
422 if (msg->payload.channelState->description)
423 free(msg->payload.channelState->description);
424 free(msg->payload.channelState->name);
425 free(msg->payload.channelState);
428 case PermissionQuery:
430 mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
432 free(msg->payload.permissionQuery);
437 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
443 void dumpmsg(uint8_t *data, int size)
445 int i, r = 0, offset = 0;
448 while (r * 8 + i < size) {
449 for (i = 0; i < 8 && r * 8 + i < size; i++) {
450 offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
452 sprintf(buf + offset, "\n");
460 message_t *Msg_networkToMessage(uint8_t *data, int size)
462 message_t *msg = NULL;
463 uint8_t *msgData = &data[6];
464 int messageType, msgLen;
466 Msg_getPreamble(data, &messageType, &msgLen);
468 Log_debug("Message type %d size %d", messageType, msgLen);
471 switch (messageType) {
474 msg = Msg_create(Version);
475 msg->unpacked = true;
476 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
479 case UDPTunnel: /* Non-standard handling of tunneled voice data */
481 msg = Msg_create(UDPTunnel);
482 msg->unpacked = false;
483 msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel));
484 if (msg->payload.UDPTunnel == NULL)
485 Log_fatal("Out of memory");
486 msg->payload.UDPTunnel->packet.data = malloc(msgLen);
487 if (msg->payload.UDPTunnel->packet.data == NULL)
488 Log_fatal("Out of memory");
489 memcpy(msg->payload.UDPTunnel->packet.data, msgData, msgLen);
490 msg->payload.UDPTunnel->packet.len = msgLen;
495 msg = Msg_create(Authenticate);
496 msg->unpacked = true;
497 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
502 msg = Msg_create(Ping);
503 msg->unpacked = true;
504 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
509 msg = Msg_create(Reject);
510 msg->unpacked = true;
511 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
516 msg = Msg_create(ServerSync);
517 msg->unpacked = true;
518 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
523 msg = Msg_create(TextMessage);
524 msg->unpacked = true;
525 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
528 case PermissionDenied:
530 msg = Msg_create(PermissionDenied);
531 msg->unpacked = true;
532 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
537 msg = Msg_create(CryptSetup);
538 msg->unpacked = true;
539 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
544 msg = Msg_create(UserList);
545 msg->unpacked = true;
546 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
551 msg = Msg_create(UserState);
552 msg->unpacked = true;
553 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
558 msg = Msg_create(VoiceTarget);
559 msg->unpacked = true;
560 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
565 msg = Msg_create(CodecVersion);
566 msg->unpacked = true;
567 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
570 case PermissionQuery:
572 msg = Msg_create(PermissionQuery);
573 msg->unpacked = true;
574 msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
579 Log_warn("Unsupported message %d", messageType);