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     silc_task_unregister_by_callback(client->timeout_queue,
438                                      silc_client_failure_callback);
439
440     /* Notify application of failure */
441     client->ops->connect(client, ctx->sock->user_data, FALSE);
442     silc_free(ctx);
443     return;
444   }
445
446   /* We now have the key material as the result of the key exchange
447      protocol. Take the key material into use. Free the raw key material
448      as soon as we've set them into use. */
449   silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
450                                    ctx->ske->prop->cipher,
451                                    ctx->ske->prop->pkcs,
452                                    ctx->ske->prop->hash,
453                                    ctx->ske->prop->hmac,
454                                    ctx->ske->prop->group);
455   silc_ske_free_key_material(ctx->keymat);
456
457   /* Allocate internal context for the authentication protocol. This
458      is sent as context for the protocol. */
459   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
460   proto_ctx->client = (void *)client;
461   proto_ctx->sock = sock = ctx->sock;
462   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
463   proto_ctx->dest_id_type = ctx->dest_id_type;
464   proto_ctx->dest_id = ctx->dest_id;
465
466   /* Resolve the authentication method to be used in this connection */
467   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
468                                     sock->port, &proto_ctx->auth_meth,
469                                     &proto_ctx->auth_data, 
470                                     &proto_ctx->auth_data_len)) {
471     client->ops->say(client, ctx->sock->user_data, 
472                      "Could not resolve authentication method to use, "
473                      "assume no authentication");
474     proto_ctx->auth_meth = SILC_AUTH_NONE;
475   }
476
477   /* Free old protocol as it is finished now */
478   silc_protocol_free(protocol);
479   if (ctx->packet)
480     silc_packet_context_free(ctx->packet);
481   silc_free(ctx);
482   sock->protocol = NULL;
483
484   /* Allocate the authentication protocol. This is allocated here
485      but we won't start it yet. We will be receiving party of this
486      protocol thus we will wait that connecting party will make
487      their first move. */
488   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
489                       &sock->protocol, (void *)proto_ctx, 
490                       silc_client_connect_to_server_final);
491
492   /* Execute the protocol */
493   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
494 }
495
496 /* Finalizes the connection to the remote SILC server. This is called
497    after authentication protocol has been completed. This send our
498    user information to the server to receive our client ID from
499    server. */
500
501 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
502 {
503   SilcProtocol protocol = (SilcProtocol)context;
504   SilcClientConnAuthInternalContext *ctx = 
505     (SilcClientConnAuthInternalContext *)protocol->context;
506   SilcClient client = (SilcClient)ctx->client;
507   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
508   SilcBuffer packet;
509
510   SILC_LOG_DEBUG(("Start"));
511
512   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
513       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
514     /* Error occured during protocol */
515     SILC_LOG_DEBUG(("Error during authentication protocol"));
516     silc_protocol_free(protocol);
517     if (ctx->auth_data)
518       silc_free(ctx->auth_data);
519     if (ctx->ske)
520       silc_ske_free(ctx->ske);
521     if (ctx->dest_id)
522       silc_free(ctx->dest_id);
523     conn->sock->protocol = NULL;
524     silc_task_unregister_by_callback(client->timeout_queue,
525                                      silc_client_failure_callback);
526
527     /* Notify application of failure */
528     client->ops->connect(client, ctx->sock->user_data, FALSE);
529     silc_free(ctx);
530     return;
531   }
532
533   /* Send NEW_CLIENT packet to the server. We will become registered
534      to the SILC network after sending this packet and we will receive
535      client ID from the server. */
536   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
537                              strlen(client->realname));
538   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
539   silc_buffer_format(packet,
540                      SILC_STR_UI_SHORT(strlen(client->username)),
541                      SILC_STR_UI_XNSTRING(client->username,
542                                           strlen(client->username)),
543                      SILC_STR_UI_SHORT(strlen(client->realname)),
544                      SILC_STR_UI_XNSTRING(client->realname,
545                                           strlen(client->realname)),
546                      SILC_STR_END);
547
548   /* Send the packet */
549   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
550                           NULL, 0, NULL, NULL, 
551                           packet->data, packet->len, TRUE);
552   silc_buffer_free(packet);
553
554   /* Save remote ID. */
555   conn->remote_id = ctx->dest_id;
556   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
557   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
558
559   /* Register re-key timeout */
560   conn->rekey->timeout = 3600; /* XXX hardcoded */
561   conn->rekey->context = (void *)client;
562   silc_task_register(client->timeout_queue, conn->sock->sock, 
563                      silc_client_rekey_callback,
564                      (void *)conn->sock, conn->rekey->timeout, 0,
565                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
566
567   silc_task_unregister_by_callback(client->timeout_queue,
568                                    silc_client_failure_callback);
569   silc_protocol_free(protocol);
570   if (ctx->auth_data)
571     silc_free(ctx->auth_data);
572   if (ctx->ske)
573     silc_ske_free(ctx->ske);
574   silc_free(ctx);
575   conn->sock->protocol = NULL;
576 }
577
578 /* Internal routine that sends packet or marks packet to be sent. This
579    is used directly only in special cases. Normal cases should use
580    silc_server_packet_send. Returns < 0 on error. */
581
582 int silc_client_packet_send_real(SilcClient client,
583                                  SilcSocketConnection sock,
584                                  int force_send)
585 {
586   int ret;
587
588   /* If rekey protocol is active we must assure that all packets are
589      sent through packet queue. */
590   if (SILC_CLIENT_IS_REKEY(sock))
591     force_send = FALSE;
592
593   /* Send the packet */
594   ret = silc_packet_send(sock, force_send);
595   if (ret != -2)
596     return ret;
597
598   /* Mark that there is some outgoing data available for this connection. 
599      This call sets the connection both for input and output (the input
600      is set always and this call keeps the input setting, actually). 
601      Actual data sending is performed by silc_client_packet_process. */
602   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
603
604   /* Mark to socket that data is pending in outgoing buffer. This flag
605      is needed if new data is added to the buffer before the earlier
606      put data is sent to the network. */
607   SILC_SET_OUTBUF_PENDING(sock);
608
609   return 0;
610 }
611
612 /* Packet processing callback. This is used to send and receive packets
613    from network. This is generic task. */
614
615 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
616 {
617   SilcClient client = (SilcClient)context;
618   SilcSocketConnection sock = NULL;
619   SilcClientConnection conn;
620   int ret;
621
622   SILC_LOG_DEBUG(("Processing packet"));
623
624   SILC_CLIENT_GET_SOCK(client, fd, sock);
625   if (sock == NULL)
626     return;
627
628   conn = (SilcClientConnection)sock->user_data;
629
630   /* Packet sending */
631   if (type == SILC_TASK_WRITE) {
632     SILC_LOG_DEBUG(("Writing data to connection"));
633
634     if (sock->outbuf->data - sock->outbuf->head)
635       silc_buffer_push(sock->outbuf, 
636                        sock->outbuf->data - sock->outbuf->head);
637
638     ret = silc_client_packet_send_real(client, sock, TRUE);
639
640     /* If returned -2 could not write to connection now, will do
641        it later. */
642     if (ret == -2)
643       return;
644     
645     /* The packet has been sent and now it is time to set the connection
646        back to only for input. When there is again some outgoing data 
647        available for this connection it will be set for output as well. 
648        This call clears the output setting and sets it only for input. */
649     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
650     SILC_UNSET_OUTBUF_PENDING(sock);
651
652     silc_buffer_clear(sock->outbuf);
653     return;
654   }
655
656   /* Packet receiving */
657   if (type == SILC_TASK_READ) {
658     SILC_LOG_DEBUG(("Reading data from connection"));
659
660     /* Read data from network */
661     ret = silc_packet_receive(sock);
662     if (ret < 0)
663       return;
664     
665     /* EOF */
666     if (ret == 0) {
667       SILC_LOG_DEBUG(("Read EOF"));
668
669       /* If connection is disconnecting already we will finally
670          close the connection */
671       if (SILC_IS_DISCONNECTING(sock)) {
672         if (sock == conn->sock)
673           client->ops->disconnect(client, conn);
674         silc_client_close_connection(client, sock, conn);
675         return;
676       }
677       
678       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
679       if (sock == conn->sock)
680         client->ops->disconnect(client, conn);
681       silc_client_close_connection(client, sock, conn);
682       return;
683     }
684
685     /* Process the packet. This will call the parser that will then
686        decrypt and parse the packet. */
687     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
688       silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
689                                   silc_client_packet_parse, client);
690     else
691       silc_packet_receive_process(sock, NULL, NULL,
692                                   silc_client_packet_parse, client);
693   }
694 }
695
696 /* Callback function that the silc_packet_decrypt will call to make the
697    decision whether the packet is normal or special packet. We will 
698    return TRUE if it is normal and FALSE if it is special */
699
700 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
701                                             SilcBuffer buffer,
702                                             SilcPacketContext *packet,
703                                             void *context)
704 {
705
706   /* Packet is normal packet, if: 
707
708      1) packet is private message packet and does not have private key set
709      2) is other packet than channel message packet
710
711      all other packets are special packets 
712   */
713
714   if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
715       (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
716     return FALSE;
717
718   if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
719     return TRUE;
720
721   return FALSE;
722 }
723
724 /* Parses whole packet, received earlier. */
725
726 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
727 {
728   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
729   SilcClient client = (SilcClient)parse_ctx->context;
730   SilcPacketContext *packet = parse_ctx->packet;
731   SilcBuffer buffer = packet->buffer;
732   SilcSocketConnection sock = parse_ctx->sock;
733   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
734   int ret;
735
736   SILC_LOG_DEBUG(("Start"));
737
738   /* Decrypt the received packet */
739   if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
740     ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet,
741                               silc_client_packet_decrypt_check, parse_ctx);
742   else
743     ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
744                               silc_client_packet_decrypt_check, parse_ctx);
745
746   if (ret < 0)
747     goto out;
748
749   if (ret == 0) {
750     /* Parse the packet. Packet type is returned. */
751     ret = silc_packet_parse(packet);
752   } else {
753     /* Parse the packet header in special way as this is "special"
754        packet type. */
755     ret = silc_packet_parse_special(packet);
756   }
757
758   if (ret == SILC_PACKET_NONE)
759     goto out;
760
761   /* Parse the incoming packet type */
762   silc_client_packet_parse_type(client, sock, packet);
763
764  out:
765   /*  silc_buffer_clear(sock->inbuf); */
766   silc_packet_context_free(packet);
767   silc_free(parse_ctx);
768 }
769
770 /* Parser callback called by silc_packet_receive_process. Thie merely
771    registers timeout that will handle the actual parsing when appropriate. */
772
773 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
774 {
775   SilcClient client = (SilcClient)parser_context->context;
776
777   /* Parse the packet */
778   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
779                      silc_client_packet_parse_real,
780                      (void *)parser_context, 0, 1, 
781                      SILC_TASK_TIMEOUT,
782                      SILC_TASK_PRI_NORMAL);
783 }
784   
785 /* Parses the packet type and calls what ever routines the packet type
786    requires. This is done for all incoming packets. */
787
788 void silc_client_packet_parse_type(SilcClient client, 
789                                    SilcSocketConnection sock,
790                                    SilcPacketContext *packet)
791 {
792   SilcBuffer buffer = packet->buffer;
793   SilcPacketType type = packet->type;
794
795   SILC_LOG_DEBUG(("Parsing packet type %d", type));
796
797   /* Parse the packet type */
798   switch(type) {
799   case SILC_PACKET_DISCONNECT:
800     silc_client_disconnected_by_server(client, sock, buffer);
801     break;
802   case SILC_PACKET_SUCCESS:
803     /*
804      * Success received for something. For now we can have only
805      * one protocol for connection executing at once hence this
806      * success message is for whatever protocol is executing currently.
807      */
808     if (sock->protocol) {
809       sock->protocol->execute(client->timeout_queue, 0,
810                               sock->protocol, sock->sock, 0, 0);
811     }
812     break;
813   case SILC_PACKET_FAILURE:
814     /*
815      * Failure received for some protocol. Set the protocol state to 
816      * error and call the protocol callback. This fill cause error on
817      * protocol and it will call the final callback.
818      */
819     silc_client_process_failure(client, sock, packet);
820     break;
821   case SILC_PACKET_REJECT:
822     break;
823
824   case SILC_PACKET_NOTIFY:
825     /*
826      * Received notify message 
827      */
828     silc_client_notify_by_server(client, sock, packet);
829     break;
830
831   case SILC_PACKET_ERROR:
832     /*
833      * Received error message
834      */
835     silc_client_error_by_server(client, sock, buffer);
836     break;
837
838   case SILC_PACKET_CHANNEL_MESSAGE:
839     /*
840      * Received message to (from, actually) a channel
841      */
842     silc_client_channel_message(client, sock, packet);
843     break;
844   case SILC_PACKET_CHANNEL_KEY:
845     /*
846      * Received key for a channel. By receiving this key the client will be
847      * able to talk to the channel it has just joined. This can also be
848      * a new key for existing channel as keys expire peridiocally.
849      */
850     silc_client_receive_channel_key(client, sock, buffer);
851     break;
852
853   case SILC_PACKET_PRIVATE_MESSAGE:
854     /*
855      * Received private message
856      */
857     silc_client_private_message(client, sock, packet);
858     break;
859   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
860     /*
861      * Received private message key
862      */
863     break;
864
865   case SILC_PACKET_COMMAND_REPLY:
866     /*
867      * Recived reply for a command
868      */
869     silc_client_command_reply_process(client, sock, packet);
870     break;
871
872   case SILC_PACKET_KEY_EXCHANGE:
873     if (sock->protocol && sock->protocol->protocol && 
874         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
875       SilcClientKEInternalContext *proto_ctx = 
876         (SilcClientKEInternalContext *)sock->protocol->context;
877
878       proto_ctx->packet = silc_packet_context_dup(packet);
879       proto_ctx->dest_id_type = packet->src_id_type;
880       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
881                                           packet->src_id_type);
882       if (!proto_ctx->dest_id)
883         break;
884
885       /* Let the protocol handle the packet */
886       sock->protocol->execute(client->timeout_queue, 0,
887                               sock->protocol, sock->sock, 0, 0);
888     } else {
889       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
890                       "protocol active, packet dropped."));
891
892       /* XXX Trigger KE protocol?? Rekey actually! */
893     }
894     break;
895
896   case SILC_PACKET_KEY_EXCHANGE_1:
897     if (sock->protocol && sock->protocol->protocol && 
898         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
899          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
900
901       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
902         SilcClientRekeyInternalContext *proto_ctx = 
903           (SilcClientRekeyInternalContext *)sock->protocol->context;
904         
905         if (proto_ctx->packet)
906           silc_packet_context_free(proto_ctx->packet);
907         
908         proto_ctx->packet = silc_packet_context_dup(packet);
909
910         /* Let the protocol handle the packet */
911         sock->protocol->execute(client->timeout_queue, 0, 
912                                 sock->protocol, sock->sock, 0, 0);
913       } else {
914         SilcClientKEInternalContext *proto_ctx = 
915           (SilcClientKEInternalContext *)sock->protocol->context;
916         
917         if (proto_ctx->packet)
918           silc_packet_context_free(proto_ctx->packet);
919         
920         proto_ctx->packet = silc_packet_context_dup(packet);
921         proto_ctx->dest_id_type = packet->src_id_type;
922         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
923                                             packet->src_id_type);
924         if (!proto_ctx->dest_id)
925           break;
926         
927         /* Let the protocol handle the packet */
928         sock->protocol->execute(client->timeout_queue, 0,
929                                 sock->protocol, sock->sock, 0, 0);
930       }
931     } else {
932       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
933                       "protocol active, packet dropped."));
934     }
935     break;
936   case SILC_PACKET_KEY_EXCHANGE_2:
937     if (sock->protocol && sock->protocol->protocol && 
938         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
939          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
940
941       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
942         SilcClientRekeyInternalContext *proto_ctx = 
943           (SilcClientRekeyInternalContext *)sock->protocol->context;
944         
945         if (proto_ctx->packet)
946           silc_packet_context_free(proto_ctx->packet);
947         
948         proto_ctx->packet = silc_packet_context_dup(packet);
949
950         /* Let the protocol handle the packet */
951         sock->protocol->execute(client->timeout_queue, 0, 
952                                 sock->protocol, sock->sock, 0, 0);
953       } else {
954         SilcClientKEInternalContext *proto_ctx = 
955           (SilcClientKEInternalContext *)sock->protocol->context;
956         
957         if (proto_ctx->packet)
958           silc_packet_context_free(proto_ctx->packet);
959         
960         proto_ctx->packet = silc_packet_context_dup(packet);
961         proto_ctx->dest_id_type = packet->src_id_type;
962         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
963                                             packet->src_id_type);
964         if (!proto_ctx->dest_id)
965           break;
966         
967         /* Let the protocol handle the packet */
968         sock->protocol->execute(client->timeout_queue, 0,
969                                 sock->protocol, sock->sock, 0, 0);
970       }
971     } else {
972       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
973                       "protocol active, packet dropped."));
974     }
975     break;
976
977   case SILC_PACKET_NEW_ID:
978     {
979       /*
980        * Received new ID from server. This packet is received at
981        * the connection to the server.  New ID is also received when 
982        * user changes nickname but in that case the new ID is received
983        * as command reply and not as this packet type.
984        */
985       SilcIDPayload idp;
986
987       idp = silc_id_payload_parse(buffer);
988       if (!idp)
989         break;
990       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
991         break;
992
993       silc_client_receive_new_id(client, sock, idp);
994       silc_id_payload_free(idp);
995       break;
996     }
997
998   case SILC_PACKET_HEARTBEAT:
999     /*
1000      * Received heartbeat packet
1001      */
1002     SILC_LOG_DEBUG(("Heartbeat packet"));
1003     break;
1004
1005   case SILC_PACKET_KEY_AGREEMENT:
1006     /*
1007      * Received key agreement packet
1008      */
1009     SILC_LOG_DEBUG(("Key agreement packet"));
1010     silc_client_key_agreement(client, sock, packet);
1011     break;
1012
1013   case SILC_PACKET_REKEY:
1014     SILC_LOG_DEBUG(("Re-key packet"));
1015     /* We ignore this for now */
1016     break;
1017
1018   case SILC_PACKET_REKEY_DONE:
1019     SILC_LOG_DEBUG(("Re-key done packet"));
1020
1021     if (sock->protocol && sock->protocol->protocol && 
1022         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1023
1024       SilcClientRekeyInternalContext *proto_ctx = 
1025         (SilcClientRekeyInternalContext *)sock->protocol->context;
1026       
1027       if (proto_ctx->packet)
1028         silc_packet_context_free(proto_ctx->packet);
1029       
1030       proto_ctx->packet = silc_packet_context_dup(packet);
1031       
1032       /* Let the protocol handle the packet */
1033       sock->protocol->execute(client->timeout_queue, 0, 
1034                               sock->protocol, sock->sock, 0, 100000);
1035     } else {
1036       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1037                       "protocol active, packet dropped."));
1038     }
1039     break;
1040
1041   default:
1042     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1043     break;
1044   }
1045 }
1046
1047 /* Sends packet. This doesn't actually send the packet instead it assembles
1048    it and marks it to be sent. However, if force_send is TRUE the packet
1049    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1050    will be derived from sock argument. Otherwise the valid arguments sent
1051    are used. */
1052
1053 void silc_client_packet_send(SilcClient client, 
1054                              SilcSocketConnection sock,
1055                              SilcPacketType type, 
1056                              void *dst_id,
1057                              SilcIdType dst_id_type,
1058                              SilcCipher cipher,
1059                              SilcHmac hmac,
1060                              unsigned char *data, 
1061                              uint32 data_len, 
1062                              int force_send)
1063 {
1064   SilcPacketContext packetdata;
1065
1066   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1067
1068   /* Get data used in the packet sending, keys and stuff */
1069   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1070     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1071       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1072
1073     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
1074       hmac = ((SilcClientConnection)sock->user_data)->hmac;
1075
1076     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1077       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1078       dst_id_type = SILC_ID_SERVER;
1079     }
1080   }
1081
1082   /* Set the packet context pointers */
1083   packetdata.flags = 0;
1084   packetdata.type = type;
1085   if (sock->user_data && 
1086       ((SilcClientConnection)sock->user_data)->local_id_data)
1087     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1088   else 
1089     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1090   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1091   packetdata.src_id_type = SILC_ID_CLIENT;
1092   if (dst_id) {
1093     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1094     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
1095     packetdata.dst_id_type = dst_id_type;
1096   } else {
1097     packetdata.dst_id = NULL;
1098     packetdata.dst_id_len = 0;
1099     packetdata.dst_id_type = SILC_ID_NONE;
1100   }
1101   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1102     packetdata.src_id_len + packetdata.dst_id_len;
1103   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1104
1105   /* Prepare outgoing data buffer for packet sending */
1106   silc_packet_send_prepare(sock, 
1107                            SILC_PACKET_HEADER_LEN +
1108                            packetdata.src_id_len + 
1109                            packetdata.dst_id_len,
1110                            packetdata.padlen,
1111                            data_len);
1112
1113   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1114
1115   packetdata.buffer = sock->outbuf;
1116
1117   /* Put the data to the buffer */
1118   if (data && data_len)
1119     silc_buffer_put(sock->outbuf, data, data_len);
1120
1121   /* Create the outgoing packet */
1122   silc_packet_assemble(&packetdata);
1123
1124   /* Encrypt the packet */
1125   if (cipher)
1126     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1127
1128   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1129                    sock->outbuf->data, sock->outbuf->len);
1130
1131   /* Now actually send the packet */
1132   silc_client_packet_send_real(client, sock, force_send);
1133 }
1134
1135 /* Closes connection to remote end. Free's all allocated data except
1136    for some information such as nickname etc. that are valid at all time. 
1137    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
1138    provided it will be checked whether the sock and `conn->sock' are the
1139    same (they can be different, ie. a socket can use `conn' as its
1140    connection but `conn->sock' might be actually a different connection
1141    than the `sock'). */
1142
1143 void silc_client_close_connection(SilcClient client,
1144                                   SilcSocketConnection sock,
1145                                   SilcClientConnection conn)
1146 {
1147   int del = FALSE;
1148
1149   if (!sock || (sock && conn->sock == sock))
1150     del = TRUE;
1151   if (!sock)
1152     sock = conn->sock;
1153
1154   /* We won't listen for this connection anymore */
1155   silc_schedule_unset_listen_fd(sock->sock);
1156
1157   /* Unregister all tasks */
1158   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1159   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1160
1161   /* Close the actual connection */
1162   silc_net_close_connection(sock->sock);
1163
1164   /* Free everything */
1165   if (del && sock->user_data) {
1166     /* XXX Free all client entries and channel entries. */
1167
1168     client->ops->say(client, sock->user_data,
1169                      "Closed connection to host %s", sock->hostname);
1170
1171     /* Clear ID caches */
1172     silc_idcache_del_all(conn->client_cache);
1173     silc_idcache_del_all(conn->channel_cache);
1174
1175     /* Free data */
1176     if (conn->remote_host)
1177       silc_free(conn->remote_host);
1178     if (conn->local_id)
1179       silc_free(conn->local_id);
1180     if (conn->local_id_data)
1181       silc_free(conn->local_id_data);
1182     if (conn->send_key)
1183       silc_cipher_free(conn->send_key);
1184     if (conn->receive_key)
1185       silc_cipher_free(conn->receive_key);
1186     if (conn->hmac)
1187       silc_hmac_free(conn->hmac);
1188     if (conn->pending_commands)
1189       silc_dlist_uninit(conn->pending_commands);
1190     if (conn->rekey)
1191       silc_free(conn->rekey);
1192
1193     conn->sock = NULL;
1194     conn->remote_port = 0;
1195     conn->remote_type = 0;
1196     conn->send_key = NULL;
1197     conn->receive_key = NULL;
1198     conn->hmac = NULL;
1199     conn->local_id = NULL;
1200     conn->local_id_data = NULL;
1201     conn->remote_host = NULL;
1202     conn->current_channel = NULL;
1203     conn->pending_commands = NULL;
1204     conn->rekey = NULL;
1205
1206     silc_client_del_connection(client, conn);
1207   }
1208
1209   if (sock->protocol) {
1210     silc_protocol_free(sock->protocol);
1211     sock->protocol = NULL;
1212   }
1213   silc_socket_free(sock);
1214 }
1215
1216 /* Called when we receive disconnection packet from server. This 
1217    closes our end properly and displays the reason of the disconnection
1218    on the screen. */
1219
1220 void silc_client_disconnected_by_server(SilcClient client,
1221                                         SilcSocketConnection sock,
1222                                         SilcBuffer message)
1223 {
1224   char *msg;
1225
1226   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1227
1228   msg = silc_calloc(message->len + 1, sizeof(char));
1229   memcpy(msg, message->data, message->len);
1230   client->ops->say(client, sock->user_data, msg);
1231   silc_free(msg);
1232
1233   SILC_SET_DISCONNECTED(sock);
1234   silc_client_close_connection(client, sock, sock->user_data);
1235 }
1236
1237 /* Received error message from server. Display it on the screen. 
1238    We don't take any action what so ever of the error message. */
1239
1240 void silc_client_error_by_server(SilcClient client,
1241                                  SilcSocketConnection sock,
1242                                  SilcBuffer message)
1243 {
1244   char *msg;
1245
1246   msg = silc_calloc(message->len + 1, sizeof(char));
1247   memcpy(msg, message->data, message->len);
1248   client->ops->say(client, sock->user_data, msg);
1249   silc_free(msg);
1250 }
1251
1252 /* Processes the received new Client ID from server. Old Client ID is
1253    deleted from cache and new one is added. */
1254
1255 void silc_client_receive_new_id(SilcClient client,
1256                                 SilcSocketConnection sock,
1257                                 SilcIDPayload idp)
1258 {
1259   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1260   int connecting = FALSE;
1261
1262   if (!conn->local_entry)
1263     connecting = TRUE;
1264
1265   /* Delete old ID from ID cache */
1266   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1267   
1268   /* Save the new ID */
1269   if (conn->local_id)
1270     silc_free(conn->local_id);
1271   if (conn->local_id_data)
1272     silc_free(conn->local_id_data);
1273
1274   conn->local_id = silc_id_payload_get_id(idp);
1275   conn->local_id_data = silc_id_payload_get_data(idp);
1276   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1277
1278   if (!conn->local_entry)
1279     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1280
1281   conn->local_entry->nickname = conn->nickname;
1282   if (!conn->local_entry->username) {
1283     conn->local_entry->username = 
1284       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1285                   sizeof(conn->local_entry->username));
1286     sprintf(conn->local_entry->username, "%s@%s", client->username,
1287             client->hostname);
1288   }
1289   conn->local_entry->server = strdup(conn->remote_host);
1290   conn->local_entry->id = conn->local_id;
1291   
1292   /* Put it to the ID cache */
1293   silc_idcache_add(conn->client_cache, conn->nickname, strlen(conn->nickname),
1294                    SILC_ID_CLIENT, conn->local_id, (void *)conn->local_entry,
1295                    TRUE, FALSE);
1296
1297   /* Notify application of successful connection. We do it here now that
1298      we've received the Client ID and are allowed to send traffic. */
1299   if (connecting)
1300     client->ops->connect(client, conn, TRUE);
1301 }
1302
1303 /* Processed received Channel ID for a channel. This is called when client
1304    joins to channel and server replies with channel ID. The ID is cached. 
1305    Returns the created channel entry. */
1306
1307 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1308                                             SilcSocketConnection sock,
1309                                             char *channel_name,
1310                                             uint32 mode, 
1311                                             SilcIDPayload idp)
1312 {
1313   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1314   SilcChannelEntry channel;
1315
1316   SILC_LOG_DEBUG(("New channel ID"));
1317
1318   channel = silc_calloc(1, sizeof(*channel));
1319   channel->channel_name = channel_name;
1320   channel->id = silc_id_payload_get_id(idp);
1321   channel->mode = mode;
1322   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1323
1324   conn->current_channel = channel;
1325
1326   /* Put it to the ID cache */
1327   silc_idcache_add(conn->channel_cache, channel_name, strlen(channel_name),
1328                    SILC_ID_CHANNEL, (void *)channel->id, (void *)channel, 
1329                    TRUE, FALSE);
1330
1331   return channel;
1332 }
1333
1334 /* Removes a client entry from all channel it has joined. This really is
1335    a performance killer (client_entry should have pointers to channel 
1336    entry list). */
1337
1338 void silc_client_remove_from_channels(SilcClient client,
1339                                       SilcClientConnection conn,
1340                                       SilcClientEntry client_entry)
1341 {
1342   SilcIDCacheEntry id_cache;
1343   SilcIDCacheList list;
1344   SilcChannelEntry channel;
1345   SilcChannelUser chu;
1346
1347   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
1348                                SILC_ID_CHANNEL, &list))
1349     return;
1350
1351   silc_idcache_list_first(list, &id_cache);
1352   channel = (SilcChannelEntry)id_cache->context;
1353   
1354   while (channel) {
1355     
1356     /* Remove client from channel */
1357     silc_list_start(channel->clients);
1358     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1359       if (chu->client == client_entry) {
1360         silc_list_del(channel->clients, chu);
1361         silc_free(chu);
1362         break;
1363       }
1364     }
1365
1366     if (!silc_idcache_list_next(list, &id_cache))
1367       break;
1368     
1369     channel = (SilcChannelEntry)id_cache->context;
1370   }
1371
1372   silc_idcache_list_free(list);
1373 }
1374
1375 /* Replaces `old' client entries from all channels to `new' client entry.
1376    This can be called for example when nickname changes and old ID entry
1377    is replaced from ID cache with the new one. If the old ID entry is only
1378    updated, then this fucntion needs not to be called. */
1379
1380 void silc_client_replace_from_channels(SilcClient client, 
1381                                        SilcClientConnection conn,
1382                                        SilcClientEntry old,
1383                                        SilcClientEntry new)
1384 {
1385   SilcIDCacheEntry id_cache;
1386   SilcIDCacheList list;
1387   SilcChannelEntry channel;
1388   SilcChannelUser chu;
1389
1390   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
1391                                SILC_ID_CHANNEL, &list))
1392     return;
1393
1394   silc_idcache_list_first(list, &id_cache);
1395   channel = (SilcChannelEntry)id_cache->context;
1396   
1397   while (channel) {
1398     
1399     /* Replace client entry */
1400     silc_list_start(channel->clients);
1401     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1402       if (chu->client == old) {
1403         chu->client = new;
1404         break;
1405       }
1406     }
1407
1408     if (!silc_idcache_list_next(list, &id_cache))
1409       break;
1410     
1411     channel = (SilcChannelEntry)id_cache->context;
1412   }
1413
1414   silc_idcache_list_free(list);
1415 }
1416
1417 /* Parses mode mask and returns the mode as string. */
1418
1419 char *silc_client_chmode(uint32 mode, SilcChannelEntry channel)
1420 {
1421   char string[100];
1422
1423   if (!mode)
1424     return NULL;
1425
1426   memset(string, 0, sizeof(string));
1427
1428   if (mode & SILC_CHANNEL_MODE_PRIVATE)
1429     strncat(string, "p", 1);
1430
1431   if (mode & SILC_CHANNEL_MODE_SECRET)
1432     strncat(string, "s", 1);
1433
1434   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
1435     strncat(string, "k", 1);
1436
1437   if (mode & SILC_CHANNEL_MODE_INVITE)
1438     strncat(string, "i", 1);
1439
1440   if (mode & SILC_CHANNEL_MODE_TOPIC)
1441     strncat(string, "t", 1);
1442
1443   if (mode & SILC_CHANNEL_MODE_ULIMIT)
1444     strncat(string, "l", 1);
1445
1446   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
1447     strncat(string, "a", 1);
1448
1449   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
1450     strncat(string, "f", 1);
1451
1452   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1453     char cipher[30];
1454     memset(cipher, 0, sizeof(cipher));
1455     snprintf(cipher, sizeof(cipher), " c (%s)", 
1456              channel->channel_key->cipher->name);
1457     strncat(string, cipher, strlen(cipher));
1458   }
1459
1460   if (mode & SILC_CHANNEL_MODE_HMAC) {
1461     char hmac[30];
1462     memset(hmac, 0, sizeof(hmac));
1463     snprintf(hmac, sizeof(hmac), " h (%s)", 
1464              channel->hmac->hmac->name);
1465     strncat(string, hmac, strlen(hmac));
1466   }
1467
1468   /* Rest of mode is ignored */
1469
1470   return strdup(string);
1471 }
1472
1473 /* Parses channel user mode mask and returns te mode as string */
1474
1475 char *silc_client_chumode(uint32 mode)
1476 {
1477   char string[4];
1478
1479   if (!mode)
1480     return NULL;
1481
1482   memset(string, 0, sizeof(string));
1483
1484   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1485     strncat(string, "f", 1);
1486
1487   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1488     strncat(string, "o", 1);
1489
1490   return strdup(string);
1491 }
1492
1493 /* Parses channel user mode and returns it as special mode character. */
1494
1495 char *silc_client_chumode_char(uint32 mode)
1496 {
1497   char string[4];
1498
1499   if (!mode)
1500     return NULL;
1501
1502   memset(string, 0, sizeof(string));
1503
1504   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1505     strncat(string, "*", 1);
1506
1507   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1508     strncat(string, "@", 1);
1509
1510   return strdup(string);
1511 }
1512
1513 /* Failure timeout callback. If this is called then we will immediately
1514    process the received failure. We always process the failure with timeout
1515    since we do not want to blindly trust to received failure packets. 
1516    This won't be called (the timeout is cancelled) if the failure was
1517    bogus (it is bogus if remote does not close the connection after sending
1518    the failure). */
1519
1520 SILC_TASK_CALLBACK_GLOBAL(silc_client_failure_callback)
1521 {
1522   SilcClientFailureContext *f = (SilcClientFailureContext *)context;
1523
1524   if (f->sock->protocol) {
1525     f->sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
1526     f->sock->protocol->execute(f->client->timeout_queue, 0,
1527                                f->sock->protocol, f->sock->sock, 0, 0);
1528     
1529     /* Notify application */
1530     f->client->ops->failure(f->client, f->sock->user_data, f->sock->protocol,
1531                             (void *)f->failure);
1532   }
1533
1534   silc_free(f);
1535 }
1536
1537 /* Registers failure timeout to process the received failure packet
1538    with timeout. */
1539
1540 void silc_client_process_failure(SilcClient client,
1541                                  SilcSocketConnection sock,
1542                                  SilcPacketContext *packet)
1543 {
1544   SilcClientFailureContext *f;
1545   uint32 failure = 0;
1546
1547   if (sock->protocol) {
1548     if (packet->buffer->len >= 4)
1549       SILC_GET32_MSB(failure, packet->buffer->data);
1550
1551     f = silc_calloc(1, sizeof(*f));
1552     f->client = client;
1553     f->sock = sock;
1554     f->failure = failure;
1555
1556     /* We will wait 5 seconds to process this failure packet */
1557     silc_task_register(client->timeout_queue, sock->sock,
1558                        silc_client_failure_callback, (void *)f, 5, 0,
1559                        SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1560   }
1561 }
1562
1563 /* A timeout callback for the re-key. We will be the initiator of the
1564    re-key protocol. */
1565
1566 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1567 {
1568   SilcSocketConnection sock = (SilcSocketConnection)context;
1569   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1570   SilcClient client = (SilcClient)conn->rekey->context;
1571   SilcProtocol protocol;
1572   SilcClientRekeyInternalContext *proto_ctx;
1573
1574   SILC_LOG_DEBUG(("Start"));
1575
1576   /* Allocate internal protocol context. This is sent as context
1577      to the protocol. */
1578   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1579   proto_ctx->client = (void *)client;
1580   proto_ctx->sock = sock;
1581   proto_ctx->responder = FALSE;
1582   proto_ctx->pfs = conn->rekey->pfs;
1583       
1584   /* Perform rekey protocol. Will call the final callback after the
1585      protocol is over. */
1586   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1587                       &protocol, proto_ctx, silc_client_rekey_final);
1588   sock->protocol = protocol;
1589       
1590   /* Run the protocol */
1591   protocol->execute(client->timeout_queue, 0, protocol, 
1592                     sock->sock, 0, 0);
1593
1594   /* Re-register re-key timeout */
1595   silc_task_register(client->timeout_queue, sock->sock, 
1596                      silc_client_rekey_callback,
1597                      context, conn->rekey->timeout, 0,
1598                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1599 }
1600
1601 /* The final callback for the REKEY protocol. This will actually take the
1602    new key material into use. */
1603
1604 SILC_TASK_CALLBACK(silc_client_rekey_final)
1605 {
1606   SilcProtocol protocol = (SilcProtocol)context;
1607   SilcClientRekeyInternalContext *ctx =
1608     (SilcClientRekeyInternalContext *)protocol->context;
1609   SilcClient client = (SilcClient)ctx->client;
1610   SilcSocketConnection sock = ctx->sock;
1611
1612   SILC_LOG_DEBUG(("Start"));
1613
1614   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1615       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1616     /* Error occured during protocol */
1617     silc_protocol_cancel(client->timeout_queue, protocol);
1618     silc_protocol_free(protocol);
1619     sock->protocol = NULL;
1620     if (ctx->packet)
1621       silc_packet_context_free(ctx->packet);
1622     if (ctx->ske)
1623       silc_ske_free(ctx->ske);
1624     silc_free(ctx);
1625     return;
1626   }
1627
1628   /* Take the keys into use */
1629   if (ctx->pfs == TRUE)
1630     silc_client_protocol_rekey_generate_pfs(client, ctx);
1631   else
1632     silc_client_protocol_rekey_generate(client, ctx);
1633
1634   /* Cleanup */
1635   silc_protocol_free(protocol);
1636   sock->protocol = NULL;
1637   if (ctx->packet)
1638     silc_packet_context_free(ctx->packet);
1639   if (ctx->ske)
1640     silc_ske_free(ctx->ske);
1641   silc_free(ctx);
1642 }