a7eaf0bdb33decdacd8062c7ac407b297b5ab58c
[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   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
775                      silc_client_packet_parse_real,
776                      (void *)parser_context, 0, 1, 
777                      SILC_TASK_TIMEOUT,
778                      SILC_TASK_PRI_NORMAL);
779 }
780
781 /* Parses the packet type and calls what ever routines the packet type
782    requires. This is done for all incoming packets. */
783
784 void silc_client_packet_parse_type(SilcClient client, 
785                                    SilcSocketConnection sock,
786                                    SilcPacketContext *packet)
787 {
788   SilcBuffer buffer = packet->buffer;
789   SilcPacketType type = packet->type;
790
791   SILC_LOG_DEBUG(("Parsing packet type %d", type));
792
793   /* Parse the packet type */
794   switch(type) {
795   case SILC_PACKET_DISCONNECT:
796     silc_client_disconnected_by_server(client, sock, buffer);
797     break;
798   case SILC_PACKET_SUCCESS:
799     /*
800      * Success received for something. For now we can have only
801      * one protocol for connection executing at once hence this
802      * success message is for whatever protocol is executing currently.
803      */
804     if (sock->protocol) {
805       sock->protocol->execute(client->timeout_queue, 0,
806                               sock->protocol, sock->sock, 0, 0);
807     }
808     break;
809   case SILC_PACKET_FAILURE:
810     /*
811      * Failure received for some protocol. Set the protocol state to 
812      * error and call the protocol callback. This fill cause error on
813      * protocol and it will call the final callback.
814      */
815     silc_client_process_failure(client, sock, packet);
816     break;
817   case SILC_PACKET_REJECT:
818     break;
819
820   case SILC_PACKET_NOTIFY:
821     /*
822      * Received notify message 
823      */
824     silc_client_notify_by_server(client, sock, packet);
825     break;
826
827   case SILC_PACKET_ERROR:
828     /*
829      * Received error message
830      */
831     silc_client_error_by_server(client, sock, buffer);
832     break;
833
834   case SILC_PACKET_CHANNEL_MESSAGE:
835     /*
836      * Received message to (from, actually) a channel
837      */
838     silc_client_channel_message(client, sock, packet);
839     break;
840   case SILC_PACKET_CHANNEL_KEY:
841     /*
842      * Received key for a channel. By receiving this key the client will be
843      * able to talk to the channel it has just joined. This can also be
844      * a new key for existing channel as keys expire peridiocally.
845      */
846     silc_client_receive_channel_key(client, sock, buffer);
847     break;
848
849   case SILC_PACKET_PRIVATE_MESSAGE:
850     /*
851      * Received private message
852      */
853     silc_client_private_message(client, sock, packet);
854     break;
855   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
856     /*
857      * Received private message key
858      */
859     break;
860
861   case SILC_PACKET_COMMAND_REPLY:
862     /*
863      * Recived reply for a command
864      */
865     silc_client_command_reply_process(client, sock, packet);
866     break;
867
868   case SILC_PACKET_KEY_EXCHANGE:
869     if (sock->protocol && sock->protocol->protocol && 
870         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
871       SilcClientKEInternalContext *proto_ctx = 
872         (SilcClientKEInternalContext *)sock->protocol->context;
873
874       proto_ctx->packet = silc_packet_context_dup(packet);
875       proto_ctx->dest_id_type = packet->src_id_type;
876       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
877                                           packet->src_id_type);
878       if (!proto_ctx->dest_id)
879         break;
880
881       /* Let the protocol handle the packet */
882       sock->protocol->execute(client->timeout_queue, 0,
883                               sock->protocol, sock->sock, 0, 0);
884     } else {
885       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
886                       "protocol active, packet dropped."));
887
888       /* XXX Trigger KE protocol?? Rekey actually! */
889     }
890     break;
891
892   case SILC_PACKET_KEY_EXCHANGE_1:
893     if (sock->protocol && sock->protocol->protocol && 
894         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
895          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
896
897       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
898         SilcClientRekeyInternalContext *proto_ctx = 
899           (SilcClientRekeyInternalContext *)sock->protocol->context;
900         
901         if (proto_ctx->packet)
902           silc_packet_context_free(proto_ctx->packet);
903         
904         proto_ctx->packet = silc_packet_context_dup(packet);
905
906         /* Let the protocol handle the packet */
907         sock->protocol->execute(client->timeout_queue, 0, 
908                                 sock->protocol, sock->sock, 0, 0);
909       } else {
910         SilcClientKEInternalContext *proto_ctx = 
911           (SilcClientKEInternalContext *)sock->protocol->context;
912         
913         if (proto_ctx->packet)
914           silc_packet_context_free(proto_ctx->packet);
915         
916         proto_ctx->packet = silc_packet_context_dup(packet);
917         proto_ctx->dest_id_type = packet->src_id_type;
918         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
919                                             packet->src_id_type);
920         if (!proto_ctx->dest_id)
921           break;
922         
923         /* Let the protocol handle the packet */
924         sock->protocol->execute(client->timeout_queue, 0,
925                                 sock->protocol, sock->sock, 0, 0);
926       }
927     } else {
928       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
929                       "protocol active, packet dropped."));
930     }
931     break;
932   case SILC_PACKET_KEY_EXCHANGE_2:
933     if (sock->protocol && sock->protocol->protocol && 
934         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
935          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
936
937       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
938         SilcClientRekeyInternalContext *proto_ctx = 
939           (SilcClientRekeyInternalContext *)sock->protocol->context;
940         
941         if (proto_ctx->packet)
942           silc_packet_context_free(proto_ctx->packet);
943         
944         proto_ctx->packet = silc_packet_context_dup(packet);
945
946         /* Let the protocol handle the packet */
947         sock->protocol->execute(client->timeout_queue, 0, 
948                                 sock->protocol, sock->sock, 0, 0);
949       } else {
950         SilcClientKEInternalContext *proto_ctx = 
951           (SilcClientKEInternalContext *)sock->protocol->context;
952         
953         if (proto_ctx->packet)
954           silc_packet_context_free(proto_ctx->packet);
955         
956         proto_ctx->packet = silc_packet_context_dup(packet);
957         proto_ctx->dest_id_type = packet->src_id_type;
958         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
959                                             packet->src_id_type);
960         if (!proto_ctx->dest_id)
961           break;
962         
963         /* Let the protocol handle the packet */
964         sock->protocol->execute(client->timeout_queue, 0,
965                                 sock->protocol, sock->sock, 0, 0);
966       }
967     } else {
968       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
969                       "protocol active, packet dropped."));
970     }
971     break;
972
973   case SILC_PACKET_NEW_ID:
974     {
975       /*
976        * Received new ID from server. This packet is received at
977        * the connection to the server.  New ID is also received when 
978        * user changes nickname but in that case the new ID is received
979        * as command reply and not as this packet type.
980        */
981       SilcIDPayload idp;
982
983       idp = silc_id_payload_parse(buffer);
984       if (!idp)
985         break;
986       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
987         break;
988
989       silc_client_receive_new_id(client, sock, idp);
990       silc_id_payload_free(idp);
991       break;
992     }
993
994   case SILC_PACKET_HEARTBEAT:
995     /*
996      * Received heartbeat packet
997      */
998     SILC_LOG_DEBUG(("Heartbeat packet"));
999     break;
1000
1001   case SILC_PACKET_KEY_AGREEMENT:
1002     /*
1003      * Received key agreement packet
1004      */
1005     SILC_LOG_DEBUG(("Key agreement packet"));
1006     silc_client_key_agreement(client, sock, packet);
1007     break;
1008
1009   case SILC_PACKET_REKEY:
1010     SILC_LOG_DEBUG(("Re-key packet"));
1011     /* We ignore this for now */
1012     break;
1013
1014   case SILC_PACKET_REKEY_DONE:
1015     SILC_LOG_DEBUG(("Re-key done packet"));
1016
1017     if (sock->protocol && sock->protocol->protocol && 
1018         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1019
1020       SilcClientRekeyInternalContext *proto_ctx = 
1021         (SilcClientRekeyInternalContext *)sock->protocol->context;
1022       
1023       if (proto_ctx->packet)
1024         silc_packet_context_free(proto_ctx->packet);
1025       
1026       proto_ctx->packet = silc_packet_context_dup(packet);
1027
1028       /* Let the protocol handle the packet */
1029       if (proto_ctx->responder == FALSE)
1030         sock->protocol->execute(client->timeout_queue, 0, 
1031                                 sock->protocol, sock->sock, 0, 0);
1032       else
1033         /* Let the protocol handle the packet */
1034         sock->protocol->execute(client->timeout_queue, 0, 
1035                                 sock->protocol, sock->sock, 0, 100000);
1036     } else {
1037       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1038                       "protocol active, packet dropped."));
1039     }
1040     break;
1041
1042   default:
1043     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1044     break;
1045   }
1046 }
1047
1048 /* Sends packet. This doesn't actually send the packet instead it assembles
1049    it and marks it to be sent. However, if force_send is TRUE the packet
1050    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1051    will be derived from sock argument. Otherwise the valid arguments sent
1052    are used. */
1053
1054 void silc_client_packet_send(SilcClient client, 
1055                              SilcSocketConnection sock,
1056                              SilcPacketType type, 
1057                              void *dst_id,
1058                              SilcIdType dst_id_type,
1059                              SilcCipher cipher,
1060                              SilcHmac hmac,
1061                              unsigned char *data, 
1062                              uint32 data_len, 
1063                              int force_send)
1064 {
1065   SilcPacketContext packetdata;
1066
1067   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1068
1069   /* Get data used in the packet sending, keys and stuff */
1070   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1071     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1072       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1073
1074     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1075       hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1076
1077     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1078       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1079       dst_id_type = SILC_ID_SERVER;
1080     }
1081   }
1082
1083   /* Set the packet context pointers */
1084   packetdata.flags = 0;
1085   packetdata.type = type;
1086   if (sock->user_data && 
1087       ((SilcClientConnection)sock->user_data)->local_id_data)
1088     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1089   else 
1090     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1091   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1092   packetdata.src_id_type = SILC_ID_CLIENT;
1093   if (dst_id) {
1094     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1095     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
1096     packetdata.dst_id_type = dst_id_type;
1097   } else {
1098     packetdata.dst_id = NULL;
1099     packetdata.dst_id_len = 0;
1100     packetdata.dst_id_type = SILC_ID_NONE;
1101   }
1102   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1103     packetdata.src_id_len + packetdata.dst_id_len;
1104   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1105
1106   /* Prepare outgoing data buffer for packet sending */
1107   silc_packet_send_prepare(sock, 
1108                            SILC_PACKET_HEADER_LEN +
1109                            packetdata.src_id_len + 
1110                            packetdata.dst_id_len,
1111                            packetdata.padlen,
1112                            data_len);
1113
1114   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1115
1116   packetdata.buffer = sock->outbuf;
1117
1118   /* Put the data to the buffer */
1119   if (data && data_len)
1120     silc_buffer_put(sock->outbuf, data, data_len);
1121
1122   /* Create the outgoing packet */
1123   silc_packet_assemble(&packetdata);
1124
1125   /* Encrypt the packet */
1126   if (cipher)
1127     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1128
1129   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1130                    sock->outbuf->data, sock->outbuf->len);
1131
1132   /* Now actually send the packet */
1133   silc_client_packet_send_real(client, sock, force_send, FALSE);
1134 }
1135
1136 void silc_client_packet_send_flush(SilcClient client, 
1137                                    SilcSocketConnection sock,
1138                                    SilcPacketType type, 
1139                                    void *dst_id,
1140                                    SilcIdType dst_id_type,
1141                                    SilcCipher cipher,
1142                                    SilcHmac hmac,
1143                                    unsigned char *data, 
1144                                    uint32 data_len)
1145 {
1146   SilcPacketContext packetdata;
1147
1148   /* First flush the packet queue. */
1149   
1150   if (sock->outbuf->data - sock->outbuf->head)
1151     silc_buffer_push(sock->outbuf, 
1152                      sock->outbuf->data - sock->outbuf->head);
1153   
1154   silc_client_packet_send_real(client, sock, TRUE, TRUE);
1155   
1156   /* The packet has been sent and now it is time to set the connection
1157      back to only for input. When there is again some outgoing data 
1158      available for this connection it will be set for output as well. 
1159      This call clears the output setting and sets it only for input. */
1160   SILC_CLIENT_SET_CONNECTION_FOR_INPUT(sock->sock);
1161   SILC_UNSET_OUTBUF_PENDING(sock);
1162   silc_buffer_clear(sock->outbuf);
1163
1164   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1165
1166   /* Get data used in the packet sending, keys and stuff */
1167   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1168     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1169       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1170
1171     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1172       hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1173
1174     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1175       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1176       dst_id_type = SILC_ID_SERVER;
1177     }
1178   }
1179
1180   /* Set the packet context pointers */
1181   packetdata.flags = 0;
1182   packetdata.type = type;
1183   if (sock->user_data && 
1184       ((SilcClientConnection)sock->user_data)->local_id_data)
1185     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1186   else 
1187     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1188   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1189   packetdata.src_id_type = SILC_ID_CLIENT;
1190   if (dst_id) {
1191     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1192     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
1193     packetdata.dst_id_type = dst_id_type;
1194   } else {
1195     packetdata.dst_id = NULL;
1196     packetdata.dst_id_len = 0;
1197     packetdata.dst_id_type = SILC_ID_NONE;
1198   }
1199   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1200     packetdata.src_id_len + packetdata.dst_id_len;
1201   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1202
1203   /* Prepare outgoing data buffer for packet sending */
1204   silc_packet_send_prepare(sock, 
1205                            SILC_PACKET_HEADER_LEN +
1206                            packetdata.src_id_len + 
1207                            packetdata.dst_id_len,
1208                            packetdata.padlen,
1209                            data_len);
1210
1211   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1212
1213   packetdata.buffer = sock->outbuf;
1214
1215   /* Put the data to the buffer */
1216   if (data && data_len)
1217     silc_buffer_put(sock->outbuf, data, data_len);
1218
1219   /* Create the outgoing packet */
1220   silc_packet_assemble(&packetdata);
1221
1222   /* Encrypt the packet */
1223   if (cipher)
1224     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1225
1226   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1227                    sock->outbuf->data, sock->outbuf->len);
1228
1229   /* Now actually send the packet */
1230   silc_client_packet_send_real(client, sock, TRUE, TRUE);
1231 }
1232
1233 /* Closes connection to remote end. Free's all allocated data except
1234    for some information such as nickname etc. that are valid at all time. 
1235    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
1236    provided it will be checked whether the sock and `conn->sock' are the
1237    same (they can be different, ie. a socket can use `conn' as its
1238    connection but `conn->sock' might be actually a different connection
1239    than the `sock'). */
1240
1241 void silc_client_close_connection(SilcClient client,
1242                                   SilcSocketConnection sock,
1243                                   SilcClientConnection conn)
1244 {
1245   int del = FALSE;
1246
1247   if (!sock || (sock && conn->sock == sock))
1248     del = TRUE;
1249   if (!sock)
1250     sock = conn->sock;
1251
1252   /* We won't listen for this connection anymore */
1253   silc_schedule_unset_listen_fd(sock->sock);
1254
1255   /* Unregister all tasks */
1256   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1257   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1258
1259   /* Close the actual connection */
1260   silc_net_close_connection(sock->sock);
1261
1262   /* Free everything */
1263   if (del && sock->user_data) {
1264     /* XXX Free all client entries and channel entries. */
1265
1266     client->ops->say(client, sock->user_data,
1267                      "Closed connection to host %s", sock->hostname);
1268
1269     /* Clear ID caches */
1270     silc_idcache_del_all(conn->client_cache);
1271     silc_idcache_del_all(conn->channel_cache);
1272
1273     /* Free data */
1274     if (conn->remote_host)
1275       silc_free(conn->remote_host);
1276     if (conn->local_id)
1277       silc_free(conn->local_id);
1278     if (conn->local_id_data)
1279       silc_free(conn->local_id_data);
1280     if (conn->send_key)
1281       silc_cipher_free(conn->send_key);
1282     if (conn->receive_key)
1283       silc_cipher_free(conn->receive_key);
1284     if (conn->hmac_send)        /* conn->hmac_receive is same */
1285       silc_hmac_free(conn->hmac_send);
1286     if (conn->pending_commands)
1287       silc_dlist_uninit(conn->pending_commands);
1288     if (conn->rekey)
1289       silc_free(conn->rekey);
1290
1291     conn->sock = NULL;
1292     conn->remote_port = 0;
1293     conn->remote_type = 0;
1294     conn->send_key = NULL;
1295     conn->receive_key = NULL;
1296     conn->hmac_send = NULL;
1297     conn->hmac_receive = NULL;
1298     conn->local_id = NULL;
1299     conn->local_id_data = NULL;
1300     conn->remote_host = NULL;
1301     conn->current_channel = NULL;
1302     conn->pending_commands = NULL;
1303     conn->rekey = NULL;
1304
1305     silc_client_del_connection(client, conn);
1306   }
1307
1308   if (sock->protocol) {
1309     silc_protocol_free(sock->protocol);
1310     sock->protocol = NULL;
1311   }
1312   silc_socket_free(sock);
1313 }
1314
1315 /* Called when we receive disconnection packet from server. This 
1316    closes our end properly and displays the reason of the disconnection
1317    on the screen. */
1318
1319 void silc_client_disconnected_by_server(SilcClient client,
1320                                         SilcSocketConnection sock,
1321                                         SilcBuffer message)
1322 {
1323   char *msg;
1324
1325   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1326
1327   msg = silc_calloc(message->len + 1, sizeof(char));
1328   memcpy(msg, message->data, message->len);
1329   client->ops->say(client, sock->user_data, msg);
1330   silc_free(msg);
1331
1332   SILC_SET_DISCONNECTED(sock);
1333   silc_client_close_connection(client, sock, sock->user_data);
1334 }
1335
1336 /* Received error message from server. Display it on the screen. 
1337    We don't take any action what so ever of the error message. */
1338
1339 void silc_client_error_by_server(SilcClient client,
1340                                  SilcSocketConnection sock,
1341                                  SilcBuffer message)
1342 {
1343   char *msg;
1344
1345   msg = silc_calloc(message->len + 1, sizeof(char));
1346   memcpy(msg, message->data, message->len);
1347   client->ops->say(client, sock->user_data, msg);
1348   silc_free(msg);
1349 }
1350
1351 /* Processes the received new Client ID from server. Old Client ID is
1352    deleted from cache and new one is added. */
1353
1354 void silc_client_receive_new_id(SilcClient client,
1355                                 SilcSocketConnection sock,
1356                                 SilcIDPayload idp)
1357 {
1358   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1359   int connecting = FALSE;
1360
1361   if (!conn->local_entry)
1362     connecting = TRUE;
1363
1364   /* Delete old ID from ID cache */
1365   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1366   
1367   /* Save the new ID */
1368   if (conn->local_id)
1369     silc_free(conn->local_id);
1370   if (conn->local_id_data)
1371     silc_free(conn->local_id_data);
1372
1373   conn->local_id = silc_id_payload_get_id(idp);
1374   conn->local_id_data = silc_id_payload_get_data(idp);
1375   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1376
1377   if (!conn->local_entry)
1378     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1379
1380   conn->local_entry->nickname = conn->nickname;
1381   if (!conn->local_entry->username) {
1382     conn->local_entry->username = 
1383       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1384                   sizeof(conn->local_entry->username));
1385     sprintf(conn->local_entry->username, "%s@%s", client->username,
1386             client->hostname);
1387   }
1388   conn->local_entry->server = strdup(conn->remote_host);
1389   conn->local_entry->id = conn->local_id;
1390   
1391   /* Put it to the ID cache */
1392   silc_idcache_add(conn->client_cache, conn->nickname, strlen(conn->nickname),
1393                    SILC_ID_CLIENT, conn->local_id, (void *)conn->local_entry,
1394                    TRUE, FALSE);
1395
1396   /* Notify application of successful connection. We do it here now that
1397      we've received the Client ID and are allowed to send traffic. */
1398   if (connecting)
1399     client->ops->connect(client, conn, TRUE);
1400 }
1401
1402 /* Processed received Channel ID for a channel. This is called when client
1403    joins to channel and server replies with channel ID. The ID is cached. 
1404    Returns the created channel entry. */
1405
1406 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1407                                             SilcSocketConnection sock,
1408                                             char *channel_name,
1409                                             uint32 mode, 
1410                                             SilcIDPayload idp)
1411 {
1412   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1413   SilcChannelEntry channel;
1414
1415   SILC_LOG_DEBUG(("New channel ID"));
1416
1417   channel = silc_calloc(1, sizeof(*channel));
1418   channel->channel_name = channel_name;
1419   channel->id = silc_id_payload_get_id(idp);
1420   channel->mode = mode;
1421   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1422
1423   conn->current_channel = channel;
1424
1425   /* Put it to the ID cache */
1426   silc_idcache_add(conn->channel_cache, channel_name, strlen(channel_name),
1427                    SILC_ID_CHANNEL, (void *)channel->id, (void *)channel, 
1428                    TRUE, FALSE);
1429
1430   return channel;
1431 }
1432
1433 /* Removes a client entry from all channel it has joined. This really is
1434    a performance killer (client_entry should have pointers to channel 
1435    entry list). */
1436
1437 void silc_client_remove_from_channels(SilcClient client,
1438                                       SilcClientConnection conn,
1439                                       SilcClientEntry client_entry)
1440 {
1441   SilcIDCacheEntry id_cache;
1442   SilcIDCacheList list;
1443   SilcChannelEntry channel;
1444   SilcChannelUser chu;
1445
1446   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
1447                                SILC_ID_CHANNEL, &list))
1448     return;
1449
1450   silc_idcache_list_first(list, &id_cache);
1451   channel = (SilcChannelEntry)id_cache->context;
1452   
1453   while (channel) {
1454     
1455     /* Remove client from channel */
1456     silc_list_start(channel->clients);
1457     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1458       if (chu->client == client_entry) {
1459         silc_list_del(channel->clients, chu);
1460         silc_free(chu);
1461         break;
1462       }
1463     }
1464
1465     if (!silc_idcache_list_next(list, &id_cache))
1466       break;
1467     
1468     channel = (SilcChannelEntry)id_cache->context;
1469   }
1470
1471   silc_idcache_list_free(list);
1472 }
1473
1474 /* Replaces `old' client entries from all channels to `new' client entry.
1475    This can be called for example when nickname changes and old ID entry
1476    is replaced from ID cache with the new one. If the old ID entry is only
1477    updated, then this fucntion needs not to be called. */
1478
1479 void silc_client_replace_from_channels(SilcClient client, 
1480                                        SilcClientConnection conn,
1481                                        SilcClientEntry old,
1482                                        SilcClientEntry new)
1483 {
1484   SilcIDCacheEntry id_cache;
1485   SilcIDCacheList list;
1486   SilcChannelEntry channel;
1487   SilcChannelUser chu;
1488
1489   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
1490                                SILC_ID_CHANNEL, &list))
1491     return;
1492
1493   silc_idcache_list_first(list, &id_cache);
1494   channel = (SilcChannelEntry)id_cache->context;
1495   
1496   while (channel) {
1497     
1498     /* Replace client entry */
1499     silc_list_start(channel->clients);
1500     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1501       if (chu->client == old) {
1502         chu->client = new;
1503         break;
1504       }
1505     }
1506
1507     if (!silc_idcache_list_next(list, &id_cache))
1508       break;
1509     
1510     channel = (SilcChannelEntry)id_cache->context;
1511   }
1512
1513   silc_idcache_list_free(list);
1514 }
1515
1516 /* Parses mode mask and returns the mode as string. */
1517
1518 char *silc_client_chmode(uint32 mode, SilcChannelEntry channel)
1519 {
1520   char string[100];
1521
1522   if (!mode)
1523     return NULL;
1524
1525   memset(string, 0, sizeof(string));
1526
1527   if (mode & SILC_CHANNEL_MODE_PRIVATE)
1528     strncat(string, "p", 1);
1529
1530   if (mode & SILC_CHANNEL_MODE_SECRET)
1531     strncat(string, "s", 1);
1532
1533   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
1534     strncat(string, "k", 1);
1535
1536   if (mode & SILC_CHANNEL_MODE_INVITE)
1537     strncat(string, "i", 1);
1538
1539   if (mode & SILC_CHANNEL_MODE_TOPIC)
1540     strncat(string, "t", 1);
1541
1542   if (mode & SILC_CHANNEL_MODE_ULIMIT)
1543     strncat(string, "l", 1);
1544
1545   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
1546     strncat(string, "a", 1);
1547
1548   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
1549     strncat(string, "f", 1);
1550
1551   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1552     char cipher[30];
1553     memset(cipher, 0, sizeof(cipher));
1554     snprintf(cipher, sizeof(cipher), " c (%s)", 
1555              channel->channel_key->cipher->name);
1556     strncat(string, cipher, strlen(cipher));
1557   }
1558
1559   if (mode & SILC_CHANNEL_MODE_HMAC) {
1560     char hmac[30];
1561     memset(hmac, 0, sizeof(hmac));
1562     snprintf(hmac, sizeof(hmac), " h (%s)", 
1563              channel->hmac->hmac->name);
1564     strncat(string, hmac, strlen(hmac));
1565   }
1566
1567   /* Rest of mode is ignored */
1568
1569   return strdup(string);
1570 }
1571
1572 /* Parses channel user mode mask and returns te mode as string */
1573
1574 char *silc_client_chumode(uint32 mode)
1575 {
1576   char string[4];
1577
1578   if (!mode)
1579     return NULL;
1580
1581   memset(string, 0, sizeof(string));
1582
1583   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1584     strncat(string, "f", 1);
1585
1586   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1587     strncat(string, "o", 1);
1588
1589   return strdup(string);
1590 }
1591
1592 /* Parses channel user mode and returns it as special mode character. */
1593
1594 char *silc_client_chumode_char(uint32 mode)
1595 {
1596   char string[4];
1597
1598   if (!mode)
1599     return NULL;
1600
1601   memset(string, 0, sizeof(string));
1602
1603   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1604     strncat(string, "*", 1);
1605
1606   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1607     strncat(string, "@", 1);
1608
1609   return strdup(string);
1610 }
1611
1612 /* Registers failure timeout to process the received failure packet
1613    with timeout. */
1614
1615 void silc_client_process_failure(SilcClient client,
1616                                  SilcSocketConnection sock,
1617                                  SilcPacketContext *packet)
1618 {
1619   uint32 failure = 0;
1620
1621   if (sock->protocol) {
1622     if (packet->buffer->len >= 4)
1623       SILC_GET32_MSB(failure, packet->buffer->data);
1624
1625     /* Notify application */
1626     client->ops->failure(client, sock->user_data, sock->protocol,
1627                          (void *)failure);
1628   }
1629 }
1630
1631 /* A timeout callback for the re-key. We will be the initiator of the
1632    re-key protocol. */
1633
1634 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1635 {
1636   SilcSocketConnection sock = (SilcSocketConnection)context;
1637   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1638   SilcClient client = (SilcClient)conn->rekey->context;
1639   SilcProtocol protocol;
1640   SilcClientRekeyInternalContext *proto_ctx;
1641
1642   SILC_LOG_DEBUG(("Start"));
1643
1644   /* Allocate internal protocol context. This is sent as context
1645      to the protocol. */
1646   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1647   proto_ctx->client = (void *)client;
1648   proto_ctx->sock = sock;
1649   proto_ctx->responder = FALSE;
1650   proto_ctx->pfs = conn->rekey->pfs;
1651       
1652   /* Perform rekey protocol. Will call the final callback after the
1653      protocol is over. */
1654   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1655                       &protocol, proto_ctx, silc_client_rekey_final);
1656   sock->protocol = protocol;
1657       
1658   /* Run the protocol */
1659   protocol->execute(client->timeout_queue, 0, protocol, 
1660                     sock->sock, 0, 0);
1661
1662   /* Re-register re-key timeout */
1663   silc_task_register(client->timeout_queue, sock->sock, 
1664                      silc_client_rekey_callback,
1665                      context, conn->rekey->timeout, 0,
1666                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1667 }
1668
1669 /* The final callback for the REKEY protocol. This will actually take the
1670    new key material into use. */
1671
1672 SILC_TASK_CALLBACK(silc_client_rekey_final)
1673 {
1674   SilcProtocol protocol = (SilcProtocol)context;
1675   SilcClientRekeyInternalContext *ctx =
1676     (SilcClientRekeyInternalContext *)protocol->context;
1677   SilcClient client = (SilcClient)ctx->client;
1678   SilcSocketConnection sock = ctx->sock;
1679
1680   SILC_LOG_DEBUG(("Start"));
1681
1682   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1683       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1684     /* Error occured during protocol */
1685     silc_protocol_cancel(client->timeout_queue, protocol);
1686     silc_protocol_free(protocol);
1687     sock->protocol = NULL;
1688     if (ctx->packet)
1689       silc_packet_context_free(ctx->packet);
1690     if (ctx->ske)
1691       silc_ske_free(ctx->ske);
1692     silc_free(ctx);
1693     return;
1694   }
1695
1696   /* Cleanup */
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 }