Added voice target (whisper) functionality.
[umurmur.git] / src / messagehandler.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 #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
56 static void sendPermissionDenied(client_t *client, const char *reason)
57 {
58         message_t *msg = Msg_create(PermissionDenied);
59         msg->payload.permissionDenied->has_type = true;
60         msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
61         msg->payload.permissionDenied->reason = strdup(reason);
62         Client_send_message(client, msg);
63 }
64
65 void Mh_handle_message(client_t *client, message_t *msg)
66 {
67         message_t *sendmsg;
68         channel_t *ch_itr = NULL;
69         client_t *client_itr;
70         
71         switch (msg->messageType) {
72         case Authenticate:
73                 /*
74                  * 1. Check stuff, Serverreject if not ok
75                  * 2. Setup UDP encryption -> MessageCryptSetup
76                  * 3. (Enter channel)
77                  * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
78                  * 5. (MessageChannelLink)
79                  * 6. MessageServerJoin
80                  * 7. MessagePlayerMove
81                  * 8. MessageServerJoin for all connected users
82                  * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
83                  * 10. MessageServerSync
84                  */
85                                 
86                 Log_debug("Authenticate message received");
87                 Log_debug("Username: %s", msg->payload.authenticate->username);
88                 
89                 client->authenticated = true;
90                 
91                 client_itr = NULL;
92                 while (Client_iterate(&client_itr) != NULL) {
93                         if (!IS_AUTH(client_itr))
94                                 continue;
95                         if (client_itr->playerName && strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
96                                 char buf[64];
97                                 sprintf(buf, "Username already in use");
98                                 Log_debug("Username already in use");
99                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
100                                 goto disconnect;
101                         }                               
102                 }
103                 if (msg->payload.authenticate->password && strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
104                         char buf[64];
105                         sprintf(buf, "Wrong server password");
106                         Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
107                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
108                         goto disconnect;
109                 }                               
110                 if (strlen(msg->payload.authenticate->username) == 0 ||
111                         strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
112                         char buf[64];
113                         sprintf(buf, "Invalid username");
114                         Log_debug("Invalid username");
115                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
116                         goto disconnect;
117                 }                               
118
119                 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
120                         char buf[64];
121                         sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
122                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
123                         goto disconnect;
124                 }
125                 
126                 /* Name & password */
127                 client->playerName = strdup(msg->payload.authenticate->username);                               
128                 
129                 /* Setup UDP encryption */
130                 CryptState_init(&client->cryptState);
131                 CryptState_genKey(&client->cryptState);
132                 sendmsg = Msg_create(CryptSetup);
133                 sendmsg->payload.cryptSetup->has_key = true;
134                 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
135                 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
136                 sendmsg->payload.cryptSetup->has_server_nonce = true;
137                 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
138                 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
139                 sendmsg->payload.cryptSetup->has_client_nonce = true;
140                 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
141                 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
142                 Client_send_message(client, sendmsg);
143
144                 /* Channel stuff */
145                 Chan_playerJoin(defaultChan, client); /* Join default channel */
146
147                 /* Codec version */
148                 if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
149                         Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
150                                          MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
151                 
152                 Log_debug("Client %d has %d CELT codecs", client->sessionId, msg->payload.authenticate->n_celt_versions);
153                 if (msg->payload.authenticate->n_celt_versions > 0) {
154                         int i;
155                         client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
156                                 MAX_CODECS : msg->payload.authenticate->n_celt_versions;
157                         for (i = 0; i < client->codec_count; i++) {
158                                 client->codecs[i] = msg->payload.authenticate->celt_versions[i];
159                                 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, client->codecs[i]);
160                         }
161                 } else {
162                         client->codecs[0] = (int32_t)0x8000000a;
163                         client->codec_count = 1;
164                 }
165                 
166                 recheckCodecVersions();
167                 
168                 sendmsg = Msg_create(CodecVersion);
169                 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
170                 sendmsg->payload.codecVersion->beta = iCodecBeta;
171                 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
172                 Client_send_message(client, sendmsg);
173                 
174                 /* Iterate channels and send channel info */
175                 ch_itr = NULL;
176                 Chan_iterate(&ch_itr);
177                 do {
178                         sendmsg = Msg_create(ChannelState);
179                         sendmsg->payload.channelState->has_channel_id = true;
180                         sendmsg->payload.channelState->channel_id = ch_itr->id;
181                         if (ch_itr->id != 0) {
182                                 sendmsg->payload.channelState->has_parent = true;
183                                 sendmsg->payload.channelState->parent = ch_itr->parent->id;
184                         }
185                         sendmsg->payload.channelState->name = strdup(ch_itr->name);
186                         if (strlen(ch_itr->desc) > 0) {
187                                 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
188                         }
189                         Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
190                         Client_send_message(client, sendmsg);
191                         
192                         Chan_iterate(&ch_itr);
193                 } while (ch_itr != NULL);
194
195                 /* Not supporting channel links yet */
196                 
197                 /* Send user state for connecting user to other users */
198                 sendmsg = Msg_create(UserState);
199                 sendmsg->payload.userState->has_session = true;
200                 sendmsg->payload.userState->session = client->sessionId;
201                 sendmsg->payload.userState->has_user_id = true;
202                 sendmsg->payload.userState->user_id = client->sessionId;
203                 sendmsg->payload.userState->name = strdup(client->playerName);
204                 sendmsg->payload.userState->has_channel_id = true;
205                 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
206                 
207                 Client_send_message_except(client, sendmsg);
208
209                 client_itr = NULL;
210                 while (Client_iterate(&client_itr) != NULL) {
211                         if (!IS_AUTH(client_itr))
212                                 continue;
213                         sendmsg = Msg_create(UserState);
214                         sendmsg->payload.userState->has_session = true;
215                         sendmsg->payload.userState->session = client_itr->sessionId;
216                         sendmsg->payload.userState->name = strdup(client_itr->playerName);
217                         sendmsg->payload.userState->has_channel_id = true;
218                         sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
219
220                         /* XXX - check if self_* is correct */
221                         if (client_itr->deaf) {
222                                 sendmsg->payload.userState->has_self_deaf = true;
223                                 sendmsg->payload.userState->self_deaf = true;
224                         }
225                         if (client_itr->mute) {
226                                 sendmsg->payload.userState->has_self_mute = true;
227                                 sendmsg->payload.userState->self_mute = true;
228                         }
229                         Client_send_message(client, sendmsg);
230                 }
231
232                 /* Sync message */
233                 sendmsg = Msg_create(ServerSync);
234                 sendmsg->payload.serverSync->has_session = true;
235                 sendmsg->payload.serverSync->session = client->sessionId;
236                 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
237                 sendmsg->payload.serverSync->has_max_bandwidth = true;
238                 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
239                 sendmsg->payload.serverSync->has_allow_html = true;
240                 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
241                 Client_send_message(client, sendmsg);
242                 
243                 Log_info("User %s authenticated", client->playerName);
244                 break;
245                 
246         case Ping:
247                 if (msg->payload.ping->has_good)
248                         client->cryptState.uiRemoteGood = msg->payload.ping->good;
249                 if (msg->payload.ping->has_late)
250                         client->cryptState.uiRemoteLate = msg->payload.ping->late;
251                 if (msg->payload.ping->has_lost)
252                         client->cryptState.uiRemoteLost = msg->payload.ping->lost;
253                 if (msg->payload.ping->has_resync)
254                         client->cryptState.uiRemoteResync = msg->payload.ping->resync;
255
256                 Log_debug("Ping <-: %d %d %d %d",
257                                   client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
258                                   client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
259                         );
260                 
261                 /* Ignoring the double values since they don't seem to be used */
262                 
263                 sendmsg = Msg_create(Ping);
264
265                 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
266                 sendmsg->payload.ping->has_timestamp = true;
267                 sendmsg->payload.ping->good = client->cryptState.uiGood;
268                 sendmsg->payload.ping->has_good = true;
269                 sendmsg->payload.ping->late = client->cryptState.uiLate;
270                 sendmsg->payload.ping->has_late = true;
271                 sendmsg->payload.ping->lost = client->cryptState.uiLost;
272                 sendmsg->payload.ping->has_lost = true;
273                 sendmsg->payload.ping->resync = client->cryptState.uiResync;
274                 sendmsg->payload.ping->has_resync = true;
275
276                 Client_send_message(client, sendmsg);
277                 Log_debug("Ping ->: %d %d %d %d",
278                                   client->cryptState.uiGood, client->cryptState.uiLate,
279                                   client->cryptState.uiLost, client->cryptState.uiResync);
280
281                 break;
282         case CryptSetup:
283                 Log_debug("Voice channel crypt resync requested");
284                 if (!msg->payload.cryptSetup->has_client_nonce) {
285                         sendmsg = Msg_create(CryptSetup);
286                         sendmsg->payload.cryptSetup->has_server_nonce = true;
287                         sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
288                         sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
289                         Client_send_message(client, sendmsg);
290                 } else {
291                         memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
292                         client->cryptState.uiResync++;
293                 }
294                 break;
295         case UserState:
296                 /* Only allow state changes for for the self user */
297                 if (msg->payload.userState->has_session &&
298                         msg->payload.userState->session != client->sessionId) {
299                         sendPermissionDenied(client, "Permission denied");
300                         break;
301                 }
302                 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
303                         msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
304                         msg->payload.userState->has_texture) {
305                         
306                         sendPermissionDenied(client, "Not supported by uMurmur");
307                         break;
308                 }
309                 if (msg->payload.userState->has_self_deaf) {
310                         client->deaf = msg->payload.userState->self_deaf;
311                 }
312                 if (msg->payload.userState->has_self_mute) {
313                         client->mute = msg->payload.userState->self_mute;                       
314                 }
315                 if (msg->payload.userState->has_channel_id) {
316                         Chan_playerJoin_id(msg->payload.userState->channel_id, client);
317                 }
318                 /* Re-use message */
319                 Msg_inc_ref(msg);
320                 msg->payload.userState->has_actor = true;
321                 msg->payload.userState->actor = client->sessionId;
322                 Client_send_message_except(NULL, msg);
323                 break;
324                 
325         case TextMessage:
326                 msg->payload.textMessage->has_actor = true;
327                 msg->payload.textMessage->actor = client->sessionId;
328
329                 /* XXX - Allow HTML stuff? */
330                 
331                 if (msg->payload.textMessage->n_tree_id > 0) {
332                         sendPermissionDenied(client, "Tree message not supported");
333                         break;
334                 }
335                         
336                 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
337                         int i;
338                         channel_t *ch_itr;
339                         for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
340                                 ch_itr = NULL;
341                                 do {
342                                         Chan_iterate(&ch_itr);
343                                 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
344                                 if (ch_itr == NULL)
345                                         Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage->channel_id[i]);
346                                 else {
347                                         struct dlist *itr;
348                                         list_iterate(itr, &ch_itr->clients) {
349                                                 client_t *c;
350                                                 c = list_get_entry(itr, client_t, chan_node);
351                                                 if (c != client && !c->deaf) {
352                                                         Msg_inc_ref(msg);
353                                                         Client_send_message(c, msg);
354                                                         Log_debug("Text message to session ID %d", c->sessionId);
355                                                 }
356                                         }
357                                 }
358                         } /* for */
359                 }
360                 if (msg->payload.textMessage->n_session > 0) { /* To user */
361                         int i;
362                         client_t *itr;
363                         for (i = 0; i < msg->payload.textMessage->n_session; i++) {
364                                 itr = NULL;
365                                 while (Client_iterate(&itr) != NULL) {
366                                         if (!IS_AUTH(itr))
367                                                 continue;
368                                         if (itr->sessionId == msg->payload.textMessage->session[i]) {
369                                                 if (!itr->deaf) {
370                                                         Msg_inc_ref(msg);
371                                                         Client_send_message(itr, msg);
372                                                         Log_debug("Text message to session ID %d", itr->sessionId);
373                                                 }
374                                                 break;
375                                         }
376                                 }
377                                 if (itr == NULL)
378                                         Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
379                         } /* for */
380                 }
381                 break;
382
383         case VoiceTarget:
384         {
385                 int i, j, count, targetId = msg->payload.voiceTarget->id;
386                 struct _MumbleProto__VoiceTarget__Target *target;
387
388                 if (!targetId || targetId >= 0x1f)
389                         break;
390                 Voicetarget_add_id(client, targetId);
391                 count = msg->payload.voiceTarget->n_targets;
392                 if (!count)
393                         break;
394                 for (i = 0; i < count; i++) {
395                         target = msg->payload.voiceTarget->targets[i];
396                         for (j = 0; j < target->n_session; j++)
397                                 Voicetarget_add_session(client, targetId, target->session[j]);
398                         if (target->has_channel_id) {
399                                 if (target->has_links || target->has_children)
400                                         Log_warn("Whisper to children or linked channels not implemented. Ignoring.");
401                                 Voicetarget_add_channel(client, targetId, target->channel_id);
402                         }
403                 }
404                 break;
405         }
406         case Version:
407                 Log_debug("Version message received");
408                 if (msg->payload.version->has_version) {
409                         client->version = msg->payload.version->version;
410                         Log_debug("Client version 0x%x", client->version);
411                 }
412                 if (msg->payload.version->release) {
413                         if (client->release) free(client->release);
414                         client->release = strdup(msg->payload.version->release);
415                         Log_debug("Client release %s", client->release);
416                 }
417                 if (msg->payload.version->os) {
418                         if (client->os) free(client->os);                       
419                         client->os = strdup(msg->payload.version->os);
420                         Log_debug("Client OS %s", client->os);
421                 }
422                 break;
423         case PermissionQuery:
424                 Msg_inc_ref(msg); /* Re-use message */
425                 msg->payload.permissionQuery->has_permissions = true;
426                 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
427                 
428                 Client_send_message(client, msg);
429                 break;
430         case UDPTunnel:
431                 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
432             break;
433                 /* Permission denied for all these messages. Not implemented. */
434         case ChannelRemove:
435         case ChannelState:
436         case ContextAction:
437         case ContextActionAdd:
438         case ACL:
439         case BanList:
440         case UserList:
441         case QueryUsers:
442                 sendPermissionDenied(client, "Not supported by uMurmur");
443                 break;
444                                 
445         default:
446                 Log_warn("Message %d not handled", msg->messageType);
447                 break;
448         }
449         Msg_free(msg);
450         return;
451 disconnect:
452         Msg_free(msg);
453         Client_close(client);
454 }
455