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