updates.
[silc.git] / lib / silcclient / client.c
1 /*
2
3   client.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "clientlibincludes.h"
23
24 /* Static task callback prototypes */
25 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
28 SILC_TASK_CALLBACK(silc_client_packet_process);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
30
31 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
32 static void silc_client_packet_parse_type(SilcClient client, 
33                                           SilcSocketConnection sock,
34                                           SilcPacketContext *packet);
35
36 /* Allocates new client object. This has to be done before client may
37    work. After calling this one must call silc_client_init to initialize
38    the client. The `application' is application specific user data pointer
39    and caller must free it. */
40
41 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
42 {
43   SilcClient new_client;
44
45   new_client = silc_calloc(1, sizeof(*new_client));
46   new_client->application = application;
47   new_client->ops = ops;
48
49   return new_client;
50 }
51
52 /* Frees client object and its internals. */
53
54 void silc_client_free(SilcClient client)
55 {
56   if (client) {
57     if (client->rng)
58       silc_rng_free(client->rng);
59
60     silc_free(client);
61   }
62 }
63
64 /* Initializes the client. This makes all the necessary steps to make
65    the client ready to be run. One must call silc_client_run to run the
66    client. Returns FALSE if error occured, TRUE otherwise. */
67
68 int silc_client_init(SilcClient client)
69 {
70   SILC_LOG_DEBUG(("Initializing client"));
71
72   /* Initialize hash functions for client to use */
73   silc_hash_alloc("md5", &client->md5hash);
74   silc_hash_alloc("sha1", &client->sha1hash);
75
76   /* Initialize none cipher */
77   silc_cipher_alloc("none", &client->none_cipher);
78
79   /* Initialize random number generator */
80   client->rng = silc_rng_alloc();
81   silc_rng_init(client->rng);
82   silc_rng_global_init(client->rng);
83
84   /* Register protocols */
85   silc_client_protocols_register();
86
87   /* Initialize the scheduler */
88   silc_schedule_init(&client->io_queue, &client->timeout_queue, 
89                      &client->generic_queue, 5000);
90
91   return TRUE;
92 }
93
94 /* Stops the client. This is called to stop the client and thus to stop
95    the program. */
96
97 void silc_client_stop(SilcClient client)
98 {
99   SILC_LOG_DEBUG(("Stopping client"));
100
101   /* Stop the scheduler, although it might be already stopped. This
102      doesn't hurt anyone. This removes all the tasks and task queues,
103      as well. */
104   silc_schedule_stop();
105   silc_schedule_uninit();
106
107   silc_client_protocols_unregister();
108
109   SILC_LOG_DEBUG(("Client stopped"));
110 }
111
112 /* Runs the client. This starts the scheduler from the utility library.
113    When this functions returns the execution of the appliation is over. */
114
115 void silc_client_run(SilcClient client)
116 {
117   SILC_LOG_DEBUG(("Running client"));
118
119   /* Start the scheduler, the heart of the SILC client. When this returns
120      the program will be terminated. */
121   silc_schedule();
122 }
123
124 /* Allocates and adds new connection to the client. This adds the allocated
125    connection to the connection table and returns a pointer to it. A client
126    can have multiple connections to multiple servers. Every connection must
127    be added to the client using this function. User data `context' may
128    be sent as argument. This function is normally used only if the 
129    application performed the connecting outside the library. The library
130    however may use this internally. */
131
132 SilcClientConnection silc_client_add_connection(SilcClient client,
133                                                 char *hostname,
134                                                 int port,
135                                                 void *context)
136 {
137   SilcClientConnection conn;
138   int i;
139
140   conn = silc_calloc(1, sizeof(*conn));
141
142   /* Initialize ID caches */
143   conn->client_cache = silc_idcache_alloc(0);
144   conn->channel_cache = silc_idcache_alloc(0);
145   conn->server_cache = silc_idcache_alloc(0);
146   conn->client = client;
147   conn->remote_host = strdup(hostname);
148   conn->remote_port = port;
149   conn->context = context;
150   conn->pending_commands = silc_dlist_init();
151
152   /* Add the connection to connections table */
153   for (i = 0; i < client->conns_count; i++)
154     if (client->conns && !client->conns[i]) {
155       client->conns[i] = conn;
156       return conn;
157     }
158
159   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
160                                * (client->conns_count + 1));
161   client->conns[client->conns_count] = conn;
162   client->conns_count++;
163
164   return conn;
165 }
166
167 /* Removes connection from client. Frees all memory. */
168
169 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
170 {
171   int i;
172
173   for (i = 0; i < client->conns_count; i++)
174     if (client->conns[i] == conn) {
175       if (conn->pending_commands)
176         silc_dlist_uninit(conn->pending_commands);
177       silc_free(conn);
178       client->conns[i] = NULL;
179     }
180 }
181
182 /* Internal context for connection process. This is needed as we
183    doing asynchronous connecting. */
184 typedef struct {
185   SilcClient client;
186   SilcClientConnection conn;
187   SilcTask task;
188   int sock;
189   char *host;
190   int port;
191   int tries;
192 } SilcClientInternalConnectContext;
193
194 static int 
195 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
196 {
197   int sock;
198
199   /* XXX In the future we should give up this non-blocking connect all
200      together and use threads instead. */
201   /* Create connection to server asynchronously */
202   sock = silc_net_create_connection_async(ctx->port, ctx->host);
203   if (sock < 0)
204     return -1;
205
206   /* Register task that will receive the async connect and will
207      read the result. */
208   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
209                                  silc_client_connect_to_server_start,
210                                  (void *)ctx, 0, 0, 
211                                  SILC_TASK_FD,
212                                  SILC_TASK_PRI_NORMAL);
213   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
214   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
215
216   ctx->sock = sock;
217
218   return sock;
219 }
220
221 /* Connects to remote server. This is the main routine used to connect
222    to SILC server. Returns -1 on error and the created socket otherwise. 
223    The `context' is user context that is saved into the SilcClientConnection
224    that is created after the connection is created. Note that application
225    may handle the connecting process outside the library. If this is the
226    case then this function is not used at all. When the connecting is
227    done the `connect' client operation is called. */
228
229 int silc_client_connect_to_server(SilcClient client, int port,
230                                   char *host, void *context)
231 {
232   SilcClientInternalConnectContext *ctx;
233   SilcClientConnection conn;
234   int sock;
235
236   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
237                   port, host));
238
239   conn = silc_client_add_connection(client, host, port, context);
240
241   client->ops->say(client, conn, 
242                    "Connecting to port %d of server %s", port, host);
243
244   /* Allocate internal context for connection process. This is
245      needed as we are doing async connecting. */
246   ctx = silc_calloc(1, sizeof(*ctx));
247   ctx->client = client;
248   ctx->conn = conn;
249   ctx->host = strdup(host);
250   ctx->port = port;
251   ctx->tries = 0;
252
253   /* Do the actual connecting process */
254   sock = silc_client_connect_to_server_internal(ctx);
255   if (sock == -1)
256     silc_client_del_connection(client, conn);
257   return sock;
258 }
259
260 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
261    key material between client and server.  This function can be called
262    directly if application is performing its own connecting and does not
263    use the connecting provided by this library. This function is normally
264    used only if the application performed the connecting outside the library.
265    The library however may use this internally. */
266
267 int silc_client_start_key_exchange(SilcClient client,
268                                    SilcClientConnection conn,
269                                    int fd)
270 {
271   SilcProtocol protocol;
272   SilcClientKEInternalContext *proto_ctx;
273   void *context;
274
275   /* Allocate new socket connection object */
276   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
277   if (conn->sock == NULL) {
278     client->ops->say(client, conn, 
279                      "Error: Could not allocate connection socket");
280     return FALSE;
281   }
282
283   conn->nickname = strdup(client->username);
284   conn->sock->hostname = conn->remote_host;
285   conn->sock->ip = strdup(conn->remote_host);
286   conn->sock->port = conn->remote_port;
287
288   /* Allocate internal Key Exchange context. This is sent to the
289      protocol as context. */
290   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
291   proto_ctx->client = (void *)client;
292   proto_ctx->sock = conn->sock;
293   proto_ctx->rng = client->rng;
294   proto_ctx->responder = FALSE;
295
296   /* Perform key exchange protocol. silc_client_connect_to_server_final
297      will be called after the protocol is finished. */
298   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
299                       &protocol, (void *)proto_ctx,
300                       silc_client_connect_to_server_second);
301   if (!protocol) {
302     client->ops->say(client, conn, 
303                      "Error: Could not start authentication protocol");
304     return FALSE;
305   }
306   conn->sock->protocol = protocol;
307
308   /* Register the connection for network input and output. This sets
309      that scheduler will listen for incoming packets for this connection 
310      and sets that outgoing packets may be sent to this connection as well.
311      However, this doesn't set the scheduler for outgoing traffic, it will 
312      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
313      later when outgoing data is available. */
314   context = (void *)client;
315   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
316
317   /* Execute the protocol */
318   protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
319   return TRUE;
320 }
321
322 /* Start of the connection to the remote server. This is called after
323    succesful TCP/IP connection has been established to the remote host. */
324
325 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
326 {
327   SilcClientInternalConnectContext *ctx =
328     (SilcClientInternalConnectContext *)context;
329   SilcClient client = ctx->client;
330   SilcClientConnection conn = ctx->conn;
331   int opt, opt_len = sizeof(opt);
332
333   SILC_LOG_DEBUG(("Start"));
334
335   /* Check the socket status as it might be in error */
336   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
337   if (opt != 0) {
338     if (ctx->tries < 2) {
339       /* Connection failed but lets try again */
340       client->ops->say(client, conn, "Could not connect to server %s: %s",
341                        ctx->host, strerror(opt));
342       client->ops->say(client, conn, 
343                        "Connecting to port %d of server %s resumed", 
344                        ctx->port, ctx->host);
345
346       /* Unregister old connection try */
347       silc_schedule_unset_listen_fd(fd);
348       silc_net_close_connection(fd);
349       silc_task_unregister(client->io_queue, ctx->task);
350
351       /* Try again */
352       silc_client_connect_to_server_internal(ctx);
353       ctx->tries++;
354     } else {
355       /* Connection failed and we won't try anymore */
356       client->ops->say(client, conn, "Could not connect to server %s: %s",
357                        ctx->host, strerror(opt));
358       silc_schedule_unset_listen_fd(fd);
359       silc_net_close_connection(fd);
360       silc_task_unregister(client->io_queue, ctx->task);
361       silc_free(ctx);
362
363       /* Notify application of failure */
364       client->ops->connect(client, conn, FALSE);
365       silc_client_del_connection(client, conn);
366     }
367     return;
368   }
369
370   silc_schedule_unset_listen_fd(fd);
371   silc_task_unregister(client->io_queue, ctx->task);
372   silc_free(ctx);
373
374   if (!silc_client_start_key_exchange(client, conn, fd)) {
375     silc_net_close_connection(fd);
376     client->ops->connect(client, conn, FALSE);
377   }
378 }
379
380 /* Second part of the connecting to the server. This executed 
381    authentication protocol. */
382
383 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
384 {
385   SilcProtocol protocol = (SilcProtocol)context;
386   SilcClientKEInternalContext *ctx = 
387     (SilcClientKEInternalContext *)protocol->context;
388   SilcClient client = (SilcClient)ctx->client;
389   SilcSocketConnection sock = NULL;
390   SilcClientConnAuthInternalContext *proto_ctx;
391
392   SILC_LOG_DEBUG(("Start"));
393
394   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
395       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
396     /* Error occured during protocol */
397     SILC_LOG_DEBUG(("Error during KE protocol"));
398     silc_protocol_free(protocol);
399     if (ctx->ske)
400       silc_ske_free(ctx->ske);
401     if (ctx->dest_id)
402       silc_free(ctx->dest_id);
403     ctx->sock->protocol = NULL;
404
405     /* Notify application of failure */
406     client->ops->connect(client, ctx->sock->user_data, FALSE);
407     silc_free(ctx);
408     return;
409   }
410
411   /* Allocate internal context for the authentication protocol. This
412      is sent as context for the protocol. */
413   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
414   proto_ctx->client = (void *)client;
415   proto_ctx->sock = sock = ctx->sock;
416   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
417   proto_ctx->dest_id_type = ctx->dest_id_type;
418   proto_ctx->dest_id = ctx->dest_id;
419
420   /* Resolve the authentication method to be used in this connection */
421   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
422                                     sock->port, &proto_ctx->auth_meth,
423                                     &proto_ctx->auth_data, 
424                                     &proto_ctx->auth_data_len))
425     {
426       /* XXX do AUTH_REQUEST resolcing with server */
427       proto_ctx->auth_meth = SILC_AUTH_NONE;
428     }
429
430   /* Free old protocol as it is finished now */
431   silc_protocol_free(protocol);
432   if (ctx->packet)
433     silc_packet_context_free(ctx->packet);
434   silc_free(ctx);
435   /* silc_free(ctx->keymat....); */
436   sock->protocol = NULL;
437
438   /* Allocate the authentication protocol. This is allocated here
439      but we won't start it yet. We will be receiving party of this
440      protocol thus we will wait that connecting party will make
441      their first move. */
442   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
443                       &sock->protocol, (void *)proto_ctx, 
444                       silc_client_connect_to_server_final);
445
446   /* Execute the protocol */
447   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
448 }
449
450 /* Finalizes the connection to the remote SILC server. This is called
451    after authentication protocol has been completed. This send our
452    user information to the server to receive our client ID from
453    server. */
454
455 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
456 {
457   SilcProtocol protocol = (SilcProtocol)context;
458   SilcClientConnAuthInternalContext *ctx = 
459     (SilcClientConnAuthInternalContext *)protocol->context;
460   SilcClient client = (SilcClient)ctx->client;
461   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
462   SilcBuffer packet;
463
464   SILC_LOG_DEBUG(("Start"));
465
466   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
467       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
468     /* Error occured during protocol */
469     SILC_LOG_DEBUG(("Error during authentication protocol"));
470     silc_protocol_free(protocol);
471     if (ctx->auth_data)
472       silc_free(ctx->auth_data);
473     if (ctx->ske)
474       silc_ske_free(ctx->ske);
475     if (ctx->dest_id)
476       silc_free(ctx->dest_id);
477     conn->sock->protocol = NULL;
478
479     /* Notify application of failure */
480     client->ops->connect(client, ctx->sock->user_data, FALSE);
481     silc_free(ctx);
482     return;
483   }
484
485   /* Send NEW_CLIENT packet to the server. We will become registered
486      to the SILC network after sending this packet and we will receive
487      client ID from the server. */
488   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
489                              strlen(client->realname));
490   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
491   silc_buffer_format(packet,
492                      SILC_STR_UI_SHORT(strlen(client->username)),
493                      SILC_STR_UI_XNSTRING(client->username,
494                                           strlen(client->username)),
495                      SILC_STR_UI_SHORT(strlen(client->realname)),
496                      SILC_STR_UI_XNSTRING(client->realname,
497                                           strlen(client->realname)),
498                      SILC_STR_END);
499
500   /* Send the packet */
501   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
502                           NULL, 0, NULL, NULL, 
503                           packet->data, packet->len, TRUE);
504   silc_buffer_free(packet);
505
506   /* Save remote ID. */
507   conn->remote_id = ctx->dest_id;
508   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
509   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
510
511   silc_protocol_free(protocol);
512   if (ctx->auth_data)
513     silc_free(ctx->auth_data);
514   if (ctx->ske)
515     silc_ske_free(ctx->ske);
516   silc_free(ctx);
517   conn->sock->protocol = NULL;
518 }
519
520 /* Internal routine that sends packet or marks packet to be sent. This
521    is used directly only in special cases. Normal cases should use
522    silc_server_packet_send. Returns < 0 on error. */
523
524 static int silc_client_packet_send_real(SilcClient client,
525                                         SilcSocketConnection sock,
526                                         int force_send)
527 {
528   int ret;
529
530   /* Send the packet */
531   ret = silc_packet_send(sock, force_send);
532   if (ret != -2)
533     return ret;
534
535   /* Mark that there is some outgoing data available for this connection. 
536      This call sets the connection both for input and output (the input
537      is set always and this call keeps the input setting, actually). 
538      Actual data sending is performed by silc_client_packet_process. */
539   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
540
541   /* Mark to socket that data is pending in outgoing buffer. This flag
542      is needed if new data is added to the buffer before the earlier
543      put data is sent to the network. */
544   SILC_SET_OUTBUF_PENDING(sock);
545
546   return 0;
547 }
548
549 /* Packet processing callback. This is used to send and receive packets
550    from network. This is generic task. */
551
552 SILC_TASK_CALLBACK(silc_client_packet_process)
553 {
554   SilcClient client = (SilcClient)context;
555   SilcSocketConnection sock = NULL;
556   SilcClientConnection conn;
557   int ret;
558
559   SILC_LOG_DEBUG(("Processing packet"));
560
561   SILC_CLIENT_GET_SOCK(client, fd, sock);
562   if (sock == NULL)
563     return;
564
565   conn = (SilcClientConnection)sock->user_data;
566
567   /* Packet sending */
568   if (type == SILC_TASK_WRITE) {
569     SILC_LOG_DEBUG(("Writing data to connection"));
570
571     if (sock->outbuf->data - sock->outbuf->head)
572       silc_buffer_push(sock->outbuf, 
573                        sock->outbuf->data - sock->outbuf->head);
574
575     ret = silc_client_packet_send_real(client, sock, TRUE);
576
577     /* If returned -2 could not write to connection now, will do
578        it later. */
579     if (ret == -2)
580       return;
581     
582     /* The packet has been sent and now it is time to set the connection
583        back to only for input. When there is again some outgoing data 
584        available for this connection it will be set for output as well. 
585        This call clears the output setting and sets it only for input. */
586     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
587     SILC_UNSET_OUTBUF_PENDING(sock);
588
589     silc_buffer_clear(sock->outbuf);
590     return;
591   }
592
593   /* Packet receiving */
594   if (type == SILC_TASK_READ) {
595     SILC_LOG_DEBUG(("Reading data from connection"));
596
597     /* Read data from network */
598     ret = silc_packet_receive(sock);
599     if (ret < 0)
600       return;
601     
602     /* EOF */
603     if (ret == 0) {
604       SILC_LOG_DEBUG(("Read EOF"));
605
606       /* If connection is disconnecting already we will finally
607          close the connection */
608       if (SILC_IS_DISCONNECTING(sock)) {
609         client->ops->disconnect(client, conn);
610         silc_client_close_connection(client, conn);
611         return;
612       }
613       
614       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
615       client->ops->disconnect(client, conn);
616       silc_client_close_connection(client, conn);
617       return;
618     }
619
620     /* Process the packet. This will call the parser that will then
621        decrypt and parse the packet. */
622     silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
623                                 silc_client_packet_parse, client);
624   }
625 }
626
627 /* Parses whole packet, received earlier. */
628
629 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
630 {
631   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
632   SilcClient client = (SilcClient)parse_ctx->context;
633   SilcPacketContext *packet = parse_ctx->packet;
634   SilcBuffer buffer = packet->buffer;
635   SilcSocketConnection sock = parse_ctx->sock;
636   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
637   int ret;
638
639   SILC_LOG_DEBUG(("Start"));
640
641   /* Decrypt the received packet */
642   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
643   if (ret < 0)
644     goto out;
645
646   if (ret == 0) {
647     /* Parse the packet. Packet type is returned. */
648     ret = silc_packet_parse(packet);
649   } else {
650     /* Parse the packet header in special way as this is "special"
651        packet type. */
652     ret = silc_packet_parse_special(packet);
653   }
654
655   if (ret == SILC_PACKET_NONE)
656     goto out;
657
658   /* Parse the incoming packet type */
659   silc_client_packet_parse_type(client, sock, packet);
660
661  out:
662   silc_buffer_clear(sock->inbuf);
663   silc_packet_context_free(packet);
664   silc_free(parse_ctx);
665 }
666
667 /* Parser callback called by silc_packet_receive_process. Thie merely
668    registers timeout that will handle the actual parsing when appropriate. */
669
670 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
671 {
672   SilcClient client = (SilcClient)parser_context->context;
673
674   /* Parse the packet */
675   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
676                      silc_client_packet_parse_real,
677                      (void *)parser_context, 0, 1, 
678                      SILC_TASK_TIMEOUT,
679                      SILC_TASK_PRI_NORMAL);
680 }
681   
682 /* Parses the packet type and calls what ever routines the packet type
683    requires. This is done for all incoming packets. */
684
685 void silc_client_packet_parse_type(SilcClient client, 
686                                    SilcSocketConnection sock,
687                                    SilcPacketContext *packet)
688 {
689   SilcBuffer buffer = packet->buffer;
690   SilcPacketType type = packet->type;
691
692   SILC_LOG_DEBUG(("Parsing packet type %d", type));
693
694   /* Parse the packet type */
695   switch(type) {
696   case SILC_PACKET_DISCONNECT:
697     silc_client_disconnected_by_server(client, sock, buffer);
698     break;
699   case SILC_PACKET_SUCCESS:
700     /*
701      * Success received for something. For now we can have only
702      * one protocol for connection executing at once hence this
703      * success message is for whatever protocol is executing currently.
704      */
705     if (sock->protocol) {
706       sock->protocol->execute(client->timeout_queue, 0,
707                               sock->protocol, sock->sock, 0, 0);
708     }
709     break;
710   case SILC_PACKET_FAILURE:
711     /*
712      * Failure received for some protocol. Set the protocol state to 
713      * error and call the protocol callback. This fill cause error on
714      * protocol and it will call the final callback.
715      */
716     if (sock->protocol) {
717       sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
718       sock->protocol->execute(client->timeout_queue, 0,
719                               sock->protocol, sock->sock, 0, 0);
720
721       /* XXX We have only two protocols currently thus we know what this
722          failure indication is. */
723       if (buffer->len >= 4) {
724         unsigned int failure;
725
726         SILC_GET32_MSB(failure, buffer->data);
727
728         /* Notify application */
729         client->ops->failure(client, sock->user_data, sock->protocol,
730                              (void *)failure);
731       }
732     }
733     break;
734   case SILC_PACKET_REJECT:
735     break;
736
737   case SILC_PACKET_NOTIFY:
738     /*
739      * Received notify message 
740      */
741     silc_client_notify_by_server(client, sock, packet);
742     break;
743
744   case SILC_PACKET_ERROR:
745     /*
746      * Received error message
747      */
748     silc_client_error_by_server(client, sock, buffer);
749     break;
750
751   case SILC_PACKET_CHANNEL_MESSAGE:
752     /*
753      * Received message to (from, actually) a channel
754      */
755     silc_client_channel_message(client, sock, packet);
756     break;
757   case SILC_PACKET_CHANNEL_KEY:
758     /*
759      * Received key for a channel. By receiving this key the client will be
760      * able to talk to the channel it has just joined. This can also be
761      * a new key for existing channel as keys expire peridiocally.
762      */
763     silc_client_receive_channel_key(client, sock, buffer);
764     break;
765
766   case SILC_PACKET_PRIVATE_MESSAGE:
767     /*
768      * Received private message
769      */
770     silc_client_private_message(client, sock, packet);
771     break;
772   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
773     /*
774      * Received private message key
775      */
776     break;
777
778   case SILC_PACKET_COMMAND_REPLY:
779     /*
780      * Recived reply for a command
781      */
782     silc_client_command_reply_process(client, sock, packet);
783     break;
784
785   case SILC_PACKET_KEY_EXCHANGE:
786     if (sock->protocol) {
787       SilcClientKEInternalContext *proto_ctx = 
788         (SilcClientKEInternalContext *)sock->protocol->context;
789
790       proto_ctx->packet = silc_packet_context_dup(packet);
791       proto_ctx->dest_id_type = packet->src_id_type;
792       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
793                                           packet->src_id_type);
794       if (!proto_ctx->dest_id)
795         break;
796
797       /* Let the protocol handle the packet */
798       sock->protocol->execute(client->timeout_queue, 0,
799                               sock->protocol, sock->sock, 0, 0);
800     } else {
801       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
802                       "protocol active, packet dropped."));
803
804       /* XXX Trigger KE protocol?? Rekey actually! */
805     }
806     break;
807
808   case SILC_PACKET_KEY_EXCHANGE_1:
809     if (sock->protocol) {
810
811     } else {
812       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
813                       "protocol active, packet dropped."));
814     }
815     break;
816   case SILC_PACKET_KEY_EXCHANGE_2:
817     if (sock->protocol) {
818       SilcClientKEInternalContext *proto_ctx = 
819         (SilcClientKEInternalContext *)sock->protocol->context;
820
821       if (proto_ctx->packet)
822         silc_packet_context_free(proto_ctx->packet);
823
824       proto_ctx->packet = silc_packet_context_dup(packet);
825       proto_ctx->dest_id_type = packet->src_id_type;
826       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
827                                           packet->src_id_type);
828       if (!proto_ctx->dest_id)
829         break;
830
831       /* Let the protocol handle the packet */
832       sock->protocol->execute(client->timeout_queue, 0,
833                               sock->protocol, sock->sock, 0, 0);
834     } else {
835       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
836                       "protocol active, packet dropped."));
837     }
838     break;
839
840   case SILC_PACKET_NEW_ID:
841     {
842       /*
843        * Received new ID from server. This packet is received at
844        * the connection to the server.  New ID is also received when 
845        * user changes nickname but in that case the new ID is received
846        * as command reply and not as this packet type.
847        */
848       SilcIDPayload idp;
849
850       idp = silc_id_payload_parse(buffer);
851       if (!idp)
852         break;
853       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
854         break;
855
856       silc_client_receive_new_id(client, sock, idp);
857       silc_id_payload_free(idp);
858       break;
859     }
860
861   case SILC_PACKET_HEARTBEAT:
862     /*
863      * Received heartbeat packet
864      */
865     SILC_LOG_DEBUG(("Heartbeat packet"));
866     break;
867
868   default:
869     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
870     break;
871   }
872 }
873
874 /* Sends packet. This doesn't actually send the packet instead it assembles
875    it and marks it to be sent. However, if force_send is TRUE the packet
876    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
877    will be derived from sock argument. Otherwise the valid arguments sent
878    are used. */
879
880 void silc_client_packet_send(SilcClient client, 
881                              SilcSocketConnection sock,
882                              SilcPacketType type, 
883                              void *dst_id,
884                              SilcIdType dst_id_type,
885                              SilcCipher cipher,
886                              SilcHmac hmac,
887                              unsigned char *data, 
888                              unsigned int data_len, 
889                              int force_send)
890 {
891   SilcPacketContext packetdata;
892
893   SILC_LOG_DEBUG(("Sending packet, type %d", type));
894
895   /* Get data used in the packet sending, keys and stuff */
896   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
897     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
898       cipher = ((SilcClientConnection)sock->user_data)->send_key;
899
900     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
901       hmac = ((SilcClientConnection)sock->user_data)->hmac;
902
903     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
904       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
905       dst_id_type = SILC_ID_SERVER;
906     }
907   }
908
909   /* Set the packet context pointers */
910   packetdata.flags = 0;
911   packetdata.type = type;
912   if (((SilcClientConnection)sock->user_data)->local_id_data)
913     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
914   else 
915     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
916   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
917   packetdata.src_id_type = SILC_ID_CLIENT;
918   if (dst_id) {
919     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
920     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
921     packetdata.dst_id_type = dst_id_type;
922   } else {
923     packetdata.dst_id = NULL;
924     packetdata.dst_id_len = 0;
925     packetdata.dst_id_type = SILC_ID_NONE;
926   }
927   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
928     packetdata.src_id_len + packetdata.dst_id_len;
929   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
930
931   /* Prepare outgoing data buffer for packet sending */
932   silc_packet_send_prepare(sock, 
933                            SILC_PACKET_HEADER_LEN +
934                            packetdata.src_id_len + 
935                            packetdata.dst_id_len,
936                            packetdata.padlen,
937                            data_len);
938
939   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
940
941   packetdata.buffer = sock->outbuf;
942
943   /* Put the data to the buffer */
944   if (data && data_len)
945     silc_buffer_put(sock->outbuf, data, data_len);
946
947   /* Create the outgoing packet */
948   silc_packet_assemble(&packetdata);
949
950   /* Encrypt the packet */
951   if (cipher)
952     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
953
954   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
955                    sock->outbuf->data, sock->outbuf->len);
956
957   /* Now actually send the packet */
958   silc_client_packet_send_real(client, sock, force_send);
959 }
960
961 /* Sends packet to the `channel'. Packet to channel is always encrypted
962    differently from "normal" packets. SILC header of the packet is 
963    encrypted with the next receiver's key and the rest of the packet is
964    encrypted with the channel specific key. Padding and HMAC is computed
965    with the next receiver's key. The `data' is the channel message. If
966    the `force_send' is TRUE then the packet is sent immediately. */
967
968 void silc_client_send_channel_message(SilcClient client, 
969                                       SilcClientConnection conn,
970                                       SilcChannelEntry channel,
971                                       unsigned char *data, 
972                                       unsigned int data_len, 
973                                       int force_send)
974 {
975   int i;
976   SilcSocketConnection sock = conn->sock;
977   SilcBuffer payload;
978   SilcPacketContext packetdata;
979   SilcCipher cipher;
980   SilcHmac hmac;
981   unsigned char *id_string;
982   unsigned int block_len;
983
984   SILC_LOG_DEBUG(("Sending packet to channel"));
985
986   if (!channel || !channel->key) {
987     client->ops->say(client, conn, 
988                      "Cannot talk to channel: key does not exist");
989     return;
990   }
991
992   /* Generate IV */
993   block_len = silc_cipher_get_block_len(channel->channel_key);
994   if (channel->iv[0] == '\0')
995     for (i = 0; i < block_len; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
996   else
997     silc_hash_make(client->md5hash, channel->iv, block_len, channel->iv);
998
999   /* Encode the channel payload */
1000   payload = silc_channel_payload_encode(data_len, data, block_len, 
1001                                         channel->iv, client->rng);
1002   if (!payload) {
1003     client->ops->say(client, conn, 
1004                      "Error: Could not create packet to be sent to channel");
1005     return;
1006   }
1007
1008   /* Get data used in packet header encryption, keys and stuff. Rest
1009      of the packet (the payload) is, however, encrypted with the 
1010      specified channel key. */
1011   cipher = conn->send_key;
1012   hmac = conn->hmac;
1013   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1014
1015   /* Set the packet context pointers. The destination ID is always
1016      the Channel ID of the channel. Server and router will handle the
1017      distribution of the packet. */
1018   packetdata.flags = 0;
1019   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1020   packetdata.src_id = conn->local_id_data;
1021   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1022   packetdata.src_id_type = SILC_ID_CLIENT;
1023   packetdata.dst_id = id_string;
1024   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1025   packetdata.dst_id_type = SILC_ID_CHANNEL;
1026   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
1027     packetdata.src_id_len + packetdata.dst_id_len;
1028   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1029                                           packetdata.src_id_len +
1030                                           packetdata.dst_id_len));
1031
1032   /* Prepare outgoing data buffer for packet sending */
1033   silc_packet_send_prepare(sock, 
1034                            SILC_PACKET_HEADER_LEN +
1035                            packetdata.src_id_len + 
1036                            packetdata.dst_id_len,
1037                            packetdata.padlen,
1038                            payload->len);
1039
1040   packetdata.buffer = sock->outbuf;
1041
1042   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1043   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1044                                         payload->data, payload->data,
1045                                         payload->len - block_len, /* -IV_LEN */
1046                                         channel->iv);
1047
1048   /* Put the actual encrypted payload data into the buffer. */
1049   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1050
1051   /* Create the outgoing packet */
1052   silc_packet_assemble(&packetdata);
1053
1054   /* Encrypt the header and padding of the packet. This is encrypted 
1055      with normal session key shared with our server. */
1056   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1057                       packetdata.src_id_len + packetdata.dst_id_len +
1058                       packetdata.padlen);
1059
1060   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1061                    sock->outbuf->data, sock->outbuf->len);
1062
1063   /* Now actually send the packet */
1064   silc_client_packet_send_real(client, sock, force_send);
1065   silc_buffer_free(payload);
1066   silc_free(id_string);
1067 }
1068
1069 /* Sends private message to remote client. If private message key has
1070    not been set with this client then the message will be encrypted using
1071    normal session keys. Private messages are special packets in SILC
1072    network hence we need this own function for them. This is similiar
1073    to silc_client_packet_send_to_channel except that we send private
1074    message. The `data' is the private message. If the `force_send' is
1075    TRUE the packet is sent immediately. */
1076
1077 void silc_client_send_private_message(SilcClient client,
1078                                       SilcClientConnection conn,
1079                                       SilcClientEntry client_entry,
1080                                       unsigned char *data, 
1081                                       unsigned int data_len, 
1082                                       int force_send)
1083 {
1084   SilcSocketConnection sock = conn->sock;
1085   SilcBuffer buffer;
1086   SilcPacketContext packetdata;
1087   unsigned int nick_len;
1088   SilcCipher cipher;
1089   SilcHmac hmac;
1090
1091   SILC_LOG_DEBUG(("Sending private message"));
1092
1093   /* Create private message payload */
1094   nick_len = strlen(conn->nickname);
1095   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1096   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1097   silc_buffer_format(buffer,
1098                      SILC_STR_UI_SHORT(nick_len),
1099                      SILC_STR_UI_XNSTRING(conn->nickname,
1100                                           nick_len),
1101                      SILC_STR_UI_XNSTRING(data, data_len),
1102                      SILC_STR_END);
1103
1104   /* If we don't have private message specific key then private messages
1105      are just as any normal packet thus call normal packet sending.  If
1106      the key exist then the encryption process is a bit different and
1107      will be done in the rest of this function. */
1108   if (!client_entry->send_key) {
1109     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1110                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1111                             buffer->data, buffer->len, force_send);
1112     goto out;
1113   }
1114
1115   /* We have private message specific key */
1116
1117   /* Get data used in the encryption */
1118   cipher = client_entry->send_key;
1119   hmac = conn->hmac;
1120
1121   /* Set the packet context pointers. */
1122   packetdata.flags = 0;
1123   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1124   packetdata.src_id = conn->local_id_data;
1125   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1126   packetdata.src_id_type = SILC_ID_CLIENT;
1127   if (client_entry)
1128     packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1129   else
1130     packetdata.dst_id = conn->local_id_data;
1131   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1132   packetdata.dst_id_type = SILC_ID_CLIENT;
1133   packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1134     packetdata.src_id_len + packetdata.dst_id_len;
1135   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1136                                           packetdata.src_id_len +
1137                                           packetdata.dst_id_len));
1138
1139   /* Prepare outgoing data buffer for packet sending */
1140   silc_packet_send_prepare(sock, 
1141                            SILC_PACKET_HEADER_LEN +
1142                            packetdata.src_id_len + 
1143                            packetdata.dst_id_len,
1144                            packetdata.padlen,
1145                            buffer->len);
1146   
1147   packetdata.buffer = sock->outbuf;
1148
1149   /* Encrypt payload of the packet. Encrypt with private message specific
1150      key if it exist, otherwise with session key. */
1151   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1152                           buffer->len, cipher->iv);
1153       
1154   /* Put the actual encrypted payload data into the buffer. */
1155   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1156
1157   /* Create the outgoing packet */
1158   silc_packet_assemble(&packetdata);
1159
1160   /* Encrypt the header and padding of the packet. */
1161   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1162                       packetdata.src_id_len + packetdata.dst_id_len +
1163                       packetdata.padlen);
1164
1165   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1166                    sock->outbuf->data, sock->outbuf->len);
1167
1168   /* Now actually send the packet */
1169   silc_client_packet_send_real(client, sock, force_send);
1170   silc_free(packetdata.dst_id);
1171
1172  out:
1173   silc_free(buffer);
1174 }     
1175
1176 /* Closes connection to remote end. Free's all allocated data except
1177    for some information such as nickname etc. that are valid at all time. */
1178
1179 void silc_client_close_connection(SilcClient client,
1180                                   SilcClientConnection conn)
1181 {
1182   SilcSocketConnection sock = conn->sock;
1183
1184   /* We won't listen for this connection anymore */
1185   silc_schedule_unset_listen_fd(sock->sock);
1186
1187   /* Unregister all tasks */
1188   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1189   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1190
1191   /* Close the actual connection */
1192   silc_net_close_connection(sock->sock);
1193
1194   client->ops->say(client, sock->user_data,
1195                    "Closed connection to host %s", sock->hostname);
1196
1197   /* Free everything */
1198   if (sock->user_data) {
1199     /* XXX Free all client entries and channel entries. */
1200
1201     /* Clear ID caches */
1202     silc_idcache_del_all(conn->client_cache);
1203     silc_idcache_del_all(conn->channel_cache);
1204
1205     /* Free data */
1206     if (conn->remote_host)
1207       silc_free(conn->remote_host);
1208     if (conn->local_id)
1209       silc_free(conn->local_id);
1210     if (conn->local_id_data)
1211       silc_free(conn->local_id_data);
1212     if (conn->send_key)
1213       silc_cipher_free(conn->send_key);
1214     if (conn->receive_key)
1215       silc_cipher_free(conn->receive_key);
1216     if (conn->hmac)
1217       silc_hmac_free(conn->hmac);
1218     if (conn->hmac_key) {
1219       memset(conn->hmac_key, 0, conn->hmac_key_len);
1220       silc_free(conn->hmac_key);
1221     }
1222     if (conn->pending_commands)
1223       silc_dlist_uninit(conn->pending_commands);
1224
1225     conn->sock = NULL;
1226     conn->remote_port = 0;
1227     conn->remote_type = 0;
1228     conn->send_key = NULL;
1229     conn->receive_key = NULL;
1230     conn->hmac = NULL;
1231     conn->hmac_key = NULL;
1232     conn->hmac_key_len = 0;
1233     conn->local_id = NULL;
1234     conn->local_id_data = NULL;
1235     conn->remote_host = NULL;
1236     conn->current_channel = NULL;
1237     conn->pending_commands = NULL;
1238
1239     silc_client_del_connection(client, conn);
1240   }
1241
1242   if (sock->protocol) {
1243     silc_protocol_free(sock->protocol);
1244     sock->protocol = NULL;
1245   }
1246   silc_socket_free(sock);
1247 }
1248
1249 /* Called when we receive disconnection packet from server. This 
1250    closes our end properly and displays the reason of the disconnection
1251    on the screen. */
1252
1253 void silc_client_disconnected_by_server(SilcClient client,
1254                                         SilcSocketConnection sock,
1255                                         SilcBuffer message)
1256 {
1257   char *msg;
1258
1259   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1260
1261   msg = silc_calloc(message->len + 1, sizeof(char));
1262   memcpy(msg, message->data, message->len);
1263   client->ops->say(client, sock->user_data, msg);
1264   silc_free(msg);
1265
1266   SILC_SET_DISCONNECTED(sock);
1267   silc_client_close_connection(client, sock->user_data);
1268 }
1269
1270 /* Received error message from server. Display it on the screen. 
1271    We don't take any action what so ever of the error message. */
1272
1273 void silc_client_error_by_server(SilcClient client,
1274                                  SilcSocketConnection sock,
1275                                  SilcBuffer message)
1276 {
1277   char *msg;
1278
1279   msg = silc_calloc(message->len + 1, sizeof(char));
1280   memcpy(msg, message->data, message->len);
1281   client->ops->say(client, sock->user_data, msg);
1282   silc_free(msg);
1283 }
1284
1285 /* Called when notify is received and some async operation (such as command)
1286    is required before processing the notify message. This calls again the
1287    silc_client_notify_by_server and reprocesses the original notify packet. */
1288
1289 static void silc_client_notify_by_server_pending(void *context)
1290 {
1291   SilcPacketContext *p = (SilcPacketContext *)context;
1292   silc_client_notify_by_server(p->context, p->sock, p);
1293 }
1294
1295 /* Destructor for the pending command callback */
1296
1297 static void silc_client_notify_by_server_destructor(void *context)
1298 {
1299   silc_packet_context_free((SilcPacketContext *)context);
1300 }
1301
1302 /* Resolve client information from server by Client ID. */
1303
1304 static void silc_client_notify_by_server_resolve(SilcClient client,
1305                                                  SilcClientConnection conn,
1306                                                  SilcPacketContext *packet,
1307                                                  SilcClientID *client_id)
1308 {
1309   SilcPacketContext *p = silc_packet_context_dup(packet);
1310   SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1311
1312   p->context = (void *)client;
1313   p->sock = conn->sock;
1314
1315   silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1316                            1, 3, idp->data, idp->len);
1317   silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1318                               silc_client_notify_by_server_destructor,
1319                               silc_client_notify_by_server_pending, p);
1320   silc_buffer_free(idp);
1321 }
1322
1323 /* Received notify message from server */
1324
1325 void silc_client_notify_by_server(SilcClient client,
1326                                   SilcSocketConnection sock,
1327                                   SilcPacketContext *packet)
1328 {
1329   SilcBuffer buffer = packet->buffer;
1330   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1331   SilcNotifyPayload payload;
1332   SilcNotifyType type;
1333   SilcArgumentPayload args;
1334
1335   SilcClientID *client_id = NULL;
1336   SilcChannelID *channel_id = NULL;
1337   SilcClientEntry client_entry;
1338   SilcClientEntry client_entry2;
1339   SilcChannelEntry channel;
1340   SilcChannelUser chu;
1341   SilcIDCacheEntry id_cache = NULL;
1342   unsigned char *tmp;
1343   unsigned int tmp_len, mode;
1344
1345   payload = silc_notify_payload_parse(buffer);
1346   if (!payload)
1347     goto out;
1348
1349   type = silc_notify_get_type(payload);
1350   args = silc_notify_get_args(payload);
1351   if (!args)
1352     goto out;
1353
1354   switch(type) {
1355   case SILC_NOTIFY_TYPE_NONE:
1356     /* Notify application */
1357     client->ops->notify(client, conn, type, 
1358                         silc_argument_get_arg_type(args, 1, NULL));
1359     break;
1360
1361   case SILC_NOTIFY_TYPE_INVITE:
1362     /* 
1363      * Someone invited me to a channel. Find Client and Channel entries
1364      * for the application.
1365      */
1366     
1367     /* Get Client ID */
1368     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1369     if (!tmp)
1370       goto out;
1371
1372     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1373     if (!client_id)
1374       goto out;
1375
1376     /* Find Client entry and if not found query it */
1377     client_entry = silc_client_get_client_by_id(client, conn, client_id);
1378     if (!client_entry) {
1379       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1380       goto out;
1381     }
1382
1383     /* Get Channel ID */
1384     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1385     if (!tmp)
1386       goto out;
1387
1388     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1389     if (!channel_id)
1390       goto out;
1391
1392     /* XXX Will ALWAYS fail because currently we don't have way to resolve
1393        channel information for channel that we're not joined to. */
1394     /* XXX ways to fix: use (extended) LIST command, or define the channel
1395        name to the notfy type when name resolving is not mandatory. */
1396     /* Find channel entry */
1397     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1398                                      SILC_ID_CHANNEL, &id_cache))
1399       goto out;
1400
1401     channel = (SilcChannelEntry)id_cache->context;
1402
1403     /* Notify application */
1404     client->ops->notify(client, conn, type, client_entry, channel);
1405     break;
1406
1407   case SILC_NOTIFY_TYPE_JOIN:
1408     /*
1409      * Someone has joined to a channel. Get their ID and nickname and
1410      * cache them for later use.
1411      */
1412
1413     /* Get Client ID */
1414     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1415     if (!tmp)
1416       goto out;
1417
1418     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1419     if (!client_id)
1420       goto out;
1421
1422     /* Find Client entry and if not found query it */
1423     client_entry = silc_client_get_client_by_id(client, conn, client_id);
1424     if (!client_entry) {
1425       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1426       goto out;
1427     }
1428
1429     /* If nickname or username hasn't been resolved, do so */
1430     if (!client_entry->nickname || !client_entry->username) {
1431       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1432       goto out;
1433     }
1434
1435     /* Get Channel ID */
1436     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1437     if (!tmp)
1438       goto out;
1439
1440     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1441     if (!channel_id)
1442       goto out;
1443
1444     /* Get channel entry */
1445     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1446                                      SILC_ID_CHANNEL, &id_cache))
1447       break;
1448
1449     channel = (SilcChannelEntry)id_cache->context;
1450
1451     /* Add client to channel */
1452     chu = silc_calloc(1, sizeof(*chu));
1453     chu->client = client_entry;
1454     silc_list_add(channel->clients, chu);
1455
1456     /* XXX add support for multiple same nicks on same channel. Check
1457        for them here */
1458
1459     /* Notify application. The channel entry is sent last as this notify
1460        is for channel but application don't know it from the arguments
1461        sent by server. */
1462     client->ops->notify(client, conn, type, client_entry, channel);
1463     break;
1464
1465   case SILC_NOTIFY_TYPE_LEAVE:
1466     /*
1467      * Someone has left a channel. We will remove it from the channel but
1468      * we'll keep it in the cache in case we'll need it later.
1469      */
1470     
1471     /* Get Client ID */
1472     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1473     if (!tmp)
1474       goto out;
1475
1476     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1477     if (!client_id)
1478       goto out;
1479
1480     /* Find Client entry */
1481     client_entry = 
1482       silc_client_get_client_by_id(client, conn, client_id);
1483     if (!client_entry)
1484       goto out;
1485
1486     /* Get channel entry */
1487     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1488                                 SILC_ID_CHANNEL);
1489     if (!channel_id)
1490       goto out;
1491     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1492                                      SILC_ID_CHANNEL, &id_cache))
1493       break;
1494
1495     channel = (SilcChannelEntry)id_cache->context;
1496
1497     /* Remove client from channel */
1498     silc_list_start(channel->clients);
1499     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1500       if (chu->client == client_entry) {
1501         silc_list_del(channel->clients, chu);
1502         silc_free(chu);
1503         break;
1504       }
1505     }
1506
1507     /* Notify application. The channel entry is sent last as this notify
1508        is for channel but application don't know it from the arguments
1509        sent by server. */
1510     client->ops->notify(client, conn, type, client_entry, channel);
1511     break;
1512
1513   case SILC_NOTIFY_TYPE_SIGNOFF:
1514     /*
1515      * Someone left SILC. We'll remove it from all channels and from cache.
1516      */
1517
1518     /* Get Client ID */
1519     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1520     if (!tmp)
1521       goto out;
1522
1523     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1524     if (!client_id)
1525       goto out;
1526
1527     /* Find Client entry */
1528     client_entry = 
1529       silc_client_get_client_by_id(client, conn, client_id);
1530     if (!client_entry)
1531       goto out;
1532
1533     /* Remove from all channels */
1534     silc_client_remove_from_channels(client, conn, client_entry);
1535
1536     /* Remove from cache */
1537     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1538                            client_entry->id);
1539
1540     /* Get signoff message */
1541     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1542     if (tmp_len > 128)
1543       tmp = NULL;
1544
1545     /* Notify application */
1546     client->ops->notify(client, conn, type, client_entry, tmp);
1547
1548     /* Free data */
1549     if (client_entry->nickname)
1550       silc_free(client_entry->nickname);
1551     if (client_entry->server)
1552       silc_free(client_entry->server);
1553     if (client_entry->id)
1554       silc_free(client_entry->id);
1555     if (client_entry->send_key)
1556       silc_cipher_free(client_entry->send_key);
1557     if (client_entry->receive_key)
1558       silc_cipher_free(client_entry->receive_key);
1559     break;
1560
1561   case SILC_NOTIFY_TYPE_TOPIC_SET:
1562     /*
1563      * Someone set the topic on a channel.
1564      */
1565
1566     /* Get Client ID */
1567     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1568     if (!tmp)
1569       goto out;
1570
1571     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1572     if (!client_id)
1573       goto out;
1574
1575     /* Find Client entry */
1576     client_entry = 
1577       silc_client_get_client_by_id(client, conn, client_id);
1578     if (!client_entry)
1579       goto out;
1580
1581     /* Get topic */
1582     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1583     if (!tmp)
1584       goto out;
1585
1586     /* Get channel entry */
1587     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1588                                 SILC_ID_CHANNEL);
1589     if (!channel_id)
1590       goto out;
1591     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1592                                      SILC_ID_CHANNEL, &id_cache))
1593       break;
1594
1595     channel = (SilcChannelEntry)id_cache->context;
1596
1597     /* Notify application. The channel entry is sent last as this notify
1598        is for channel but application don't know it from the arguments
1599        sent by server. */
1600     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1601     break;
1602
1603   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1604     /*
1605      * Someone changed their nickname. If we don't have entry for the new
1606      * ID we will query it and return here after it's done. After we've
1607      * returned we fetch the old entry and free it and notify the 
1608      * application.
1609      */
1610
1611     /* Get new Client ID */
1612     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1613     if (!tmp)
1614       goto out;
1615
1616     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1617     if (!client_id)
1618       goto out;
1619
1620     /* Ignore my ID */
1621     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1622       break;
1623
1624     /* Find Client entry and if not found query it */
1625     client_entry2 = 
1626       silc_client_get_client_by_id(client, conn, client_id);
1627     if (!client_entry2) {
1628       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1629       goto out;
1630     }
1631     silc_free(client_id);
1632
1633     /* Get old Client ID */
1634     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1635     if (!tmp)
1636       goto out;
1637
1638     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1639     if (!client_id)
1640       goto out;
1641
1642     /* Find old Client entry */
1643     client_entry = 
1644       silc_client_get_client_by_id(client, conn, client_id);
1645     if (!client_entry)
1646       goto out;
1647
1648     /* Remove the old from cache */
1649     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1650                            client_entry->id);
1651
1652     /* Replace old ID entry with new one on all channels. */
1653     silc_client_replace_from_channels(client, conn, client_entry,
1654                                       client_entry2);
1655
1656     /* Notify application */
1657     client->ops->notify(client, conn, type, client_entry, client_entry2);
1658
1659     /* Free data */
1660     if (client_entry->nickname)
1661       silc_free(client_entry->nickname);
1662     if (client_entry->server)
1663       silc_free(client_entry->server);
1664     if (client_entry->id)
1665       silc_free(client_entry->id);
1666     if (client_entry->send_key)
1667       silc_cipher_free(client_entry->send_key);
1668     if (client_entry->receive_key)
1669       silc_cipher_free(client_entry->receive_key);
1670     break;
1671
1672   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1673     /*
1674      * Someone changed a channel mode
1675      */
1676
1677     /* Get Client ID */
1678     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1679     if (!tmp)
1680       goto out;
1681
1682     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1683     if (!client_id)
1684       goto out;
1685
1686     /* Find Client entry */
1687     client_entry = 
1688       silc_client_get_client_by_id(client, conn, client_id);
1689     if (!client_entry)
1690       goto out;
1691
1692     /* Get the mode */
1693     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1694     if (!tmp)
1695       goto out;
1696
1697     SILC_GET32_MSB(mode, tmp);
1698
1699     /* Get channel entry */
1700     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1701                                 SILC_ID_CHANNEL);
1702     if (!channel_id)
1703       goto out;
1704     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1705                                      SILC_ID_CHANNEL, &id_cache))
1706       break;
1707
1708     channel = (SilcChannelEntry)id_cache->context;
1709
1710     /* Save the new mode */
1711     channel->mode = mode;
1712
1713     /* Notify application. The channel entry is sent last as this notify
1714        is for channel but application don't know it from the arguments
1715        sent by server. */
1716     client->ops->notify(client, conn, type, client_entry, mode, channel);
1717     break;
1718
1719   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1720     /*
1721      * Someone changed user's mode on a channel
1722      */
1723
1724     /* Get Client ID */
1725     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1726     if (!tmp)
1727       goto out;
1728
1729     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1730     if (!client_id)
1731       goto out;
1732
1733     /* Find Client entry */
1734     client_entry = 
1735       silc_client_get_client_by_id(client, conn, client_id);
1736     if (!client_entry)
1737       goto out;
1738
1739     /* Get the mode */
1740     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1741     if (!tmp)
1742       goto out;
1743
1744     SILC_GET32_MSB(mode, tmp);
1745
1746     /* Get target Client ID */
1747     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1748     if (!tmp)
1749       goto out;
1750
1751     silc_free(client_id);
1752     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1753     if (!client_id)
1754       goto out;
1755
1756     /* Find target Client entry */
1757     client_entry2 = 
1758       silc_client_get_client_by_id(client, conn, client_id);
1759     if (!client_entry2)
1760       goto out;
1761
1762     /* Get channel entry */
1763     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1764                                 SILC_ID_CHANNEL);
1765     if (!channel_id)
1766       goto out;
1767     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1768                                      SILC_ID_CHANNEL, &id_cache))
1769       break;
1770
1771     channel = (SilcChannelEntry)id_cache->context;
1772
1773     /* Save the mode */
1774     silc_list_start(channel->clients);
1775     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1776       if (chu->client == client_entry) {
1777         chu->mode = mode;
1778         break;
1779       }
1780     }
1781
1782     /* Notify application. The channel entry is sent last as this notify
1783        is for channel but application don't know it from the arguments
1784        sent by server. */
1785     client->ops->notify(client, conn, type, client_entry, mode, 
1786                         client_entry2, channel);
1787     break;
1788
1789   case SILC_NOTIFY_TYPE_MOTD:
1790     /*
1791      * Received Message of the day
1792      */
1793
1794     /* Get motd */
1795     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1796     if (!tmp)
1797       goto out;
1798     
1799     /* Notify application */
1800     client->ops->notify(client, conn, type, tmp);
1801     break;
1802
1803   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1804     /*
1805      * Router has enforced a new ID to a channel. Let's change the old
1806      * ID to the one provided here.
1807      */
1808
1809     /* Get the old ID */
1810     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1811     if (!tmp)
1812       goto out;
1813     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1814     if (!channel_id)
1815       goto out;
1816     
1817     /* Get the channel entry */
1818     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1819                                      SILC_ID_CHANNEL, &id_cache))
1820       break;
1821
1822     channel = (SilcChannelEntry)id_cache->context;
1823
1824     /* Free the old ID */
1825     silc_free(channel_id);
1826     silc_free(channel->id);
1827
1828     /* Get the new ID */
1829     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1830     if (!tmp)
1831       goto out;
1832     channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1833     if (!channel->id)
1834       goto out;
1835
1836     id_cache->id = (void *)channel->id;
1837
1838     /* Notify application */
1839     client->ops->notify(client, conn, type, channel, channel);
1840     break;
1841
1842   case SILC_NOTIFY_TYPE_KICKED:
1843     /*
1844      * A client (maybe me) was kicked from a channel
1845      */
1846
1847     /* Get Client ID */
1848     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1849     if (!tmp)
1850       goto out;
1851
1852     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1853     if (!client_id)
1854       goto out;
1855
1856     /* Find Client entry */
1857     client_entry = 
1858       silc_client_get_client_by_id(client, conn, client_id);
1859     if (!client_entry)
1860       goto out;
1861
1862     /* Get channel entry */
1863     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1864                                 SILC_ID_CHANNEL);
1865     if (!channel_id)
1866       goto out;
1867     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1868                                      SILC_ID_CHANNEL, &id_cache))
1869       break;
1870
1871     channel = (SilcChannelEntry)id_cache->context;
1872
1873     /* Get comment */
1874     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1875
1876     /* Notify application. The channel entry is sent last as this notify
1877        is for channel but application don't know it from the arguments
1878        sent by server. */
1879     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1880
1881     /* If I was kicked from channel, remove the channel */
1882     if (client_entry == conn->local_entry) {
1883       if (conn->current_channel == channel)
1884         conn->current_channel = NULL;
1885       silc_idcache_del_by_id(conn->channel_cache, 
1886                              SILC_ID_CHANNEL, channel->id);
1887       silc_free(channel->channel_name);
1888       silc_free(channel->id);
1889       silc_free(channel->key);
1890       silc_cipher_free(channel->channel_key);
1891       silc_free(channel);
1892     }
1893     break;
1894     
1895   default:
1896     break;
1897   }
1898
1899  out:
1900   silc_notify_payload_free(payload);
1901   if (client_id)
1902     silc_free(client_id);
1903   if (channel_id)
1904     silc_free(channel_id);
1905 }
1906
1907 /* Processes the received new Client ID from server. Old Client ID is
1908    deleted from cache and new one is added. */
1909
1910 void silc_client_receive_new_id(SilcClient client,
1911                                 SilcSocketConnection sock,
1912                                 SilcIDPayload idp)
1913 {
1914   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1915   int connecting = FALSE;
1916
1917   if (!conn->local_entry)
1918     connecting = TRUE;
1919
1920   /* Delete old ID from ID cache */
1921   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1922   
1923   /* Save the new ID */
1924   if (conn->local_id)
1925     silc_free(conn->local_id);
1926   if (conn->local_id_data)
1927     silc_free(conn->local_id_data);
1928
1929   conn->local_id = silc_id_payload_get_id(idp);
1930   conn->local_id_data = silc_id_payload_get_data(idp);
1931   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1932
1933   if (!conn->local_entry)
1934     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1935
1936   conn->local_entry->nickname = conn->nickname;
1937   if (!conn->local_entry->username) {
1938     conn->local_entry->username = 
1939       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1940                   sizeof(conn->local_entry->username));
1941     sprintf(conn->local_entry->username, "%s@%s", client->username,
1942             client->hostname);
1943   }
1944   conn->local_entry->server = strdup(conn->remote_host);
1945   conn->local_entry->id = conn->local_id;
1946   
1947   /* Put it to the ID cache */
1948   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1949                    conn->local_id, (void *)conn->local_entry, TRUE);
1950
1951   /* Notify application of successful connection. We do it here now that
1952      we've received the Client ID and are allowed to send traffic. */
1953   if (connecting)
1954     client->ops->connect(client, conn, TRUE);
1955 }
1956
1957 /* Processed received Channel ID for a channel. This is called when client
1958    joins to channel and server replies with channel ID. The ID is cached. */
1959
1960 void silc_client_new_channel_id(SilcClient client,
1961                                 SilcSocketConnection sock,
1962                                 char *channel_name,
1963                                 unsigned int mode, SilcIDPayload idp)
1964 {
1965   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1966   SilcChannelEntry channel;
1967
1968   SILC_LOG_DEBUG(("New channel ID"));
1969
1970   channel = silc_calloc(1, sizeof(*channel));
1971   channel->channel_name = channel_name;
1972   channel->id = silc_id_payload_get_id(idp);
1973   channel->mode = mode;
1974   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1975
1976   conn->current_channel = channel;
1977
1978   /* Put it to the ID cache */
1979   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1980                    (void *)channel->id, (void *)channel, TRUE);
1981 }
1982
1983 /* Saves channel key from encoded `key_payload'. This is used when we
1984    receive Channel Key Payload and when we are processing JOIN command 
1985    reply. */
1986
1987 void silc_client_save_channel_key(SilcClientConnection conn,
1988                                   SilcBuffer key_payload, 
1989                                   SilcChannelEntry channel)
1990 {
1991   unsigned char *id_string, *key, *cipher;
1992   unsigned int tmp_len;
1993   SilcChannelID *id;
1994   SilcIDCacheEntry id_cache = NULL;
1995   SilcChannelKeyPayload payload;
1996
1997   payload = silc_channel_key_payload_parse(key_payload);
1998   if (!payload)
1999     return;
2000
2001   id_string = silc_channel_key_get_id(payload, &tmp_len);
2002   if (!id_string) {
2003     silc_channel_key_payload_free(payload);
2004     return;
2005   }
2006
2007   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
2008   if (!id) {
2009     silc_channel_key_payload_free(payload);
2010     return;
2011   }
2012
2013   /* Find channel. */
2014   if (!channel) {
2015     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2016                                      SILC_ID_CHANNEL, &id_cache))
2017       goto out;
2018     
2019     /* Get channel entry */
2020     channel = (SilcChannelEntry)id_cache->context;
2021   }
2022
2023   /* Save the key */
2024   key = silc_channel_key_get_key(payload, &tmp_len);
2025   cipher = silc_channel_key_get_cipher(payload, NULL);
2026   channel->key_len = tmp_len * 8;
2027   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
2028   memcpy(channel->key, key, tmp_len);
2029
2030   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
2031     conn->client->ops->say(conn->client, conn,
2032                      "Cannot talk to channel: unsupported cipher %s", cipher);
2033     goto out;
2034   }
2035   channel->channel_key->cipher->set_key(channel->channel_key->context, 
2036                                         key, channel->key_len);
2037
2038   /* Client is now joined to the channel */
2039   channel->on_channel = TRUE;
2040
2041  out:
2042   silc_free(id);
2043   silc_channel_key_payload_free(payload);
2044 }
2045
2046 /* Processes received key for channel. The received key will be used
2047    to protect the traffic on the channel for now on. Client must receive
2048    the key to the channel before talking on the channel is possible. 
2049    This is the key that server has generated, this is not the channel
2050    private key, it is entirely local setting. */
2051
2052 void silc_client_receive_channel_key(SilcClient client,
2053                                      SilcSocketConnection sock,
2054                                      SilcBuffer packet)
2055 {
2056   SILC_LOG_DEBUG(("Received key for channel"));
2057
2058   /* Save the key */
2059   silc_client_save_channel_key(sock->user_data, packet, NULL);
2060 }
2061
2062 /* Process received message to a channel (or from a channel, really). This
2063    decrypts the channel message with channel specific key and parses the
2064    channel payload. Finally it displays the message on the screen. */
2065
2066 void silc_client_channel_message(SilcClient client, 
2067                                  SilcSocketConnection sock, 
2068                                  SilcPacketContext *packet)
2069 {
2070   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2071   SilcBuffer buffer = packet->buffer;
2072   SilcChannelPayload payload = NULL;
2073   SilcChannelID *id = NULL;
2074   SilcChannelEntry channel;
2075   SilcChannelUser chu;
2076   SilcIDCacheEntry id_cache = NULL;
2077   SilcClientID *client_id = NULL;
2078   int found = FALSE;
2079   unsigned int block_len;
2080
2081   /* Sanity checks */
2082   if (packet->dst_id_type != SILC_ID_CHANNEL)
2083     goto out;
2084
2085   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2086                              SILC_ID_CLIENT);
2087   if (!client_id)
2088     goto out;
2089   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2090   if (!id)
2091     goto out;
2092
2093   /* Find the channel entry from channels on this connection */
2094   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2095                                    SILC_ID_CHANNEL, &id_cache))
2096     goto out;
2097
2098   channel = (SilcChannelEntry)id_cache->context;
2099
2100   /* Decrypt the channel message payload. Push the IV out of the way,
2101      since it is not encrypted (after pushing buffer->tail has the IV). */
2102   block_len = silc_cipher_get_block_len(channel->channel_key);
2103   silc_buffer_push_tail(buffer, block_len);
2104   channel->channel_key->cipher->decrypt(channel->channel_key->context,
2105                                         buffer->data, buffer->data,
2106                                         buffer->len, buffer->tail);
2107   silc_buffer_pull_tail(buffer, block_len);
2108
2109   /* Parse the channel message payload */
2110   payload = silc_channel_payload_parse(buffer);
2111   if (!payload)
2112     goto out;
2113
2114   /* Find client entry */
2115   silc_list_start(channel->clients);
2116   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2117     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2118       found = TRUE;
2119       break;
2120     }
2121   }
2122
2123   /* Pass the message to application */
2124   client->ops->channel_message(client, conn, found ? chu->client : NULL,
2125                                channel, silc_channel_get_data(payload, NULL));
2126
2127  out:
2128   if (id)
2129     silc_free(id);
2130   if (client_id)
2131     silc_free(client_id);
2132   if (payload)
2133     silc_channel_payload_free(payload);
2134 }
2135
2136 /* Private message received. This processes the private message and
2137    finally displays it on the screen. */
2138
2139 void silc_client_private_message(SilcClient client, 
2140                                  SilcSocketConnection sock, 
2141                                  SilcPacketContext *packet)
2142 {
2143   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2144   SilcBuffer buffer = packet->buffer;
2145   SilcIDCacheEntry id_cache;
2146   SilcClientID *remote_id = NULL;
2147   SilcClientEntry remote_client;
2148   unsigned short nick_len;
2149   unsigned char *nickname, *message = NULL;
2150   int ret;
2151
2152   if (packet->src_id_type != SILC_ID_CLIENT)
2153     goto out;
2154
2155   /* Get nickname */
2156   ret = silc_buffer_unformat(buffer, 
2157                              SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2158                              SILC_STR_END);
2159   if (ret == -1)
2160     return;
2161
2162   silc_buffer_pull(buffer, 2 + nick_len);
2163
2164   message = silc_calloc(buffer->len + 1, sizeof(char));
2165   memcpy(message, buffer->data, buffer->len);
2166
2167   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2168                              SILC_ID_CLIENT);
2169   if (!remote_id)
2170     goto out;
2171
2172   /* Check whether we know this client already */
2173   if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2174                                    SILC_ID_CLIENT, &id_cache))
2175     {
2176       /* Allocate client entry */
2177       remote_client = silc_calloc(1, sizeof(*remote_client));
2178       remote_client->id = remote_id;
2179       silc_parse_nickname(nickname, &remote_client->nickname, 
2180                           &remote_client->server, &remote_client->num);
2181       
2182       /* Save the client to cache */
2183       silc_idcache_add(conn->client_cache, remote_client->nickname,
2184                        SILC_ID_CLIENT, remote_client->id, remote_client, 
2185                        TRUE);
2186     } else {
2187       remote_client = (SilcClientEntry)id_cache->context;
2188     }
2189
2190   /* Pass the private message to application */
2191   client->ops->private_message(client, conn, remote_client, message);
2192
2193   /* See if we are away (gone). If we are away we will reply to the
2194      sender with the set away message. */
2195   if (conn->away && conn->away->away) {
2196     /* If it's me, ignore */
2197     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2198       goto out;
2199
2200     /* Send the away message */
2201     silc_client_send_private_message(client, conn, remote_client,
2202                                      conn->away->away,
2203                                      strlen(conn->away->away), TRUE);
2204   }
2205
2206  out:
2207   if (remote_id)
2208     silc_free(remote_id);
2209
2210   if (message) {
2211     memset(message, 0, buffer->len);
2212     silc_free(message);
2213   }
2214   silc_free(nickname);
2215 }
2216
2217 /* Removes a client entry from all channel it has joined. This really is
2218    a performance killer (client_entry should have pointers to channel 
2219    entry list). */
2220
2221 void silc_client_remove_from_channels(SilcClient client,
2222                                       SilcClientConnection conn,
2223                                       SilcClientEntry client_entry)
2224 {
2225   SilcIDCacheEntry id_cache;
2226   SilcIDCacheList list;
2227   SilcChannelEntry channel;
2228   SilcChannelUser chu;
2229
2230   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2231                                SILC_ID_CHANNEL, &list))
2232     return;
2233
2234   silc_idcache_list_first(list, &id_cache);
2235   channel = (SilcChannelEntry)id_cache->context;
2236   
2237   while (channel) {
2238     
2239     /* Remove client from channel */
2240     silc_list_start(channel->clients);
2241     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2242       if (chu->client == client_entry) {
2243         silc_list_del(channel->clients, chu);
2244         silc_free(chu);
2245         break;
2246       }
2247     }
2248
2249     if (!silc_idcache_list_next(list, &id_cache))
2250       break;
2251     
2252     channel = (SilcChannelEntry)id_cache->context;
2253   }
2254
2255   silc_idcache_list_free(list);
2256 }
2257
2258 /* Replaces `old' client entries from all channels to `new' client entry.
2259    This can be called for example when nickname changes and old ID entry
2260    is replaced from ID cache with the new one. If the old ID entry is only
2261    updated, then this fucntion needs not to be called. */
2262
2263 void silc_client_replace_from_channels(SilcClient client, 
2264                                        SilcClientConnection conn,
2265                                        SilcClientEntry old,
2266                                        SilcClientEntry new)
2267 {
2268   SilcIDCacheEntry id_cache;
2269   SilcIDCacheList list;
2270   SilcChannelEntry channel;
2271   SilcChannelUser chu;
2272
2273   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2274                                SILC_ID_CHANNEL, &list))
2275     return;
2276
2277   silc_idcache_list_first(list, &id_cache);
2278   channel = (SilcChannelEntry)id_cache->context;
2279   
2280   while (channel) {
2281     
2282     /* Replace client entry */
2283     silc_list_start(channel->clients);
2284     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2285       if (chu->client == old) {
2286         chu->client = new;
2287         break;
2288       }
2289     }
2290
2291     if (!silc_idcache_list_next(list, &id_cache))
2292       break;
2293     
2294     channel = (SilcChannelEntry)id_cache->context;
2295   }
2296
2297   silc_idcache_list_free(list);
2298 }
2299
2300 /* Parses mode mask and returns the mode as string. */
2301
2302 char *silc_client_chmode(unsigned int mode)
2303 {
2304   char string[20];
2305
2306   if (!mode)
2307     return NULL;
2308
2309   memset(string, 0, sizeof(string));
2310
2311   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2312     strncat(string, "p", 1);
2313
2314   if (mode & SILC_CHANNEL_MODE_SECRET)
2315     strncat(string, "s", 1);
2316
2317   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2318     strncat(string, "k", 1);
2319
2320   if (mode & SILC_CHANNEL_MODE_INVITE)
2321     strncat(string, "i", 1);
2322
2323   if (mode & SILC_CHANNEL_MODE_TOPIC)
2324     strncat(string, "t", 1);
2325
2326   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2327     strncat(string, "l", 1);
2328
2329   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2330     strncat(string, "a", 1);
2331
2332   /* Rest of mode is ignored */
2333
2334   return strdup(string);
2335 }
2336
2337 /* Parses channel user mode mask and returns te mode as string */
2338
2339 char *silc_client_chumode(unsigned int mode)
2340 {
2341   char string[4];
2342
2343   if (!mode)
2344     return NULL;
2345
2346   memset(string, 0, sizeof(string));
2347
2348   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2349     strncat(string, "f", 1);
2350
2351   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2352     strncat(string, "o", 1);
2353
2354   return strdup(string);
2355 }
2356
2357 /* Parses channel user mode and returns it as special mode character. */
2358
2359 char *silc_client_chumode_char(unsigned int mode)
2360 {
2361   char string[4];
2362
2363   if (!mode)
2364     return NULL;
2365
2366   memset(string, 0, sizeof(string));
2367
2368   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2369     strncat(string, "*", 1);
2370
2371   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2372     strncat(string, "@", 1);
2373
2374   return strdup(string);
2375 }