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