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