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