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);
83 len = mumble_proto__udptunnel__get_packed_size(msg->payload.UDPTunnel);
84 if (len > MAX_MSGSIZE) {
85 Log_warn("Too big tx message. Discarding");
88 Msg_addPreamble(buffer, msg->messageType, len);
89 mumble_proto__udptunnel__pack(msg->payload.UDPTunnel, bufptr);
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(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);
227 switch (messageType) {
229 msg->payload.version = malloc(sizeof(MumbleProto__Version));
230 mumble_proto__version__init(msg->payload.version);
233 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
234 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
237 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
238 mumble_proto__authenticate__init(msg->payload.authenticate);
241 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
242 mumble_proto__ping__init(msg->payload.ping);
245 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
246 mumble_proto__reject__init(msg->payload.reject);
249 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
250 mumble_proto__server_sync__init(msg->payload.serverSync);
253 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
254 mumble_proto__text_message__init(msg->payload.textMessage);
256 case PermissionDenied:
257 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
258 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
261 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
262 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
265 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
266 mumble_proto__user_list__init(msg->payload.userList);
269 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
270 mumble_proto__user_state__init(msg->payload.userState);
273 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
274 mumble_proto__user_remove__init(msg->payload.userRemove);
277 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
278 mumble_proto__voice_target__init(msg->payload.voiceTarget);
281 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
282 mumble_proto__codec_version__init(msg->payload.codecVersion);
285 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
286 mumble_proto__channel_state__init(msg->payload.channelState);
288 case PermissionQuery:
289 msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
290 mumble_proto__permission_query__init(msg->payload.permissionQuery);
294 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
301 void Msg_inc_ref(message_t *msg)
306 void Msg_free(message_t *msg)
308 if (msg->refcount) msg->refcount--;
309 if (msg->refcount > 0)
312 switch (msg->messageType) {
315 mumble_proto__version__free_unpacked(msg->payload.version, NULL);
317 if (msg->payload.version->release)
318 free(msg->payload.version->release);
319 if (msg->payload.version->os)
320 free(msg->payload.version->os);
321 if (msg->payload.version->os_version)
322 free(msg->payload.version->os_version);
323 free(msg->payload.version);
328 mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
330 free(msg->payload.UDPTunnel->packet.data);
331 free(msg->payload.UDPTunnel);
336 mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
340 mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
342 free(msg->payload.ping);
347 mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
349 free(msg->payload.reject->reason);
350 free(msg->payload.reject);
355 mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
357 free(msg->payload.serverSync->welcome_text);
358 free(msg->payload.serverSync);
363 mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
365 free(msg->payload.textMessage);
368 case PermissionDenied:
370 mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
372 free(msg->payload.permissionDenied->reason);
373 free(msg->payload.permissionDenied);
378 mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
380 free(msg->payload.cryptSetup);
385 mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
387 free(msg->payload.userList);
392 mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
394 free(msg->payload.userState->name);
395 free(msg->payload.userState);
400 mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
402 free(msg->payload.userRemove);
407 mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
409 free(msg->payload.voiceTarget);
414 mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
416 free(msg->payload.codecVersion);
421 mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
423 if (msg->payload.channelState->description)
424 free(msg->payload.channelState->description);
425 free(msg->payload.channelState->name);
426 free(msg->payload.channelState);
429 case PermissionQuery:
431 mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
433 free(msg->payload.permissionQuery);
438 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
444 void dumpmsg(uint8_t *data, int size)
446 int i, r = 0, offset = 0;
449 while (r * 8 + i < size) {
450 for (i = 0; i < 8 && r * 8 + i < size; i++) {
451 offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
453 sprintf(buf + offset, "\n");
461 message_t *Msg_networkToMessage(uint8_t *data, int size)
463 message_t *msg = NULL;
464 uint8_t *msgData = &data[6];
465 int messageType, msgLen;
467 Msg_getPreamble(data, &messageType, &msgLen);
469 Log_debug("Message type %d size %d", messageType, msgLen);
472 switch (messageType) {
475 msg = Msg_create(Version);
476 msg->unpacked = true;
477 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
482 msg = Msg_create(UDPTunnel);
483 msg->unpacked = true;
484 msg->payload.UDPTunnel = mumble_proto__udptunnel__unpack(NULL, msgLen, msgData);
489 msg = Msg_create(Authenticate);
490 msg->unpacked = true;
491 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
496 msg = Msg_create(Ping);
497 msg->unpacked = true;
498 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
503 msg = Msg_create(Reject);
504 msg->unpacked = true;
505 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
510 msg = Msg_create(ServerSync);
511 msg->unpacked = true;
512 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
517 msg = Msg_create(TextMessage);
518 msg->unpacked = true;
519 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
522 case PermissionDenied:
524 msg = Msg_create(PermissionDenied);
525 msg->unpacked = true;
526 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
531 msg = Msg_create(CryptSetup);
532 msg->unpacked = true;
533 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
538 msg = Msg_create(UserList);
539 msg->unpacked = true;
540 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
545 msg = Msg_create(UserState);
546 msg->unpacked = true;
547 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
552 msg = Msg_create(VoiceTarget);
553 msg->unpacked = true;
554 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
559 msg = Msg_create(CodecVersion);
560 msg->unpacked = true;
561 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
564 case PermissionQuery:
566 msg = Msg_create(PermissionQuery);
567 msg->unpacked = true;
568 msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
573 Log_warn("Unsupported message %d", messageType);