a5b3f8157c0599cd50530c7325e26a5e2e0fcc3f
[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                                  bool flush)
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 (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
648     force_send = FALSE;
649
650   /* Send the packet */
651   ret = silc_packet_send(sock, force_send);
652   if (ret != -2)
653     return ret;
654
655   /* Mark that there is some outgoing data available for this connection. 
656      This call sets the connection both for input and output (the input
657      is set always and this call keeps the input setting, actually). 
658      Actual data sending is performed by silc_client_packet_process. */
659   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
660
661   /* Mark to socket that data is pending in outgoing buffer. This flag
662      is needed if new data is added to the buffer before the earlier
663      put data is sent to the network. */
664   SILC_SET_OUTBUF_PENDING(sock);
665
666   return 0;
667 }
668
669 /* Packet processing callback. This is used to send and receive packets
670    from network. This is generic task. */
671
672 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
673 {
674   SilcClient client = (SilcClient)context;
675   SilcSocketConnection sock = NULL;
676   SilcClientConnection conn;
677   int ret;
678
679   SILC_LOG_DEBUG(("Processing packet"));
680
681   SILC_CLIENT_GET_SOCK(client, fd, sock);
682   if (sock == NULL)
683     return;
684
685   conn = (SilcClientConnection)sock->user_data;
686
687   /* Packet sending */
688   if (type == SILC_TASK_WRITE) {
689     SILC_LOG_DEBUG(("Writing data to connection"));
690
691     if (sock->outbuf->data - sock->outbuf->head)
692       silc_buffer_push(sock->outbuf, 
693                        sock->outbuf->data - sock->outbuf->head);
694
695     ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
696
697     /* If returned -2 could not write to connection now, will do
698        it later. */
699     if (ret == -2)
700       return;
701     
702     /* The packet has been sent and now it is time to set the connection
703        back to only for input. When there is again some outgoing data 
704        available for this connection it will be set for output as well. 
705        This call clears the output setting and sets it only for input. */
706     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
707     SILC_UNSET_OUTBUF_PENDING(sock);
708
709     silc_buffer_clear(sock->outbuf);
710     return;
711   }
712
713   /* Packet receiving */
714   if (type == SILC_TASK_READ) {
715     SILC_LOG_DEBUG(("Reading data from connection"));
716
717     /* Read data from network */
718     ret = silc_packet_receive(sock);
719     if (ret < 0)
720       return;
721     
722     /* EOF */
723     if (ret == 0) {
724       SILC_LOG_DEBUG(("Read EOF"));
725
726       /* If connection is disconnecting already we will finally
727          close the connection */
728       if (SILC_IS_DISCONNECTING(sock)) {
729         if (sock == conn->sock)
730           client->ops->disconnect(client, conn);
731         silc_client_close_connection(client, sock, conn);
732         return;
733       }
734       
735       SILC_LOG_DEBUG(("EOF from connection %d", sock->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     /* Process the packet. This will call the parser that will then
743        decrypt and parse the packet. */
744     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
745       silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
746                                   silc_client_packet_parse, client);
747     else
748       silc_packet_receive_process(sock, NULL, NULL,
749                                   silc_client_packet_parse, client);
750   }
751 }
752
753 /* Callback function that the silc_packet_decrypt will call to make the
754    decision whether the packet is normal or special packet. We will 
755    return TRUE if it is normal and FALSE if it is special */
756
757 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
758                                             SilcBuffer buffer,
759                                             SilcPacketContext *packet,
760                                             void *context)
761 {
762
763   /* Packet is normal packet, if: 
764
765      1) packet is private message packet and does not have private key set
766      2) is other packet than channel message packet
767
768      all other packets are special packets 
769   */
770
771   if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
772       (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
773     return FALSE;
774
775   if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
776     return TRUE;
777
778   return FALSE;
779 }
780
781 /* Parses whole packet, received earlier. */
782
783 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
784 {
785   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
786   SilcClient client = (SilcClient)parse_ctx->context;
787   SilcPacketContext *packet = parse_ctx->packet;
788   SilcBuffer buffer = packet->buffer;
789   SilcSocketConnection sock = parse_ctx->sock;
790   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
791   int ret;
792
793   SILC_LOG_DEBUG(("Start"));
794
795   /* Decrypt the received packet */
796   if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
797     ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive, 
798                               buffer, packet,
799                               silc_client_packet_decrypt_check, parse_ctx);
800   else
801     ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
802                               silc_client_packet_decrypt_check, parse_ctx);
803
804   if (ret < 0)
805     goto out;
806
807   if (ret == 0) {
808     /* Parse the packet. Packet type is returned. */
809     ret = silc_packet_parse(packet);
810   } else {
811     /* Parse the packet header in special way as this is "special"
812        packet type. */
813     ret = silc_packet_parse_special(packet);
814   }
815
816   if (ret == SILC_PACKET_NONE)
817     goto out;
818
819   /* Parse the incoming packet type */
820   silc_client_packet_parse_type(client, sock, packet);
821
822  out:
823   /*  silc_buffer_clear(sock->inbuf); */
824   silc_packet_context_free(packet);
825   silc_free(parse_ctx);
826 }
827
828 /* Parser callback called by silc_packet_receive_process. Thie merely
829    registers timeout that will handle the actual parsing when appropriate. */
830
831 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
832 {
833   SilcClient client = (SilcClient)parser_context->context;
834
835   /* Parse the packet */
836   silc_schedule_task_add(client->schedule, parser_context->sock->sock, 
837                          silc_client_packet_parse_real,
838                          (void *)parser_context, 0, 1, 
839                          SILC_TASK_TIMEOUT,
840                          SILC_TASK_PRI_NORMAL);
841 }
842
843 /* Parses the packet type and calls what ever routines the packet type
844    requires. This is done for all incoming packets. */
845
846 void silc_client_packet_parse_type(SilcClient client, 
847                                    SilcSocketConnection sock,
848                                    SilcPacketContext *packet)
849 {
850   SilcBuffer buffer = packet->buffer;
851   SilcPacketType type = packet->type;
852
853   SILC_LOG_DEBUG(("Parsing packet type %d", type));
854
855   /* Parse the packet type */
856   switch(type) {
857   case SILC_PACKET_DISCONNECT:
858     silc_client_disconnected_by_server(client, sock, buffer);
859     break;
860   case SILC_PACKET_SUCCESS:
861     /*
862      * Success received for something. For now we can have only
863      * one protocol for connection executing at once hence this
864      * success message is for whatever protocol is executing currently.
865      */
866     if (sock->protocol)
867       silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
868     break;
869   case SILC_PACKET_FAILURE:
870     /*
871      * Failure received for some protocol. Set the protocol state to 
872      * error and call the protocol callback. This fill cause error on
873      * protocol and it will call the final callback.
874      */
875     silc_client_process_failure(client, sock, packet);
876     break;
877   case SILC_PACKET_REJECT:
878     break;
879
880   case SILC_PACKET_NOTIFY:
881     /*
882      * Received notify message 
883      */
884     silc_client_notify_by_server(client, sock, packet);
885     break;
886
887   case SILC_PACKET_ERROR:
888     /*
889      * Received error message
890      */
891     silc_client_error_by_server(client, sock, buffer);
892     break;
893
894   case SILC_PACKET_CHANNEL_MESSAGE:
895     /*
896      * Received message to (from, actually) a channel
897      */
898     silc_client_channel_message(client, sock, packet);
899     break;
900   case SILC_PACKET_CHANNEL_KEY:
901     /*
902      * Received key for a channel. By receiving this key the client will be
903      * able to talk to the channel it has just joined. This can also be
904      * a new key for existing channel as keys expire peridiocally.
905      */
906     silc_client_receive_channel_key(client, sock, buffer);
907     break;
908
909   case SILC_PACKET_PRIVATE_MESSAGE:
910     /*
911      * Received private message
912      */
913     silc_client_private_message(client, sock, packet);
914     break;
915   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
916     /*
917      * Received private message key
918      */
919     break;
920
921   case SILC_PACKET_COMMAND_REPLY:
922     /*
923      * Recived reply for a command
924      */
925     silc_client_command_reply_process(client, sock, packet);
926     break;
927
928   case SILC_PACKET_KEY_EXCHANGE:
929     if (sock->protocol && sock->protocol->protocol && 
930         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
931       SilcClientKEInternalContext *proto_ctx = 
932         (SilcClientKEInternalContext *)sock->protocol->context;
933
934       proto_ctx->packet = silc_packet_context_dup(packet);
935       proto_ctx->dest_id_type = packet->src_id_type;
936       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
937                                           packet->src_id_type);
938       if (!proto_ctx->dest_id)
939         break;
940
941       /* Let the protocol handle the packet */
942       silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
943     } else {
944       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
945                       "protocol active, packet dropped."));
946     }
947     break;
948
949   case SILC_PACKET_KEY_EXCHANGE_1:
950     if (sock->protocol && sock->protocol->protocol && 
951         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
952          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
953
954       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
955         SilcClientRekeyInternalContext *proto_ctx = 
956           (SilcClientRekeyInternalContext *)sock->protocol->context;
957         
958         if (proto_ctx->packet)
959           silc_packet_context_free(proto_ctx->packet);
960         
961         proto_ctx->packet = silc_packet_context_dup(packet);
962
963         /* Let the protocol handle the packet */
964         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
965       } else {
966         SilcClientKEInternalContext *proto_ctx = 
967           (SilcClientKEInternalContext *)sock->protocol->context;
968         
969         if (proto_ctx->packet)
970           silc_packet_context_free(proto_ctx->packet);
971         
972         proto_ctx->packet = silc_packet_context_dup(packet);
973         proto_ctx->dest_id_type = packet->src_id_type;
974         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
975                                             packet->src_id_type);
976         if (!proto_ctx->dest_id)
977           break;
978         
979         /* Let the protocol handle the packet */
980         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
981       }
982     } else {
983       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
984                       "protocol active, packet dropped."));
985     }
986     break;
987   case SILC_PACKET_KEY_EXCHANGE_2:
988     if (sock->protocol && sock->protocol->protocol && 
989         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
990          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
991
992       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
993         SilcClientRekeyInternalContext *proto_ctx = 
994           (SilcClientRekeyInternalContext *)sock->protocol->context;
995         
996         if (proto_ctx->packet)
997           silc_packet_context_free(proto_ctx->packet);
998         
999         proto_ctx->packet = silc_packet_context_dup(packet);
1000
1001         /* Let the protocol handle the packet */
1002         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1003       } else {
1004         SilcClientKEInternalContext *proto_ctx = 
1005           (SilcClientKEInternalContext *)sock->protocol->context;
1006         
1007         if (proto_ctx->packet)
1008           silc_packet_context_free(proto_ctx->packet);
1009         
1010         proto_ctx->packet = silc_packet_context_dup(packet);
1011         proto_ctx->dest_id_type = packet->src_id_type;
1012         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1013                                             packet->src_id_type);
1014         if (!proto_ctx->dest_id)
1015           break;
1016         
1017         /* Let the protocol handle the packet */
1018         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1019       }
1020     } else {
1021       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1022                       "protocol active, packet dropped."));
1023     }
1024     break;
1025
1026   case SILC_PACKET_NEW_ID:
1027     {
1028       /*
1029        * Received new ID from server. This packet is received at
1030        * the connection to the server.  New ID is also received when 
1031        * user changes nickname but in that case the new ID is received
1032        * as command reply and not as this packet type.
1033        */
1034       SilcIDPayload idp;
1035
1036       idp = silc_id_payload_parse(buffer);
1037       if (!idp)
1038         break;
1039       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1040         break;
1041
1042       silc_client_receive_new_id(client, sock, idp);
1043       silc_id_payload_free(idp);
1044       break;
1045     }
1046
1047   case SILC_PACKET_HEARTBEAT:
1048     /*
1049      * Received heartbeat packet
1050      */
1051     SILC_LOG_DEBUG(("Heartbeat packet"));
1052     break;
1053
1054   case SILC_PACKET_KEY_AGREEMENT:
1055     /*
1056      * Received key agreement packet
1057      */
1058     SILC_LOG_DEBUG(("Key agreement packet"));
1059     silc_client_key_agreement(client, sock, packet);
1060     break;
1061
1062   case SILC_PACKET_REKEY:
1063     SILC_LOG_DEBUG(("Re-key packet"));
1064     /* We ignore this for now */
1065     break;
1066
1067   case SILC_PACKET_REKEY_DONE:
1068     SILC_LOG_DEBUG(("Re-key done packet"));
1069
1070     if (sock->protocol && sock->protocol->protocol && 
1071         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1072
1073       SilcClientRekeyInternalContext *proto_ctx = 
1074         (SilcClientRekeyInternalContext *)sock->protocol->context;
1075       
1076       if (proto_ctx->packet)
1077         silc_packet_context_free(proto_ctx->packet);
1078       
1079       proto_ctx->packet = silc_packet_context_dup(packet);
1080
1081       /* Let the protocol handle the packet */
1082       if (proto_ctx->responder == FALSE)
1083         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1084       else
1085         /* Let the protocol handle the packet */
1086         silc_protocol_execute(sock->protocol, client->schedule, 
1087                               0, 100000);
1088     } else {
1089       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1090                       "protocol active, packet dropped."));
1091     }
1092     break;
1093
1094   case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1095     /*
1096      * Reveived reply to our connection authentication method request
1097      * packet. This is used to resolve the authentication method for the
1098      * current session from the server if the client does not know it.
1099      */
1100     silc_client_connection_auth_request(client, sock, packet);
1101     break;
1102
1103   default:
1104     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1105     break;
1106   }
1107 }
1108
1109 /* Sends packet. This doesn't actually send the packet instead it assembles
1110    it and marks it to be sent. However, if force_send is TRUE the packet
1111    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1112    will be derived from sock argument. Otherwise the valid arguments sent
1113    are used. */
1114
1115 void silc_client_packet_send(SilcClient client, 
1116                              SilcSocketConnection sock,
1117                              SilcPacketType type, 
1118                              void *dst_id,
1119                              SilcIdType dst_id_type,
1120                              SilcCipher cipher,
1121                              SilcHmac hmac,
1122                              unsigned char *data, 
1123                              uint32 data_len, 
1124                              int force_send)
1125 {
1126   SilcPacketContext packetdata;
1127
1128   if (!sock)
1129     return;
1130
1131   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1132
1133   /* Get data used in the packet sending, keys and stuff */
1134   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1135     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1136       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1137
1138     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1139       hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1140
1141     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1142       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1143       dst_id_type = SILC_ID_SERVER;
1144     }
1145   }
1146
1147   /* Set the packet context pointers */
1148   packetdata.flags = 0;
1149   packetdata.type = type;
1150   if (sock->user_data && 
1151       ((SilcClientConnection)sock->user_data)->local_id_data) {
1152     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1153     packetdata.src_id_len = 
1154       silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1155                       SILC_ID_CLIENT);
1156   } else { 
1157     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1158     packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1159   }
1160   packetdata.src_id_type = SILC_ID_CLIENT;
1161   if (dst_id) {
1162     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1163     packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1164     packetdata.dst_id_type = dst_id_type;
1165   } else {
1166     packetdata.dst_id = NULL;
1167     packetdata.dst_id_len = 0;
1168     packetdata.dst_id_type = SILC_ID_NONE;
1169   }
1170   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1171     packetdata.src_id_len + packetdata.dst_id_len;
1172   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1173
1174   /* Prepare outgoing data buffer for packet sending */
1175   silc_packet_send_prepare(sock, 
1176                            SILC_PACKET_HEADER_LEN +
1177                            packetdata.src_id_len + 
1178                            packetdata.dst_id_len,
1179                            packetdata.padlen,
1180                            data_len);
1181
1182   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1183
1184   packetdata.buffer = sock->outbuf;
1185
1186   /* Put the data to the buffer */
1187   if (data && data_len)
1188     silc_buffer_put(sock->outbuf, data, data_len);
1189
1190   /* Create the outgoing packet */
1191   silc_packet_assemble(&packetdata);
1192
1193   /* Encrypt the packet */
1194   if (cipher)
1195     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1196
1197   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1198                    sock->outbuf->data, sock->outbuf->len);
1199
1200   /* Now actually send the packet */
1201   silc_client_packet_send_real(client, sock, force_send, FALSE);
1202 }
1203
1204 /* Closes connection to remote end. Free's all allocated data except
1205    for some information such as nickname etc. that are valid at all time. 
1206    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
1207    provided it will be checked whether the sock and `conn->sock' are the
1208    same (they can be different, ie. a socket can use `conn' as its
1209    connection but `conn->sock' might be actually a different connection
1210    than the `sock'). */
1211
1212 void silc_client_close_connection(SilcClient client,
1213                                   SilcSocketConnection sock,
1214                                   SilcClientConnection conn)
1215 {
1216   int del = FALSE;
1217
1218   if (!sock || (sock && conn->sock == sock))
1219     del = TRUE;
1220   if (!sock)
1221     sock = conn->sock;
1222
1223   /* We won't listen for this connection anymore */
1224   silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1225
1226   /* Unregister all tasks */
1227   silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1228   silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1229
1230   /* Close the actual connection */
1231   silc_net_close_connection(sock->sock);
1232
1233   /* Cancel any active protocol */
1234   if (sock->protocol) {
1235     if (sock->protocol->protocol->type == 
1236         SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1237         sock->protocol->protocol->type == 
1238         SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1239       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1240       silc_protocol_execute_final(sock->protocol, client->schedule);
1241       /* The application will recall this function with these protocols
1242          (the ops->connect client operation). */
1243       return;
1244     } else {
1245       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1246       silc_protocol_execute_final(sock->protocol, client->schedule);
1247       sock->protocol = NULL;
1248     }
1249   }
1250
1251   /* Free everything */
1252   if (del && sock->user_data) {
1253     /* Free all cache entries */
1254     SilcIDCacheList list;
1255     SilcIDCacheEntry entry;
1256     bool ret;
1257
1258     if (silc_idcache_get_all(conn->client_cache, &list)) {
1259       ret = silc_idcache_list_first(list, &entry);
1260       while (ret) {
1261         silc_client_del_client(client, conn, entry->context);
1262         ret = silc_idcache_list_next(list, &entry);
1263       }
1264       silc_idcache_list_free(list);
1265     }
1266
1267     if (silc_idcache_get_all(conn->channel_cache, &list)) {
1268       ret = silc_idcache_list_first(list, &entry);
1269       while (ret) {
1270         silc_client_del_channel(client, conn, entry->context);
1271         ret = silc_idcache_list_next(list, &entry);
1272       }
1273       silc_idcache_list_free(list);
1274     }
1275
1276     if (silc_idcache_get_all(conn->server_cache, &list)) {
1277       ret = silc_idcache_list_first(list, &entry);
1278       while (ret) {
1279         silc_client_del_server(client, conn, entry->context);
1280         ret = silc_idcache_list_next(list, &entry);
1281       }
1282       silc_idcache_list_free(list);
1283     }
1284
1285     /* Clear ID caches */
1286     if (conn->client_cache)
1287       silc_idcache_del_all(conn->client_cache);
1288     if (conn->channel_cache)
1289       silc_idcache_del_all(conn->channel_cache);
1290     if (conn->server_cache)
1291       silc_idcache_del_all(conn->server_cache);
1292
1293     /* Free data (my ID is freed in above silc_client_del_client) */
1294     if (conn->remote_host)
1295       silc_free(conn->remote_host);
1296     if (conn->local_id_data)
1297       silc_free(conn->local_id_data);
1298     if (conn->send_key)
1299       silc_cipher_free(conn->send_key);
1300     if (conn->receive_key)
1301       silc_cipher_free(conn->receive_key);
1302     if (conn->hmac_send)        /* conn->hmac_receive is same */
1303       silc_hmac_free(conn->hmac_send);
1304     if (conn->pending_commands)
1305       silc_dlist_uninit(conn->pending_commands);
1306     if (conn->rekey)
1307       silc_free(conn->rekey);
1308
1309     memset(conn, 0, sizeof(*conn));
1310     silc_client_del_connection(client, conn);
1311   }
1312
1313   silc_socket_free(sock);
1314 }
1315
1316 /* Called when we receive disconnection packet from server. This 
1317    closes our end properly and displays the reason of the disconnection
1318    on the screen. */
1319
1320 void silc_client_disconnected_by_server(SilcClient client,
1321                                         SilcSocketConnection sock,
1322                                         SilcBuffer message)
1323 {
1324   char *msg;
1325
1326   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1327
1328   msg = silc_calloc(message->len + 1, sizeof(char));
1329   memcpy(msg, message->data, message->len);
1330   client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1331   silc_free(msg);
1332
1333   SILC_SET_DISCONNECTED(sock);
1334   silc_client_close_connection(client, sock, sock->user_data);
1335 }
1336
1337 /* Received error message from server. Display it on the screen. 
1338    We don't take any action what so ever of the error message. */
1339
1340 void silc_client_error_by_server(SilcClient client,
1341                                  SilcSocketConnection sock,
1342                                  SilcBuffer message)
1343 {
1344   char *msg;
1345
1346   msg = silc_calloc(message->len + 1, sizeof(char));
1347   memcpy(msg, message->data, message->len);
1348   client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1349   silc_free(msg);
1350 }
1351
1352 /* Processes the received new Client ID from server. Old Client ID is
1353    deleted from cache and new one is added. */
1354
1355 void silc_client_receive_new_id(SilcClient client,
1356                                 SilcSocketConnection sock,
1357                                 SilcIDPayload idp)
1358 {
1359   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1360   int connecting = FALSE;
1361   SilcBuffer sidp;
1362
1363   if (!conn->local_entry)
1364     connecting = TRUE;
1365
1366   /* Delete old ID from ID cache */
1367   if (conn->local_id) {
1368     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1369     silc_free(conn->local_id);
1370   }
1371   
1372   /* Save the new ID */
1373
1374   if (conn->local_id_data)
1375     silc_free(conn->local_id_data);
1376
1377   conn->local_id = silc_id_payload_get_id(idp);
1378   conn->local_id_data = silc_id_payload_get_data(idp);
1379   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1380
1381   if (!conn->local_entry)
1382     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1383
1384   conn->local_entry->nickname = conn->nickname;
1385   if (!conn->local_entry->username)
1386     conn->local_entry->username = strdup(client->username);
1387   if (!conn->local_entry->hostname)
1388     conn->local_entry->hostname = strdup(client->hostname);
1389   conn->local_entry->server = strdup(conn->remote_host);
1390   conn->local_entry->id = conn->local_id;
1391   conn->local_entry->valid = TRUE;
1392   
1393   /* Put it to the ID cache */
1394   silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id, 
1395                    (void *)conn->local_entry, FALSE);
1396
1397   /* Issue INFO command to fetch the real server name and server information
1398      and other stuff. */
1399   sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1400   silc_client_send_command(client, conn, SILC_COMMAND_INFO,
1401                            ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1402   silc_buffer_free(sidp);
1403
1404   /* Notify application of successful connection. We do it here now that
1405      we've received the Client ID and are allowed to send traffic. */
1406   if (connecting)
1407     client->ops->connect(client, conn, TRUE);
1408 }
1409
1410 /* Processed received Channel ID for a channel. This is called when client
1411    joins to channel and server replies with channel ID. The ID is cached. 
1412    Returns the created channel entry. This is also called when received
1413    channel ID in for example USERS command reply that we do not have. */
1414
1415 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1416                                             SilcSocketConnection sock,
1417                                             char *channel_name,
1418                                             uint32 mode, 
1419                                             SilcIDPayload idp)
1420 {
1421   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1422   SilcChannelEntry channel;
1423
1424   SILC_LOG_DEBUG(("New channel ID"));
1425
1426   channel = silc_calloc(1, sizeof(*channel));
1427   channel->channel_name = channel_name;
1428   channel->id = silc_id_payload_get_id(idp);
1429   channel->mode = mode;
1430   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1431
1432   /* Put it to the ID cache */
1433   silc_idcache_add(conn->channel_cache, channel->channel_name, 
1434                    (void *)channel->id, (void *)channel, FALSE);
1435
1436   return channel;
1437 }
1438
1439 /* Removes a client entry from all channel it has joined. This really is
1440    a performance killer (client_entry should have pointers to channel 
1441    entry list). */
1442
1443 void silc_client_remove_from_channels(SilcClient client,
1444                                       SilcClientConnection conn,
1445                                       SilcClientEntry client_entry)
1446 {
1447   SilcIDCacheEntry id_cache;
1448   SilcIDCacheList list;
1449   SilcChannelEntry channel;
1450   SilcChannelUser chu;
1451
1452   if (!silc_idcache_get_all(conn->channel_cache, &list))
1453     return;
1454
1455   silc_idcache_list_first(list, &id_cache);
1456   channel = (SilcChannelEntry)id_cache->context;
1457   
1458   while (channel) {
1459     
1460     /* Remove client from channel */
1461     silc_list_start(channel->clients);
1462     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1463       if (chu->client == client_entry) {
1464         silc_list_del(channel->clients, chu);
1465         silc_free(chu);
1466         break;
1467       }
1468     }
1469
1470     if (!silc_idcache_list_next(list, &id_cache))
1471       break;
1472     
1473     channel = (SilcChannelEntry)id_cache->context;
1474   }
1475
1476   silc_idcache_list_free(list);
1477 }
1478
1479 /* Replaces `old' client entries from all channels to `new' client entry.
1480    This can be called for example when nickname changes and old ID entry
1481    is replaced from ID cache with the new one. If the old ID entry is only
1482    updated, then this fucntion needs not to be called. */
1483
1484 void silc_client_replace_from_channels(SilcClient client, 
1485                                        SilcClientConnection conn,
1486                                        SilcClientEntry old,
1487                                        SilcClientEntry new)
1488 {
1489   SilcIDCacheEntry id_cache;
1490   SilcIDCacheList list;
1491   SilcChannelEntry channel;
1492   SilcChannelUser chu;
1493
1494   if (!silc_idcache_get_all(conn->channel_cache, &list))
1495     return;
1496
1497   silc_idcache_list_first(list, &id_cache);
1498   channel = (SilcChannelEntry)id_cache->context;
1499   
1500   while (channel) {
1501     
1502     /* Replace client entry */
1503     silc_list_start(channel->clients);
1504     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1505       if (chu->client == old) {
1506         chu->client = new;
1507         break;
1508       }
1509     }
1510
1511     if (!silc_idcache_list_next(list, &id_cache))
1512       break;
1513     
1514     channel = (SilcChannelEntry)id_cache->context;
1515   }
1516
1517   silc_idcache_list_free(list);
1518 }
1519
1520 /* Registers failure timeout to process the received failure packet
1521    with timeout. */
1522
1523 void silc_client_process_failure(SilcClient client,
1524                                  SilcSocketConnection sock,
1525                                  SilcPacketContext *packet)
1526 {
1527   uint32 failure = 0;
1528
1529   if (sock->protocol) {
1530     if (packet->buffer->len >= 4)
1531       SILC_GET32_MSB(failure, packet->buffer->data);
1532
1533     /* Notify application */
1534     client->ops->failure(client, sock->user_data, sock->protocol,
1535                          (void *)failure);
1536   }
1537 }
1538
1539 /* A timeout callback for the re-key. We will be the initiator of the
1540    re-key protocol. */
1541
1542 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1543 {
1544   SilcSocketConnection sock = (SilcSocketConnection)context;
1545   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1546   SilcClient client = (SilcClient)conn->rekey->context;
1547   SilcProtocol protocol;
1548   SilcClientRekeyInternalContext *proto_ctx;
1549
1550   SILC_LOG_DEBUG(("Start"));
1551
1552   /* Allocate internal protocol context. This is sent as context
1553      to the protocol. */
1554   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1555   proto_ctx->client = (void *)client;
1556   proto_ctx->sock = silc_socket_dup(sock);
1557   proto_ctx->responder = FALSE;
1558   proto_ctx->pfs = conn->rekey->pfs;
1559       
1560   /* Perform rekey protocol. Will call the final callback after the
1561      protocol is over. */
1562   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1563                       &protocol, proto_ctx, silc_client_rekey_final);
1564   sock->protocol = protocol;
1565       
1566   /* Run the protocol */
1567   silc_protocol_execute(protocol, client->schedule, 0, 0);
1568
1569   /* Re-register re-key timeout */
1570   silc_schedule_task_add(client->schedule, sock->sock, 
1571                          silc_client_rekey_callback,
1572                          context, conn->rekey->timeout, 0,
1573                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1574 }
1575
1576 /* The final callback for the REKEY protocol. This will actually take the
1577    new key material into use. */
1578
1579 SILC_TASK_CALLBACK(silc_client_rekey_final)
1580 {
1581   SilcProtocol protocol = (SilcProtocol)context;
1582   SilcClientRekeyInternalContext *ctx =
1583     (SilcClientRekeyInternalContext *)protocol->context;
1584   SilcClient client = (SilcClient)ctx->client;
1585   SilcSocketConnection sock = ctx->sock;
1586
1587   SILC_LOG_DEBUG(("Start"));
1588
1589   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1590       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1591     /* Error occured during protocol */
1592     silc_protocol_cancel(protocol, client->schedule);
1593     silc_protocol_free(protocol);
1594     sock->protocol = NULL;
1595     if (ctx->packet)
1596       silc_packet_context_free(ctx->packet);
1597     if (ctx->ske)
1598       silc_ske_free(ctx->ske);
1599     silc_socket_free(ctx->sock);
1600     silc_free(ctx);
1601     return;
1602   }
1603
1604   /* Cleanup */
1605   silc_protocol_free(protocol);
1606   sock->protocol = NULL;
1607   if (ctx->packet)
1608     silc_packet_context_free(ctx->packet);
1609   if (ctx->ske)
1610     silc_ske_free(ctx->ske);
1611   silc_socket_free(ctx->sock);
1612   silc_free(ctx);
1613 }
1614
1615 /* Processes incoming connection authentication method request packet.
1616    It is a reply to our previously sent request. The packet can be used
1617    to resolve the authentication method for the current session if the
1618    client does not know it beforehand. */
1619
1620 void silc_client_connection_auth_request(SilcClient client,
1621                                          SilcSocketConnection sock,
1622                                          SilcPacketContext *packet)
1623 {
1624   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1625   uint16 conn_type, auth_meth;
1626   int ret;
1627
1628   /* If we haven't send our request then ignore this one. */
1629   if (!conn->connauth)
1630     return;
1631
1632   /* Parse the payload */
1633   ret = silc_buffer_unformat(packet->buffer,
1634                              SILC_STR_UI_SHORT(&conn_type),
1635                              SILC_STR_UI_SHORT(&auth_meth),
1636                              SILC_STR_END);
1637   if (ret == -1)
1638     auth_meth = SILC_AUTH_NONE;
1639
1640   /* Call the request callback to notify application for received 
1641      authentication method information. */
1642   if (conn->connauth->callback)
1643     (*conn->connauth->callback)(client, conn, auth_meth,
1644                                 conn->connauth->context);
1645
1646   silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1647
1648   silc_free(conn->connauth);
1649   conn->connauth = NULL;
1650 }
1651
1652 /* Timeout task callback called if the server does not reply to our 
1653    connection authentication method request in the specified time interval. */
1654
1655 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1656 {
1657   SilcClientConnection conn = (SilcClientConnection)context;
1658   SilcClient client = conn->client;
1659
1660   if (!conn->connauth)
1661     return;
1662
1663   /* Call the request callback to notify application */
1664   if (conn->connauth->callback)
1665     (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1666                                 conn->connauth->context);
1667
1668   silc_free(conn->connauth);
1669   conn->connauth = NULL;
1670 }
1671
1672 /* This function can be used to request the current authentication method
1673    from the server. This may be called when connecting to the server
1674    and the client library requests the authentication data from the
1675    application. If the application does not know the current authentication
1676    method it can request it from the server using this function.
1677    The `callback' with `context' will be called after the server has
1678    replied back with the current authentication method. */
1679
1680 void 
1681 silc_client_request_authentication_method(SilcClient client,
1682                                           SilcClientConnection conn,
1683                                           SilcConnectionAuthRequest callback,
1684                                           void *context)
1685 {
1686   SilcClientConnAuthRequest connauth;
1687   SilcBuffer packet;
1688
1689   connauth = silc_calloc(1, sizeof(*connauth));
1690   connauth->callback = callback;
1691   connauth->context = context;
1692
1693   if (conn->connauth)
1694     silc_free(conn->connauth);
1695
1696   conn->connauth = connauth;
1697
1698   /* Assemble the request packet and send it to the server */
1699   packet = silc_buffer_alloc(4);
1700   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1701   silc_buffer_format(packet,
1702                      SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1703                      SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1704                      SILC_STR_END);
1705   silc_client_packet_send(client, conn->sock, 
1706                           SILC_PACKET_CONNECTION_AUTH_REQUEST,
1707                           NULL, 0, NULL, NULL, 
1708                           packet->data, packet->len, FALSE);
1709   silc_buffer_free(packet);
1710
1711   /* Register a timeout in case server does not reply anything back. */
1712   connauth->timeout =
1713     silc_schedule_task_add(client->schedule, conn->sock->sock, 
1714                            silc_client_request_authentication_method_timeout,
1715                            conn, client->params->connauth_request_secs, 0,
1716                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1717 }