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