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