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