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