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