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