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