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