Changed channel->clients to SilcList.
[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_buffer_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(buffer);
652   if (packet->src_id)
653     silc_free(packet->src_id);
654   if (packet->dst_id)
655     silc_free(packet->dst_id);
656   silc_free(packet);
657   silc_free(parse_ctx);
658 }
659
660 /* Parser callback called by silc_packet_receive_process. Thie merely
661    registers timeout that will handle the actual parsing when appropriate. */
662
663 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
664 {
665   SilcClient client = (SilcClient)parser_context->context;
666
667   /* Parse the packet */
668   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
669                      silc_client_packet_parse_real,
670                      (void *)parser_context, 0, 1, 
671                      SILC_TASK_TIMEOUT,
672                      SILC_TASK_PRI_NORMAL);
673 }
674   
675 /* Parses the packet type and calls what ever routines the packet type
676    requires. This is done for all incoming packets. */
677
678 void silc_client_packet_parse_type(SilcClient client, 
679                                    SilcSocketConnection sock,
680                                    SilcPacketContext *packet)
681 {
682   SilcBuffer buffer = packet->buffer;
683   SilcPacketType type = packet->type;
684
685   SILC_LOG_DEBUG(("Parsing packet type %d", type));
686
687   /* Parse the packet type */
688   switch(type) {
689   case SILC_PACKET_DISCONNECT:
690     silc_client_disconnected_by_server(client, sock, buffer);
691     break;
692   case SILC_PACKET_SUCCESS:
693     /*
694      * Success received for something. For now we can have only
695      * one protocol for connection executing at once hence this
696      * success message is for whatever protocol is executing currently.
697      */
698     if (sock->protocol) {
699       sock->protocol->execute(client->timeout_queue, 0,
700                               sock->protocol, sock->sock, 0, 0);
701     }
702     break;
703   case SILC_PACKET_FAILURE:
704     /*
705      * Failure received for some protocol. Set the protocol state to 
706      * error and call the protocol callback. This fill cause error on
707      * protocol and it will call the final callback.
708      */
709     if (sock->protocol) {
710       sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
711       sock->protocol->execute(client->timeout_queue, 0,
712                               sock->protocol, sock->sock, 0, 0);
713
714       /* XXX We have only two protocols currently thus we know what this
715          failure indication is. */
716       if (buffer->len >= 4) {
717         unsigned int failure;
718
719         SILC_GET32_MSB(failure, buffer->data);
720
721         /* Notify application */
722         client->ops->failure(client, sock->user_data, sock->protocol,
723                              (void *)failure);
724       }
725     }
726     break;
727   case SILC_PACKET_REJECT:
728     break;
729
730   case SILC_PACKET_NOTIFY:
731     /*
732      * Received notify message 
733      */
734     silc_client_notify_by_server(client, sock, packet);
735     break;
736
737   case SILC_PACKET_ERROR:
738     /*
739      * Received error message
740      */
741     silc_client_error_by_server(client, sock, buffer);
742     break;
743
744   case SILC_PACKET_CHANNEL_MESSAGE:
745     /*
746      * Received message to (from, actually) a channel
747      */
748     silc_client_channel_message(client, sock, packet);
749     break;
750   case SILC_PACKET_CHANNEL_KEY:
751     /*
752      * Received key for a channel. By receiving this key the client will be
753      * able to talk to the channel it has just joined. This can also be
754      * a new key for existing channel as keys expire peridiocally.
755      */
756     silc_client_receive_channel_key(client, sock, buffer);
757     break;
758
759   case SILC_PACKET_PRIVATE_MESSAGE:
760     /*
761      * Received private message
762      */
763     silc_client_private_message(client, sock, packet);
764     break;
765   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
766     /*
767      * Received private message key
768      */
769     break;
770
771   case SILC_PACKET_COMMAND_REPLY:
772     /*
773      * Recived reply for a command
774      */
775     silc_client_command_reply_process(client, sock, packet);
776     break;
777
778   case SILC_PACKET_KEY_EXCHANGE:
779     if (sock->protocol) {
780       SilcClientKEInternalContext *proto_ctx = 
781         (SilcClientKEInternalContext *)sock->protocol->context;
782
783       proto_ctx->packet = buffer;
784       proto_ctx->dest_id_type = packet->src_id_type;
785       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
786
787       /* Let the protocol handle the packet */
788       sock->protocol->execute(client->timeout_queue, 0,
789                               sock->protocol, sock->sock, 0, 0);
790     } else {
791       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
792                       "protocol active, packet dropped."));
793
794       /* XXX Trigger KE protocol?? Rekey actually! */
795     }
796     break;
797
798   case SILC_PACKET_KEY_EXCHANGE_1:
799     if (sock->protocol) {
800
801     } else {
802       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
803                       "protocol active, packet dropped."));
804     }
805     break;
806   case SILC_PACKET_KEY_EXCHANGE_2:
807     if (sock->protocol) {
808       SilcClientKEInternalContext *proto_ctx = 
809         (SilcClientKEInternalContext *)sock->protocol->context;
810
811       if (proto_ctx->packet)
812         silc_buffer_free(proto_ctx->packet);
813
814       proto_ctx->packet = buffer;
815       proto_ctx->dest_id_type = packet->src_id_type;
816       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
817
818       /* Let the protocol handle the packet */
819       sock->protocol->execute(client->timeout_queue, 0,
820                               sock->protocol, sock->sock, 0, 0);
821     } else {
822       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
823                       "protocol active, packet dropped."));
824     }
825     break;
826
827   case SILC_PACKET_NEW_ID:
828     {
829       /*
830        * Received new ID from server. This packet is received at
831        * the connection to the server.  New ID is also received when 
832        * user changes nickname but in that case the new ID is received
833        * as command reply and not as this packet type.
834        */
835       SilcIDPayload idp;
836
837       idp = silc_id_payload_parse(buffer);
838       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
839         break;
840
841       silc_client_receive_new_id(client, sock, idp);
842       silc_id_payload_free(idp);
843       break;
844     }
845
846   default:
847     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
848     break;
849   }
850 }
851
852 /* Sends packet. This doesn't actually send the packet instead it assembles
853    it and marks it to be sent. However, if force_send is TRUE the packet
854    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
855    will be derived from sock argument. Otherwise the valid arguments sent
856    are used. */
857
858 void silc_client_packet_send(SilcClient client, 
859                              SilcSocketConnection sock,
860                              SilcPacketType type, 
861                              void *dst_id,
862                              SilcIdType dst_id_type,
863                              SilcCipher cipher,
864                              SilcHmac hmac,
865                              unsigned char *data, 
866                              unsigned int data_len, 
867                              int force_send)
868 {
869   SilcPacketContext packetdata;
870
871   SILC_LOG_DEBUG(("Sending packet, type %d", type));
872
873   /* Get data used in the packet sending, keys and stuff */
874   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
875     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
876       cipher = ((SilcClientConnection)sock->user_data)->send_key;
877
878     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
879       hmac = ((SilcClientConnection)sock->user_data)->hmac;
880
881     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
882       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
883       dst_id_type = SILC_ID_SERVER;
884     }
885   }
886
887   /* Set the packet context pointers */
888   packetdata.flags = 0;
889   packetdata.type = type;
890   if (((SilcClientConnection)sock->user_data)->local_id_data)
891     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
892   else 
893     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
894   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
895   packetdata.src_id_type = SILC_ID_CLIENT;
896   if (dst_id) {
897     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
898     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
899     packetdata.dst_id_type = dst_id_type;
900   } else {
901     packetdata.dst_id = NULL;
902     packetdata.dst_id_len = 0;
903     packetdata.dst_id_type = SILC_ID_NONE;
904   }
905   packetdata.rng = client->rng;
906   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
907     packetdata.src_id_len + packetdata.dst_id_len;
908   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
909
910   /* Prepare outgoing data buffer for packet sending */
911   silc_packet_send_prepare(sock, 
912                            SILC_PACKET_HEADER_LEN +
913                            packetdata.src_id_len + 
914                            packetdata.dst_id_len,
915                            packetdata.padlen,
916                            data_len);
917
918   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
919
920   packetdata.buffer = sock->outbuf;
921
922   /* Put the data to the buffer */
923   if (data && data_len)
924     silc_buffer_put(sock->outbuf, data, data_len);
925
926   /* Create the outgoing packet */
927   silc_packet_assemble(&packetdata);
928
929   /* Encrypt the packet */
930   if (cipher)
931     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
932
933   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
934                    sock->outbuf->data, sock->outbuf->len);
935
936   /* Now actually send the packet */
937   silc_client_packet_send_real(client, sock, force_send);
938 }
939
940 /* Sends packet to a channel. Packet to channel is always encrypted
941    differently from "normal" packets. SILC header of the packet is 
942    encrypted with the next receiver's key and the rest of the packet is
943    encrypted with the channel specific key. Padding and HMAC is computed
944    with the next receiver's key. */
945
946 void silc_client_packet_send_to_channel(SilcClient client, 
947                                         SilcSocketConnection sock,
948                                         SilcChannelEntry channel,
949                                         unsigned char *data, 
950                                         unsigned int data_len, 
951                                         int force_send)
952 {
953   int i;
954   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
955   SilcBuffer payload;
956   SilcPacketContext packetdata;
957   SilcCipher cipher;
958   SilcHmac hmac;
959   unsigned char *id_string;
960
961   SILC_LOG_DEBUG(("Sending packet to channel"));
962
963   if (!channel || !channel->key) {
964     client->ops->say(client, conn, 
965                      "Cannot talk to channel: key does not exist");
966     return;
967   }
968
969   /* Generate IV */
970   if (!channel->iv)
971     for (i = 0; i < 16; i++)
972       channel->iv[i] = silc_rng_get_byte(client->rng);
973   else
974     silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
975
976   /* Encode the channel payload */
977   payload = silc_channel_payload_encode(data_len, data, 16, channel->iv, 
978                                         client->rng);
979   if (!payload) {
980     client->ops->say(client, conn, 
981                      "Error: Could not create packet to be sent to channel");
982     return;
983   }
984
985   /* Get data used in packet header encryption, keys and stuff. Rest
986      of the packet (the payload) is, however, encrypted with the 
987      specified channel key. */
988   cipher = conn->send_key;
989   hmac = conn->hmac;
990   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
991
992   /* Set the packet context pointers. The destination ID is always
993      the Channel ID of the channel. Server and router will handle the
994      distribution of the packet. */
995   packetdata.flags = 0;
996   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
997   packetdata.src_id = conn->local_id_data;
998   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
999   packetdata.src_id_type = SILC_ID_CLIENT;
1000   packetdata.dst_id = id_string;
1001   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1002   packetdata.dst_id_type = SILC_ID_CHANNEL;
1003   packetdata.rng = client->rng;
1004   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
1005     packetdata.src_id_len + packetdata.dst_id_len;
1006   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1007                                           packetdata.src_id_len +
1008                                           packetdata.dst_id_len));
1009
1010   /* Prepare outgoing data buffer for packet sending */
1011   silc_packet_send_prepare(sock, 
1012                            SILC_PACKET_HEADER_LEN +
1013                            packetdata.src_id_len + 
1014                            packetdata.dst_id_len,
1015                            packetdata.padlen,
1016                            payload->len);
1017
1018   packetdata.buffer = sock->outbuf;
1019
1020   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1021   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1022                                         payload->data, payload->data,
1023                                         payload->len - 16, /* -IV_LEN */
1024                                         channel->iv);
1025
1026   /* Put the actual encrypted payload data into the buffer. */
1027   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1028
1029   /* Create the outgoing packet */
1030   silc_packet_assemble(&packetdata);
1031
1032   /* Encrypt the header and padding of the packet. This is encrypted 
1033      with normal session key shared with our server. */
1034   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1035                       packetdata.src_id_len + packetdata.dst_id_len +
1036                       packetdata.padlen);
1037
1038   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1039                    sock->outbuf->data, sock->outbuf->len);
1040
1041   /* Now actually send the packet */
1042   silc_client_packet_send_real(client, sock, force_send);
1043   silc_buffer_free(payload);
1044   silc_free(id_string);
1045 }
1046
1047 /* Sends private message to remote client. If private message key has
1048    not been set with this client then the message will be encrypted using
1049    normal session keys. Private messages are special packets in SILC
1050    network hence we need this own function for them. This is similiar
1051    to silc_client_packet_send_to_channel except that we send private
1052    message. */
1053
1054 void silc_client_packet_send_private_message(SilcClient client,
1055                                              SilcSocketConnection sock,
1056                                              SilcClientEntry client_entry,
1057                                              unsigned char *data, 
1058                                              unsigned int data_len, 
1059                                              int force_send)
1060 {
1061   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1062   SilcBuffer buffer;
1063   SilcPacketContext packetdata;
1064   unsigned int nick_len;
1065   SilcCipher cipher;
1066   SilcHmac hmac;
1067
1068   SILC_LOG_DEBUG(("Sending private message"));
1069
1070   /* Create private message payload */
1071   nick_len = strlen(conn->nickname);
1072   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1073   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1074   silc_buffer_format(buffer,
1075                      SILC_STR_UI_SHORT(nick_len),
1076                      SILC_STR_UI_XNSTRING(conn->nickname,
1077                                           nick_len),
1078                      SILC_STR_UI_XNSTRING(data, data_len),
1079                      SILC_STR_END);
1080
1081   /* If we don't have private message specific key then private messages
1082      are just as any normal packet thus call normal packet sending.  If
1083      the key exist then the encryption process is a bit different and
1084      will be done in the rest of this function. */
1085   if (!client_entry->send_key) {
1086     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1087                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1088                             buffer->data, buffer->len, force_send);
1089     goto out;
1090   }
1091
1092   /* We have private message specific key */
1093
1094   /* Get data used in the encryption */
1095   cipher = client_entry->send_key;
1096   hmac = conn->hmac;
1097
1098   /* Set the packet context pointers. */
1099   packetdata.flags = 0;
1100   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1101   packetdata.src_id = conn->local_id_data;
1102   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1103   packetdata.src_id_type = SILC_ID_CLIENT;
1104   if (client_entry)
1105     packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1106   else
1107     packetdata.dst_id = conn->local_id_data;
1108   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1109   packetdata.dst_id_type = SILC_ID_CLIENT;
1110   packetdata.rng = client->rng;
1111   packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1112     packetdata.src_id_len + packetdata.dst_id_len;
1113   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1114                                           packetdata.src_id_len +
1115                                           packetdata.dst_id_len));
1116
1117   /* Prepare outgoing data buffer for packet sending */
1118   silc_packet_send_prepare(sock, 
1119                            SILC_PACKET_HEADER_LEN +
1120                            packetdata.src_id_len + 
1121                            packetdata.dst_id_len,
1122                            packetdata.padlen,
1123                            buffer->len);
1124   
1125   packetdata.buffer = sock->outbuf;
1126
1127   /* Encrypt payload of the packet. Encrypt with private message specific
1128      key if it exist, otherwise with session key. */
1129   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1130                           buffer->len, cipher->iv);
1131       
1132   /* Put the actual encrypted payload data into the buffer. */
1133   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1134
1135   /* Create the outgoing packet */
1136   silc_packet_assemble(&packetdata);
1137
1138   /* Encrypt the header and padding of the packet. */
1139   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1140                       packetdata.src_id_len + packetdata.dst_id_len +
1141                       packetdata.padlen);
1142
1143   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1144                    sock->outbuf->data, sock->outbuf->len);
1145
1146   /* Now actually send the packet */
1147   silc_client_packet_send_real(client, sock, force_send);
1148   silc_free(packetdata.dst_id);
1149
1150  out:
1151   silc_free(buffer);
1152 }     
1153
1154 /* Closes connection to remote end. Free's all allocated data except
1155    for some information such as nickname etc. that are valid at all time. */
1156
1157 void silc_client_close_connection(SilcClient client,
1158                                   SilcSocketConnection sock)
1159 {
1160   SilcClientConnection conn;
1161
1162   /* We won't listen for this connection anymore */
1163   silc_schedule_unset_listen_fd(sock->sock);
1164
1165   /* Unregister all tasks */
1166   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1167   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1168
1169   /* Close the actual connection */
1170   silc_net_close_connection(sock->sock);
1171
1172   client->ops->say(client, sock->user_data,
1173                    "Closed connection to host %s", sock->hostname ?
1174                    sock->hostname : sock->ip);
1175
1176   /* Free everything */
1177   if (sock->user_data) {
1178     conn = (SilcClientConnection)sock->user_data;
1179
1180     /* XXX Free all client entries and channel entries. */
1181
1182     /* Clear ID caches */
1183     silc_idcache_del_all(conn->client_cache);
1184     silc_idcache_del_all(conn->channel_cache);
1185
1186     /* Free data */
1187     if (conn->remote_host)
1188       silc_free(conn->remote_host);
1189     if (conn->local_id)
1190       silc_free(conn->local_id);
1191     if (conn->local_id_data)
1192       silc_free(conn->local_id_data);
1193     if (conn->send_key)
1194       silc_cipher_free(conn->send_key);
1195     if (conn->receive_key)
1196       silc_cipher_free(conn->receive_key);
1197     if (conn->hmac)
1198       silc_hmac_free(conn->hmac);
1199     if (conn->hmac_key) {
1200       memset(conn->hmac_key, 0, conn->hmac_key_len);
1201       silc_free(conn->hmac_key);
1202     }
1203
1204     conn->sock = NULL;
1205     conn->remote_port = 0;
1206     conn->remote_type = 0;
1207     conn->send_key = NULL;
1208     conn->receive_key = NULL;
1209     conn->hmac = NULL;
1210     conn->hmac_key = NULL;
1211     conn->hmac_key_len = 0;
1212     conn->local_id = NULL;
1213     conn->local_id_data = NULL;
1214     conn->remote_host = NULL;
1215     conn->current_channel = NULL;
1216
1217     silc_client_del_connection(client, conn);
1218   }
1219
1220   if (sock->protocol) {
1221     silc_protocol_free(sock->protocol);
1222     sock->protocol = NULL;
1223   }
1224   silc_socket_free(sock);
1225 }
1226
1227 /* Called when we receive disconnection packet from server. This 
1228    closes our end properly and displays the reason of the disconnection
1229    on the screen. */
1230
1231 void silc_client_disconnected_by_server(SilcClient client,
1232                                         SilcSocketConnection sock,
1233                                         SilcBuffer message)
1234 {
1235   char *msg;
1236
1237   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1238
1239   msg = silc_calloc(message->len + 1, sizeof(char));
1240   memcpy(msg, message->data, message->len);
1241   client->ops->say(client, sock->user_data, msg);
1242   silc_free(msg);
1243
1244   SILC_SET_DISCONNECTED(sock);
1245   silc_client_close_connection(client, sock);
1246 }
1247
1248 /* Received error message from server. Display it on the screen. 
1249    We don't take any action what so ever of the error message. */
1250
1251 void silc_client_error_by_server(SilcClient client,
1252                                  SilcSocketConnection sock,
1253                                  SilcBuffer message)
1254 {
1255   char *msg;
1256
1257   msg = silc_calloc(message->len + 1, sizeof(char));
1258   memcpy(msg, message->data, message->len);
1259   client->ops->say(client, sock->user_data, msg);
1260   silc_free(msg);
1261 }
1262
1263 /* Called when notify is received and some async operation (such as command)
1264    is required before processing the notify message. This calls again the
1265    silc_client_notify_by_server and reprocesses the original notify packet. */
1266
1267 static void silc_client_notify_by_server_pending(void *context)
1268 {
1269   SilcPacketContext *p = (SilcPacketContext *)context;
1270   silc_client_notify_by_server(p->context, p->sock, p);
1271   if (p->src_id)
1272     silc_free(p->src_id);
1273   if (p->dst_id)
1274     silc_free(p->dst_id);
1275   silc_buffer_free(p->buffer);
1276   silc_free(p);
1277 }
1278
1279 /* Received notify message from server */
1280
1281 void silc_client_notify_by_server(SilcClient client,
1282                                   SilcSocketConnection sock,
1283                                   SilcPacketContext *packet)
1284 {
1285   SilcBuffer buffer = packet->buffer;
1286   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1287   SilcNotifyPayload payload;
1288   SilcNotifyType type;
1289   SilcArgumentPayload args;
1290   int i;
1291
1292   SilcClientID *client_id = NULL;
1293   SilcChannelID *channel_id = NULL;
1294   SilcClientEntry client_entry;
1295   SilcClientEntry client_entry2;
1296   SilcChannelEntry channel;
1297   SilcChannelUser chu;
1298   SilcIDCacheEntry id_cache = NULL;
1299   unsigned char *tmp;
1300   unsigned int tmp_len, mode;
1301
1302   payload = silc_notify_payload_parse(buffer);
1303   type = silc_notify_get_type(payload);
1304   args = silc_notify_get_args(payload);
1305   if (!args)
1306     goto out;
1307
1308   switch(type) {
1309   case SILC_NOTIFY_TYPE_NONE:
1310     /* Notify application */
1311     client->ops->notify(client, conn, type, 
1312                         silc_argument_get_arg_type(args, 1, NULL));
1313     break;
1314
1315   case SILC_NOTIFY_TYPE_INVITE:
1316     /* 
1317      * Someone invited me to a channel. Find Client and Channel entries
1318      * for the application.
1319      */
1320     
1321     /* Get Client ID */
1322     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1323     if (!tmp)
1324       goto out;
1325
1326     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1327
1328     /* Find Client entry and if not found query it */
1329     client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1330     if (!client_entry) {
1331       SilcPacketContext *p = silc_packet_context_dup(packet);
1332       p->context = (void *)client;
1333       p->sock = sock;
1334       silc_client_command_pending(SILC_COMMAND_WHOIS, 
1335                                   silc_client_notify_by_server_pending, p);
1336       goto out;
1337     }
1338
1339     /* Get Channel ID */
1340     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1341     if (!tmp)
1342       goto out;
1343
1344     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1345
1346     /* XXX Will ALWAYS fail because currently we don't have way to resolve
1347        channel information for channel that we're not joined to. */
1348     /* XXX ways to fix: use (extended) LIST command, or define the channel
1349        name to the notfy type when name resolving is not mandatory. */
1350     /* Find channel entry */
1351     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1352                                      SILC_ID_CHANNEL, &id_cache))
1353       goto out;
1354
1355     channel = (SilcChannelEntry)id_cache->context;
1356
1357     /* Notify application */
1358     client->ops->notify(client, conn, type, client_entry, channel);
1359     break;
1360
1361   case SILC_NOTIFY_TYPE_JOIN:
1362     /*
1363      * Someone has joined to a channel. Get their ID and nickname and
1364      * cache them for later use.
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
1374     /* Find Client entry and if not found query it */
1375     client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1376     if (!client_entry) {
1377       SilcPacketContext *p = silc_packet_context_dup(packet);
1378       p->context = (void *)client;
1379       p->sock = sock;
1380       silc_client_command_pending(SILC_COMMAND_WHOIS, 
1381                                   silc_client_notify_by_server_pending, p);
1382       goto out;
1383     }
1384
1385     /* Get channel entry */
1386     channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1387     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1388                                      SILC_ID_CHANNEL, &id_cache))
1389       break;
1390
1391     channel = (SilcChannelEntry)id_cache->context;
1392
1393     /* Add client to channel */
1394     chu = silc_calloc(1, sizeof(*chu));
1395     chu->client = client_entry;
1396     silc_list_add(channel->clients, chu);
1397
1398     /* XXX add support for multiple same nicks on same channel. Check
1399        for them here */
1400
1401     /* Notify application. The channel entry is sent last as this notify
1402        is for channel but application don't know it from the arguments
1403        sent by server. */
1404     client->ops->notify(client, conn, type, client_entry, channel);
1405     break;
1406
1407   case SILC_NOTIFY_TYPE_LEAVE:
1408     /*
1409      * Someone has left a channel. We will remove it from the channel but
1410      * we'll keep it in the cache in case we'll need it later.
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
1420     /* Find Client entry */
1421     client_entry = 
1422       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1423     if (!client_entry)
1424       goto out;
1425
1426     /* Get channel entry */
1427     channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1428     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1429                                      SILC_ID_CHANNEL, &id_cache))
1430       break;
1431
1432     channel = (SilcChannelEntry)id_cache->context;
1433
1434     /* Remove client from channel */
1435     silc_list_start(channel->clients);
1436     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1437       if (chu->client == client_entry) {
1438         silc_list_del(channel->clients, chu);
1439         silc_free(chu);
1440         break;
1441       }
1442     }
1443
1444     /* Notify application. The channel entry is sent last as this notify
1445        is for channel but application don't know it from the arguments
1446        sent by server. */
1447     client->ops->notify(client, conn, type, client_entry, channel);
1448     break;
1449
1450   case SILC_NOTIFY_TYPE_SIGNOFF:
1451     /*
1452      * Someone left SILC. We'll remove it from all channels and from cache.
1453      */
1454
1455     /* Get Client ID */
1456     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1457     if (!tmp)
1458       goto out;
1459
1460     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1461
1462     /* Find Client entry */
1463     client_entry = 
1464       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1465     if (!client_entry)
1466       goto out;
1467
1468     /* Remove from all channels */
1469     silc_client_remove_from_channels(client, conn, client_entry);
1470
1471     /* Remove from cache */
1472     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1473                            client_entry->id);
1474
1475     /* Notify application */
1476     client->ops->notify(client, conn, type, client_entry);
1477
1478     /* Free data */
1479     if (client_entry->nickname)
1480       silc_free(client_entry->nickname);
1481     if (client_entry->server)
1482       silc_free(client_entry->server);
1483     if (client_entry->id)
1484       silc_free(client_entry->id);
1485     if (client_entry->send_key)
1486       silc_cipher_free(client_entry->send_key);
1487     if (client_entry->receive_key)
1488       silc_cipher_free(client_entry->receive_key);
1489     break;
1490
1491   case SILC_NOTIFY_TYPE_TOPIC_SET:
1492     /*
1493      * Someone set the topic on a channel.
1494      */
1495
1496     /* Get Client ID */
1497     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1498     if (!tmp)
1499       goto out;
1500
1501     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1502
1503     /* Find Client entry */
1504     client_entry = 
1505       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1506     if (!client_entry)
1507       goto out;
1508
1509     /* Get topic */
1510     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1511     if (!tmp)
1512       goto out;
1513
1514     /* Get channel entry */
1515     channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1516     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1517                                      SILC_ID_CHANNEL, &id_cache))
1518       break;
1519
1520     channel = (SilcChannelEntry)id_cache->context;
1521
1522     /* Notify application. The channel entry is sent last as this notify
1523        is for channel but application don't know it from the arguments
1524        sent by server. */
1525     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1526     break;
1527
1528   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1529     /*
1530      * Someone changed their nickname. If we don't have entry for the new
1531      * ID we will query it and return here after it's done. After we've
1532      * returned we fetch the old entry and free it and notify the 
1533      * application.
1534      */
1535
1536     /* Get new Client ID */
1537     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1538     if (!tmp)
1539       goto out;
1540
1541     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1542
1543     /* Ignore my ID */
1544     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1545       break;
1546
1547     /* Find Client entry and if not found query it */
1548     client_entry2 = 
1549       silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1550     if (!client_entry2) {
1551       SilcPacketContext *p = silc_packet_context_dup(packet);
1552       p->context = (void *)client;
1553       p->sock = sock;
1554       silc_client_command_pending(SILC_COMMAND_WHOIS, 
1555                                   silc_client_notify_by_server_pending, p);
1556       goto out;
1557     }
1558
1559     /* Get old Client ID */
1560     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1561     if (!tmp)
1562       goto out;
1563
1564     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1565
1566     /* Find old Client entry */
1567     client_entry = 
1568       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1569     if (!client_entry)
1570       goto out;
1571
1572     /* Remove the old from cache */
1573     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1574                            client_entry->id);
1575
1576     /* Replace old ID entry with new one on all channels. */
1577     silc_client_replace_from_channels(client, conn, client_entry,
1578                                       client_entry2);
1579
1580     /* Notify application */
1581     client->ops->notify(client, conn, type, client_entry, client_entry2);
1582
1583     /* Free data */
1584     if (client_entry->nickname)
1585       silc_free(client_entry->nickname);
1586     if (client_entry->server)
1587       silc_free(client_entry->server);
1588     if (client_entry->id)
1589       silc_free(client_entry->id);
1590     if (client_entry->send_key)
1591       silc_cipher_free(client_entry->send_key);
1592     if (client_entry->receive_key)
1593       silc_cipher_free(client_entry->receive_key);
1594     break;
1595
1596   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1597     /*
1598      * Someone changed a channel mode
1599      */
1600
1601     /* Get Client ID */
1602     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1603     if (!tmp)
1604       goto out;
1605
1606     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1607
1608     /* Find Client entry */
1609     client_entry = 
1610       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1611     if (!client_entry)
1612       goto out;
1613
1614     /* Get the mode */
1615     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1616     if (!tmp)
1617       goto out;
1618
1619     SILC_GET32_MSB(mode, tmp);
1620
1621     /* Get channel entry */
1622     channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1623     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1624                                      SILC_ID_CHANNEL, &id_cache))
1625       break;
1626
1627     channel = (SilcChannelEntry)id_cache->context;
1628
1629     /* Save the new mode */
1630     channel->mode = mode;
1631
1632     /* Notify application. The channel entry is sent last as this notify
1633        is for channel but application don't know it from the arguments
1634        sent by server. */
1635     client->ops->notify(client, conn, type, client_entry, mode, channel);
1636     break;
1637
1638   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1639     /*
1640      * Someone changed user's mode on a channel
1641      */
1642
1643     /* Get Client ID */
1644     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1645     if (!tmp)
1646       goto out;
1647
1648     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1649
1650     /* Find Client entry */
1651     client_entry = 
1652       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1653     if (!client_entry)
1654       goto out;
1655
1656     /* Get the mode */
1657     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1658     if (!tmp)
1659       goto out;
1660
1661     SILC_GET32_MSB(mode, tmp);
1662
1663     /* Get target Client ID */
1664     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1665     if (!tmp)
1666       goto out;
1667
1668     silc_free(client_id);
1669     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1670
1671     /* Find target Client entry */
1672     client_entry2 = 
1673       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1674     if (!client_entry2)
1675       goto out;
1676
1677     /* Get channel entry */
1678     channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1679     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1680                                      SILC_ID_CHANNEL, &id_cache))
1681       break;
1682
1683     channel = (SilcChannelEntry)id_cache->context;
1684
1685     /* Save the mode */
1686     silc_list_start(channel->clients);
1687     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1688       if (chu->client == client_entry) {
1689         chu->mode = mode;
1690         break;
1691       }
1692     }
1693
1694     /* Notify application. The channel entry is sent last as this notify
1695        is for channel but application don't know it from the arguments
1696        sent by server. */
1697     client->ops->notify(client, conn, type, client_entry, mode, 
1698                         client_entry2, channel);
1699     break;
1700
1701   case SILC_NOTIFY_TYPE_MOTD:
1702     /*
1703      * Received Message of the day
1704      */
1705
1706     /* Get motd */
1707     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1708     if (!tmp)
1709       goto out;
1710     
1711     /* Notify application */
1712     client->ops->notify(client, conn, type, tmp);
1713     break;
1714     
1715   default:
1716     break;
1717   }
1718
1719  out:
1720   silc_notify_payload_free(payload);
1721   if (client_id)
1722     silc_free(client_id);
1723   if (channel_id)
1724     silc_free(channel_id);
1725 }
1726
1727 /* Processes the received new Client ID from server. Old Client ID is
1728    deleted from cache and new one is added. */
1729
1730 void silc_client_receive_new_id(SilcClient client,
1731                                 SilcSocketConnection sock,
1732                                 SilcIDPayload idp)
1733 {
1734   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1735
1736   /* Delete old ID from ID cache */
1737   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1738   
1739   /* Save the new ID */
1740   if (conn->local_id)
1741     silc_free(conn->local_id);
1742   if (conn->local_id_data)
1743     silc_free(conn->local_id_data);
1744
1745   conn->local_id = silc_id_payload_get_id(idp);
1746   conn->local_id_data = silc_id_payload_get_data(idp);
1747   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1748
1749   if (!conn->local_entry)
1750     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1751
1752   conn->local_entry->nickname = conn->nickname;
1753   if (!conn->local_entry->username) {
1754     conn->local_entry->username = 
1755       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1756                   sizeof(conn->local_entry->username));
1757     sprintf(conn->local_entry->username, "%s@%s", client->username,
1758             client->hostname);
1759   }
1760   conn->local_entry->server = strdup(conn->remote_host);
1761   conn->local_entry->id = conn->local_id;
1762   
1763   /* Put it to the ID cache */
1764   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1765                    conn->local_id, (void *)conn->local_entry, TRUE);
1766 }
1767
1768 /* Processed received Channel ID for a channel. This is called when client
1769    joins to channel and server replies with channel ID. The ID is cached. */
1770
1771 void silc_client_new_channel_id(SilcClient client,
1772                                 SilcSocketConnection sock,
1773                                 char *channel_name,
1774                                 unsigned int mode, SilcIDPayload idp)
1775 {
1776   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1777   SilcChannelEntry channel;
1778
1779   SILC_LOG_DEBUG(("New channel ID"));
1780
1781   channel = silc_calloc(1, sizeof(*channel));
1782   channel->channel_name = channel_name;
1783   channel->id = silc_id_payload_get_id(idp);
1784   channel->mode = mode;
1785   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1786
1787   conn->current_channel = channel;
1788
1789   /* Put it to the ID cache */
1790   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1791                    (void *)channel->id, (void *)channel, TRUE);
1792 }
1793
1794 /* Processes received key for channel. The received key will be used
1795    to protect the traffic on the channel for now on. Client must receive
1796    the key to the channel before talking on the channel is possible. 
1797    This is the key that server has generated, this is not the channel
1798    private key, it is entirely local setting. */
1799
1800 void silc_client_receive_channel_key(SilcClient client,
1801                                      SilcSocketConnection sock,
1802                                      SilcBuffer packet)
1803 {
1804   unsigned char *id_string, *key, *cipher;
1805   unsigned int tmp_len;
1806   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1807   SilcChannelID *id;
1808   SilcIDCacheEntry id_cache = NULL;
1809   SilcChannelEntry channel;
1810   SilcChannelKeyPayload payload;
1811
1812   SILC_LOG_DEBUG(("Received key for channel"));
1813   
1814   payload = silc_channel_key_payload_parse(packet);
1815   if (!payload)
1816     return;
1817
1818   id_string = silc_channel_key_get_id(payload, &tmp_len);
1819   if (!id_string) {
1820     silc_channel_key_payload_free(payload);
1821     return;
1822   }
1823   id = silc_id_payload_parse_id(id_string, tmp_len);
1824
1825   /* Find channel. */
1826   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1827                                    SILC_ID_CHANNEL, &id_cache))
1828     goto out;
1829     
1830   /* Save the key */
1831   key = silc_channel_key_get_key(payload, &tmp_len);
1832   cipher = silc_channel_key_get_cipher(payload, NULL);
1833
1834   channel = (SilcChannelEntry)id_cache->context;
1835   channel->key_len = tmp_len;
1836   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
1837   memcpy(channel->key, key, tmp_len);
1838
1839   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
1840     client->ops->say(client, conn,
1841                      "Cannot talk to channel: unsupported cipher %s", cipher);
1842     goto out;
1843   }
1844   channel->channel_key->cipher->set_key(channel->channel_key->context, 
1845                                         key, tmp_len);
1846
1847   /* Client is now joined to the channel */
1848   channel->on_channel = TRUE;
1849
1850  out:
1851   silc_free(id);
1852   silc_channel_key_payload_free(payload);
1853 }
1854
1855 /* Process received message to a channel (or from a channel, really). This
1856    decrypts the channel message with channel specific key and parses the
1857    channel payload. Finally it displays the message on the screen. */
1858
1859 void silc_client_channel_message(SilcClient client, 
1860                                  SilcSocketConnection sock, 
1861                                  SilcPacketContext *packet)
1862 {
1863   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1864   SilcBuffer buffer = packet->buffer;
1865   SilcChannelPayload payload = NULL;
1866   SilcChannelID *id = NULL;
1867   SilcChannelEntry channel;
1868   SilcChannelUser chu;
1869   SilcIDCacheEntry id_cache = NULL;
1870   SilcClientID *client_id = NULL;
1871   int i;
1872   char *nickname;
1873
1874   /* Sanity checks */
1875   if (packet->dst_id_type != SILC_ID_CHANNEL)
1876     goto out;
1877
1878   client_id = silc_id_str2id(packet->src_id, SILC_ID_CLIENT);
1879   id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1880
1881   /* Find the channel entry from channels on this connection */
1882   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1883                                    SILC_ID_CHANNEL, &id_cache))
1884     goto out;
1885
1886   channel = (SilcChannelEntry)id_cache->context;
1887
1888   /* Decrypt the channel message payload. Push the IV out of the way,
1889      since it is not encrypted (after pushing buffer->tail has the IV). */
1890   silc_buffer_push_tail(buffer, 16);
1891   channel->channel_key->cipher->decrypt(channel->channel_key->context,
1892                                         buffer->data, buffer->data,
1893                                         buffer->len, buffer->tail);
1894   silc_buffer_pull_tail(buffer, 16);
1895
1896   /* Parse the channel message payload */
1897   payload = silc_channel_payload_parse(buffer);
1898   if (!payload)
1899     goto out;
1900
1901   /* Find nickname */
1902   nickname = "[unknown]";
1903   silc_list_start(channel->clients);
1904   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1905     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
1906       nickname = chu->client->nickname;
1907       break;
1908     }
1909   }
1910
1911   /* Pass the message to application */
1912   client->ops->channel_message(client, conn, nickname,
1913                                channel->channel_name,
1914                                silc_channel_get_data(payload, NULL));
1915
1916  out:
1917   if (id)
1918     silc_free(id);
1919   if (client_id)
1920     silc_free(client_id);
1921   if (payload)
1922     silc_channel_payload_free(payload);
1923 }
1924
1925 /* Private message received. This processes the private message and
1926    finally displays it on the screen. */
1927
1928 void silc_client_private_message(SilcClient client, 
1929                                  SilcSocketConnection sock, 
1930                                  SilcPacketContext *packet)
1931 {
1932   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1933   SilcBuffer buffer = packet->buffer;
1934   unsigned short nick_len;
1935   unsigned char *nickname, *message;
1936
1937   /* Get nickname */
1938   silc_buffer_unformat(buffer, 
1939                        SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
1940                        SILC_STR_END);
1941   silc_buffer_pull(buffer, 2 + nick_len);
1942      
1943   message = silc_calloc(buffer->len + 1, sizeof(char));
1944   memcpy(message, buffer->data, buffer->len);
1945
1946   /* Pass the private message to application */
1947   client->ops->private_message(client, conn, nickname, message);
1948
1949   /* See if we are away (gone). If we are away we will reply to the
1950      sender with the set away message. */
1951   if (conn->away && conn->away->away) {
1952     SilcClientID *remote_id;
1953     SilcClientEntry remote_client;
1954     SilcIDCacheEntry id_cache;
1955
1956     if (packet->src_id_type != SILC_ID_CLIENT)
1957       goto out;
1958
1959     remote_id = silc_id_str2id(packet->src_id, SILC_ID_CLIENT);
1960     if (!remote_id)
1961       goto out;
1962
1963     /* If it's me, ignore */
1964     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
1965       goto out;
1966
1967     /* Check whether we know this client already */
1968     if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
1969                                      SILC_ID_CLIENT, &id_cache))
1970       {
1971         /* Allocate client entry */
1972         remote_client = silc_calloc(1, sizeof(*remote_client));
1973         remote_client->id = remote_id;
1974         silc_parse_nickname(nickname, &remote_client->nickname, 
1975                             &remote_client->server, &remote_client->num);
1976
1977         /* Save the client to cache */
1978         silc_idcache_add(conn->client_cache, remote_client->nickname,
1979                          SILC_ID_CLIENT, remote_client->id, remote_client, 
1980                          TRUE);
1981       } else {
1982         silc_free(remote_id);
1983         remote_client = (SilcClientEntry)id_cache->context;
1984       }
1985
1986     /* Send the away message */
1987     silc_client_packet_send_private_message(client, sock, remote_client,
1988                                             conn->away->away,
1989                                             strlen(conn->away->away), TRUE);
1990   }
1991
1992  out:
1993   memset(message, 0, buffer->len);
1994   silc_free(message);
1995   silc_free(nickname);
1996 }
1997
1998 /* Removes a client entry from all channel it has joined. This really is
1999    a performance killer (client_entry should have pointers to channel 
2000    entry list). */
2001
2002 void silc_client_remove_from_channels(SilcClient client,
2003                                       SilcClientConnection conn,
2004                                       SilcClientEntry client_entry)
2005 {
2006   SilcIDCacheEntry id_cache;
2007   SilcIDCacheList list;
2008   SilcChannelEntry channel;
2009   SilcChannelUser chu;
2010   int i;
2011
2012   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2013                                SILC_ID_CHANNEL, &list))
2014     return;
2015
2016   silc_idcache_list_first(list, &id_cache);
2017   channel = (SilcChannelEntry)id_cache->context;
2018   
2019   while (channel) {
2020     
2021     /* Remove client from channel */
2022     silc_list_start(channel->clients);
2023     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2024       if (chu->client == client_entry) {
2025         silc_list_del(channel->clients, chu);
2026         silc_free(chu);
2027         break;
2028       }
2029     }
2030
2031     if (!silc_idcache_list_next(list, &id_cache))
2032       break;
2033     
2034     channel = (SilcChannelEntry)id_cache->context;
2035   }
2036
2037   silc_idcache_list_free(list);
2038 }
2039
2040 /* Replaces `old' client entries from all channels to `new' client entry.
2041    This can be called for example when nickname changes and old ID entry
2042    is replaced from ID cache with the new one. If the old ID entry is only
2043    updated, then this fucntion needs not to be called. */
2044
2045 void silc_client_replace_from_channels(SilcClient client, 
2046                                        SilcClientConnection conn,
2047                                        SilcClientEntry old,
2048                                        SilcClientEntry new)
2049 {
2050   SilcIDCacheEntry id_cache;
2051   SilcIDCacheList list;
2052   SilcChannelEntry channel;
2053   SilcChannelUser chu;
2054   int i;
2055
2056   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2057                                SILC_ID_CHANNEL, &list))
2058     return;
2059
2060   silc_idcache_list_first(list, &id_cache);
2061   channel = (SilcChannelEntry)id_cache->context;
2062   
2063   while (channel) {
2064     
2065     /* Replace client entry */
2066     silc_list_start(channel->clients);
2067     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2068       if (chu->client == old) {
2069         chu->client = new;
2070         break;
2071       }
2072     }
2073
2074     if (!silc_idcache_list_next(list, &id_cache))
2075       break;
2076     
2077     channel = (SilcChannelEntry)id_cache->context;
2078   }
2079
2080   silc_idcache_list_free(list);
2081 }
2082
2083 /* Parses mode mask and returns the mode as string. */
2084
2085 char *silc_client_chmode(unsigned int mode)
2086 {
2087   char string[20];
2088
2089   if (!mode)
2090     return NULL;
2091
2092   memset(string, 0, sizeof(string));
2093
2094   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2095     strncat(string, "p", 1);
2096
2097   if (mode & SILC_CHANNEL_MODE_SECRET)
2098     strncat(string, "s", 1);
2099
2100   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2101     strncat(string, "k", 1);
2102
2103   if (mode & SILC_CHANNEL_MODE_INVITE)
2104     strncat(string, "i", 1);
2105
2106   if (mode & SILC_CHANNEL_MODE_TOPIC)
2107     strncat(string, "t", 1);
2108
2109   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2110     strncat(string, "l", 1);
2111
2112   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2113     strncat(string, "a", 1);
2114
2115   /* Rest of mode is ignored */
2116
2117   return strdup(string);
2118 }
2119
2120 /* Parses channel user mode mask and returns te mode as string */
2121
2122 char *silc_client_chumode(unsigned int mode)
2123 {
2124   char string[4];
2125
2126   if (!mode)
2127     return NULL;
2128
2129   memset(string, 0, sizeof(string));
2130
2131   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2132     strncat(string, "f", 1);
2133
2134   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2135     strncat(string, "o", 1);
2136
2137   return strdup(string);
2138 }
2139
2140 /* Parses channel user mode and returns it as special mode character. */
2141
2142 char *silc_client_chumode_char(unsigned int mode)
2143 {
2144   char string[4];
2145
2146   if (!mode)
2147     return NULL;
2148
2149   memset(string, 0, sizeof(string));
2150
2151   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2152     strncat(string, "*", 1);
2153
2154   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2155     strncat(string, "@", 1);
2156
2157   return strdup(string);
2158 }