updates.
[silc.git] / lib / silcclient / client.c
1 /*
2
3   client.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "clientlibincludes.h"
23 #include "client_internal.h"
24
25 /* Static task callback prototypes */
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
28 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
30 SILC_TASK_CALLBACK(silc_client_rekey_callback);
31 SILC_TASK_CALLBACK(silc_client_rekey_final);
32
33 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
34 static void silc_client_packet_parse_type(SilcClient client, 
35                                           SilcSocketConnection sock,
36                                           SilcPacketContext *packet);
37
38 /* Allocates new client object. This has to be done before client may
39    work. After calling this one must call silc_client_init to initialize
40    the client. The `application' is application specific user data pointer
41    and caller must free it. */
42
43 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
44 {
45   SilcClient new_client;
46
47   new_client = silc_calloc(1, sizeof(*new_client));
48   new_client->application = application;
49   new_client->ops = ops;
50
51   return new_client;
52 }
53
54 /* Frees client object and its internals. */
55
56 void silc_client_free(SilcClient client)
57 {
58   if (client) {
59     if (client->rng)
60       silc_rng_free(client->rng);
61
62     silc_free(client);
63   }
64 }
65
66 /* Initializes the client. This makes all the necessary steps to make
67    the client ready to be run. One must call silc_client_run to run the
68    client. Returns FALSE if error occured, TRUE otherwise. */
69
70 int silc_client_init(SilcClient client)
71 {
72   SILC_LOG_DEBUG(("Initializing client"));
73
74   /* Initialize hash functions for client to use */
75   silc_hash_alloc("md5", &client->md5hash);
76   silc_hash_alloc("sha1", &client->sha1hash);
77
78   /* Initialize none cipher */
79   silc_cipher_alloc("none", &client->none_cipher);
80
81   /* Initialize random number generator */
82   client->rng = silc_rng_alloc();
83   silc_rng_init(client->rng);
84   silc_rng_global_init(client->rng);
85
86   /* Register protocols */
87   silc_client_protocols_register();
88
89   /* Initialize the scheduler */
90   silc_schedule_init(&client->io_queue, &client->timeout_queue, 
91                      &client->generic_queue, 5000);
92
93   return TRUE;
94 }
95
96 /* Stops the client. This is called to stop the client and thus to stop
97    the program. */
98
99 void silc_client_stop(SilcClient client)
100 {
101   SILC_LOG_DEBUG(("Stopping client"));
102
103   /* Stop the scheduler, although it might be already stopped. This
104      doesn't hurt anyone. This removes all the tasks and task queues,
105      as well. */
106   silc_schedule_stop();
107   silc_schedule_uninit();
108
109   silc_client_protocols_unregister();
110
111   SILC_LOG_DEBUG(("Client stopped"));
112 }
113
114 /* Runs the client. This starts the scheduler from the utility library.
115    When this functions returns the execution of the appliation is over. */
116
117 void silc_client_run(SilcClient client)
118 {
119   SILC_LOG_DEBUG(("Running client"));
120
121   /* Start the scheduler, the heart of the SILC client. When this returns
122      the program will be terminated. */
123   silc_schedule();
124 }
125
126 /* Allocates and adds new connection to the client. This adds the allocated
127    connection to the connection table and returns a pointer to it. A client
128    can have multiple connections to multiple servers. Every connection must
129    be added to the client using this function. User data `context' may
130    be sent as argument. This function is normally used only if the 
131    application performed the connecting outside the library. The library
132    however may use this internally. */
133
134 SilcClientConnection silc_client_add_connection(SilcClient client,
135                                                 char *hostname,
136                                                 int port,
137                                                 void *context)
138 {
139   SilcClientConnection conn;
140   int i;
141
142   conn = silc_calloc(1, sizeof(*conn));
143
144   /* Initialize ID caches */
145   conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
146   conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
147   conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
148   conn->client = client;
149   conn->remote_host = strdup(hostname);
150   conn->remote_port = port;
151   conn->context = context;
152   conn->pending_commands = silc_dlist_init();
153
154   /* Add the connection to connections table */
155   for (i = 0; i < client->conns_count; i++)
156     if (client->conns && !client->conns[i]) {
157       client->conns[i] = conn;
158       return conn;
159     }
160
161   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
162                                * (client->conns_count + 1));
163   client->conns[client->conns_count] = conn;
164   client->conns_count++;
165
166   return conn;
167 }
168
169 /* Removes connection from client. Frees all memory. */
170
171 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
172 {
173   int i;
174
175   for (i = 0; i < client->conns_count; i++)
176     if (client->conns[i] == conn) {
177       if (conn->pending_commands)
178         silc_dlist_uninit(conn->pending_commands);
179       silc_free(conn);
180       client->conns[i] = NULL;
181     }
182 }
183
184 /* Adds listener socket to the listener sockets table. This function is
185    used to add socket objects that are listeners to the client.  This should
186    not be used to add other connection objects. */
187
188 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
189 {
190   int i;
191
192   if (!client->sockets) {
193     client->sockets = silc_calloc(1, sizeof(*client->sockets));
194     client->sockets[0] = silc_socket_dup(sock);
195     client->sockets_count = 1;
196     return;
197   }
198
199   for (i = 0; i < client->sockets_count; i++) {
200     if (client->sockets[i] == NULL) {
201       client->sockets[i] = silc_socket_dup(sock);
202       return;
203     }
204   }
205
206   client->sockets = silc_realloc(client->sockets, sizeof(*client->sockets) *
207                                  (client->sockets_count + 1));
208   client->sockets[client->sockets_count] = silc_socket_dup(sock);
209   client->sockets_count++;
210 }
211
212 /* Deletes listener socket from the listener sockets table. */
213
214 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
215 {
216   int i;
217
218   if (!client->sockets)
219     return;
220
221   for (i = 0; i < client->sockets_count; i++) {
222     if (client->sockets[i] == sock) {
223       silc_socket_free(sock);
224       client->sockets[i] = NULL;
225       return;
226     }
227   }
228 }
229
230 static int 
231 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
232 {
233   int sock;
234
235   /* XXX In the future we should give up this non-blocking connect all
236      together and use threads instead. */
237   /* Create connection to server asynchronously */
238   sock = silc_net_create_connection_async(ctx->port, ctx->host);
239   if (sock < 0)
240     return -1;
241
242   /* Register task that will receive the async connect and will
243      read the result. */
244   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
245                                  silc_client_connect_to_server_start,
246                                  (void *)ctx, 0, 0, 
247                                  SILC_TASK_FD,
248                                  SILC_TASK_PRI_NORMAL);
249   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
250   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
251
252   ctx->sock = sock;
253
254   return sock;
255 }
256
257 /* Connects to remote server. This is the main routine used to connect
258    to SILC server. Returns -1 on error and the created socket otherwise. 
259    The `context' is user context that is saved into the SilcClientConnection
260    that is created after the connection is created. Note that application
261    may handle the connecting process outside the library. If this is the
262    case then this function is not used at all. When the connecting is
263    done the `connect' client operation is called. */
264
265 int silc_client_connect_to_server(SilcClient client, int port,
266                                   char *host, void *context)
267 {
268   SilcClientInternalConnectContext *ctx;
269   SilcClientConnection conn;
270   int sock;
271
272   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
273                   port, host));
274
275   conn = silc_client_add_connection(client, host, port, context);
276
277   client->ops->say(client, conn, 
278                    "Connecting to port %d of server %s", port, host);
279
280   /* Allocate internal context for connection process. This is
281      needed as we are doing async connecting. */
282   ctx = silc_calloc(1, sizeof(*ctx));
283   ctx->client = client;
284   ctx->conn = conn;
285   ctx->host = strdup(host);
286   ctx->port = port;
287   ctx->tries = 0;
288
289   /* Do the actual connecting process */
290   sock = silc_client_connect_to_server_internal(ctx);
291   if (sock == -1)
292     silc_client_del_connection(client, conn);
293   return sock;
294 }
295
296 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
297    key material between client and server.  This function can be called
298    directly if application is performing its own connecting and does not
299    use the connecting provided by this library. This function is normally
300    used only if the application performed the connecting outside the library.
301    The library however may use this internally. */
302
303 int silc_client_start_key_exchange(SilcClient client,
304                                    SilcClientConnection conn,
305                                    int fd)
306 {
307   SilcProtocol protocol;
308   SilcClientKEInternalContext *proto_ctx;
309   void *context;
310
311   /* Allocate new socket connection object */
312   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
313
314   conn->nickname = strdup(client->username);
315   conn->sock->hostname = conn->remote_host;
316   conn->sock->ip = strdup(conn->remote_host);
317   conn->sock->port = conn->remote_port;
318
319   /* Allocate internal Key Exchange context. This is sent to the
320      protocol as context. */
321   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
322   proto_ctx->client = (void *)client;
323   proto_ctx->sock = silc_socket_dup(conn->sock);
324   proto_ctx->rng = client->rng;
325   proto_ctx->responder = FALSE;
326   proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
327   proto_ctx->verify = silc_client_protocol_ke_verify_key;
328
329   /* Perform key exchange protocol. silc_client_connect_to_server_final
330      will be called after the protocol is finished. */
331   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
332                       &protocol, (void *)proto_ctx,
333                       silc_client_connect_to_server_second);
334   if (!protocol) {
335     client->ops->say(client, conn, 
336                      "Error: Could not start authentication protocol");
337     return FALSE;
338   }
339   conn->sock->protocol = protocol;
340
341   /* Register the connection for network input and output. This sets
342      that scheduler will listen for incoming packets for this connection 
343      and sets that outgoing packets may be sent to this connection as well.
344      However, this doesn't set the scheduler for outgoing traffic, it will 
345      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
346      later when outgoing data is available. */
347   context = (void *)client;
348   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
349
350   /* Execute the protocol */
351   silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
352   return TRUE;
353 }
354
355 /* Start of the connection to the remote server. This is called after
356    succesful TCP/IP connection has been established to the remote host. */
357
358 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
359 {
360   SilcClientInternalConnectContext *ctx =
361     (SilcClientInternalConnectContext *)context;
362   SilcClient client = ctx->client;
363   SilcClientConnection conn = ctx->conn;
364   int opt, opt_len = sizeof(opt);
365
366   SILC_LOG_DEBUG(("Start"));
367
368   /* Check the socket status as it might be in error */
369   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
370   if (opt != 0) {
371     if (ctx->tries < 2) {
372       /* Connection failed but lets try again */
373       client->ops->say(client, conn, "Could not connect to server %s: %s",
374                        ctx->host, strerror(opt));
375       client->ops->say(client, conn, 
376                        "Connecting to port %d of server %s resumed", 
377                        ctx->port, ctx->host);
378
379       /* Unregister old connection try */
380       silc_schedule_unset_listen_fd(fd);
381       silc_net_close_connection(fd);
382       silc_task_unregister(client->io_queue, ctx->task);
383
384       /* Try again */
385       silc_client_connect_to_server_internal(ctx);
386       ctx->tries++;
387     } else {
388       /* Connection failed and we won't try anymore */
389       client->ops->say(client, conn, "Could not connect to server %s: %s",
390                        ctx->host, strerror(opt));
391       silc_schedule_unset_listen_fd(fd);
392       silc_net_close_connection(fd);
393       silc_task_unregister(client->io_queue, ctx->task);
394       silc_free(ctx);
395
396       /* Notify application of failure */
397       client->ops->connect(client, conn, FALSE);
398       silc_client_del_connection(client, conn);
399     }
400     return;
401   }
402
403   silc_schedule_unset_listen_fd(fd);
404   silc_task_unregister(client->io_queue, ctx->task);
405   silc_free(ctx);
406
407   if (!silc_client_start_key_exchange(client, conn, fd)) {
408     silc_net_close_connection(fd);
409     client->ops->connect(client, conn, FALSE);
410   }
411 }
412
413 /* Second part of the connecting to the server. This executed 
414    authentication protocol. */
415
416 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
417 {
418   SilcProtocol protocol = (SilcProtocol)context;
419   SilcClientKEInternalContext *ctx = 
420     (SilcClientKEInternalContext *)protocol->context;
421   SilcClient client = (SilcClient)ctx->client;
422   SilcSocketConnection sock = NULL;
423   SilcClientConnAuthInternalContext *proto_ctx;
424
425   SILC_LOG_DEBUG(("Start"));
426
427   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
428       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
429     /* Error occured during protocol */
430     SILC_LOG_DEBUG(("Error during KE protocol"));
431     silc_protocol_free(protocol);
432     silc_ske_free_key_material(ctx->keymat);
433     if (ctx->ske)
434       silc_ske_free(ctx->ske);
435     if (ctx->dest_id)
436       silc_free(ctx->dest_id);
437     ctx->sock->protocol = NULL;
438     silc_socket_free(ctx->sock);
439
440     /* Notify application of failure */
441     client->ops->connect(client, ctx->sock->user_data, FALSE);
442     silc_free(ctx);
443     return;
444   }
445
446   /* We now have the key material as the result of the key exchange
447      protocol. Take the key material into use. Free the raw key material
448      as soon as we've set them into use. */
449   silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
450                                    ctx->ske->prop->cipher,
451                                    ctx->ske->prop->pkcs,
452                                    ctx->ske->prop->hash,
453                                    ctx->ske->prop->hmac,
454                                    ctx->ske->prop->group);
455   silc_ske_free_key_material(ctx->keymat);
456
457   /* Allocate internal context for the authentication protocol. This
458      is sent as context for the protocol. */
459   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
460   proto_ctx->client = (void *)client;
461   proto_ctx->sock = sock = ctx->sock;
462   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
463   proto_ctx->dest_id_type = ctx->dest_id_type;
464   proto_ctx->dest_id = ctx->dest_id;
465
466   /* Resolve the authentication method to be used in this connection */
467   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
468                                     sock->port, &proto_ctx->auth_meth,
469                                     &proto_ctx->auth_data, 
470                                     &proto_ctx->auth_data_len))
471     proto_ctx->auth_meth = SILC_AUTH_NONE;
472
473   /* Free old protocol as it is finished now */
474   silc_protocol_free(protocol);
475   if (ctx->packet)
476     silc_packet_context_free(ctx->packet);
477   silc_free(ctx);
478   sock->protocol = NULL;
479
480   /* Allocate the authenteication protocol and execute it. */
481   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
482                       &sock->protocol, (void *)proto_ctx, 
483                       silc_client_connect_to_server_final);
484
485   /* Execute the protocol */
486   silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
487 }
488
489 /* Finalizes the connection to the remote SILC server. This is called
490    after authentication protocol has been completed. This send our
491    user information to the server to receive our client ID from
492    server. */
493
494 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
495 {
496   SilcProtocol protocol = (SilcProtocol)context;
497   SilcClientConnAuthInternalContext *ctx = 
498     (SilcClientConnAuthInternalContext *)protocol->context;
499   SilcClient client = (SilcClient)ctx->client;
500   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
501   SilcBuffer packet;
502
503   SILC_LOG_DEBUG(("Start"));
504
505   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
506       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
507     /* Error occured during protocol */
508     SILC_LOG_DEBUG(("Error during authentication protocol"));
509     silc_protocol_free(protocol);
510     if (ctx->auth_data)
511       silc_free(ctx->auth_data);
512     if (ctx->ske)
513       silc_ske_free(ctx->ske);
514     if (ctx->dest_id)
515       silc_free(ctx->dest_id);
516     conn->sock->protocol = NULL;
517     silc_socket_free(ctx->sock);
518
519     /* Notify application of failure */
520     client->ops->connect(client, ctx->sock->user_data, FALSE);
521     silc_free(ctx);
522     return;
523   }
524
525   /* Send NEW_CLIENT packet to the server. We will become registered
526      to the SILC network after sending this packet and we will receive
527      client ID from the server. */
528   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
529                              strlen(client->realname));
530   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
531   silc_buffer_format(packet,
532                      SILC_STR_UI_SHORT(strlen(client->username)),
533                      SILC_STR_UI_XNSTRING(client->username,
534                                           strlen(client->username)),
535                      SILC_STR_UI_SHORT(strlen(client->realname)),
536                      SILC_STR_UI_XNSTRING(client->realname,
537                                           strlen(client->realname)),
538                      SILC_STR_END);
539
540   /* Send the packet */
541   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
542                           NULL, 0, NULL, NULL, 
543                           packet->data, packet->len, TRUE);
544   silc_buffer_free(packet);
545
546   /* Save remote ID. */
547   conn->remote_id = ctx->dest_id;
548   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
549   conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
550
551   /* Register re-key timeout */
552   conn->rekey->timeout = 3600; /* XXX hardcoded */
553   conn->rekey->context = (void *)client;
554   silc_task_register(client->timeout_queue, conn->sock->sock, 
555                      silc_client_rekey_callback,
556                      (void *)conn->sock, conn->rekey->timeout, 0,
557                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
558
559   silc_protocol_free(protocol);
560   if (ctx->auth_data)
561     silc_free(ctx->auth_data);
562   if (ctx->ske)
563     silc_ske_free(ctx->ske);
564   silc_socket_free(ctx->sock);
565   silc_free(ctx);
566   conn->sock->protocol = NULL;
567 }
568
569 /* Internal routine that sends packet or marks packet to be sent. This
570    is used directly only in special cases. Normal cases should use
571    silc_server_packet_send. Returns < 0 on error. */
572
573 int silc_client_packet_send_real(SilcClient client,
574                                  SilcSocketConnection sock,
575                                  bool force_send,
576                                  bool flush)
577 {
578   int ret;
579
580   /* If rekey protocol is active we must assure that all packets are
581      sent through packet queue. */
582   if (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
583     force_send = FALSE;
584
585   /* Send the packet */
586   ret = silc_packet_send(sock, force_send);
587   if (ret != -2)
588     return ret;
589
590   /* Mark that there is some outgoing data available for this connection. 
591      This call sets the connection both for input and output (the input
592      is set always and this call keeps the input setting, actually). 
593      Actual data sending is performed by silc_client_packet_process. */
594   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
595
596   /* Mark to socket that data is pending in outgoing buffer. This flag
597      is needed if new data is added to the buffer before the earlier
598      put data is sent to the network. */
599   SILC_SET_OUTBUF_PENDING(sock);
600
601   return 0;
602 }
603
604 /* Packet processing callback. This is used to send and receive packets
605    from network. This is generic task. */
606
607 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
608 {
609   SilcClient client = (SilcClient)context;
610   SilcSocketConnection sock = NULL;
611   SilcClientConnection conn;
612   int ret;
613
614   SILC_LOG_DEBUG(("Processing packet"));
615
616   SILC_CLIENT_GET_SOCK(client, fd, sock);
617   if (sock == NULL)
618     return;
619
620   conn = (SilcClientConnection)sock->user_data;
621
622   /* Packet sending */
623   if (type == SILC_TASK_WRITE) {
624     SILC_LOG_DEBUG(("Writing data to connection"));
625
626     if (sock->outbuf->data - sock->outbuf->head)
627       silc_buffer_push(sock->outbuf, 
628                        sock->outbuf->data - sock->outbuf->head);
629
630     ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
631
632     /* If returned -2 could not write to connection now, will do
633        it later. */
634     if (ret == -2)
635       return;
636     
637     /* The packet has been sent and now it is time to set the connection
638        back to only for input. When there is again some outgoing data 
639        available for this connection it will be set for output as well. 
640        This call clears the output setting and sets it only for input. */
641     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
642     SILC_UNSET_OUTBUF_PENDING(sock);
643
644     silc_buffer_clear(sock->outbuf);
645     return;
646   }
647
648   /* Packet receiving */
649   if (type == SILC_TASK_READ) {
650     SILC_LOG_DEBUG(("Reading data from connection"));
651
652     /* Read data from network */
653     ret = silc_packet_receive(sock);
654     if (ret < 0)
655       return;
656     
657     /* EOF */
658     if (ret == 0) {
659       SILC_LOG_DEBUG(("Read EOF"));
660
661       /* If connection is disconnecting already we will finally
662          close the connection */
663       if (SILC_IS_DISCONNECTING(sock)) {
664         if (sock == conn->sock)
665           client->ops->disconnect(client, conn);
666         silc_client_close_connection(client, sock, conn);
667         return;
668       }
669       
670       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
671       if (sock == conn->sock)
672         client->ops->disconnect(client, conn);
673       silc_client_close_connection(client, sock, conn);
674       return;
675     }
676
677     /* Process the packet. This will call the parser that will then
678        decrypt and parse the packet. */
679     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
680       silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
681                                   silc_client_packet_parse, client);
682     else
683       silc_packet_receive_process(sock, NULL, NULL,
684                                   silc_client_packet_parse, client);
685   }
686 }
687
688 /* Callback function that the silc_packet_decrypt will call to make the
689    decision whether the packet is normal or special packet. We will 
690    return TRUE if it is normal and FALSE if it is special */
691
692 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
693                                             SilcBuffer buffer,
694                                             SilcPacketContext *packet,
695                                             void *context)
696 {
697
698   /* Packet is normal packet, if: 
699
700      1) packet is private message packet and does not have private key set
701      2) is other packet than channel message packet
702
703      all other packets are special packets 
704   */
705
706   if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
707       (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
708     return FALSE;
709
710   if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
711     return TRUE;
712
713   return FALSE;
714 }
715
716 /* Parses whole packet, received earlier. */
717
718 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
719 {
720   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
721   SilcClient client = (SilcClient)parse_ctx->context;
722   SilcPacketContext *packet = parse_ctx->packet;
723   SilcBuffer buffer = packet->buffer;
724   SilcSocketConnection sock = parse_ctx->sock;
725   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
726   int ret;
727
728   SILC_LOG_DEBUG(("Start"));
729
730   /* Decrypt the received packet */
731   if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
732     ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive, 
733                               buffer, packet,
734                               silc_client_packet_decrypt_check, parse_ctx);
735   else
736     ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
737                               silc_client_packet_decrypt_check, parse_ctx);
738
739   if (ret < 0)
740     goto out;
741
742   if (ret == 0) {
743     /* Parse the packet. Packet type is returned. */
744     ret = silc_packet_parse(packet);
745   } else {
746     /* Parse the packet header in special way as this is "special"
747        packet type. */
748     ret = silc_packet_parse_special(packet);
749   }
750
751   if (ret == SILC_PACKET_NONE)
752     goto out;
753
754   /* Parse the incoming packet type */
755   silc_client_packet_parse_type(client, sock, packet);
756
757  out:
758   /*  silc_buffer_clear(sock->inbuf); */
759   silc_packet_context_free(packet);
760   silc_free(parse_ctx);
761 }
762
763 /* Parser callback called by silc_packet_receive_process. Thie merely
764    registers timeout that will handle the actual parsing when appropriate. */
765
766 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
767 {
768   SilcClient client = (SilcClient)parser_context->context;
769
770   /* Parse the packet */
771   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
772                      silc_client_packet_parse_real,
773                      (void *)parser_context, 0, 1, 
774                      SILC_TASK_TIMEOUT,
775                      SILC_TASK_PRI_NORMAL);
776 }
777
778 /* Parses the packet type and calls what ever routines the packet type
779    requires. This is done for all incoming packets. */
780
781 void silc_client_packet_parse_type(SilcClient client, 
782                                    SilcSocketConnection sock,
783                                    SilcPacketContext *packet)
784 {
785   SilcBuffer buffer = packet->buffer;
786   SilcPacketType type = packet->type;
787
788   SILC_LOG_DEBUG(("Parsing packet type %d", type));
789
790   /* Parse the packet type */
791   switch(type) {
792   case SILC_PACKET_DISCONNECT:
793     silc_client_disconnected_by_server(client, sock, buffer);
794     break;
795   case SILC_PACKET_SUCCESS:
796     /*
797      * Success received for something. For now we can have only
798      * one protocol for connection executing at once hence this
799      * success message is for whatever protocol is executing currently.
800      */
801     if (sock->protocol)
802       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
803     break;
804   case SILC_PACKET_FAILURE:
805     /*
806      * Failure received for some protocol. Set the protocol state to 
807      * error and call the protocol callback. This fill cause error on
808      * protocol and it will call the final callback.
809      */
810     silc_client_process_failure(client, sock, packet);
811     break;
812   case SILC_PACKET_REJECT:
813     break;
814
815   case SILC_PACKET_NOTIFY:
816     /*
817      * Received notify message 
818      */
819     silc_client_notify_by_server(client, sock, packet);
820     break;
821
822   case SILC_PACKET_ERROR:
823     /*
824      * Received error message
825      */
826     silc_client_error_by_server(client, sock, buffer);
827     break;
828
829   case SILC_PACKET_CHANNEL_MESSAGE:
830     /*
831      * Received message to (from, actually) a channel
832      */
833     silc_client_channel_message(client, sock, packet);
834     break;
835   case SILC_PACKET_CHANNEL_KEY:
836     /*
837      * Received key for a channel. By receiving this key the client will be
838      * able to talk to the channel it has just joined. This can also be
839      * a new key for existing channel as keys expire peridiocally.
840      */
841     silc_client_receive_channel_key(client, sock, buffer);
842     break;
843
844   case SILC_PACKET_PRIVATE_MESSAGE:
845     /*
846      * Received private message
847      */
848     silc_client_private_message(client, sock, packet);
849     break;
850   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
851     /*
852      * Received private message key
853      */
854     break;
855
856   case SILC_PACKET_COMMAND_REPLY:
857     /*
858      * Recived reply for a command
859      */
860     silc_client_command_reply_process(client, sock, packet);
861     break;
862
863   case SILC_PACKET_KEY_EXCHANGE:
864     if (sock->protocol && sock->protocol->protocol && 
865         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
866       SilcClientKEInternalContext *proto_ctx = 
867         (SilcClientKEInternalContext *)sock->protocol->context;
868
869       proto_ctx->packet = silc_packet_context_dup(packet);
870       proto_ctx->dest_id_type = packet->src_id_type;
871       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
872                                           packet->src_id_type);
873       if (!proto_ctx->dest_id)
874         break;
875
876       /* Let the protocol handle the packet */
877       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
878     } else {
879       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
880                       "protocol active, packet dropped."));
881     }
882     break;
883
884   case SILC_PACKET_KEY_EXCHANGE_1:
885     if (sock->protocol && sock->protocol->protocol && 
886         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
887          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
888
889       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
890         SilcClientRekeyInternalContext *proto_ctx = 
891           (SilcClientRekeyInternalContext *)sock->protocol->context;
892         
893         if (proto_ctx->packet)
894           silc_packet_context_free(proto_ctx->packet);
895         
896         proto_ctx->packet = silc_packet_context_dup(packet);
897
898         /* Let the protocol handle the packet */
899         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
900       } else {
901         SilcClientKEInternalContext *proto_ctx = 
902           (SilcClientKEInternalContext *)sock->protocol->context;
903         
904         if (proto_ctx->packet)
905           silc_packet_context_free(proto_ctx->packet);
906         
907         proto_ctx->packet = silc_packet_context_dup(packet);
908         proto_ctx->dest_id_type = packet->src_id_type;
909         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
910                                             packet->src_id_type);
911         if (!proto_ctx->dest_id)
912           break;
913         
914         /* Let the protocol handle the packet */
915         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
916       }
917     } else {
918       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
919                       "protocol active, packet dropped."));
920     }
921     break;
922   case SILC_PACKET_KEY_EXCHANGE_2:
923     if (sock->protocol && sock->protocol->protocol && 
924         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
925          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
926
927       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
928         SilcClientRekeyInternalContext *proto_ctx = 
929           (SilcClientRekeyInternalContext *)sock->protocol->context;
930         
931         if (proto_ctx->packet)
932           silc_packet_context_free(proto_ctx->packet);
933         
934         proto_ctx->packet = silc_packet_context_dup(packet);
935
936         /* Let the protocol handle the packet */
937         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
938       } else {
939         SilcClientKEInternalContext *proto_ctx = 
940           (SilcClientKEInternalContext *)sock->protocol->context;
941         
942         if (proto_ctx->packet)
943           silc_packet_context_free(proto_ctx->packet);
944         
945         proto_ctx->packet = silc_packet_context_dup(packet);
946         proto_ctx->dest_id_type = packet->src_id_type;
947         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
948                                             packet->src_id_type);
949         if (!proto_ctx->dest_id)
950           break;
951         
952         /* Let the protocol handle the packet */
953         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
954       }
955     } else {
956       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
957                       "protocol active, packet dropped."));
958     }
959     break;
960
961   case SILC_PACKET_NEW_ID:
962     {
963       /*
964        * Received new ID from server. This packet is received at
965        * the connection to the server.  New ID is also received when 
966        * user changes nickname but in that case the new ID is received
967        * as command reply and not as this packet type.
968        */
969       SilcIDPayload idp;
970
971       idp = silc_id_payload_parse(buffer);
972       if (!idp)
973         break;
974       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
975         break;
976
977       silc_client_receive_new_id(client, sock, idp);
978       silc_id_payload_free(idp);
979       break;
980     }
981
982   case SILC_PACKET_HEARTBEAT:
983     /*
984      * Received heartbeat packet
985      */
986     SILC_LOG_DEBUG(("Heartbeat packet"));
987     break;
988
989   case SILC_PACKET_KEY_AGREEMENT:
990     /*
991      * Received key agreement packet
992      */
993     SILC_LOG_DEBUG(("Key agreement packet"));
994     silc_client_key_agreement(client, sock, packet);
995     break;
996
997   case SILC_PACKET_REKEY:
998     SILC_LOG_DEBUG(("Re-key packet"));
999     /* We ignore this for now */
1000     break;
1001
1002   case SILC_PACKET_REKEY_DONE:
1003     SILC_LOG_DEBUG(("Re-key done packet"));
1004
1005     if (sock->protocol && sock->protocol->protocol && 
1006         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1007
1008       SilcClientRekeyInternalContext *proto_ctx = 
1009         (SilcClientRekeyInternalContext *)sock->protocol->context;
1010       
1011       if (proto_ctx->packet)
1012         silc_packet_context_free(proto_ctx->packet);
1013       
1014       proto_ctx->packet = silc_packet_context_dup(packet);
1015
1016       /* Let the protocol handle the packet */
1017       if (proto_ctx->responder == FALSE)
1018         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
1019       else
1020         /* Let the protocol handle the packet */
1021         silc_protocol_execute(sock->protocol, client->timeout_queue, 
1022                               0, 100000);
1023     } else {
1024       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1025                       "protocol active, packet dropped."));
1026     }
1027     break;
1028
1029   default:
1030     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1031     break;
1032   }
1033 }
1034
1035 /* Sends packet. This doesn't actually send the packet instead it assembles
1036    it and marks it to be sent. However, if force_send is TRUE the packet
1037    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1038    will be derived from sock argument. Otherwise the valid arguments sent
1039    are used. */
1040
1041 void silc_client_packet_send(SilcClient client, 
1042                              SilcSocketConnection sock,
1043                              SilcPacketType type, 
1044                              void *dst_id,
1045                              SilcIdType dst_id_type,
1046                              SilcCipher cipher,
1047                              SilcHmac hmac,
1048                              unsigned char *data, 
1049                              uint32 data_len, 
1050                              int force_send)
1051 {
1052   SilcPacketContext packetdata;
1053
1054   if (!sock)
1055     return;
1056
1057   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1058
1059   /* Get data used in the packet sending, keys and stuff */
1060   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1061     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1062       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1063
1064     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1065       hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1066
1067     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1068       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1069       dst_id_type = SILC_ID_SERVER;
1070     }
1071   }
1072
1073   /* Set the packet context pointers */
1074   packetdata.flags = 0;
1075   packetdata.type = type;
1076   if (sock->user_data && 
1077       ((SilcClientConnection)sock->user_data)->local_id_data) {
1078     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1079     packetdata.src_id_len = 
1080       silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1081                       SILC_ID_CLIENT);
1082   } else { 
1083     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1084     packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1085   }
1086   packetdata.src_id_type = SILC_ID_CLIENT;
1087   if (dst_id) {
1088     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1089     packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1090     packetdata.dst_id_type = dst_id_type;
1091   } else {
1092     packetdata.dst_id = NULL;
1093     packetdata.dst_id_len = 0;
1094     packetdata.dst_id_type = SILC_ID_NONE;
1095   }
1096   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1097     packetdata.src_id_len + packetdata.dst_id_len;
1098   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1099
1100   /* Prepare outgoing data buffer for packet sending */
1101   silc_packet_send_prepare(sock, 
1102                            SILC_PACKET_HEADER_LEN +
1103                            packetdata.src_id_len + 
1104                            packetdata.dst_id_len,
1105                            packetdata.padlen,
1106                            data_len);
1107
1108   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1109
1110   packetdata.buffer = sock->outbuf;
1111
1112   /* Put the data to the buffer */
1113   if (data && data_len)
1114     silc_buffer_put(sock->outbuf, data, data_len);
1115
1116   /* Create the outgoing packet */
1117   silc_packet_assemble(&packetdata);
1118
1119   /* Encrypt the packet */
1120   if (cipher)
1121     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1122
1123   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1124                    sock->outbuf->data, sock->outbuf->len);
1125
1126   /* Now actually send the packet */
1127   silc_client_packet_send_real(client, sock, force_send, FALSE);
1128 }
1129
1130 /* Closes connection to remote end. Free's all allocated data except
1131    for some information such as nickname etc. that are valid at all time. 
1132    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
1133    provided it will be checked whether the sock and `conn->sock' are the
1134    same (they can be different, ie. a socket can use `conn' as its
1135    connection but `conn->sock' might be actually a different connection
1136    than the `sock'). */
1137
1138 void silc_client_close_connection(SilcClient client,
1139                                   SilcSocketConnection sock,
1140                                   SilcClientConnection conn)
1141 {
1142   int del = FALSE;
1143
1144   if (!sock || (sock && conn->sock == sock))
1145     del = TRUE;
1146   if (!sock)
1147     sock = conn->sock;
1148
1149   /* We won't listen for this connection anymore */
1150   silc_schedule_unset_listen_fd(sock->sock);
1151
1152   /* Unregister all tasks */
1153   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1154   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1155
1156   /* Close the actual connection */
1157   silc_net_close_connection(sock->sock);
1158
1159   /* Free everything */
1160   if (del && sock->user_data) {
1161     /* XXX Free all client entries and channel entries. */
1162
1163     client->ops->say(client, sock->user_data,
1164                      "Closed connection to host %s", sock->hostname);
1165
1166     /* Clear ID caches */
1167     silc_idcache_del_all(conn->client_cache);
1168     silc_idcache_del_all(conn->channel_cache);
1169
1170     /* Free data */
1171     if (conn->remote_host)
1172       silc_free(conn->remote_host);
1173     if (conn->local_id)
1174       silc_free(conn->local_id);
1175     if (conn->local_id_data)
1176       silc_free(conn->local_id_data);
1177     if (conn->send_key)
1178       silc_cipher_free(conn->send_key);
1179     if (conn->receive_key)
1180       silc_cipher_free(conn->receive_key);
1181     if (conn->hmac_send)        /* conn->hmac_receive is same */
1182       silc_hmac_free(conn->hmac_send);
1183     if (conn->pending_commands)
1184       silc_dlist_uninit(conn->pending_commands);
1185     if (conn->rekey)
1186       silc_free(conn->rekey);
1187
1188     conn->sock = NULL;
1189     conn->remote_port = 0;
1190     conn->remote_type = 0;
1191     conn->send_key = NULL;
1192     conn->receive_key = NULL;
1193     conn->hmac_send = NULL;
1194     conn->hmac_receive = NULL;
1195     conn->local_id = NULL;
1196     conn->local_id_data = NULL;
1197     conn->remote_host = NULL;
1198     conn->current_channel = NULL;
1199     conn->pending_commands = NULL;
1200     conn->rekey = NULL;
1201
1202     silc_client_del_connection(client, conn);
1203   }
1204
1205   if (sock->protocol) {
1206     silc_protocol_free(sock->protocol);
1207     sock->protocol = NULL;
1208   }
1209   silc_socket_free(sock);
1210 }
1211
1212 /* Called when we receive disconnection packet from server. This 
1213    closes our end properly and displays the reason of the disconnection
1214    on the screen. */
1215
1216 void silc_client_disconnected_by_server(SilcClient client,
1217                                         SilcSocketConnection sock,
1218                                         SilcBuffer message)
1219 {
1220   char *msg;
1221
1222   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1223
1224   msg = silc_calloc(message->len + 1, sizeof(char));
1225   memcpy(msg, message->data, message->len);
1226   client->ops->say(client, sock->user_data, msg);
1227   silc_free(msg);
1228
1229   SILC_SET_DISCONNECTED(sock);
1230   silc_client_close_connection(client, sock, sock->user_data);
1231 }
1232
1233 /* Received error message from server. Display it on the screen. 
1234    We don't take any action what so ever of the error message. */
1235
1236 void silc_client_error_by_server(SilcClient client,
1237                                  SilcSocketConnection sock,
1238                                  SilcBuffer message)
1239 {
1240   char *msg;
1241
1242   msg = silc_calloc(message->len + 1, sizeof(char));
1243   memcpy(msg, message->data, message->len);
1244   client->ops->say(client, sock->user_data, msg);
1245   silc_free(msg);
1246 }
1247
1248 /* Processes the received new Client ID from server. Old Client ID is
1249    deleted from cache and new one is added. */
1250
1251 void silc_client_receive_new_id(SilcClient client,
1252                                 SilcSocketConnection sock,
1253                                 SilcIDPayload idp)
1254 {
1255   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1256   int connecting = FALSE;
1257
1258   if (!conn->local_entry)
1259     connecting = TRUE;
1260
1261   /* Delete old ID from ID cache */
1262   if (conn->local_id) {
1263     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1264     silc_free(conn->local_id);
1265   }
1266   
1267   /* Save the new ID */
1268
1269   if (conn->local_id_data)
1270     silc_free(conn->local_id_data);
1271
1272   conn->local_id = silc_id_payload_get_id(idp);
1273   conn->local_id_data = silc_id_payload_get_data(idp);
1274   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1275
1276   if (!conn->local_entry)
1277     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1278
1279   conn->local_entry->nickname = conn->nickname;
1280   if (!conn->local_entry->username) {
1281     conn->local_entry->username = 
1282       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1283                   sizeof(conn->local_entry->username));
1284     sprintf(conn->local_entry->username, "%s@%s", client->username,
1285             client->hostname);
1286   }
1287   conn->local_entry->server = strdup(conn->remote_host);
1288   conn->local_entry->id = conn->local_id;
1289   
1290   /* Put it to the ID cache */
1291   silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id, 
1292                    (void *)conn->local_entry, FALSE);
1293
1294   /* Notify application of successful connection. We do it here now that
1295      we've received the Client ID and are allowed to send traffic. */
1296   if (connecting)
1297     client->ops->connect(client, conn, TRUE);
1298 }
1299
1300 /* Processed received Channel ID for a channel. This is called when client
1301    joins to channel and server replies with channel ID. The ID is cached. 
1302    Returns the created channel entry. */
1303
1304 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1305                                             SilcSocketConnection sock,
1306                                             char *channel_name,
1307                                             uint32 mode, 
1308                                             SilcIDPayload idp)
1309 {
1310   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1311   SilcChannelEntry channel;
1312
1313   SILC_LOG_DEBUG(("New channel ID"));
1314
1315   channel = silc_calloc(1, sizeof(*channel));
1316   channel->channel_name = channel_name;
1317   channel->id = silc_id_payload_get_id(idp);
1318   channel->mode = mode;
1319   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1320
1321   conn->current_channel = channel;
1322
1323   /* Put it to the ID cache */
1324   silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id, 
1325                    (void *)channel, FALSE);
1326
1327   return channel;
1328 }
1329
1330 /* Removes a client entry from all channel it has joined. This really is
1331    a performance killer (client_entry should have pointers to channel 
1332    entry list). */
1333
1334 void silc_client_remove_from_channels(SilcClient client,
1335                                       SilcClientConnection conn,
1336                                       SilcClientEntry client_entry)
1337 {
1338   SilcIDCacheEntry id_cache;
1339   SilcIDCacheList list;
1340   SilcChannelEntry channel;
1341   SilcChannelUser chu;
1342
1343   if (!silc_idcache_get_all(conn->channel_cache, &list))
1344     return;
1345
1346   silc_idcache_list_first(list, &id_cache);
1347   channel = (SilcChannelEntry)id_cache->context;
1348   
1349   while (channel) {
1350     
1351     /* Remove client from channel */
1352     silc_list_start(channel->clients);
1353     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1354       if (chu->client == client_entry) {
1355         silc_list_del(channel->clients, chu);
1356         silc_free(chu);
1357         break;
1358       }
1359     }
1360
1361     if (!silc_idcache_list_next(list, &id_cache))
1362       break;
1363     
1364     channel = (SilcChannelEntry)id_cache->context;
1365   }
1366
1367   silc_idcache_list_free(list);
1368 }
1369
1370 /* Replaces `old' client entries from all channels to `new' client entry.
1371    This can be called for example when nickname changes and old ID entry
1372    is replaced from ID cache with the new one. If the old ID entry is only
1373    updated, then this fucntion needs not to be called. */
1374
1375 void silc_client_replace_from_channels(SilcClient client, 
1376                                        SilcClientConnection conn,
1377                                        SilcClientEntry old,
1378                                        SilcClientEntry new)
1379 {
1380   SilcIDCacheEntry id_cache;
1381   SilcIDCacheList list;
1382   SilcChannelEntry channel;
1383   SilcChannelUser chu;
1384
1385   if (!silc_idcache_get_all(conn->channel_cache, &list))
1386     return;
1387
1388   silc_idcache_list_first(list, &id_cache);
1389   channel = (SilcChannelEntry)id_cache->context;
1390   
1391   while (channel) {
1392     
1393     /* Replace client entry */
1394     silc_list_start(channel->clients);
1395     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1396       if (chu->client == old) {
1397         chu->client = new;
1398         break;
1399       }
1400     }
1401
1402     if (!silc_idcache_list_next(list, &id_cache))
1403       break;
1404     
1405     channel = (SilcChannelEntry)id_cache->context;
1406   }
1407
1408   silc_idcache_list_free(list);
1409 }
1410
1411 /* Registers failure timeout to process the received failure packet
1412    with timeout. */
1413
1414 void silc_client_process_failure(SilcClient client,
1415                                  SilcSocketConnection sock,
1416                                  SilcPacketContext *packet)
1417 {
1418   uint32 failure = 0;
1419
1420   if (sock->protocol) {
1421     if (packet->buffer->len >= 4)
1422       SILC_GET32_MSB(failure, packet->buffer->data);
1423
1424     /* Notify application */
1425     client->ops->failure(client, sock->user_data, sock->protocol,
1426                          (void *)failure);
1427   }
1428 }
1429
1430 /* A timeout callback for the re-key. We will be the initiator of the
1431    re-key protocol. */
1432
1433 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1434 {
1435   SilcSocketConnection sock = (SilcSocketConnection)context;
1436   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1437   SilcClient client = (SilcClient)conn->rekey->context;
1438   SilcProtocol protocol;
1439   SilcClientRekeyInternalContext *proto_ctx;
1440
1441   SILC_LOG_DEBUG(("Start"));
1442
1443   /* Allocate internal protocol context. This is sent as context
1444      to the protocol. */
1445   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1446   proto_ctx->client = (void *)client;
1447   proto_ctx->sock = silc_socket_dup(sock);
1448   proto_ctx->responder = FALSE;
1449   proto_ctx->pfs = conn->rekey->pfs;
1450       
1451   /* Perform rekey protocol. Will call the final callback after the
1452      protocol is over. */
1453   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1454                       &protocol, proto_ctx, silc_client_rekey_final);
1455   sock->protocol = protocol;
1456       
1457   /* Run the protocol */
1458   silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
1459
1460   /* Re-register re-key timeout */
1461   silc_task_register(client->timeout_queue, sock->sock, 
1462                      silc_client_rekey_callback,
1463                      context, conn->rekey->timeout, 0,
1464                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1465 }
1466
1467 /* The final callback for the REKEY protocol. This will actually take the
1468    new key material into use. */
1469
1470 SILC_TASK_CALLBACK(silc_client_rekey_final)
1471 {
1472   SilcProtocol protocol = (SilcProtocol)context;
1473   SilcClientRekeyInternalContext *ctx =
1474     (SilcClientRekeyInternalContext *)protocol->context;
1475   SilcClient client = (SilcClient)ctx->client;
1476   SilcSocketConnection sock = ctx->sock;
1477
1478   SILC_LOG_DEBUG(("Start"));
1479
1480   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1481       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1482     /* Error occured during protocol */
1483     silc_protocol_cancel(protocol, client->timeout_queue);
1484     silc_protocol_free(protocol);
1485     sock->protocol = NULL;
1486     if (ctx->packet)
1487       silc_packet_context_free(ctx->packet);
1488     if (ctx->ske)
1489       silc_ske_free(ctx->ske);
1490     silc_socket_free(ctx->sock);
1491     silc_free(ctx);
1492     return;
1493   }
1494
1495   /* Cleanup */
1496   silc_protocol_free(protocol);
1497   sock->protocol = NULL;
1498   if (ctx->packet)
1499     silc_packet_context_free(ctx->packet);
1500   if (ctx->ske)
1501     silc_ske_free(ctx->ske);
1502   silc_socket_free(ctx->sock);
1503   silc_free(ctx);
1504 }