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