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, SILC_ID_CLIENT, NULL);
146   conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
147   conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, 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] = silc_socket_dup(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] = silc_socket_dup(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] = silc_socket_dup(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       silc_socket_free(sock);
224       client->sockets[i] = NULL;
225       return;
226     }
227   }
228 }
229
230 static int 
231 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
232 {
233   int sock;
234
235   /* XXX In the future we should give up this non-blocking connect all
236      together and use threads instead. */
237   /* Create connection to server asynchronously */
238   sock = silc_net_create_connection_async(ctx->port, ctx->host);
239   if (sock < 0)
240     return -1;
241
242   /* Register task that will receive the async connect and will
243      read the result. */
244   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
245                                  silc_client_connect_to_server_start,
246                                  (void *)ctx, 0, 0, 
247                                  SILC_TASK_FD,
248                                  SILC_TASK_PRI_NORMAL);
249   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
250   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
251
252   ctx->sock = sock;
253
254   return sock;
255 }
256
257 /* Connects to remote server. This is the main routine used to connect
258    to SILC server. Returns -1 on error and the created socket otherwise. 
259    The `context' is user context that is saved into the SilcClientConnection
260    that is created after the connection is created. Note that application
261    may handle the connecting process outside the library. If this is the
262    case then this function is not used at all. When the connecting is
263    done the `connect' client operation is called. */
264
265 int silc_client_connect_to_server(SilcClient client, int port,
266                                   char *host, void *context)
267 {
268   SilcClientInternalConnectContext *ctx;
269   SilcClientConnection conn;
270   int sock;
271
272   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
273                   port, host));
274
275   conn = silc_client_add_connection(client, host, port, context);
276
277   client->ops->say(client, conn, 
278                    "Connecting to port %d of server %s", port, host);
279
280   /* Allocate internal context for connection process. This is
281      needed as we are doing async connecting. */
282   ctx = silc_calloc(1, sizeof(*ctx));
283   ctx->client = client;
284   ctx->conn = conn;
285   ctx->host = strdup(host);
286   ctx->port = port;
287   ctx->tries = 0;
288
289   /* Do the actual connecting process */
290   sock = silc_client_connect_to_server_internal(ctx);
291   if (sock == -1)
292     silc_client_del_connection(client, conn);
293   return sock;
294 }
295
296 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
297    key material between client and server.  This function can be called
298    directly if application is performing its own connecting and does not
299    use the connecting provided by this library. This function is normally
300    used only if the application performed the connecting outside the library.
301    The library however may use this internally. */
302
303 int silc_client_start_key_exchange(SilcClient client,
304                                    SilcClientConnection conn,
305                                    int fd)
306 {
307   SilcProtocol protocol;
308   SilcClientKEInternalContext *proto_ctx;
309   void *context;
310
311   /* Allocate new socket connection object */
312   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
313
314   conn->nickname = strdup(client->username);
315   conn->sock->hostname = conn->remote_host;
316   conn->sock->ip = strdup(conn->remote_host);
317   conn->sock->port = conn->remote_port;
318
319   /* Allocate internal Key Exchange context. This is sent to the
320      protocol as context. */
321   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
322   proto_ctx->client = (void *)client;
323   proto_ctx->sock = silc_socket_dup(conn->sock);
324   proto_ctx->rng = client->rng;
325   proto_ctx->responder = FALSE;
326   proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
327   proto_ctx->verify = silc_client_protocol_ke_verify_key;
328
329   /* Perform key exchange protocol. silc_client_connect_to_server_final
330      will be called after the protocol is finished. */
331   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
332                       &protocol, (void *)proto_ctx,
333                       silc_client_connect_to_server_second);
334   if (!protocol) {
335     client->ops->say(client, conn, 
336                      "Error: Could not start authentication protocol");
337     return FALSE;
338   }
339   conn->sock->protocol = protocol;
340
341   /* Register the connection for network input and output. This sets
342      that scheduler will listen for incoming packets for this connection 
343      and sets that outgoing packets may be sent to this connection as well.
344      However, this doesn't set the scheduler for outgoing traffic, it will 
345      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
346      later when outgoing data is available. */
347   context = (void *)client;
348   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
349
350   /* Execute the protocol */
351   silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
352   return TRUE;
353 }
354
355 /* Start of the connection to the remote server. This is called after
356    succesful TCP/IP connection has been established to the remote host. */
357
358 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
359 {
360   SilcClientInternalConnectContext *ctx =
361     (SilcClientInternalConnectContext *)context;
362   SilcClient client = ctx->client;
363   SilcClientConnection conn = ctx->conn;
364   int opt, opt_len = sizeof(opt);
365
366   SILC_LOG_DEBUG(("Start"));
367
368   /* Check the socket status as it might be in error */
369   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
370   if (opt != 0) {
371     if (ctx->tries < 2) {
372       /* Connection failed but lets try again */
373       client->ops->say(client, conn, "Could not connect to server %s: %s",
374                        ctx->host, strerror(opt));
375       client->ops->say(client, conn, 
376                        "Connecting to port %d of server %s resumed", 
377                        ctx->port, ctx->host);
378
379       /* Unregister old connection try */
380       silc_schedule_unset_listen_fd(fd);
381       silc_net_close_connection(fd);
382       silc_task_unregister(client->io_queue, ctx->task);
383
384       /* Try again */
385       silc_client_connect_to_server_internal(ctx);
386       ctx->tries++;
387     } else {
388       /* Connection failed and we won't try anymore */
389       client->ops->say(client, conn, "Could not connect to server %s: %s",
390                        ctx->host, strerror(opt));
391       silc_schedule_unset_listen_fd(fd);
392       silc_net_close_connection(fd);
393       silc_task_unregister(client->io_queue, ctx->task);
394       silc_free(ctx);
395
396       /* Notify application of failure */
397       client->ops->connect(client, conn, FALSE);
398       silc_client_del_connection(client, conn);
399     }
400     return;
401   }
402
403   silc_schedule_unset_listen_fd(fd);
404   silc_task_unregister(client->io_queue, ctx->task);
405   silc_free(ctx);
406
407   if (!silc_client_start_key_exchange(client, conn, fd)) {
408     silc_net_close_connection(fd);
409     client->ops->connect(client, conn, FALSE);
410   }
411 }
412
413 /* Second part of the connecting to the server. This executed 
414    authentication protocol. */
415
416 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
417 {
418   SilcProtocol protocol = (SilcProtocol)context;
419   SilcClientKEInternalContext *ctx = 
420     (SilcClientKEInternalContext *)protocol->context;
421   SilcClient client = (SilcClient)ctx->client;
422   SilcSocketConnection sock = NULL;
423   SilcClientConnAuthInternalContext *proto_ctx;
424
425   SILC_LOG_DEBUG(("Start"));
426
427   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
428       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
429     /* Error occured during protocol */
430     SILC_LOG_DEBUG(("Error during KE protocol"));
431     silc_protocol_free(protocol);
432     silc_ske_free_key_material(ctx->keymat);
433     if (ctx->ske)
434       silc_ske_free(ctx->ske);
435     if (ctx->dest_id)
436       silc_free(ctx->dest_id);
437     ctx->sock->protocol = NULL;
438     silc_socket_free(ctx->sock);
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     proto_ctx->auth_meth = SILC_AUTH_NONE;
472
473   /* Free old protocol as it is finished now */
474   silc_protocol_free(protocol);
475   if (ctx->packet)
476     silc_packet_context_free(ctx->packet);
477   silc_free(ctx);
478   sock->protocol = NULL;
479
480   /* Allocate the authenteication protocol and execute it. */
481   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
482                       &sock->protocol, (void *)proto_ctx, 
483                       silc_client_connect_to_server_final);
484
485   /* Execute the protocol */
486   silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
487 }
488
489 /* Finalizes the connection to the remote SILC server. This is called
490    after authentication protocol has been completed. This send our
491    user information to the server to receive our client ID from
492    server. */
493
494 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
495 {
496   SilcProtocol protocol = (SilcProtocol)context;
497   SilcClientConnAuthInternalContext *ctx = 
498     (SilcClientConnAuthInternalContext *)protocol->context;
499   SilcClient client = (SilcClient)ctx->client;
500   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
501   SilcBuffer packet;
502
503   SILC_LOG_DEBUG(("Start"));
504
505   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
506       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
507     /* Error occured during protocol */
508     SILC_LOG_DEBUG(("Error during authentication protocol"));
509     silc_protocol_free(protocol);
510     if (ctx->auth_data)
511       silc_free(ctx->auth_data);
512     if (ctx->ske)
513       silc_ske_free(ctx->ske);
514     if (ctx->dest_id)
515       silc_free(ctx->dest_id);
516     conn->sock->protocol = NULL;
517     silc_socket_free(ctx->sock);
518
519     /* Notify application of failure */
520     client->ops->connect(client, ctx->sock->user_data, FALSE);
521     silc_free(ctx);
522     return;
523   }
524
525   /* Send NEW_CLIENT packet to the server. We will become registered
526      to the SILC network after sending this packet and we will receive
527      client ID from the server. */
528   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
529                              strlen(client->realname));
530   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
531   silc_buffer_format(packet,
532                      SILC_STR_UI_SHORT(strlen(client->username)),
533                      SILC_STR_UI_XNSTRING(client->username,
534                                           strlen(client->username)),
535                      SILC_STR_UI_SHORT(strlen(client->realname)),
536                      SILC_STR_UI_XNSTRING(client->realname,
537                                           strlen(client->realname)),
538                      SILC_STR_END);
539
540   /* Send the packet */
541   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
542                           NULL, 0, NULL, NULL, 
543                           packet->data, packet->len, TRUE);
544   silc_buffer_free(packet);
545
546   /* Save remote ID. */
547   conn->remote_id = ctx->dest_id;
548   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
549   conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
550
551   /* Register re-key timeout */
552   conn->rekey->timeout = 3600; /* XXX hardcoded */
553   conn->rekey->context = (void *)client;
554   silc_task_register(client->timeout_queue, conn->sock->sock, 
555                      silc_client_rekey_callback,
556                      (void *)conn->sock, conn->rekey->timeout, 0,
557                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
558
559   silc_protocol_free(protocol);
560   if (ctx->auth_data)
561     silc_free(ctx->auth_data);
562   if (ctx->ske)
563     silc_ske_free(ctx->ske);
564   silc_socket_free(ctx->sock);
565   silc_free(ctx);
566   conn->sock->protocol = NULL;
567 }
568
569 /* Internal routine that sends packet or marks packet to be sent. This
570    is used directly only in special cases. Normal cases should use
571    silc_server_packet_send. Returns < 0 on error. */
572
573 int silc_client_packet_send_real(SilcClient client,
574                                  SilcSocketConnection sock,
575                                  bool force_send,
576                                  bool flush)
577 {
578   int ret;
579
580   /* If rekey protocol is active we must assure that all packets are
581      sent through packet queue. */
582   if (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
583     force_send = FALSE;
584
585   /* Send the packet */
586   ret = silc_packet_send(sock, force_send);
587   if (ret != -2)
588     return ret;
589
590   /* Mark that there is some outgoing data available for this connection. 
591      This call sets the connection both for input and output (the input
592      is set always and this call keeps the input setting, actually). 
593      Actual data sending is performed by silc_client_packet_process. */
594   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
595
596   /* Mark to socket that data is pending in outgoing buffer. This flag
597      is needed if new data is added to the buffer before the earlier
598      put data is sent to the network. */
599   SILC_SET_OUTBUF_PENDING(sock);
600
601   return 0;
602 }
603
604 /* Packet processing callback. This is used to send and receive packets
605    from network. This is generic task. */
606
607 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
608 {
609   SilcClient client = (SilcClient)context;
610   SilcSocketConnection sock = NULL;
611   SilcClientConnection conn;
612   int ret;
613
614   SILC_LOG_DEBUG(("Processing packet"));
615
616   SILC_CLIENT_GET_SOCK(client, fd, sock);
617   if (sock == NULL)
618     return;
619
620   conn = (SilcClientConnection)sock->user_data;
621
622   /* Packet sending */
623   if (type == SILC_TASK_WRITE) {
624     SILC_LOG_DEBUG(("Writing data to connection"));
625
626     if (sock->outbuf->data - sock->outbuf->head)
627       silc_buffer_push(sock->outbuf, 
628                        sock->outbuf->data - sock->outbuf->head);
629
630     ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
631
632     /* If returned -2 could not write to connection now, will do
633        it later. */
634     if (ret == -2)
635       return;
636     
637     /* The packet has been sent and now it is time to set the connection
638        back to only for input. When there is again some outgoing data 
639        available for this connection it will be set for output as well. 
640        This call clears the output setting and sets it only for input. */
641     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
642     SILC_UNSET_OUTBUF_PENDING(sock);
643
644     silc_buffer_clear(sock->outbuf);
645     return;
646   }
647
648   /* Packet receiving */
649   if (type == SILC_TASK_READ) {
650     SILC_LOG_DEBUG(("Reading data from connection"));
651
652     /* Read data from network */
653     ret = silc_packet_receive(sock);
654     if (ret < 0)
655       return;
656     
657     /* EOF */
658     if (ret == 0) {
659       SILC_LOG_DEBUG(("Read EOF"));
660
661       /* If connection is disconnecting already we will finally
662          close the connection */
663       if (SILC_IS_DISCONNECTING(sock)) {
664         if (sock == conn->sock)
665           client->ops->disconnect(client, conn);
666         silc_client_close_connection(client, sock, conn);
667         return;
668       }
669       
670       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
671       if (sock == conn->sock)
672         client->ops->disconnect(client, conn);
673       silc_client_close_connection(client, sock, conn);
674       return;
675     }
676
677     /* Process the packet. This will call the parser that will then
678        decrypt and parse the packet. */
679     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
680       silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
681                                   silc_client_packet_parse, client);
682     else
683       silc_packet_receive_process(sock, NULL, NULL,
684                                   silc_client_packet_parse, client);
685   }
686 }
687
688 /* Callback function that the silc_packet_decrypt will call to make the
689    decision whether the packet is normal or special packet. We will 
690    return TRUE if it is normal and FALSE if it is special */
691
692 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
693                                             SilcBuffer buffer,
694                                             SilcPacketContext *packet,
695                                             void *context)
696 {
697
698   /* Packet is normal packet, if: 
699
700      1) packet is private message packet and does not have private key set
701      2) is other packet than channel message packet
702
703      all other packets are special packets 
704   */
705
706   if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
707       (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
708     return FALSE;
709
710   if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
711     return TRUE;
712
713   return FALSE;
714 }
715
716 /* Parses whole packet, received earlier. */
717
718 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
719 {
720   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
721   SilcClient client = (SilcClient)parse_ctx->context;
722   SilcPacketContext *packet = parse_ctx->packet;
723   SilcBuffer buffer = packet->buffer;
724   SilcSocketConnection sock = parse_ctx->sock;
725   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
726   int ret;
727
728   SILC_LOG_DEBUG(("Start"));
729
730   /* Decrypt the received packet */
731   if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
732     ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive, 
733                               buffer, packet,
734                               silc_client_packet_decrypt_check, parse_ctx);
735   else
736     ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
737                               silc_client_packet_decrypt_check, parse_ctx);
738
739   if (ret < 0)
740     goto out;
741
742   if (ret == 0) {
743     /* Parse the packet. Packet type is returned. */
744     ret = silc_packet_parse(packet);
745   } else {
746     /* Parse the packet header in special way as this is "special"
747        packet type. */
748     ret = silc_packet_parse_special(packet);
749   }
750
751   if (ret == SILC_PACKET_NONE)
752     goto out;
753
754   /* Parse the incoming packet type */
755   silc_client_packet_parse_type(client, sock, packet);
756
757  out:
758   /*  silc_buffer_clear(sock->inbuf); */
759   silc_packet_context_free(packet);
760   silc_free(parse_ctx);
761 }
762
763 /* Parser callback called by silc_packet_receive_process. Thie merely
764    registers timeout that will handle the actual parsing when appropriate. */
765
766 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
767 {
768   SilcClient client = (SilcClient)parser_context->context;
769
770   /* Parse the packet */
771   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
772                      silc_client_packet_parse_real,
773                      (void *)parser_context, 0, 1, 
774                      SILC_TASK_TIMEOUT,
775                      SILC_TASK_PRI_NORMAL);
776 }
777
778 /* Parses the packet type and calls what ever routines the packet type
779    requires. This is done for all incoming packets. */
780
781 void silc_client_packet_parse_type(SilcClient client, 
782                                    SilcSocketConnection sock,
783                                    SilcPacketContext *packet)
784 {
785   SilcBuffer buffer = packet->buffer;
786   SilcPacketType type = packet->type;
787
788   SILC_LOG_DEBUG(("Parsing packet type %d", type));
789
790   /* Parse the packet type */
791   switch(type) {
792   case SILC_PACKET_DISCONNECT:
793     silc_client_disconnected_by_server(client, sock, buffer);
794     break;
795   case SILC_PACKET_SUCCESS:
796     /*
797      * Success received for something. For now we can have only
798      * one protocol for connection executing at once hence this
799      * success message is for whatever protocol is executing currently.
800      */
801     if (sock->protocol)
802       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
803     break;
804   case SILC_PACKET_FAILURE:
805     /*
806      * Failure received for some protocol. Set the protocol state to 
807      * error and call the protocol callback. This fill cause error on
808      * protocol and it will call the final callback.
809      */
810     silc_client_process_failure(client, sock, packet);
811     break;
812   case SILC_PACKET_REJECT:
813     break;
814
815   case SILC_PACKET_NOTIFY:
816     /*
817      * Received notify message 
818      */
819     silc_client_notify_by_server(client, sock, packet);
820     break;
821
822   case SILC_PACKET_ERROR:
823     /*
824      * Received error message
825      */
826     silc_client_error_by_server(client, sock, buffer);
827     break;
828
829   case SILC_PACKET_CHANNEL_MESSAGE:
830     /*
831      * Received message to (from, actually) a channel
832      */
833     silc_client_channel_message(client, sock, packet);
834     break;
835   case SILC_PACKET_CHANNEL_KEY:
836     /*
837      * Received key for a channel. By receiving this key the client will be
838      * able to talk to the channel it has just joined. This can also be
839      * a new key for existing channel as keys expire peridiocally.
840      */
841     silc_client_receive_channel_key(client, sock, buffer);
842     break;
843
844   case SILC_PACKET_PRIVATE_MESSAGE:
845     /*
846      * Received private message
847      */
848     silc_client_private_message(client, sock, packet);
849     break;
850   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
851     /*
852      * Received private message key
853      */
854     break;
855
856   case SILC_PACKET_COMMAND_REPLY:
857     /*
858      * Recived reply for a command
859      */
860     silc_client_command_reply_process(client, sock, packet);
861     break;
862
863   case SILC_PACKET_KEY_EXCHANGE:
864     if (sock->protocol && sock->protocol->protocol && 
865         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
866       SilcClientKEInternalContext *proto_ctx = 
867         (SilcClientKEInternalContext *)sock->protocol->context;
868
869       proto_ctx->packet = silc_packet_context_dup(packet);
870       proto_ctx->dest_id_type = packet->src_id_type;
871       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
872                                           packet->src_id_type);
873       if (!proto_ctx->dest_id)
874         break;
875
876       /* Let the protocol handle the packet */
877       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
878     } else {
879       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
880                       "protocol active, packet dropped."));
881     }
882     break;
883
884   case SILC_PACKET_KEY_EXCHANGE_1:
885     if (sock->protocol && sock->protocol->protocol && 
886         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
887          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
888
889       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
890         SilcClientRekeyInternalContext *proto_ctx = 
891           (SilcClientRekeyInternalContext *)sock->protocol->context;
892         
893         if (proto_ctx->packet)
894           silc_packet_context_free(proto_ctx->packet);
895         
896         proto_ctx->packet = silc_packet_context_dup(packet);
897
898         /* Let the protocol handle the packet */
899         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
900       } else {
901         SilcClientKEInternalContext *proto_ctx = 
902           (SilcClientKEInternalContext *)sock->protocol->context;
903         
904         if (proto_ctx->packet)
905           silc_packet_context_free(proto_ctx->packet);
906         
907         proto_ctx->packet = silc_packet_context_dup(packet);
908         proto_ctx->dest_id_type = packet->src_id_type;
909         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
910                                             packet->src_id_type);
911         if (!proto_ctx->dest_id)
912           break;
913         
914         /* Let the protocol handle the packet */
915         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
916       }
917     } else {
918       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
919                       "protocol active, packet dropped."));
920     }
921     break;
922   case SILC_PACKET_KEY_EXCHANGE_2:
923     if (sock->protocol && sock->protocol->protocol && 
924         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
925          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
926
927       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
928         SilcClientRekeyInternalContext *proto_ctx = 
929           (SilcClientRekeyInternalContext *)sock->protocol->context;
930         
931         if (proto_ctx->packet)
932           silc_packet_context_free(proto_ctx->packet);
933         
934         proto_ctx->packet = silc_packet_context_dup(packet);
935
936         /* Let the protocol handle the packet */
937         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
938       } else {
939         SilcClientKEInternalContext *proto_ctx = 
940           (SilcClientKEInternalContext *)sock->protocol->context;
941         
942         if (proto_ctx->packet)
943           silc_packet_context_free(proto_ctx->packet);
944         
945         proto_ctx->packet = silc_packet_context_dup(packet);
946         proto_ctx->dest_id_type = packet->src_id_type;
947         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
948                                             packet->src_id_type);
949         if (!proto_ctx->dest_id)
950           break;
951         
952         /* Let the protocol handle the packet */
953         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
954       }
955     } else {
956       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
957                       "protocol active, packet dropped."));
958     }
959     break;
960
961   case SILC_PACKET_NEW_ID:
962     {
963       /*
964        * Received new ID from server. This packet is received at
965        * the connection to the server.  New ID is also received when 
966        * user changes nickname but in that case the new ID is received
967        * as command reply and not as this packet type.
968        */
969       SilcIDPayload idp;
970
971       idp = silc_id_payload_parse(buffer);
972       if (!idp)
973         break;
974       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
975         break;
976
977       silc_client_receive_new_id(client, sock, idp);
978       silc_id_payload_free(idp);
979       break;
980     }
981
982   case SILC_PACKET_HEARTBEAT:
983     /*
984      * Received heartbeat packet
985      */
986     SILC_LOG_DEBUG(("Heartbeat packet"));
987     break;
988
989   case SILC_PACKET_KEY_AGREEMENT:
990     /*
991      * Received key agreement packet
992      */
993     SILC_LOG_DEBUG(("Key agreement packet"));
994     silc_client_key_agreement(client, sock, packet);
995     break;
996
997   case SILC_PACKET_REKEY:
998     SILC_LOG_DEBUG(("Re-key packet"));
999     /* We ignore this for now */
1000     break;
1001
1002   case SILC_PACKET_REKEY_DONE:
1003     SILC_LOG_DEBUG(("Re-key done packet"));
1004
1005     if (sock->protocol && sock->protocol->protocol && 
1006         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1007
1008       SilcClientRekeyInternalContext *proto_ctx = 
1009         (SilcClientRekeyInternalContext *)sock->protocol->context;
1010       
1011       if (proto_ctx->packet)
1012         silc_packet_context_free(proto_ctx->packet);
1013       
1014       proto_ctx->packet = silc_packet_context_dup(packet);
1015
1016       /* Let the protocol handle the packet */
1017       if (proto_ctx->responder == FALSE)
1018         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
1019       else
1020         /* Let the protocol handle the packet */
1021         silc_protocol_execute(sock->protocol, client->timeout_queue, 
1022                               0, 100000);
1023     } else {
1024       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1025                       "protocol active, packet dropped."));
1026     }
1027     break;
1028
1029   default:
1030     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1031     break;
1032   }
1033 }
1034
1035 /* Sends packet. This doesn't actually send the packet instead it assembles
1036    it and marks it to be sent. However, if force_send is TRUE the packet
1037    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1038    will be derived from sock argument. Otherwise the valid arguments sent
1039    are used. */
1040
1041 void silc_client_packet_send(SilcClient client, 
1042                              SilcSocketConnection sock,
1043                              SilcPacketType type, 
1044                              void *dst_id,
1045                              SilcIdType dst_id_type,
1046                              SilcCipher cipher,
1047                              SilcHmac hmac,
1048                              unsigned char *data, 
1049                              uint32 data_len, 
1050                              int force_send)
1051 {
1052   SilcPacketContext packetdata;
1053
1054   if (!sock)
1055     return;
1056
1057   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1058
1059   /* Get data used in the packet sending, keys and stuff */
1060   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1061     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1062       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1063
1064     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1065       hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1066
1067     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1068       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1069       dst_id_type = SILC_ID_SERVER;
1070     }
1071   }
1072
1073   /* Set the packet context pointers */
1074   packetdata.flags = 0;
1075   packetdata.type = type;
1076   if (sock->user_data && 
1077       ((SilcClientConnection)sock->user_data)->local_id_data) {
1078     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1079     packetdata.src_id_len = 
1080       silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1081                       SILC_ID_CLIENT);
1082   } else { 
1083     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1084     packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1085   }
1086   packetdata.src_id_type = SILC_ID_CLIENT;
1087   if (dst_id) {
1088     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1089     packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1090     packetdata.dst_id_type = dst_id_type;
1091   } else {
1092     packetdata.dst_id = NULL;
1093     packetdata.dst_id_len = 0;
1094     packetdata.dst_id_type = SILC_ID_NONE;
1095   }
1096   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1097     packetdata.src_id_len + packetdata.dst_id_len;
1098   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1099
1100   /* Prepare outgoing data buffer for packet sending */
1101   silc_packet_send_prepare(sock, 
1102                            SILC_PACKET_HEADER_LEN +
1103                            packetdata.src_id_len + 
1104                            packetdata.dst_id_len,
1105                            packetdata.padlen,
1106                            data_len);
1107
1108   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1109
1110   packetdata.buffer = sock->outbuf;
1111
1112   /* Put the data to the buffer */
1113   if (data && data_len)
1114     silc_buffer_put(sock->outbuf, data, data_len);
1115
1116   /* Create the outgoing packet */
1117   silc_packet_assemble(&packetdata);
1118
1119   /* Encrypt the packet */
1120   if (cipher)
1121     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1122
1123   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1124                    sock->outbuf->data, sock->outbuf->len);
1125
1126   /* Now actually send the packet */
1127   silc_client_packet_send_real(client, sock, force_send, FALSE);
1128 }
1129
1130 /* Closes connection to remote end. Free's all allocated data except
1131    for some information such as nickname etc. that are valid at all time. 
1132    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
1133    provided it will be checked whether the sock and `conn->sock' are the
1134    same (they can be different, ie. a socket can use `conn' as its
1135    connection but `conn->sock' might be actually a different connection
1136    than the `sock'). */
1137
1138 void silc_client_close_connection(SilcClient client,
1139                                   SilcSocketConnection sock,
1140                                   SilcClientConnection conn)
1141 {
1142   int del = FALSE;
1143
1144   if (!sock || (sock && conn->sock == sock))
1145     del = TRUE;
1146   if (!sock)
1147     sock = conn->sock;
1148
1149   /* We won't listen for this connection anymore */
1150   silc_schedule_unset_listen_fd(sock->sock);
1151
1152   /* Unregister all tasks */
1153   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1154   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1155
1156   /* Close the actual connection */
1157   silc_net_close_connection(sock->sock);
1158
1159   /* Cancel any active protocol */
1160   if (sock->protocol) {
1161     if (sock->protocol->protocol->type == 
1162         SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1163         sock->protocol->protocol->type == 
1164         SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1165       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1166       silc_protocol_execute_final(sock->protocol, client->timeout_queue);
1167       sock->protocol = NULL;
1168       /* The application will recall this function with these protocols
1169          (the ops->connect client operation). */
1170       return;
1171     } else {
1172       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1173       silc_protocol_execute_final(sock->protocol, client->timeout_queue);
1174       sock->protocol = NULL;
1175     }
1176   }
1177
1178   /* Free everything */
1179   if (del && sock->user_data) {
1180     /* XXX Free all client entries and channel entries. */
1181
1182     /* Clear ID caches */
1183     if (conn->client_cache)
1184       silc_idcache_del_all(conn->client_cache);
1185     if (conn->channel_cache)
1186       silc_idcache_del_all(conn->channel_cache);
1187
1188     /* Free data */
1189     if (conn->remote_host)
1190       silc_free(conn->remote_host);
1191     if (conn->local_id)
1192       silc_free(conn->local_id);
1193     if (conn->local_id_data)
1194       silc_free(conn->local_id_data);
1195     if (conn->send_key)
1196       silc_cipher_free(conn->send_key);
1197     if (conn->receive_key)
1198       silc_cipher_free(conn->receive_key);
1199     if (conn->hmac_send)        /* conn->hmac_receive is same */
1200       silc_hmac_free(conn->hmac_send);
1201     if (conn->pending_commands)
1202       silc_dlist_uninit(conn->pending_commands);
1203     if (conn->rekey)
1204       silc_free(conn->rekey);
1205
1206     memset(conn, 0, sizeof(*conn));
1207     silc_client_del_connection(client, conn);
1208   }
1209
1210   silc_socket_free(sock);
1211 }
1212
1213 /* Called when we receive disconnection packet from server. This 
1214    closes our end properly and displays the reason of the disconnection
1215    on the screen. */
1216
1217 void silc_client_disconnected_by_server(SilcClient client,
1218                                         SilcSocketConnection sock,
1219                                         SilcBuffer message)
1220 {
1221   char *msg;
1222
1223   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1224
1225   msg = silc_calloc(message->len + 1, sizeof(char));
1226   memcpy(msg, message->data, message->len);
1227   client->ops->say(client, sock->user_data, msg);
1228   silc_free(msg);
1229
1230   SILC_SET_DISCONNECTED(sock);
1231   silc_client_close_connection(client, sock, sock->user_data);
1232 }
1233
1234 /* Received error message from server. Display it on the screen. 
1235    We don't take any action what so ever of the error message. */
1236
1237 void silc_client_error_by_server(SilcClient client,
1238                                  SilcSocketConnection sock,
1239                                  SilcBuffer message)
1240 {
1241   char *msg;
1242
1243   msg = silc_calloc(message->len + 1, sizeof(char));
1244   memcpy(msg, message->data, message->len);
1245   client->ops->say(client, sock->user_data, msg);
1246   silc_free(msg);
1247 }
1248
1249 /* Processes the received new Client ID from server. Old Client ID is
1250    deleted from cache and new one is added. */
1251
1252 void silc_client_receive_new_id(SilcClient client,
1253                                 SilcSocketConnection sock,
1254                                 SilcIDPayload idp)
1255 {
1256   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1257   int connecting = FALSE;
1258
1259   if (!conn->local_entry)
1260     connecting = TRUE;
1261
1262   /* Delete old ID from ID cache */
1263   if (conn->local_id) {
1264     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1265     silc_free(conn->local_id);
1266   }
1267   
1268   /* Save the new ID */
1269
1270   if (conn->local_id_data)
1271     silc_free(conn->local_id_data);
1272
1273   conn->local_id = silc_id_payload_get_id(idp);
1274   conn->local_id_data = silc_id_payload_get_data(idp);
1275   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1276
1277   if (!conn->local_entry)
1278     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1279
1280   conn->local_entry->nickname = conn->nickname;
1281   if (!conn->local_entry->username) {
1282     conn->local_entry->username = 
1283       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1284                   sizeof(conn->local_entry->username));
1285     sprintf(conn->local_entry->username, "%s@%s", client->username,
1286             client->hostname);
1287   }
1288   conn->local_entry->server = strdup(conn->remote_host);
1289   conn->local_entry->id = conn->local_id;
1290   
1291   /* Put it to the ID cache */
1292   silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id, 
1293                    (void *)conn->local_entry, FALSE);
1294
1295   /* Notify application of successful connection. We do it here now that
1296      we've received the Client ID and are allowed to send traffic. */
1297   if (connecting)
1298     client->ops->connect(client, conn, TRUE);
1299 }
1300
1301 /* Processed received Channel ID for a channel. This is called when client
1302    joins to channel and server replies with channel ID. The ID is cached. 
1303    Returns the created channel entry. */
1304
1305 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1306                                             SilcSocketConnection sock,
1307                                             char *channel_name,
1308                                             uint32 mode, 
1309                                             SilcIDPayload idp)
1310 {
1311   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1312   SilcChannelEntry channel;
1313
1314   SILC_LOG_DEBUG(("New channel ID"));
1315
1316   channel = silc_calloc(1, sizeof(*channel));
1317   channel->channel_name = channel_name;
1318   channel->id = silc_id_payload_get_id(idp);
1319   channel->mode = mode;
1320   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1321
1322   conn->current_channel = channel;
1323
1324   /* Put it to the ID cache */
1325   silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id, 
1326                    (void *)channel, FALSE);
1327
1328   return channel;
1329 }
1330
1331 /* Removes a client entry from all channel it has joined. This really is
1332    a performance killer (client_entry should have pointers to channel 
1333    entry list). */
1334
1335 void silc_client_remove_from_channels(SilcClient client,
1336                                       SilcClientConnection conn,
1337                                       SilcClientEntry client_entry)
1338 {
1339   SilcIDCacheEntry id_cache;
1340   SilcIDCacheList list;
1341   SilcChannelEntry channel;
1342   SilcChannelUser chu;
1343
1344   if (!silc_idcache_get_all(conn->channel_cache, &list))
1345     return;
1346
1347   silc_idcache_list_first(list, &id_cache);
1348   channel = (SilcChannelEntry)id_cache->context;
1349   
1350   while (channel) {
1351     
1352     /* Remove client from channel */
1353     silc_list_start(channel->clients);
1354     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1355       if (chu->client == client_entry) {
1356         silc_list_del(channel->clients, chu);
1357         silc_free(chu);
1358         break;
1359       }
1360     }
1361
1362     if (!silc_idcache_list_next(list, &id_cache))
1363       break;
1364     
1365     channel = (SilcChannelEntry)id_cache->context;
1366   }
1367
1368   silc_idcache_list_free(list);
1369 }
1370
1371 /* Replaces `old' client entries from all channels to `new' client entry.
1372    This can be called for example when nickname changes and old ID entry
1373    is replaced from ID cache with the new one. If the old ID entry is only
1374    updated, then this fucntion needs not to be called. */
1375
1376 void silc_client_replace_from_channels(SilcClient client, 
1377                                        SilcClientConnection conn,
1378                                        SilcClientEntry old,
1379                                        SilcClientEntry new)
1380 {
1381   SilcIDCacheEntry id_cache;
1382   SilcIDCacheList list;
1383   SilcChannelEntry channel;
1384   SilcChannelUser chu;
1385
1386   if (!silc_idcache_get_all(conn->channel_cache, &list))
1387     return;
1388
1389   silc_idcache_list_first(list, &id_cache);
1390   channel = (SilcChannelEntry)id_cache->context;
1391   
1392   while (channel) {
1393     
1394     /* Replace client entry */
1395     silc_list_start(channel->clients);
1396     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1397       if (chu->client == old) {
1398         chu->client = new;
1399         break;
1400       }
1401     }
1402
1403     if (!silc_idcache_list_next(list, &id_cache))
1404       break;
1405     
1406     channel = (SilcChannelEntry)id_cache->context;
1407   }
1408
1409   silc_idcache_list_free(list);
1410 }
1411
1412 /* Registers failure timeout to process the received failure packet
1413    with timeout. */
1414
1415 void silc_client_process_failure(SilcClient client,
1416                                  SilcSocketConnection sock,
1417                                  SilcPacketContext *packet)
1418 {
1419   uint32 failure = 0;
1420
1421   if (sock->protocol) {
1422     if (packet->buffer->len >= 4)
1423       SILC_GET32_MSB(failure, packet->buffer->data);
1424
1425     /* Notify application */
1426     client->ops->failure(client, sock->user_data, sock->protocol,
1427                          (void *)failure);
1428   }
1429 }
1430
1431 /* A timeout callback for the re-key. We will be the initiator of the
1432    re-key protocol. */
1433
1434 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1435 {
1436   SilcSocketConnection sock = (SilcSocketConnection)context;
1437   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1438   SilcClient client = (SilcClient)conn->rekey->context;
1439   SilcProtocol protocol;
1440   SilcClientRekeyInternalContext *proto_ctx;
1441
1442   SILC_LOG_DEBUG(("Start"));
1443
1444   /* Allocate internal protocol context. This is sent as context
1445      to the protocol. */
1446   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1447   proto_ctx->client = (void *)client;
1448   proto_ctx->sock = silc_socket_dup(sock);
1449   proto_ctx->responder = FALSE;
1450   proto_ctx->pfs = conn->rekey->pfs;
1451       
1452   /* Perform rekey protocol. Will call the final callback after the
1453      protocol is over. */
1454   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1455                       &protocol, proto_ctx, silc_client_rekey_final);
1456   sock->protocol = protocol;
1457       
1458   /* Run the protocol */
1459   silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
1460
1461   /* Re-register re-key timeout */
1462   silc_task_register(client->timeout_queue, sock->sock, 
1463                      silc_client_rekey_callback,
1464                      context, conn->rekey->timeout, 0,
1465                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1466 }
1467
1468 /* The final callback for the REKEY protocol. This will actually take the
1469    new key material into use. */
1470
1471 SILC_TASK_CALLBACK(silc_client_rekey_final)
1472 {
1473   SilcProtocol protocol = (SilcProtocol)context;
1474   SilcClientRekeyInternalContext *ctx =
1475     (SilcClientRekeyInternalContext *)protocol->context;
1476   SilcClient client = (SilcClient)ctx->client;
1477   SilcSocketConnection sock = ctx->sock;
1478
1479   SILC_LOG_DEBUG(("Start"));
1480
1481   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1482       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1483     /* Error occured during protocol */
1484     silc_protocol_cancel(protocol, client->timeout_queue);
1485     silc_protocol_free(protocol);
1486     sock->protocol = NULL;
1487     if (ctx->packet)
1488       silc_packet_context_free(ctx->packet);
1489     if (ctx->ske)
1490       silc_ske_free(ctx->ske);
1491     silc_socket_free(ctx->sock);
1492     silc_free(ctx);
1493     return;
1494   }
1495
1496   /* Cleanup */
1497   silc_protocol_free(protocol);
1498   sock->protocol = NULL;
1499   if (ctx->packet)
1500     silc_packet_context_free(ctx->packet);
1501   if (ctx->ske)
1502     silc_ske_free(ctx->ske);
1503   silc_socket_free(ctx->sock);
1504   silc_free(ctx);
1505 }