Added creation of temporary channels.
[umurmur.git] / src / messagehandler.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 #include <string.h>
32 #include <openssl/aes.h>
33
34 #include "log.h"
35 #include "list.h"
36 #include "client.h"
37 #include "messages.h"
38 #include "crypt.h"
39 #include "channel.h"
40 #include "conf.h"
41 #include "voicetarget.h"
42
43 extern channel_t *defaultChan;
44 extern int iCodecAlpha, iCodecBeta;
45 extern bool_t bPreferAlpha;
46
47 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
48 {
49         message_t *msg = Msg_create(Reject);
50         msg->payload.reject->reason = strdup(reason);
51         msg->payload.reject->type = type;
52         msg->payload.reject->has_type = true;
53         Client_send_message(client, msg);
54         
55         Log_info("Server reject reason: %s. Disconnecting session %d - %s@%s:%d",
56                          reason,
57                          client->sessionId,
58                          client->playerName,
59                          inet_ntoa(client->remote_tcp.sin_addr),
60                          ntohs(client->remote_tcp.sin_port));
61         
62 }
63
64 static void sendPermissionDenied(client_t *client, const char *reason)
65 {
66         message_t *msg = Msg_create(PermissionDenied);
67         msg->payload.permissionDenied->has_type = true;
68         msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
69         msg->payload.permissionDenied->reason = strdup(reason);
70         Client_send_message(client, msg);
71 }
72
73 void Mh_handle_message(client_t *client, message_t *msg)
74 {
75         message_t *sendmsg = NULL;
76         channel_t *ch_itr = NULL;
77         client_t *client_itr;
78
79         if (!client->authenticated && !(msg->messageType == Authenticate ||
80                                                                         msg->messageType == Version)) {
81                 goto out;
82         }       
83         switch (msg->messageType) {
84         case Authenticate:
85                 /*
86                  * 1. Check stuff, Serverreject if not ok
87                  * 2. Setup UDP encryption -> MessageCryptSetup
88                  * 3. (Enter channel)
89                  * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
90                  * 5. (MessageChannelLink)
91                  * 6. MessageServerJoin
92                  * 7. MessagePlayerMove
93                  * 8. MessageServerJoin for all connected users
94                  * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
95                  * 10. MessageServerSync
96                  */
97                                 
98                 Log_debug("Authenticate message received");
99                 Log_debug("Username: %s", msg->payload.authenticate->username);
100                 
101                 client->authenticated = true;
102                 
103                 client_itr = NULL;
104                 while (Client_iterate(&client_itr) != NULL) {
105                         if (!IS_AUTH(client_itr))
106                                 continue;
107                         if (client_itr->playerName && strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
108                                 char buf[64];
109                                 sprintf(buf, "Username already in use");
110                                 Log_debug("Username already in use");
111                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
112                                 goto disconnect;
113                         }                               
114                 }
115                 if (msg->payload.authenticate->password && strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
116                         char buf[64];
117                         sprintf(buf, "Wrong server password");
118                         Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
119                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
120                         goto disconnect;
121                 }                               
122                 if (strlen(msg->payload.authenticate->username) == 0 ||
123                         strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
124                         char buf[64];
125                         sprintf(buf, "Invalid username");
126                         Log_debug("Invalid username");
127                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
128                         goto disconnect;
129                 }                               
130
131                 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
132                         char buf[64];
133                         sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
134                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
135                         goto disconnect;
136                 }
137                 
138                 /* Name & password */
139                 client->playerName = strdup(msg->payload.authenticate->username);                               
140                 
141                 /* Setup UDP encryption */
142                 CryptState_init(&client->cryptState);
143                 CryptState_genKey(&client->cryptState);
144                 sendmsg = Msg_create(CryptSetup);
145                 sendmsg->payload.cryptSetup->has_key = true;
146                 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
147                 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
148                 sendmsg->payload.cryptSetup->has_server_nonce = true;
149                 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
150                 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
151                 sendmsg->payload.cryptSetup->has_client_nonce = true;
152                 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
153                 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
154                 Client_send_message(client, sendmsg);
155
156                 /* Channel stuff */
157                 Chan_playerJoin(defaultChan, client); /* Join default channel */
158
159                 /* Codec version */
160                 if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
161                         Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
162                                          MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
163                 
164                 Log_debug("Client %d has %d CELT codecs", client->sessionId, msg->payload.authenticate->n_celt_versions);
165                 if (msg->payload.authenticate->n_celt_versions > 0) {
166                         int i;
167                         client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
168                                 MAX_CODECS : msg->payload.authenticate->n_celt_versions;
169                         for (i = 0; i < client->codec_count; i++) {
170                                 client->codecs[i] = msg->payload.authenticate->celt_versions[i];
171                                 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, client->codecs[i]);
172                         }
173                 } else {
174                         client->codecs[0] = (int32_t)0x8000000a;
175                         client->codec_count = 1;
176                 }
177                 
178                 recheckCodecVersions();
179                 
180                 sendmsg = Msg_create(CodecVersion);
181                 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
182                 sendmsg->payload.codecVersion->beta = iCodecBeta;
183                 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
184                 Client_send_message(client, sendmsg);
185                 
186                 /* Iterate channels and send channel info */
187                 ch_itr = NULL;
188                 Chan_iterate(&ch_itr);
189                 do {
190                         sendmsg = Msg_create(ChannelState);
191                         sendmsg->payload.channelState->has_channel_id = true;
192                         sendmsg->payload.channelState->channel_id = ch_itr->id;
193                         if (ch_itr->id != 0) {
194                                 sendmsg->payload.channelState->has_parent = true;
195                                 sendmsg->payload.channelState->parent = ch_itr->parent->id;
196                         }
197                         sendmsg->payload.channelState->name = strdup(ch_itr->name);
198                         if (strlen(ch_itr->desc) > 0) {
199                                 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
200                         }
201                         Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
202                         Client_send_message(client, sendmsg);
203                         
204                         Chan_iterate(&ch_itr);
205                 } while (ch_itr != NULL);
206
207                 /* Not supporting channel links yet */
208                 
209                 /* Send user state for connecting user to other users */
210                 sendmsg = Msg_create(UserState);
211                 sendmsg->payload.userState->has_session = true;
212                 sendmsg->payload.userState->session = client->sessionId;
213                 sendmsg->payload.userState->has_user_id = true;
214                 sendmsg->payload.userState->user_id = client->sessionId;
215                 sendmsg->payload.userState->name = strdup(client->playerName);
216                 sendmsg->payload.userState->has_channel_id = true;
217                 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
218                 
219                 Client_send_message_except(client, sendmsg);
220
221                 client_itr = NULL;
222                 while (Client_iterate(&client_itr) != NULL) {
223                         if (!IS_AUTH(client_itr))
224                                 continue;
225                         sendmsg = Msg_create(UserState);
226                         sendmsg->payload.userState->has_session = true;
227                         sendmsg->payload.userState->session = client_itr->sessionId;
228                         sendmsg->payload.userState->name = strdup(client_itr->playerName);
229                         sendmsg->payload.userState->has_channel_id = true;
230                         sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
231
232                         /* Only self_mute/deaf supported */
233                         if (client_itr->deaf) {
234                                 sendmsg->payload.userState->has_self_deaf = true;
235                                 sendmsg->payload.userState->self_deaf = true;
236                         }
237                         if (client_itr->mute) {
238                                 sendmsg->payload.userState->has_self_mute = true;
239                                 sendmsg->payload.userState->self_mute = true;
240                         }
241                         Client_send_message(client, sendmsg);
242                 }
243
244                 /* Sync message */
245                 sendmsg = Msg_create(ServerSync);
246                 sendmsg->payload.serverSync->has_session = true;
247                 sendmsg->payload.serverSync->session = client->sessionId;
248                 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
249                 sendmsg->payload.serverSync->has_max_bandwidth = true;
250                 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
251                 sendmsg->payload.serverSync->has_allow_html = true;
252                 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
253                 Client_send_message(client, sendmsg);
254                 
255                 Log_info("User %s authenticated", client->playerName);
256                 break;
257                 
258         case Ping:
259                 if (msg->payload.ping->has_good)
260                         client->cryptState.uiRemoteGood = msg->payload.ping->good;
261                 if (msg->payload.ping->has_late)
262                         client->cryptState.uiRemoteLate = msg->payload.ping->late;
263                 if (msg->payload.ping->has_lost)
264                         client->cryptState.uiRemoteLost = msg->payload.ping->lost;
265                 if (msg->payload.ping->has_resync)
266                         client->cryptState.uiRemoteResync = msg->payload.ping->resync;
267
268                 Log_debug("Ping <-: %d %d %d %d",
269                                   client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
270                                   client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
271                         );
272                 
273                 /* Ignoring the double values since they don't seem to be used */
274                 
275                 sendmsg = Msg_create(Ping);
276
277                 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
278                 sendmsg->payload.ping->has_timestamp = true;
279                 sendmsg->payload.ping->good = client->cryptState.uiGood;
280                 sendmsg->payload.ping->has_good = true;
281                 sendmsg->payload.ping->late = client->cryptState.uiLate;
282                 sendmsg->payload.ping->has_late = true;
283                 sendmsg->payload.ping->lost = client->cryptState.uiLost;
284                 sendmsg->payload.ping->has_lost = true;
285                 sendmsg->payload.ping->resync = client->cryptState.uiResync;
286                 sendmsg->payload.ping->has_resync = true;
287
288                 Client_send_message(client, sendmsg);
289                 Log_debug("Ping ->: %d %d %d %d",
290                                   client->cryptState.uiGood, client->cryptState.uiLate,
291                                   client->cryptState.uiLost, client->cryptState.uiResync);
292
293                 break;
294         case CryptSetup:
295                 Log_debug("Voice channel crypt resync requested");
296                 if (!msg->payload.cryptSetup->has_client_nonce) {
297                         sendmsg = Msg_create(CryptSetup);
298                         sendmsg->payload.cryptSetup->has_server_nonce = true;
299                         sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
300                         sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
301                         Client_send_message(client, sendmsg);
302                 } else {
303                         memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
304                         client->cryptState.uiResync++;
305                 }
306                 break;
307         case UserState:
308                 /* Only allow state changes for for the self user */
309                 if (msg->payload.userState->has_session &&
310                         msg->payload.userState->session != client->sessionId) {
311                         sendPermissionDenied(client, "Permission denied");
312                         break;
313                 }
314                 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
315                         msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
316                         msg->payload.userState->has_texture) {
317                         
318                         sendPermissionDenied(client, "Not supported by uMurmur");
319                         break;
320                 }
321                 if (msg->payload.userState->has_self_deaf) {
322                         client->deaf = msg->payload.userState->self_deaf;
323                 }
324                 if (msg->payload.userState->has_self_mute) {
325                         client->mute = msg->payload.userState->self_mute;                       
326                 }
327                 if (msg->payload.userState->has_channel_id) {
328                         int leave_id;
329                         leave_id = Chan_playerJoin_id(msg->payload.userState->channel_id, client);
330                         if (leave_id > 0) {
331                                 /* XXX - need to send update to remove channel if temporary */
332                                 Log_debug("Removing channel ID %d", leave_id);
333                                 sendmsg = Msg_create(ChannelRemove);
334                                 sendmsg->payload.channelRemove->channel_id = leave_id;
335                         }
336                 }
337                 if (msg->payload.userState->plugin_context != NULL) {
338                         if (client->context)
339                                 free(client->context);
340                         client->context = strdup(msg->payload.userState->plugin_context);
341                         if (client->context == NULL)
342                                 Log_fatal("Out of memory");
343                         
344                         break; /* Don't inform other users about this state */
345                 }
346                 
347                 /* Re-use message */
348                 Msg_inc_ref(msg);
349                 msg->payload.userState->has_actor = true;
350                 msg->payload.userState->actor = client->sessionId;
351                 Client_send_message_except(NULL, msg);
352
353                 /* Need to send remove channel message _after_ UserState message */
354                 if (sendmsg != NULL)
355                         Client_send_message_except(NULL, sendmsg);
356                 break;
357         case TextMessage:
358                 msg->payload.textMessage->has_actor = true;
359                 msg->payload.textMessage->actor = client->sessionId;
360
361                 /* XXX - HTML is allowed and can't be turned off */
362                 if (msg->payload.textMessage->n_tree_id > 0) {
363                         sendPermissionDenied(client, "Tree message not supported");
364                         break;
365                 }
366                         
367                 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
368                         int i;
369                         channel_t *ch_itr;
370                         for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
371                                 ch_itr = NULL;
372                                 do {
373                                         Chan_iterate(&ch_itr);
374                                 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
375                                 if (ch_itr == NULL)
376                                         Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage->channel_id[i]);
377                                 else {
378                                         struct dlist *itr;
379                                         list_iterate(itr, &ch_itr->clients) {
380                                                 client_t *c;
381                                                 c = list_get_entry(itr, client_t, chan_node);
382                                                 if (c != client && !c->deaf) {
383                                                         Msg_inc_ref(msg);
384                                                         Client_send_message(c, msg);
385                                                         Log_debug("Text message to session ID %d", c->sessionId);
386                                                 }
387                                         }
388                                 }
389                         } /* for */
390                 }
391                 if (msg->payload.textMessage->n_session > 0) { /* To user */
392                         int i;
393                         client_t *itr;
394                         for (i = 0; i < msg->payload.textMessage->n_session; i++) {
395                                 itr = NULL;
396                                 while (Client_iterate(&itr) != NULL) {
397                                         if (!IS_AUTH(itr))
398                                                 continue;
399                                         if (itr->sessionId == msg->payload.textMessage->session[i]) {
400                                                 if (!itr->deaf) {
401                                                         Msg_inc_ref(msg);
402                                                         Client_send_message(itr, msg);
403                                                         Log_debug("Text message to session ID %d", itr->sessionId);
404                                                 }
405                                                 break;
406                                         }
407                                 }
408                                 if (itr == NULL)
409                                         Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
410                         } /* for */
411                 }
412                 break;
413
414         case VoiceTarget:
415         {
416                 int i, j, count, targetId = msg->payload.voiceTarget->id;
417                 struct _MumbleProto__VoiceTarget__Target *target;
418
419                 if (!targetId || targetId >= 0x1f)
420                         break;
421                 Voicetarget_add_id(client, targetId);
422                 count = msg->payload.voiceTarget->n_targets;
423                 if (!count)
424                         break;
425                 for (i = 0; i < count; i++) {
426                         target = msg->payload.voiceTarget->targets[i];
427                         for (j = 0; j < target->n_session; j++)
428                                 Voicetarget_add_session(client, targetId, target->session[j]);
429                         if (target->has_channel_id) {
430                                 if (target->has_links || target->has_children)
431                                         Log_warn("Whisper to children or linked channels not implemented. Ignoring.");
432                                 Voicetarget_add_channel(client, targetId, target->channel_id);
433                         }
434                 }
435                 break;
436         }
437         case Version:
438                 Log_debug("Version message received");
439                 if (msg->payload.version->has_version) {
440                         client->version = msg->payload.version->version;
441                         Log_debug("Client version 0x%x", client->version);
442                 }
443                 if (msg->payload.version->release) {
444                         if (client->release) free(client->release);
445                         client->release = strdup(msg->payload.version->release);
446                         Log_debug("Client release %s", client->release);
447                 }
448                 if (msg->payload.version->os) {
449                         if (client->os) free(client->os);                       
450                         client->os = strdup(msg->payload.version->os);
451                         Log_debug("Client OS %s", client->os);
452                 }
453                 break;
454         case PermissionQuery:
455                 Msg_inc_ref(msg); /* Re-use message */
456                 msg->payload.permissionQuery->has_permissions = true;
457                 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
458                 
459                 Client_send_message(client, msg);
460                 break;
461         case UDPTunnel:
462                 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
463             break;
464         case ChannelState:
465         {
466                 channel_t *ch_itr, *parent, *newchan;
467                 
468                 /* Don't allow any changes to existing channels */
469                 if (msg->payload.channelState->has_channel_id) {
470                         sendPermissionDenied(client, "Not supported by uMurmur");
471                         break;
472                 }
473                 /* Must have parent */
474                 if (!msg->payload.channelState->has_parent) {
475                         sendPermissionDenied(client, "Not supported by uMurmur");
476                         break;
477                 }
478                 /* Must have name */
479                 if (msg->payload.channelState->name == NULL) {
480                         sendPermissionDenied(client, "Not supported by uMurmur");
481                         break;
482                 }
483                 /* Must be temporary channel */
484                 if (msg->payload.channelState->temporary != true) {
485                         sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
486                         break;
487                 }
488                 /* Check channel name is OK */
489                 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
490                         sendPermissionDenied(client, "Channel name too long");
491                         break;
492                 }
493                         
494                 parent = Chan_fromId(msg->payload.channelState->parent);
495                 if (parent == NULL)
496                         break;
497                 ch_itr = NULL;
498                 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
499                         if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
500                                 sendPermissionDenied(client, "Channel already exists");
501                                 break;
502                         }
503                 }
504                 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
505                  * I don't know why so I don't do that here...
506                  */
507
508                 /* Create the channel */
509                 newchan = Chan_createChannel(msg->payload.channelState->name,
510                                                                          msg->payload.channelState->description);
511                 newchan->temporary = true;
512                 Chan_addChannel(parent, newchan);
513                 msg->payload.channelState->has_channel_id = true;
514                 msg->payload.channelState->channel_id = newchan->id;
515                 Msg_inc_ref(msg);
516                 Client_send_message_except(NULL, msg);
517
518                 /* Join the creating user */
519                 sendmsg = Msg_create(UserState);
520                 sendmsg->payload.userState->has_session = true;
521                 sendmsg->payload.userState->session = client->sessionId;
522                 sendmsg->payload.userState->has_channel_id = true;
523                 sendmsg->payload.userState->channel_id = newchan->id;
524                 Client_send_message_except(NULL, sendmsg);
525                 Chan_playerJoin(newchan, client);
526         }               
527         break;
528
529                 /* Permission denied for all these messages. Not implemented. */
530         case ChannelRemove:
531         case ContextAction:
532         case ContextActionAdd:
533         case ACL:
534         case BanList:
535         case UserList:
536         case QueryUsers:
537                 sendPermissionDenied(client, "Not supported by uMurmur");
538                 break;
539                                 
540         default:
541                 Log_warn("Message %d not handled", msg->messageType);
542                 break;
543         }
544 out:
545         Msg_free(msg);
546         return;
547         
548 disconnect:
549         Msg_free(msg);
550         Client_close(client);
551 }
552