Fix TCP 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                 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);
81                 break;
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");
85                         break;
86                 }
87                 Msg_addPreamble(buffer, msg->messageType, msg->payload.UDPTunnel->packet.len);
88                 memcpy(bufptr, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
89                 break;
90         case Authenticate:
91                 len = mumble_proto__authenticate__get_packed_size(msg->payload.authenticate);
92                 if (len > MAX_MSGSIZE) {
93                         Log_warn("Too big tx message. Discarding");
94                         break;
95                         }
96                 Msg_addPreamble(buffer, msg->messageType, len);
97                 mumble_proto__authenticate__pack(msg->payload.authenticate, bufptr);
98                 break;
99         case Ping:
100                 len = mumble_proto__ping__get_packed_size(msg->payload.ping);
101                 if (len > MAX_MSGSIZE) {
102                         Log_warn("Too big tx message. Discarding");
103                         break;
104                         }
105                 Msg_addPreamble(buffer, msg->messageType, len);
106                 mumble_proto__ping__pack(msg->payload.ping, bufptr);
107                 break;
108         case Reject:
109                 len = mumble_proto__reject__get_packed_size(msg->payload.reject);
110                 if (len > MAX_MSGSIZE) {
111                         Log_warn("Too big tx message. Discarding");
112                         break;
113                         }
114                 Msg_addPreamble(buffer, msg->messageType, len);
115                 mumble_proto__reject__pack(msg->payload.reject, bufptr);
116                 break;
117         case ServerSync:
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");
121                         break;
122                         }
123                 Msg_addPreamble(buffer, msg->messageType, len);
124                 mumble_proto__server_sync__pack(msg->payload.serverSync, bufptr);
125                 break;
126         case TextMessage:
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");
130                         break;
131                         }
132                 Msg_addPreamble(buffer, msg->messageType, len);
133                 mumble_proto__text_message__pack(msg->payload.textMessage, bufptr);
134                 break;
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");
139                         break;
140                         }
141                 Msg_addPreamble(buffer, msg->messageType, len);
142                 mumble_proto__permission_denied__pack(msg->payload.permissionDenied, bufptr);
143                 break;
144         case CryptSetup:
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");
148                         break;
149                         }
150                 Msg_addPreamble(buffer, msg->messageType, len);
151                 mumble_proto__crypt_setup__pack(msg->payload.cryptSetup, bufptr);
152                 break;
153         case UserList:
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");
157                         break;
158                         }
159                 Msg_addPreamble(buffer, msg->messageType, len);
160                 mumble_proto__user_list__pack(msg->payload.userList, bufptr);
161                 break;
162         case UserState:
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");
166                         break;
167                         }
168                 Msg_addPreamble(buffer, msg->messageType, len);
169                 mumble_proto__user_state__pack(msg->payload.userState, bufptr);
170                 break;
171         case ChannelState:
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");
175                         break;
176                         }
177                 Msg_addPreamble(buffer, msg->messageType, len);
178                 mumble_proto__channel_state__pack(msg->payload.channelState, bufptr);
179                 break;
180         case VoiceTarget:
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");
184                         break;
185                         }
186                 Msg_addPreamble(buffer, msg->messageType, len);
187                 mumble_proto__voice_target__pack(msg->payload.voiceTarget, bufptr);
188                 break;
189         case CodecVersion:
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");
193                         break;
194                         }
195                 Msg_addPreamble(buffer, msg->messageType, len);
196                 mumble_proto__codec_version__pack(msg->payload.codecVersion, bufptr);
197                 break;
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");
202                         break;
203                         }
204                 Msg_addPreamble(buffer, msg->messageType, len);
205                 mumble_proto__permission_query__pack(msg->payload.permissionQuery, bufptr);
206                 break;
207
208         default:
209                 Log_warn("Unsupported message %d", msg->messageType);
210                 return 0;
211         }
212         return len + 6;
213 }
214
215 message_t *Msg_create(messageType_t messageType)
216 {
217         message_t *msg = malloc(sizeof(message_t));
218
219         if (msg == NULL)
220                 Log_fatal("Out of memory");
221         memset(msg, 0, sizeof(message_t));
222         msg->refcount = 1;
223         msg->messageType = messageType;
224         init_list_entry(&msg->node);
225         
226         switch (messageType) {
227         case Version:
228                 msg->payload.version = malloc(sizeof(MumbleProto__Version));
229                 mumble_proto__version__init(msg->payload.version);
230                 break;
231         case UDPTunnel:
232                 msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
233                 mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
234                 break;
235         case Authenticate:
236                 msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
237                 mumble_proto__authenticate__init(msg->payload.authenticate);
238                 break;
239         case Ping:
240                 msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
241                 mumble_proto__ping__init(msg->payload.ping);
242                 break;
243         case Reject:
244                 msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
245                 mumble_proto__reject__init(msg->payload.reject);
246                 break;
247         case ServerSync:
248                 msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
249                 mumble_proto__server_sync__init(msg->payload.serverSync);
250                 break;
251         case TextMessage:
252                 msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
253                 mumble_proto__text_message__init(msg->payload.textMessage);
254                 break;
255         case PermissionDenied:
256                 msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
257                 mumble_proto__permission_denied__init(msg->payload.permissionDenied);
258                 break;
259         case CryptSetup:
260                 msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
261                 mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
262                 break;
263         case UserList:
264                 msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
265                 mumble_proto__user_list__init(msg->payload.userList);
266                 break;
267         case UserState:
268                 msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
269                 mumble_proto__user_state__init(msg->payload.userState);
270                 break;
271         case UserRemove:
272                 msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
273                 mumble_proto__user_remove__init(msg->payload.userRemove);
274                 break;
275         case VoiceTarget:
276                 msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
277                 mumble_proto__voice_target__init(msg->payload.voiceTarget);
278                 break;
279         case CodecVersion:
280                 msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
281                 mumble_proto__codec_version__init(msg->payload.codecVersion);
282                 break;
283         case ChannelState:
284                 msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
285                 mumble_proto__channel_state__init(msg->payload.channelState);
286                 break;
287         case PermissionQuery:
288                 msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
289                 mumble_proto__permission_query__init(msg->payload.permissionQuery);
290                 break;
291
292         default:
293                 Log_warn("Msg_create: Unsupported message %d", msg->messageType);
294                 break;
295         }
296
297         return msg;
298 }
299
300 void Msg_inc_ref(message_t *msg)
301 {
302         msg->refcount++;
303 }
304
305 void Msg_free(message_t *msg)
306 {
307         if (msg->refcount) msg->refcount--;
308         if (msg->refcount > 0)
309                 return;
310
311         switch (msg->messageType) {
312         case Version:
313                 if (msg->unpacked)
314                         mumble_proto__version__free_unpacked(msg->payload.version, NULL);
315                 else {
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);
323                 }
324                 break;
325         case UDPTunnel:
326                 if (msg->unpacked)
327                         mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
328                 else {
329                         free(msg->payload.UDPTunnel->packet.data);
330                         free(msg->payload.UDPTunnel);
331                 }
332                 break;
333         case Authenticate:
334                 if (msg->unpacked)
335                         mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
336                 break;
337         case Ping:
338                 if (msg->unpacked)
339                         mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
340                 else {
341                         free(msg->payload.ping);
342                 }
343                 break;
344         case Reject:
345                 if (msg->unpacked)
346                         mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
347                 else {
348                         free(msg->payload.reject->reason);
349                         free(msg->payload.reject);
350                 }
351                 break;
352         case ServerSync:
353                 if (msg->unpacked)
354                         mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
355                 else {
356                         free(msg->payload.serverSync->welcome_text);
357                         free(msg->payload.serverSync);
358                 }
359                 break;
360         case TextMessage:
361                 if (msg->unpacked)
362                         mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
363                 else {
364                         free(msg->payload.textMessage);
365                 }
366                 break;
367         case PermissionDenied:
368                 if (msg->unpacked)
369                         mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
370                 else {
371                         free(msg->payload.permissionDenied->reason);
372                         free(msg->payload.permissionDenied);
373                 }
374                 break;
375         case CryptSetup:
376                 if (msg->unpacked)
377                         mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
378                 else {
379                         free(msg->payload.cryptSetup);
380                 }
381                 break;
382         case UserList:
383                 if (msg->unpacked)
384                         mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
385                 else {
386                         free(msg->payload.userList);
387                 }
388                 break;
389         case UserState:
390                 if (msg->unpacked)
391                         mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
392                 else {
393                         free(msg->payload.userState->name);
394                         free(msg->payload.userState);
395                 }
396                 break;
397         case UserRemove:
398                 if (msg->unpacked)
399                         mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
400                 else {
401                         free(msg->payload.userRemove);
402                 }
403                 break;
404         case VoiceTarget:
405                 if (msg->unpacked)
406                         mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
407                 else {
408                         free(msg->payload.voiceTarget);
409                 }
410                 break;
411         case CodecVersion:
412                 if (msg->unpacked)
413                         mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
414                 else {
415                         free(msg->payload.codecVersion);
416                 }
417                 break;
418         case ChannelState:
419                 if (msg->unpacked)
420                         mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
421                 else {
422                         if (msg->payload.channelState->description)
423                                 free(msg->payload.channelState->description);
424                         free(msg->payload.channelState->name);
425                         free(msg->payload.channelState);
426                 }
427                 break;
428         case PermissionQuery:
429                 if (msg->unpacked)
430                         mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
431                 else {
432                         free(msg->payload.permissionQuery);
433                 }
434                 break;
435
436         default:
437                 Log_warn("Msg_free: Unsupported message %d", msg->messageType);
438                 break;
439         }
440         free(msg);
441 }
442
443 void dumpmsg(uint8_t *data, int size)
444 {
445         int i, r = 0, offset = 0;
446         char buf[512];
447         
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]);
451                 }
452                 sprintf(buf + offset, "\n");
453                 printf(buf);
454                 offset = 0;
455                 r++;
456                 i = 0;
457         } 
458 }
459
460 message_t *Msg_networkToMessage(uint8_t *data, int size)
461 {
462         message_t *msg = NULL;
463         uint8_t *msgData = &data[6];
464         int messageType, msgLen;
465
466         Msg_getPreamble(data, &messageType, &msgLen);
467
468         Log_debug("Message type %d size %d", messageType, msgLen);
469         dumpmsg(data, size);
470         
471         switch (messageType) {
472         case Version:
473         {
474                 msg = Msg_create(Version);
475                 msg->unpacked = true;
476                 msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
477                 break;
478         }
479         case UDPTunnel: /* Non-standard handling of tunneled voice data */
480         {
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;
491                 break;
492         }
493         case Authenticate:
494         {
495                 msg = Msg_create(Authenticate);
496                 msg->unpacked = true;
497                 msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
498                 break;
499         }
500         case Ping:
501         {
502                 msg = Msg_create(Ping);
503                 msg->unpacked = true;
504                 msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
505                 break;
506         }
507         case Reject:
508         {
509                 msg = Msg_create(Reject);
510                 msg->unpacked = true;
511                 msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
512                 break;
513         }
514         case ServerSync:
515         {
516                 msg = Msg_create(ServerSync);
517                 msg->unpacked = true;
518                 msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
519                 break;
520         }
521         case TextMessage:
522         {
523                 msg = Msg_create(TextMessage);
524                 msg->unpacked = true;
525                 msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
526                 break;
527         }
528         case PermissionDenied:
529         {
530                 msg = Msg_create(PermissionDenied);
531                 msg->unpacked = true;
532                 msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
533                 break;
534         }
535         case CryptSetup:
536         {
537                 msg = Msg_create(CryptSetup);
538                 msg->unpacked = true;
539                 msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
540                 break;
541         }
542         case UserList:
543         {
544                 msg = Msg_create(UserList);
545                 msg->unpacked = true;
546                 msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
547                 break;
548         }
549         case UserState:
550         {
551                 msg = Msg_create(UserState);
552                 msg->unpacked = true;
553                 msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
554                 break;
555         }
556         case VoiceTarget:
557         {
558                 msg = Msg_create(VoiceTarget);
559                 msg->unpacked = true;
560                 msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
561                 break;
562         }
563         case CodecVersion:
564         {
565                 msg = Msg_create(CodecVersion);
566                 msg->unpacked = true;
567                 msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
568                 break;
569         }
570         case PermissionQuery:
571         {
572                 msg = Msg_create(PermissionQuery);
573                 msg->unpacked = true;
574                 msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
575                 break;
576         }
577
578         default:
579                 Log_warn("Unsupported message %d", messageType);
580                 break;
581         }
582         return msg;
583 }