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