Mumble 1.2.x compatible server. Kind of working, at least in server loopback mode.
[umurmur.git] / src / messages.c
1 /* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
3
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
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.
18
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.
30 */
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <arpa/inet.h>
36
37 #include "messages.h"
38 #include "client.h"
39 #include "pds.h"
40 #include "log.h"
41
42
43 void dumpmsg(uint8_t *data, int size);
44
45 void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
46 {
47         uint16_t *msgType = (uint16_t *) &buffer[0];
48         uint32_t *msgLen = (uint32_t *) &buffer[2];
49         
50         *msgType = htons(type);
51         *msgLen = htonl(len);
52 }
53
54 static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
55 {
56         uint16_t *msgType = (uint16_t *) &buffer[0];
57         uint32_t *msgLen = (uint32_t *) &buffer[2];
58         
59         *type = (int)ntohs(*msgType);
60         *len = (int)ntohl(*msgLen);
61 }
62
63 #define MAX_MSGSIZE (BUFSIZE - 6)
64 int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
65 {
66         int len;
67         uint8_t *bufptr = buffer + 6;
68                 
69         Log_debug("To net: msg type %d", msg->messageType);
70         switch (msg->messageType) {
71         case Version:
72                 len = mumble_proto__version__get_packed_size(msg->payload.version);
73                 if (len > MAX_MSGSIZE) {
74                         Log_warn("Too big tx message. Discarding");
75                         break;
76                 }
77                 Msg_addPreamble(buffer, msg->messageType, len);
78                 mumble_proto__version__pack(msg->payload.version, bufptr);
79                 break;
80         case UDPTunnel:
81                 len = mumble_proto__udptunnel__get_packed_size(msg->payload.UDPTunnel);
82                 if (len > MAX_MSGSIZE) {
83                         Log_warn("Too big tx message. Discarding");
84                         break;
85                 }
86                 Msg_addPreamble(buffer, msg->messageType, len);
87                 mumble_proto__udptunnel__pack(msg->payload.UDPTunnel, bufptr);          
88                 break;
89         case Authenticate:
90                 len = mumble_proto__authenticate__get_packed_size(msg->payload.authenticate);
91                 if (len > MAX_MSGSIZE) {
92                         Log_warn("Too big tx message. Discarding");
93                         break;
94                         }
95                 Msg_addPreamble(buffer, msg->messageType, len);
96                 mumble_proto__authenticate__pack(msg->payload.authenticate, bufptr);
97                 break;
98         case Ping:
99                 len = mumble_proto__ping__get_packed_size(msg->payload.ping);
100                 if (len > MAX_MSGSIZE) {
101                         Log_warn("Too big tx message. Discarding");
102                         break;
103                         }
104                 Msg_addPreamble(buffer, msg->messageType, len);
105                 mumble_proto__ping__pack(msg->payload.ping, bufptr);
106                 break;
107         case Reject:
108                 len = mumble_proto__reject__get_packed_size(msg->payload.reject);
109                 if (len > MAX_MSGSIZE) {
110                         Log_warn("Too big tx message. Discarding");
111                         break;
112                         }
113                 Msg_addPreamble(buffer, msg->messageType, len);
114                 mumble_proto__reject__pack(msg->payload.reject, bufptr);
115                 break;
116         case ServerSync:
117                 len = mumble_proto__server_sync__get_packed_size(msg->payload.serverSync);
118                 if (len > MAX_MSGSIZE) {
119                         Log_warn("Too big tx message. Discarding");
120                         break;
121                         }
122                 Msg_addPreamble(buffer, msg->messageType, len);
123                 mumble_proto__server_sync__pack(msg->payload.serverSync, bufptr);
124                 break;
125         case TextMessage:
126                 len = mumble_proto__text_message__get_packed_size(msg->payload.textMessage);
127                 if (len > MAX_MSGSIZE) {
128                         Log_warn("Too big tx message. Discarding");
129                         break;
130                         }
131                 Msg_addPreamble(buffer, msg->messageType, len);
132                 mumble_proto__text_message__pack(msg->payload.textMessage, bufptr);
133                 break;
134         case PermissionDenied:
135                 len = mumble_proto__permission_denied__get_packed_size(msg->payload.permissionDenied);
136                 if (len > MAX_MSGSIZE) {
137                         Log_warn("Too big tx message. Discarding");
138                         break;
139                         }
140                 Msg_addPreamble(buffer, msg->messageType, len);
141                 mumble_proto__permission_denied__pack(msg->payload.permissionDenied, bufptr);
142                 break;
143         case CryptSetup:
144                 len = mumble_proto__crypt_setup__get_packed_size(msg->payload.cryptSetup);
145                 if (len > MAX_MSGSIZE) {
146                         Log_warn("Too big tx message. Discarding");
147                         break;
148                         }
149                 Msg_addPreamble(buffer, msg->messageType, len);
150                 mumble_proto__crypt_setup__pack(msg->payload.cryptSetup, bufptr);
151                 break;
152         case UserList:
153                 len = mumble_proto__user_list__get_packed_size(msg->payload.userList);
154                 if (len > MAX_MSGSIZE) {
155                         Log_warn("Too big tx message. Discarding");
156                         break;
157                         }
158                 Msg_addPreamble(buffer, msg->messageType, len);
159                 mumble_proto__user_list__pack(msg->payload.userList, bufptr);
160                 break;
161         case UserState:
162                 len = mumble_proto__user_state__get_packed_size(msg->payload.userState);
163                 if (len > MAX_MSGSIZE) {
164                         Log_warn("Too big tx message. Discarding");
165                         break;
166                         }
167                 Msg_addPreamble(buffer, msg->messageType, len);
168                 mumble_proto__user_state__pack(msg->payload.userState, bufptr);
169                 break;
170         case ChannelState:
171                 len = mumble_proto__channel_state__get_packed_size(msg->payload.channelState);
172                 if (len > MAX_MSGSIZE) {
173                         Log_warn("Too big tx message. Discarding");
174                         break;
175                         }
176                 Msg_addPreamble(buffer, msg->messageType, len);
177                 mumble_proto__channel_state__pack(msg->payload.channelState, bufptr);
178                 break;
179         case VoiceTarget:
180                 len = mumble_proto__voice_target__get_packed_size(msg->payload.voiceTarget);
181                 if (len > MAX_MSGSIZE) {
182                         Log_warn("Too big tx message. Discarding");
183                         break;
184                         }
185                 Msg_addPreamble(buffer, msg->messageType, len);
186                 mumble_proto__voice_target__pack(msg->payload.voiceTarget, bufptr);
187                 break;
188         case CodecVersion:
189                 len = mumble_proto__codec_version__get_packed_size(msg->payload.codecVersion);
190                 if (len > MAX_MSGSIZE) {
191                         Log_warn("Too big tx message. Discarding");
192                         break;
193                         }
194                 Msg_addPreamble(buffer, msg->messageType, len);
195                 mumble_proto__codec_version__pack(msg->payload.codecVersion, bufptr);
196                 break;
197
198         default:
199                 Log_warn("Unsupported message %d", msg->messageType);
200                 return 0;
201         }
202         return len + 6;
203 }
204
205 message_t *Msg_create(messageType_t messageType)
206 {
207         message_t *msg = malloc(sizeof(message_t));
208
209         if (msg == NULL)
210                 Log_fatal("Out of memory");
211         memset(msg, 0, sizeof(message_t));
212         msg->refcount = 1;
213         msg->messageType = messageType;
214         init_list_entry(&msg->node);
215         
216         switch (messageType) {
217         case Version:
218                 msg->payload.version = malloc(sizeof(MumbleProto__Version));
219                 mumble_proto__version__init(msg->payload.version);
220                 break;
221         case UDPTunnel:
222                 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
223                 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
224                 break;
225         case Authenticate:
226                 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
227                 mumble_proto__authenticate__init(msg->payload.authenticate);
228                 break;
229         case Ping:
230                 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
231                 mumble_proto__ping__init(msg->payload.ping);
232                 break;
233         case Reject:
234                 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
235                 mumble_proto__reject__init(msg->payload.reject);
236                 break;
237         case ServerSync:
238                 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
239                 mumble_proto__server_sync__init(msg->payload.serverSync);
240                 break;
241         case TextMessage:
242                 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
243                 mumble_proto__text_message__init(msg->payload.textMessage);
244                 break;
245         case PermissionDenied:
246                 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
247                 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
248                 break;
249         case CryptSetup:
250                 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
251                 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
252                 break;
253         case UserList:
254                 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
255                 mumble_proto__user_list__init(msg->payload.userList);
256                 break;
257         case UserState:
258                 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
259                 mumble_proto__user_state__init(msg->payload.userState);
260                 break;
261         case UserRemove:
262                 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
263                 mumble_proto__user_remove__init(msg->payload.userRemove);
264                 break;
265         case VoiceTarget:
266                 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
267                 mumble_proto__voice_target__init(msg->payload.voiceTarget);
268                 break;
269         case CodecVersion:
270                 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
271                 mumble_proto__codec_version__init(msg->payload.codecVersion);
272                 break;
273         case ChannelState:
274                 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
275                 mumble_proto__channel_state__init(msg->payload.channelState);
276                 break;
277
278         default:
279                 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
280                 break;
281         }
282
283         return msg;
284 }
285
286 void Msg_inc_ref(message_t *msg)
287 {
288         msg->refcount++;
289 }
290
291 void Msg_free(message_t *msg)
292 {
293         if (msg->refcount) msg->refcount--;
294         if (msg->refcount > 0)
295                 return;
296
297         /* XXX - add free for locally generated messages too */
298         switch (msg->messageType) {
299         case Version:
300                 if (msg->unpacked)
301                         mumble_proto__version__free_unpacked(msg->payload.version, NULL);
302                 else {
303                         free(msg->payload.version);
304                 }
305                 break;
306         case UDPTunnel:
307                 if (msg->unpacked)
308                         mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
309                 else {
310                         free(msg->payload.UDPTunnel->packet.data);
311                         free(msg->payload.UDPTunnel);
312                 }
313                 break;
314         case Authenticate:
315                 if (msg->unpacked)
316                         mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
317                 break;
318         case Ping:
319                 if (msg->unpacked)
320                         mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
321                 else {
322                         free(msg->payload.ping);
323                 }
324                 break;
325         case Reject:
326                 if (msg->unpacked)
327                         mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
328                 else {
329                         free(msg->payload.reject->reason);
330                         free(msg->payload.reject);
331                 }
332                 break;
333         case ServerSync:
334                 if (msg->unpacked)
335                         mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
336                 else {
337                         free(msg->payload.serverSync->welcome_text);
338                         free(msg->payload.serverSync);
339                 }
340                 break;
341         case TextMessage:
342                 if (msg->unpacked)
343                         mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
344                 else {
345                         free(msg->payload.textMessage);
346                 }
347                 break;
348         case PermissionDenied:
349                 if (msg->unpacked)
350                         mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
351                 else {
352                         free(msg->payload.permissionDenied->reason);
353                         free(msg->payload.permissionDenied);
354                 }
355                 break;
356         case CryptSetup:
357                 if (msg->unpacked)
358                         mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
359                 else {
360                         free(msg->payload.cryptSetup);
361                 }
362                 break;
363         case UserList:
364                 if (msg->unpacked)
365                         mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
366                 else {
367                         free(msg->payload.userList);
368                 }
369                 break;
370         case UserState:
371                 if (msg->unpacked)
372                         mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
373                 else {
374                         free(msg->payload.userState->name);
375                         free(msg->payload.userState);
376                 }
377                 break;
378         case UserRemove:
379                 if (msg->unpacked)
380                         mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
381                 else {
382                         free(msg->payload.userRemove);
383                 }
384                 break;
385         case VoiceTarget:
386                 if (msg->unpacked)
387                         mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
388                 else {
389                         free(msg->payload.voiceTarget);
390                 }
391                 break;
392         case CodecVersion:
393                 if (msg->unpacked)
394                         mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
395                 else {
396                         free(msg->payload.codecVersion);
397                 }
398                 break;
399         case ChannelState:
400                 if (msg->unpacked)
401                         mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
402                 else {
403                         if (msg->payload.channelState->description)
404                                 free(msg->payload.channelState->description);
405                         free(msg->payload.channelState->name);
406                         free(msg->payload.channelState);
407                 }
408                 break;
409
410         default:
411                 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
412                 break;
413         }
414         free(msg);
415 }
416
417 void dumpmsg(uint8_t *data, int size)
418 {
419         int i, r = 0, offset = 0;
420         char buf[512];
421         
422         while (r * 8 + i < size) {
423                 for (i = 0; i < 8 && r * 8 + i < size; i++) {
424                         offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
425                 }
426                 sprintf(buf + offset, "\n");
427                 printf(buf);
428                 offset = 0;
429                 r++;
430                 i = 0;
431         } 
432 }
433
434 message_t *Msg_networkToMessage(uint8_t *data, int size)
435 {
436         message_t *msg = NULL;
437         uint8_t *msgData = &data[6];
438         int messageType, msgLen;
439
440         Msg_getPreamble(data, &messageType, &msgLen);
441
442         Log_debug("Message type %d size %d", messageType, msgLen);
443         dumpmsg(data, size);
444         
445         switch (messageType) {
446         case Version:
447         {
448                 msg = Msg_create(Version);
449                 msg->unpacked = true;
450                 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
451                 break;
452         }
453         case UDPTunnel:
454         {
455                 msg = Msg_create(UDPTunnel);
456                 msg->unpacked = true;
457                 msg->payload.UDPTunnel = mumble_proto__udptunnel__unpack(NULL, msgLen, msgData);
458                 break;
459         }
460         case Authenticate:
461         {
462                 msg = Msg_create(Authenticate);
463                 msg->unpacked = true;
464                 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
465                 break;
466         }
467         case Ping:
468         {
469                 msg = Msg_create(Ping);
470                 msg->unpacked = true;
471                 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
472                 break;
473         }
474         case Reject:
475         {
476                 msg = Msg_create(Reject);
477                 msg->unpacked = true;
478                 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
479                 break;
480         }
481         case ServerSync:
482         {
483                 msg = Msg_create(ServerSync);
484                 msg->unpacked = true;
485                 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
486                 break;
487         }
488         case TextMessage:
489         {
490                 msg = Msg_create(TextMessage);
491                 msg->unpacked = true;
492                 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
493                 break;
494         }
495         case PermissionDenied:
496         {
497                 msg = Msg_create(PermissionDenied);
498                 msg->unpacked = true;
499                 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
500                 break;
501         }
502         case CryptSetup:
503         {
504                 msg = Msg_create(CryptSetup);
505                 msg->unpacked = true;
506                 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
507                 break;
508         }
509         case UserList:
510         {
511                 msg = Msg_create(UserList);
512                 msg->unpacked = true;
513                 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
514                 break;
515         }
516         case UserState:
517         {
518                 msg = Msg_create(UserState);
519                 msg->unpacked = true;
520                 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
521                 break;
522         }
523         case VoiceTarget:
524         {
525                 msg = Msg_create(VoiceTarget);
526                 msg->unpacked = true;
527                 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
528                 break;
529         }
530         case CodecVersion:
531         {
532                 msg = Msg_create(CodecVersion);
533                 msg->unpacked = true;
534                 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
535                 break;
536         }
537
538         default:
539                 Log_warn("Unsupported message %d", messageType);
540                 break;
541         }
542         return msg;
543 }