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