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