Make logging more uniform. Fix copyright year
[umurmur.git] / src / messages.c
1 /* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2010, 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 static message_t *Msg_create_nopayload(messageType_t messageType);
45
46 void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
47 {
48         type = htons(type);
49         len = htonl(len);
50         
51         buffer[0] = (type) & 0xff;
52         buffer[1] = (type >> 8) & 0xff;
53         
54         buffer[2] = (len) & 0xff;
55         buffer[3] = (len >> 8) & 0xff;
56         buffer[4] = (len >> 16) & 0xff;
57         buffer[5] = (len >> 24) & 0xff; 
58 }
59
60 static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
61 {
62         uint16_t msgType;
63         uint32_t msgLen;
64         
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);
69 }
70
71 #define MAX_MSGSIZE (BUFSIZE - 6)
72 int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
73 {
74         int len;
75         uint8_t *bufptr = buffer + 6;
76                 
77         Log_debug("To net: msg type %d", msg->messageType);
78         switch (msg->messageType) {
79         case Version:
80                 len = mumble_proto__version__get_packed_size(msg->payload.version);
81                 if (len > MAX_MSGSIZE) {
82                         Log_warn("Too big tx message. Discarding");
83                         break;
84                 }
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);
89                 break;
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");
93                         break;
94                 }
95                 Msg_addPreamble(buffer, msg->messageType, msg->payload.UDPTunnel->packet.len);
96                 memcpy(bufptr, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
97                 break;
98         case Authenticate:
99                 len = mumble_proto__authenticate__get_packed_size(msg->payload.authenticate);
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__authenticate__pack(msg->payload.authenticate, bufptr);
106                 break;
107         case Ping:
108                 len = mumble_proto__ping__get_packed_size(msg->payload.ping);
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__ping__pack(msg->payload.ping, bufptr);
115                 break;
116         case Reject:
117                 len = mumble_proto__reject__get_packed_size(msg->payload.reject);
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__reject__pack(msg->payload.reject, bufptr);
124                 break;
125         case ServerSync:
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");
129                         break;
130                         }
131                 Msg_addPreamble(buffer, msg->messageType, len);
132                 mumble_proto__server_sync__pack(msg->payload.serverSync, bufptr);
133                 break;
134         case TextMessage:
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");
138                         break;
139                         }
140                 Msg_addPreamble(buffer, msg->messageType, len);
141                 mumble_proto__text_message__pack(msg->payload.textMessage, bufptr);
142                 break;
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");
147                         break;
148                         }
149                 Msg_addPreamble(buffer, msg->messageType, len);
150                 mumble_proto__permission_denied__pack(msg->payload.permissionDenied, bufptr);
151                 break;
152         case CryptSetup:
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");
156                         break;
157                         }
158                 Msg_addPreamble(buffer, msg->messageType, len);
159                 mumble_proto__crypt_setup__pack(msg->payload.cryptSetup, bufptr);
160                 break;
161         case UserList:
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");
165                         break;
166                         }
167                 Msg_addPreamble(buffer, msg->messageType, len);
168                 mumble_proto__user_list__pack(msg->payload.userList, bufptr);
169                 break;
170         case UserState:
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");
174                         break;
175                         }
176                 Msg_addPreamble(buffer, msg->messageType, len);
177                 mumble_proto__user_state__pack(msg->payload.userState, bufptr);
178                 break;
179         case ChannelState:
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");
183                         break;
184                         }
185                 Msg_addPreamble(buffer, msg->messageType, len);
186                 mumble_proto__channel_state__pack(msg->payload.channelState, bufptr);
187                 break;
188         case VoiceTarget:
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");
192                         break;
193                         }
194                 Msg_addPreamble(buffer, msg->messageType, len);
195                 mumble_proto__voice_target__pack(msg->payload.voiceTarget, bufptr);
196                 break;
197         case CodecVersion:
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");
201                         break;
202                         }
203                 Msg_addPreamble(buffer, msg->messageType, len);
204                 mumble_proto__codec_version__pack(msg->payload.codecVersion, bufptr);
205                 break;
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");
210                         break;
211                         }
212                 Msg_addPreamble(buffer, msg->messageType, len);
213                 mumble_proto__permission_query__pack(msg->payload.permissionQuery, bufptr);
214                 break;
215
216         default:
217                 Log_warn("Unsupported message %d", msg->messageType);
218                 return 0;
219         }
220         return len + 6;
221 }
222
223 message_t *Msg_create_nopayload(messageType_t messageType)
224 {
225         message_t *msg = malloc(sizeof(message_t));
226
227         if (msg == NULL)
228                 Log_fatal("Out of memory");
229         memset(msg, 0, sizeof(message_t));
230         msg->refcount = 1;
231         msg->messageType = messageType;
232         init_list_entry(&msg->node);
233         return msg;
234 }
235
236 message_t *Msg_create(messageType_t messageType)
237 {
238         message_t *msg = Msg_create_nopayload(messageType);
239         
240         switch (messageType) {
241         case Version:
242                 msg->payload.version = malloc(sizeof(MumbleProto__Version));
243                 mumble_proto__version__init(msg->payload.version);
244                 break;
245         case UDPTunnel:
246                 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
247                 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
248                 break;
249         case Authenticate:
250                 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
251                 mumble_proto__authenticate__init(msg->payload.authenticate);
252                 break;
253         case Ping:
254                 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
255                 mumble_proto__ping__init(msg->payload.ping);
256                 break;
257         case Reject:
258                 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
259                 mumble_proto__reject__init(msg->payload.reject);
260                 break;
261         case ServerSync:
262                 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
263                 mumble_proto__server_sync__init(msg->payload.serverSync);
264                 break;
265         case TextMessage:
266                 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
267                 mumble_proto__text_message__init(msg->payload.textMessage);
268                 break;
269         case PermissionDenied:
270                 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
271                 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
272                 break;
273         case CryptSetup:
274                 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
275                 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
276                 break;
277         case UserList:
278                 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
279                 mumble_proto__user_list__init(msg->payload.userList);
280                 break;
281         case UserState:
282                 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
283                 mumble_proto__user_state__init(msg->payload.userState);
284                 break;
285         case UserRemove:
286                 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
287                 mumble_proto__user_remove__init(msg->payload.userRemove);
288                 break;
289         case VoiceTarget:
290                 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
291                 mumble_proto__voice_target__init(msg->payload.voiceTarget);
292                 break;
293         case CodecVersion:
294                 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
295                 mumble_proto__codec_version__init(msg->payload.codecVersion);
296                 break;
297         case ChannelState:
298                 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
299                 mumble_proto__channel_state__init(msg->payload.channelState);
300                 break;
301         case PermissionQuery:
302                 msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
303                 mumble_proto__permission_query__init(msg->payload.permissionQuery);
304                 break;
305
306         default:
307                 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
308                 break;
309         }
310
311         return msg;
312 }
313
314 void Msg_inc_ref(message_t *msg)
315 {
316         msg->refcount++;
317 }
318
319 void Msg_free(message_t *msg)
320 {
321         if (msg->refcount) msg->refcount--;
322         if (msg->refcount > 0)
323                 return;
324
325         switch (msg->messageType) {
326         case Version:
327                 if (msg->unpacked)
328                         mumble_proto__version__free_unpacked(msg->payload.version, NULL);
329                 else {
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);
337                 }
338                 break;
339         case UDPTunnel:
340                 if (msg->unpacked)
341                         mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
342                 else {
343                         free(msg->payload.UDPTunnel->packet.data);
344                         free(msg->payload.UDPTunnel);
345                 }
346                 break;
347         case Authenticate:
348                 if (msg->unpacked)
349                         mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
350                 else
351                         free(msg->payload.authenticate);
352                 break;
353         case Ping:
354                 if (msg->unpacked)
355                         mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
356                 else {
357                         free(msg->payload.ping);
358                 }
359                 break;
360         case Reject:
361                 if (msg->unpacked)
362                         mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
363                 else {
364                         free(msg->payload.reject->reason);
365                         free(msg->payload.reject);
366                 }
367                 break;
368         case ServerSync:
369                 if (msg->unpacked)
370                         mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
371                 else {
372                         free(msg->payload.serverSync->welcome_text);
373                         free(msg->payload.serverSync);
374                 }
375                 break;
376         case TextMessage:
377                 if (msg->unpacked)
378                         mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
379                 else {
380                         free(msg->payload.textMessage);
381                 }
382                 break;
383         case PermissionDenied:
384                 if (msg->unpacked)
385                         mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
386                 else {
387                         free(msg->payload.permissionDenied->reason);
388                         free(msg->payload.permissionDenied);
389                 }
390                 break;
391         case CryptSetup:
392                 if (msg->unpacked)
393                         mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
394                 else {
395                         free(msg->payload.cryptSetup);
396                 }
397                 break;
398         case UserList:
399                 if (msg->unpacked)
400                         mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
401                 else {
402                         free(msg->payload.userList);
403                 }
404                 break;
405         case UserState:
406                 if (msg->unpacked)
407                         mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
408                 else {
409                         free(msg->payload.userState->name);
410                         free(msg->payload.userState);
411                 }
412                 break;
413         case UserRemove:
414                 if (msg->unpacked)
415                         mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
416                 else {
417                         free(msg->payload.userRemove);
418                 }
419                 break;
420         case VoiceTarget:
421                 if (msg->unpacked)
422                         mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
423                 else {
424                         free(msg->payload.voiceTarget);
425                 }
426                 break;
427         case CodecVersion:
428                 if (msg->unpacked)
429                         mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
430                 else {
431                         free(msg->payload.codecVersion);
432                 }
433                 break;
434         case ChannelState:
435                 if (msg->unpacked)
436                         mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
437                 else {
438                         if (msg->payload.channelState->description)
439                                 free(msg->payload.channelState->description);
440                         free(msg->payload.channelState->name);
441                         free(msg->payload.channelState);
442                 }
443                 break;
444         case PermissionQuery:
445                 if (msg->unpacked)
446                         mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
447                 else {
448                         free(msg->payload.permissionQuery);
449                 }
450                 break;
451
452         default:
453                 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
454                 break;
455         }
456         free(msg);
457 }
458
459 void dumpmsg(uint8_t *data, int size)
460 {
461         int i, r = 0, offset = 0;
462         char buf[512];
463         
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]);
467                 }
468                 sprintf(buf + offset, "\n");
469                 printf(buf);
470                 offset = 0;
471                 r++;
472                 i = 0;
473         } 
474 }
475
476 message_t *Msg_networkToMessage(uint8_t *data, int size)
477 {
478         message_t *msg = NULL;
479         uint8_t *msgData = &data[6];
480         int messageType, msgLen;
481
482         Msg_getPreamble(data, &messageType, &msgLen);
483
484         Log_debug("Message type %d size %d", messageType, msgLen);
485         //dumpmsg(data, size);
486         
487         switch (messageType) {
488         case Version:
489         {
490                 msg = Msg_create_nopayload(Version);
491                 msg->unpacked = true;
492                 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
493                 break;
494         }
495         case UDPTunnel: /* Non-standard handling of tunneled voice data */
496         {
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;
507                 break;
508         }
509         case Authenticate:
510         {
511                 msg = Msg_create_nopayload(Authenticate);
512                 msg->unpacked = true;
513                 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
514                 break;
515         }
516         case Ping:
517         {
518                 msg = Msg_create_nopayload(Ping);
519                 msg->unpacked = true;
520                 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
521                 break;
522         }
523         case Reject:
524         {
525                 msg = Msg_create_nopayload(Reject);
526                 msg->unpacked = true;
527                 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
528                 break;
529         }
530         case ServerSync:
531         {
532                 msg = Msg_create_nopayload(ServerSync);
533                 msg->unpacked = true;
534                 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
535                 break;
536         }
537         case TextMessage:
538         {
539                 msg = Msg_create_nopayload(TextMessage);
540                 msg->unpacked = true;
541                 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
542                 break;
543         }
544         case PermissionDenied:
545         {
546                 msg = Msg_create_nopayload(PermissionDenied);
547                 msg->unpacked = true;
548                 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
549                 break;
550         }
551         case CryptSetup:
552         {
553                 msg = Msg_create_nopayload(CryptSetup);
554                 msg->unpacked = true;
555                 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
556                 break;
557         }
558         case UserList:
559         {
560                 msg = Msg_create_nopayload(UserList);
561                 msg->unpacked = true;
562                 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
563                 break;
564         }
565         case UserState:
566         {
567                 msg = Msg_create_nopayload(UserState);
568                 msg->unpacked = true;
569                 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
570                 break;
571         }
572         case VoiceTarget:
573         {
574                 msg = Msg_create_nopayload(VoiceTarget);
575                 msg->unpacked = true;
576                 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
577                 break;
578         }
579         case CodecVersion:
580         {
581                 msg = Msg_create_nopayload(CodecVersion);
582                 msg->unpacked = true;
583                 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
584                 break;
585         }
586         case PermissionQuery:
587         {
588                 msg = Msg_create_nopayload(PermissionQuery);
589                 msg->unpacked = true;
590                 msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
591                 break;
592         }
593
594         default:
595                 Log_warn("Unsupported message %d", messageType);
596                 break;
597         }
598         return msg;
599 }