Added client_del_connection functions. Patch by cras.
[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 - 2000 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
24 /* Static task callback prototypes */
25 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
28 SILC_TASK_CALLBACK(silc_client_packet_process);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
30
31 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
32 static void silc_client_packet_parse_type(SilcClient client, 
33                                           SilcSocketConnection sock,
34                                           SilcPacketContext *packet);
35
36 /* Allocates new client object. This has to be done before client may
37    work. After calling this one must call silc_client_init to initialize
38    the client. The `application' is application specific user data pointer
39    and caller must free it. */
40
41 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
42 {
43   SilcClient new_client;
44
45   new_client = silc_calloc(1, sizeof(*new_client));
46   new_client->application = application;
47   new_client->ops = ops;
48
49   return new_client;
50 }
51
52 /* Free's client object */
53
54 void silc_client_free(SilcClient client)
55 {
56   if (client) {
57     silc_free(client);
58   }
59 }
60
61 /* Initializes the client. This makes all the necessary steps to make
62    the client ready to be run. One must call silc_client_run to run the
63    client. */
64
65 int silc_client_init(SilcClient client)
66 {
67   SILC_LOG_DEBUG(("Initializing client"));
68
69   /* Initialize hash functions for client to use */
70   silc_hash_alloc("md5", &client->md5hash);
71   silc_hash_alloc("sha1", &client->sha1hash);
72
73   /* Initialize none cipher */
74   silc_cipher_alloc("none", &client->none_cipher);
75
76   /* Initialize random number generator */
77   client->rng = silc_rng_alloc();
78   silc_rng_init(client->rng);
79   silc_math_primegen_init(); /* XXX */
80
81   /* Register protocols */
82   silc_client_protocols_register();
83
84   /* Initialize the scheduler */
85   silc_schedule_init(&client->io_queue, &client->timeout_queue, 
86                      &client->generic_queue, 5000);
87
88   return TRUE;
89 }
90
91 /* Stops the client. This is called to stop the client and thus to stop
92    the program. */
93
94 void silc_client_stop(SilcClient client)
95 {
96   SILC_LOG_DEBUG(("Stopping client"));
97
98   /* Stop the scheduler, although it might be already stopped. This
99      doesn't hurt anyone. This removes all the tasks and task queues,
100      as well. */
101   silc_schedule_stop();
102   silc_schedule_uninit();
103
104   silc_client_protocols_unregister();
105
106   SILC_LOG_DEBUG(("Client stopped"));
107 }
108
109 /* Runs the client. */
110
111 void silc_client_run(SilcClient client)
112 {
113   SILC_LOG_DEBUG(("Running client"));
114
115   /* Start the scheduler, the heart of the SILC client. When this returns
116      the program will be terminated. */
117   silc_schedule();
118 }
119
120 /* Allocates and adds new connection to the client. This adds the allocated
121    connection to the connection table and returns a pointer to it. A client
122    can have multiple connections to multiple servers. Every connection must
123    be added to the client using this function. User data `context' may
124    be sent as argument. */
125
126 SilcClientConnection silc_client_add_connection(SilcClient client,
127                                                 void *context)
128 {
129   SilcClientConnection conn;
130   int i;
131
132   conn = silc_calloc(1, sizeof(*conn));
133
134   /* Initialize ID caches */
135   conn->client_cache = silc_idcache_alloc(0);
136   conn->channel_cache = silc_idcache_alloc(0);
137   conn->server_cache = silc_idcache_alloc(0);
138   conn->client = client;
139   conn->context = context;
140
141   /* Add the connection to connections table */
142   for (i = 0; i < client->conns_count; i++)
143     if (client->conns && !client->conns[i]) {
144       client->conns[i] = conn;
145       return conn;
146     }
147
148   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
149                                * (client->conns_count + 1));
150   client->conns[client->conns_count] = conn;
151   client->conns_count++;
152
153   return conn;
154 }
155
156 /* Removes connection from client. */
157
158 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
159 {
160   int i;
161
162   for (i = 0; i < client->conns_count; i++)
163     if (client->conns[i] == conn) {
164       silc_free(conn);
165       client->conns[i] = NULL;
166     }
167 }
168
169 /* Internal context for connection process. This is needed as we
170    doing asynchronous connecting. */
171 typedef struct {
172   SilcClient client;
173   SilcClientConnection conn;
174   SilcTask task;
175   int sock;
176   char *host;
177   int port;
178   int tries;
179 } SilcClientInternalConnectContext;
180
181 static int 
182 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
183 {
184   int sock;
185
186   /* XXX In the future we should give up this non-blocking connect all
187      together and use threads instead. */
188   /* Create connection to server asynchronously */
189   sock = silc_net_create_connection_async(ctx->port, ctx->host);
190   if (sock < 0)
191     return -1;
192
193   /* Register task that will receive the async connect and will
194      read the result. */
195   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
196                                  silc_client_connect_to_server_start,
197                                  (void *)ctx, 0, 0, 
198                                  SILC_TASK_FD,
199                                  SILC_TASK_PRI_NORMAL);
200   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
201   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
202
203   ctx->sock = sock;
204
205   return sock;
206 }
207
208 /* Connects to remote server. This is the main routine used to connect
209    to SILC server. Returns -1 on error and the created socket otherwise. 
210    The `context' is user context that is saved into the SilcClientConnection
211    that is created after the connection is created. */
212
213 int silc_client_connect_to_server(SilcClient client, int port,
214                                   char *host, void *context)
215 {
216   SilcClientInternalConnectContext *ctx;
217   SilcClientConnection conn;
218   int sock;
219
220   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
221                   port, host));
222
223   conn = silc_client_add_connection(client, context);
224   conn->remote_host = strdup(host);
225   conn->remote_port = port;
226
227   client->ops->say(client, conn, 
228                    "Connecting to port %d of server %s", port, host);
229
230   /* Allocate internal context for connection process. This is
231      needed as we are doing async connecting. */
232   ctx = silc_calloc(1, sizeof(*ctx));
233   ctx->client = client;
234   ctx->conn = conn;
235   ctx->host = strdup(host);
236   ctx->port = port;
237   ctx->tries = 0;
238
239   /* Do the actual connecting process */
240   sock = silc_client_connect_to_server_internal(ctx);
241   if (sock == -1)
242     silc_client_del_connection(client, conn);
243   return sock;
244 }
245
246 /* Start of the connection to the remote server. This is called after
247    succesful TCP/IP connection has been established to the remote host. */
248
249 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
250 {
251   SilcClientInternalConnectContext *ctx =
252     (SilcClientInternalConnectContext *)context;
253   SilcClient client = ctx->client;
254   SilcClientConnection conn = ctx->conn;
255   SilcProtocol protocol;
256   SilcClientKEInternalContext *proto_ctx;
257   int opt, opt_len = sizeof(opt);
258
259   SILC_LOG_DEBUG(("Start"));
260
261   /* Check the socket status as it might be in error */
262   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
263   if (opt != 0) {
264     if (ctx->tries < 2) {
265       /* Connection failed but lets try again */
266       client->ops->say(client, conn, "Could not connect to server %s: %s",
267                        ctx->host, strerror(opt));
268       client->ops->say(client, conn, 
269                        "Connecting to port %d of server %s resumed", 
270                        ctx->port, ctx->host);
271
272       /* Unregister old connection try */
273       silc_schedule_unset_listen_fd(fd);
274       silc_net_close_connection(fd);
275       silc_task_unregister(client->io_queue, ctx->task);
276
277       /* Try again */
278       silc_client_connect_to_server_internal(ctx);
279       ctx->tries++;
280     } else {
281       /* Connection failed and we won't try anymore */
282       client->ops->say(client, conn, "Could not connect to server %s: %s",
283                        ctx->host, strerror(opt));
284       silc_schedule_unset_listen_fd(fd);
285       silc_net_close_connection(fd);
286       silc_task_unregister(client->io_queue, ctx->task);
287       silc_free(ctx);
288
289       /* Notify application of failure */
290       client->ops->connect(client, conn, FALSE);
291       silc_client_del_connection(client, conn);
292     }
293     return;
294   }
295
296   silc_schedule_unset_listen_fd(fd);
297   silc_task_unregister(client->io_queue, ctx->task);
298   silc_free(ctx);
299
300   /* Allocate new socket connection object */
301   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
302   if (conn->sock == NULL) {
303     client->ops->say(client, conn, 
304                      "Error: Could not allocate connection socket");
305     silc_net_close_connection(fd);
306     client->ops->connect(client, conn, FALSE);
307     return;
308   }
309
310   conn->nickname = strdup(client->username);
311   conn->sock->hostname = conn->remote_host;
312   conn->sock->port = conn->remote_port;
313
314   /* Allocate internal Key Exchange context. This is sent to the
315      protocol as context. */
316   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
317   proto_ctx->client = (void *)client;
318   proto_ctx->sock = conn->sock;
319   proto_ctx->rng = client->rng;
320   proto_ctx->responder = FALSE;
321
322   /* Perform key exchange protocol. silc_client_connect_to_server_final
323      will be called after the protocol is finished. */
324   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
325                       &protocol, (void *)proto_ctx,
326                       silc_client_connect_to_server_second);
327   if (!protocol) {
328     client->ops->say(client, conn, 
329                      "Error: Could not start authentication protocol");
330     client->ops->connect(client, conn, FALSE);
331     return;
332   }
333   conn->sock->protocol = protocol;
334
335   /* Register the connection for network input and output. This sets
336      that scheduler will listen for incoming packets for this connection 
337      and sets that outgoing packets may be sent to this connection as well.
338      However, this doesn't set the scheduler for outgoing traffic, it will 
339      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
340      later when outgoing data is available. */
341   context = (void *)client;
342   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
343
344   /* Execute the protocol */
345   protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
346 }
347
348 /* Second part of the connecting to the server. This executed 
349    authentication protocol. */
350
351 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
352 {
353   SilcProtocol protocol = (SilcProtocol)context;
354   SilcClientKEInternalContext *ctx = 
355     (SilcClientKEInternalContext *)protocol->context;
356   SilcClient client = (SilcClient)ctx->client;
357   SilcSocketConnection sock = NULL;
358   SilcClientConnAuthInternalContext *proto_ctx;
359
360   SILC_LOG_DEBUG(("Start"));
361
362   if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
363     /* Error occured during protocol */
364     SILC_LOG_DEBUG(("Error during KE protocol"));
365     silc_protocol_free(protocol);
366     if (ctx->ske)
367       silc_ske_free(ctx->ske);
368     if (ctx->dest_id)
369       silc_free(ctx->dest_id);
370     ctx->sock->protocol = NULL;
371     silc_free(ctx);
372
373     /* Notify application of failure */
374     client->ops->connect(client, ctx->sock->user_data, FALSE);
375     return;
376   }
377
378   /* Allocate internal context for the authentication protocol. This
379      is sent as context for the protocol. */
380   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
381   proto_ctx->client = (void *)client;
382   proto_ctx->sock = sock = ctx->sock;
383   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
384   proto_ctx->dest_id_type = ctx->dest_id_type;
385   proto_ctx->dest_id = ctx->dest_id;
386
387   /* Resolve the authentication method to be used in this connection */
388   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
389                                     sock->port, &proto_ctx->auth_meth,
390                                     &proto_ctx->auth_data, 
391                                     &proto_ctx->auth_data_len))
392     {
393       /* XXX do AUTH_REQUEST resolcing with server */
394       proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
395     }
396
397   /* Free old protocol as it is finished now */
398   silc_protocol_free(protocol);
399   if (ctx->packet)
400     silc_buffer_free(ctx->packet);
401   silc_free(ctx);
402   /* silc_free(ctx->keymat....); */
403   sock->protocol = NULL;
404
405   /* Allocate the authentication protocol. This is allocated here
406      but we won't start it yet. We will be receiving party of this
407      protocol thus we will wait that connecting party will make
408      their first move. */
409   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
410                       &sock->protocol, (void *)proto_ctx, 
411                       silc_client_connect_to_server_final);
412
413   /* Execute the protocol */
414   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
415 }
416
417 /* Finalizes the connection to the remote SILC server. This is called
418    after authentication protocol has been completed. This send our
419    user information to the server to receive our client ID from
420    server. */
421
422 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
423 {
424   SilcProtocol protocol = (SilcProtocol)context;
425   SilcClientConnAuthInternalContext *ctx = 
426     (SilcClientConnAuthInternalContext *)protocol->context;
427   SilcClient client = (SilcClient)ctx->client;
428   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
429   SilcBuffer packet;
430
431   SILC_LOG_DEBUG(("Start"));
432
433   if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
434     /* Error occured during protocol */
435     SILC_LOG_DEBUG(("Error during authentication protocol"));
436     silc_protocol_free(protocol);
437     if (ctx->auth_data)
438       silc_free(ctx->auth_data);
439     if (ctx->ske)
440       silc_ske_free(ctx->ske);
441     if (ctx->dest_id)
442       silc_free(ctx->dest_id);
443     silc_free(ctx);
444     conn->sock->protocol = NULL;
445
446     /* Notify application of failure */
447     client->ops->connect(client, ctx->sock->user_data, FALSE);
448     return;
449   }
450
451   /* Send NEW_CLIENT packet to the server. We will become registered
452      to the SILC network after sending this packet and we will receive
453      client ID from the server. */
454   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
455                              strlen(client->realname));
456   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
457   silc_buffer_format(packet,
458                      SILC_STR_UI_SHORT(strlen(client->username)),
459                      SILC_STR_UI_XNSTRING(client->username,
460                                           strlen(client->username)),
461                      SILC_STR_UI_SHORT(strlen(client->realname)),
462                      SILC_STR_UI_XNSTRING(client->realname,
463                                           strlen(client->realname)),
464                      SILC_STR_END);
465
466   /* Send the packet */
467   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
468                           NULL, 0, NULL, NULL, 
469                           packet->data, packet->len, TRUE);
470   silc_buffer_free(packet);
471
472   /* Save remote ID. */
473   conn->remote_id = ctx->dest_id;
474   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
475   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
476
477   client->ops->say(client, conn, "Connected to port %d of host %s",
478                    conn->remote_port, conn->remote_host);
479
480   /* Notify application of successful connection */
481   client->ops->connect(client, conn, TRUE);
482
483   silc_protocol_free(protocol);
484   if (ctx->auth_data)
485     silc_free(ctx->auth_data);
486   if (ctx->ske)
487     silc_ske_free(ctx->ske);
488   if (ctx->dest_id)
489     silc_free(ctx->dest_id);
490   silc_free(ctx);
491   conn->sock->protocol = NULL;
492 }
493
494 /* Internal routine that sends packet or marks packet to be sent. This
495    is used directly only in special cases. Normal cases should use
496    silc_server_packet_send. Returns < 0 on error. */
497
498 static int silc_client_packet_send_real(SilcClient client,
499                                         SilcSocketConnection sock,
500                                         int force_send)
501 {
502   int ret;
503
504   /* Send the packet */
505   ret = silc_packet_send(sock, force_send);
506   if (ret != -2)
507     return ret;
508
509   /* Mark that there is some outgoing data available for this connection. 
510      This call sets the connection both for input and output (the input
511      is set always and this call keeps the input setting, actually). 
512      Actual data sending is performed by silc_client_packet_process. */
513   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
514
515   /* Mark to socket that data is pending in outgoing buffer. This flag
516      is needed if new data is added to the buffer before the earlier
517      put data is sent to the network. */
518   SILC_SET_OUTBUF_PENDING(sock);
519
520   return 0;
521 }
522
523 /* Packet processing callback. This is used to send and receive packets
524    from network. This is generic task. */
525
526 SILC_TASK_CALLBACK(silc_client_packet_process)
527 {
528   SilcClient client = (SilcClient)context;
529   SilcSocketConnection sock = NULL;
530   SilcClientConnection conn;
531   int ret;
532
533   SILC_LOG_DEBUG(("Processing packet"));
534
535   SILC_CLIENT_GET_SOCK(client, fd, sock);
536   if (sock == NULL)
537     return;
538
539   conn = (SilcClientConnection)sock->user_data;
540
541   /* Packet sending */
542   if (type == SILC_TASK_WRITE) {
543     SILC_LOG_DEBUG(("Writing data to connection"));
544
545     if (sock->outbuf->data - sock->outbuf->head)
546       silc_buffer_push(sock->outbuf, 
547                        sock->outbuf->data - sock->outbuf->head);
548
549     ret = silc_client_packet_send_real(client, sock, TRUE);
550
551     /* If returned -2 could not write to connection now, will do
552        it later. */
553     if (ret == -2)
554       return;
555     
556     /* The packet has been sent and now it is time to set the connection
557        back to only for input. When there is again some outgoing data 
558        available for this connection it will be set for output as well. 
559        This call clears the output setting and sets it only for input. */
560     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
561     SILC_UNSET_OUTBUF_PENDING(sock);
562
563     silc_buffer_clear(sock->outbuf);
564     return;
565   }
566
567   /* Packet receiving */
568   if (type == SILC_TASK_READ) {
569     SILC_LOG_DEBUG(("Reading data from connection"));
570
571     /* Read data from network */
572     ret = silc_packet_receive(sock);
573     if (ret < 0)
574       return;
575     
576     /* EOF */
577     if (ret == 0) {
578       SILC_LOG_DEBUG(("Read EOF"));
579
580       /* If connection is disconnecting already we will finally
581          close the connection */
582       if (SILC_IS_DISCONNECTING(sock)) {
583         client->ops->disconnect(client, conn);
584         silc_client_close_connection(client, sock);
585         return;
586       }
587       
588       client->ops->say(client, conn, "Connection closed: premature EOF");
589       SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
590       client->ops->disconnect(client, conn);
591       silc_client_close_connection(client, sock);
592       return;
593     }
594
595     /* Process the packet. This will call the parser that will then
596        decrypt and parse the packet. */
597     if (!silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
598                                      silc_client_packet_parse, client)) {
599       silc_buffer_clear(sock->inbuf);
600       return;
601     }
602   }
603 }
604
605 /* Parses whole packet, received earlier. */
606
607 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
608 {
609   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
610   SilcClient client = (SilcClient)parse_ctx->context;
611   SilcPacketContext *packet = parse_ctx->packet;
612   SilcBuffer buffer = packet->buffer;
613   SilcSocketConnection sock = parse_ctx->sock;
614   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
615   int ret;
616
617   SILC_LOG_DEBUG(("Start"));
618
619   /* Decrypt the received packet */
620   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
621   if (ret < 0)
622     goto out;
623
624   if (ret == 0) {
625     /* Parse the packet. Packet type is returned. */
626     ret = silc_packet_parse(packet);
627   } else {
628     /* Parse the packet header in special way as this is "special"
629        packet type. */
630     ret = silc_packet_parse_special(packet);
631   }
632
633   if (ret == SILC_PACKET_NONE)
634     goto out;
635
636   /* Parse the incoming packet type */
637   silc_client_packet_parse_type(client, sock, packet);
638
639  out:
640   silc_buffer_clear(buffer);
641   silc_free(packet);
642   silc_free(parse_ctx);
643 }
644
645 /* Parser callback called by silc_packet_receive_process. Thie merely
646    registers timeout that will handle the actual parsing when appropriate. */
647
648 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
649 {
650   SilcClient client = (SilcClient)parser_context->context;
651
652   /* Parse the packet */
653   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
654                      silc_client_packet_parse_real,
655                      (void *)parser_context, 0, 1, 
656                      SILC_TASK_TIMEOUT,
657                      SILC_TASK_PRI_NORMAL);
658 }
659   
660 /* Parses the packet type and calls what ever routines the packet type
661    requires. This is done for all incoming packets. */
662
663 void silc_client_packet_parse_type(SilcClient client, 
664                                    SilcSocketConnection sock,
665                                    SilcPacketContext *packet)
666 {
667   SilcBuffer buffer = packet->buffer;
668   SilcPacketType type = packet->type;
669
670   SILC_LOG_DEBUG(("Parsing packet type %d", type));
671
672   /* Parse the packet type */
673   switch(type) {
674   case SILC_PACKET_DISCONNECT:
675     silc_client_disconnected_by_server(client, sock, buffer);
676     break;
677   case SILC_PACKET_SUCCESS:
678     /*
679      * Success received for something. For now we can have only
680      * one protocol for connection executing at once hence this
681      * success message is for whatever protocol is executing currently.
682      */
683     if (sock->protocol) {
684       sock->protocol->execute(client->timeout_queue, 0,
685                               sock->protocol, sock->sock, 0, 0);
686     }
687     break;
688   case SILC_PACKET_FAILURE:
689     /*
690      * Failure received for some protocol. Set the protocol state to 
691      * error and call the protocol callback. This fill cause error on
692      * protocol and it will call the final callback.
693      */
694     if (sock->protocol) {
695       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
696       sock->protocol->execute(client->timeout_queue, 0,
697                               sock->protocol, sock->sock, 0, 0);
698     }
699     break;
700   case SILC_PACKET_REJECT:
701     break;
702
703   case SILC_PACKET_NOTIFY:
704     /*
705      * Received notify message 
706      */
707     silc_client_notify_by_server(client, sock, buffer);
708     break;
709
710   case SILC_PACKET_ERROR:
711     /*
712      * Received error message
713      */
714     silc_client_error_by_server(client, sock, buffer);
715     break;
716
717   case SILC_PACKET_CHANNEL_MESSAGE:
718     /*
719      * Received message to (from, actually) a channel
720      */
721     silc_client_channel_message(client, sock, packet);
722     break;
723   case SILC_PACKET_CHANNEL_KEY:
724     /*
725      * Received key for a channel. By receiving this key the client will be
726      * able to talk to the channel it has just joined. This can also be
727      * a new key for existing channel as keys expire peridiocally.
728      */
729     silc_client_receive_channel_key(client, sock, buffer);
730     break;
731
732   case SILC_PACKET_PRIVATE_MESSAGE:
733     /*
734      * Received private message
735      */
736     silc_client_private_message(client, sock, packet);
737     break;
738   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
739     /*
740      * Received private message key
741      */
742     break;
743
744   case SILC_PACKET_COMMAND_REPLY:
745     /*
746      * Recived reply for a command
747      */
748     silc_client_command_reply_process(client, sock, packet);
749     break;
750
751   case SILC_PACKET_KEY_EXCHANGE:
752     if (sock->protocol) {
753       SilcClientKEInternalContext *proto_ctx = 
754         (SilcClientKEInternalContext *)sock->protocol->context;
755
756       proto_ctx->packet = buffer;
757       proto_ctx->dest_id_type = packet->src_id_type;
758       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
759
760       /* Let the protocol handle the packet */
761       sock->protocol->execute(client->timeout_queue, 0,
762                               sock->protocol, sock->sock, 0, 0);
763     } else {
764       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
765                       "protocol active, packet dropped."));
766
767       /* XXX Trigger KE protocol?? Rekey actually! */
768     }
769     break;
770
771   case SILC_PACKET_KEY_EXCHANGE_1:
772     if (sock->protocol) {
773
774     } else {
775       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
776                       "protocol active, packet dropped."));
777     }
778     break;
779   case SILC_PACKET_KEY_EXCHANGE_2:
780     if (sock->protocol) {
781       SilcClientKEInternalContext *proto_ctx = 
782         (SilcClientKEInternalContext *)sock->protocol->context;
783
784       if (proto_ctx->packet)
785         silc_buffer_free(proto_ctx->packet);
786
787       proto_ctx->packet = buffer;
788       proto_ctx->dest_id_type = packet->src_id_type;
789       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
790
791       /* Let the protocol handle the packet */
792       sock->protocol->execute(client->timeout_queue, 0,
793                               sock->protocol, sock->sock, 0, 0);
794     } else {
795       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
796                       "protocol active, packet dropped."));
797     }
798     break;
799
800   case SILC_PACKET_NEW_ID:
801     {
802       /*
803        * Received new ID from server. This packet is received at
804        * the connection to the server.  New ID is also received when 
805        * user changes nickname but in that case the new ID is received
806        * as command reply and not as this packet type.
807        */
808       unsigned char *id_string;
809       unsigned short id_type;
810       
811       silc_buffer_unformat(buffer,
812                            SILC_STR_UI_SHORT(&id_type),
813                            SILC_STR_UI16_STRING_ALLOC(&id_string),
814                            SILC_STR_END);
815       
816       if ((SilcIdType)id_type != SILC_ID_CLIENT)
817         break;
818
819       silc_client_receive_new_id(client, sock, id_string);
820       silc_free(id_string);
821       break;
822     }
823
824   default:
825     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
826     break;
827   }
828 }
829
830 /* Sends packet. This doesn't actually send the packet instead it assembles
831    it and marks it to be sent. However, if force_send is TRUE the packet
832    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
833    will be derived from sock argument. Otherwise the valid arguments sent
834    are used. */
835
836 void silc_client_packet_send(SilcClient client, 
837                              SilcSocketConnection sock,
838                              SilcPacketType type, 
839                              void *dst_id,
840                              SilcIdType dst_id_type,
841                              SilcCipher cipher,
842                              SilcHmac hmac,
843                              unsigned char *data, 
844                              unsigned int data_len, 
845                              int force_send)
846 {
847   SilcPacketContext packetdata;
848
849   SILC_LOG_DEBUG(("Sending packet, type %d", type));
850
851   /* Get data used in the packet sending, keys and stuff */
852   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
853     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
854       cipher = ((SilcClientConnection)sock->user_data)->send_key;
855
856     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
857       hmac = ((SilcClientConnection)sock->user_data)->hmac;
858
859     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
860       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
861       dst_id_type = SILC_ID_SERVER;
862     }
863   }
864
865   /* Set the packet context pointers */
866   packetdata.flags = 0;
867   packetdata.type = type;
868   if (((SilcClientConnection)sock->user_data)->local_id_data)
869     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
870   else 
871     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
872   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
873   packetdata.src_id_type = SILC_ID_CLIENT;
874   if (dst_id) {
875     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
876     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
877     packetdata.dst_id_type = dst_id_type;
878   } else {
879     packetdata.dst_id = NULL;
880     packetdata.dst_id_len = 0;
881     packetdata.dst_id_type = SILC_ID_NONE;
882   }
883   packetdata.rng = client->rng;
884   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
885     packetdata.src_id_len + packetdata.dst_id_len;
886   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
887
888   /* Prepare outgoing data buffer for packet sending */
889   silc_packet_send_prepare(sock, 
890                            SILC_PACKET_HEADER_LEN +
891                            packetdata.src_id_len + 
892                            packetdata.dst_id_len,
893                            packetdata.padlen,
894                            data_len);
895
896   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
897
898   packetdata.buffer = sock->outbuf;
899
900   /* Put the data to the buffer */
901   if (data && data_len)
902     silc_buffer_put(sock->outbuf, data, data_len);
903
904   /* Create the outgoing packet */
905   silc_packet_assemble(&packetdata);
906
907   /* Encrypt the packet */
908   if (cipher)
909     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
910
911   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
912                    sock->outbuf->data, sock->outbuf->len);
913
914   /* Now actually send the packet */
915   silc_client_packet_send_real(client, sock, force_send);
916 }
917
918 /* Sends packet to a channel. Packet to channel is always encrypted
919    differently from "normal" packets. SILC header of the packet is 
920    encrypted with the next receiver's key and the rest of the packet is
921    encrypted with the channel specific key. Padding and HMAC is computed
922    with the next receiver's key. */
923
924 void silc_client_packet_send_to_channel(SilcClient client, 
925                                         SilcSocketConnection sock,
926                                         SilcChannelEntry channel,
927                                         unsigned char *data, 
928                                         unsigned int data_len, 
929                                         int force_send)
930 {
931   int i;
932   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
933   SilcBuffer payload;
934   SilcPacketContext packetdata;
935   SilcCipher cipher;
936   SilcHmac hmac;
937   unsigned char *id_string;
938
939   SILC_LOG_DEBUG(("Sending packet to channel"));
940
941   if (!channel || !channel->key) {
942     client->ops->say(client, conn, 
943                      "Cannot talk to channel: key does not exist");
944     return;
945   }
946
947   /* Generate IV */
948   if (!channel->iv)
949     for (i = 0; i < 16; i++)
950       channel->iv[i] = silc_rng_get_byte(client->rng);
951   else
952     silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
953
954   /* Encode the channel payload */
955   payload = silc_channel_encode_payload(strlen(conn->nickname), conn->nickname,
956                                         data_len, data, 16, channel->iv, 
957                                         client->rng);
958   if (!payload) {
959     client->ops->say(client, conn, 
960                      "Error: Could not create packet to be sent to channel");
961     return;
962   }
963
964   /* Get data used in packet header encryption, keys and stuff. Rest
965      of the packet (the payload) is, however, encrypted with the 
966      specified channel key. */
967   cipher = conn->send_key;
968   hmac = conn->hmac;
969   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
970
971   /* Set the packet context pointers. The destination ID is always
972      the Channel ID of the channel. Server and router will handle the
973      distribution of the packet. */
974   packetdata.flags = 0;
975   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
976   packetdata.src_id = conn->local_id_data;
977   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
978   packetdata.src_id_type = SILC_ID_CLIENT;
979   packetdata.dst_id = id_string;
980   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
981   packetdata.dst_id_type = SILC_ID_CHANNEL;
982   packetdata.rng = client->rng;
983   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
984     packetdata.src_id_len + packetdata.dst_id_len;
985   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
986                                           packetdata.src_id_len +
987                                           packetdata.dst_id_len));
988
989   /* Prepare outgoing data buffer for packet sending */
990   silc_packet_send_prepare(sock, 
991                            SILC_PACKET_HEADER_LEN +
992                            packetdata.src_id_len + 
993                            packetdata.dst_id_len,
994                            packetdata.padlen,
995                            payload->len);
996
997   packetdata.buffer = sock->outbuf;
998
999   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1000   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1001                                         payload->data, payload->data,
1002                                         payload->len - 16, /* -IV_LEN */
1003                                         channel->iv);
1004
1005   /* Put the actual encrypted payload data into the buffer. */
1006   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1007
1008   /* Create the outgoing packet */
1009   silc_packet_assemble(&packetdata);
1010
1011   /* Encrypt the header and padding of the packet. This is encrypted 
1012      with normal session key shared with our server. */
1013   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1014                       packetdata.src_id_len + packetdata.dst_id_len +
1015                       packetdata.padlen);
1016
1017   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1018                    sock->outbuf->data, sock->outbuf->len);
1019
1020   /* Now actually send the packet */
1021   silc_client_packet_send_real(client, sock, force_send);
1022   silc_buffer_free(payload);
1023   silc_free(id_string);
1024 }
1025
1026 /* Sends private message to remote client. If private message key has
1027    not been set with this client then the message will be encrypted using
1028    normal session keys. Private messages are special packets in SILC
1029    network hence we need this own function for them. This is similiar
1030    to silc_client_packet_send_to_channel except that we send private
1031    message. */
1032
1033 void silc_client_packet_send_private_message(SilcClient client,
1034                                              SilcSocketConnection sock,
1035                                              SilcClientEntry client_entry,
1036                                              unsigned char *data, 
1037                                              unsigned int data_len, 
1038                                              int force_send)
1039 {
1040   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1041   SilcBuffer buffer;
1042   SilcPacketContext packetdata;
1043   unsigned int nick_len;
1044   SilcCipher cipher;
1045   SilcHmac hmac;
1046
1047   SILC_LOG_DEBUG(("Sending private message"));
1048
1049   /* Create private message payload */
1050   nick_len = strlen(conn->nickname);
1051   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1052   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1053   silc_buffer_format(buffer,
1054                      SILC_STR_UI_SHORT(nick_len),
1055                      SILC_STR_UI_XNSTRING(conn->nickname,
1056                                           nick_len),
1057                      SILC_STR_UI_XNSTRING(data, data_len),
1058                      SILC_STR_END);
1059
1060   /* If we don't have private message specific key then private messages
1061      are just as any normal packet thus call normal packet sending.  If
1062      the key exist then the encryption process is a bit different and
1063      will be done in the rest of this function. */
1064   if (!client_entry->send_key) {
1065     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1066                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1067                             buffer->data, buffer->len, force_send);
1068     goto out;
1069   }
1070
1071   /* We have private message specific key */
1072
1073   /* Get data used in the encryption */
1074   cipher = client_entry->send_key;
1075   hmac = conn->hmac;
1076
1077   /* Set the packet context pointers. */
1078   packetdata.flags = 0;
1079   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1080   packetdata.src_id = conn->local_id_data;
1081   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1082   packetdata.src_id_type = SILC_ID_CLIENT;
1083   if (client_entry)
1084     packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1085   else
1086     packetdata.dst_id = conn->local_id_data;
1087   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1088   packetdata.dst_id_type = SILC_ID_CLIENT;
1089   packetdata.rng = client->rng;
1090   packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1091     packetdata.src_id_len + packetdata.dst_id_len;
1092   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1093                                           packetdata.src_id_len +
1094                                           packetdata.dst_id_len));
1095
1096   /* Prepare outgoing data buffer for packet sending */
1097   silc_packet_send_prepare(sock, 
1098                            SILC_PACKET_HEADER_LEN +
1099                            packetdata.src_id_len + 
1100                            packetdata.dst_id_len,
1101                            packetdata.padlen,
1102                            buffer->len);
1103   
1104   packetdata.buffer = sock->outbuf;
1105
1106   /* Encrypt payload of the packet. Encrypt with private message specific
1107      key if it exist, otherwise with session key. */
1108   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1109                           buffer->len, cipher->iv);
1110       
1111   /* Put the actual encrypted payload data into the buffer. */
1112   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1113
1114   /* Create the outgoing packet */
1115   silc_packet_assemble(&packetdata);
1116
1117   /* Encrypt the header and padding of the packet. */
1118   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1119                       packetdata.src_id_len + packetdata.dst_id_len +
1120                       packetdata.padlen);
1121
1122   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1123                    sock->outbuf->data, sock->outbuf->len);
1124
1125   /* Now actually send the packet */
1126   silc_client_packet_send_real(client, sock, force_send);
1127   silc_free(packetdata.dst_id);
1128
1129  out:
1130   silc_free(buffer);
1131 }     
1132
1133 /* Closes connection to remote end. Free's all allocated data except
1134    for some information such as nickname etc. that are valid at all time. */
1135
1136 void silc_client_close_connection(SilcClient client,
1137                                   SilcSocketConnection sock)
1138 {
1139   SilcClientConnection conn;
1140
1141   /* We won't listen for this connection anymore */
1142   silc_schedule_unset_listen_fd(sock->sock);
1143
1144   /* Unregister all tasks */
1145   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1146   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1147
1148   /* Close the actual connection */
1149   silc_net_close_connection(sock->sock);
1150
1151   client->ops->say(client, sock->user_data,
1152                    "Closed connection to host %s", sock->hostname ?
1153                    sock->hostname : sock->ip);
1154
1155   /* Free everything */
1156   if (sock->user_data) {
1157     conn = (SilcClientConnection)sock->user_data;
1158
1159     /* XXX Free all client entries and channel entries. */
1160
1161     /* Clear ID caches */
1162     silc_idcache_del_all(conn->client_cache);
1163     silc_idcache_del_all(conn->channel_cache);
1164
1165     /* Free data */
1166     if (conn->remote_host)
1167       silc_free(conn->remote_host);
1168     if (conn->local_id)
1169       silc_free(conn->local_id);
1170     if (conn->local_id_data)
1171       silc_free(conn->local_id_data);
1172     if (conn->send_key)
1173       silc_cipher_free(conn->send_key);
1174     if (conn->receive_key)
1175       silc_cipher_free(conn->receive_key);
1176     if (conn->hmac)
1177       silc_hmac_free(conn->hmac);
1178     if (conn->hmac_key) {
1179       memset(conn->hmac_key, 0, conn->hmac_key_len);
1180       silc_free(conn->hmac_key);
1181     }
1182
1183     conn->sock = NULL;
1184     conn->remote_port = 0;
1185     conn->remote_type = 0;
1186     conn->send_key = NULL;
1187     conn->receive_key = NULL;
1188     conn->hmac = NULL;
1189     conn->hmac_key = NULL;
1190     conn->hmac_key_len = 0;
1191     conn->local_id = NULL;
1192     conn->local_id_data = NULL;
1193     conn->remote_host = NULL;
1194     conn->current_channel = NULL;
1195
1196     silc_client_del_connection(client, conn);
1197   }
1198
1199   if (sock->protocol) {
1200     silc_protocol_free(sock->protocol);
1201     sock->protocol = NULL;
1202   }
1203   silc_socket_free(sock);
1204 }
1205
1206 /* Called when we receive disconnection packet from server. This 
1207    closes our end properly and displays the reason of the disconnection
1208    on the screen. */
1209
1210 void silc_client_disconnected_by_server(SilcClient client,
1211                                         SilcSocketConnection sock,
1212                                         SilcBuffer message)
1213 {
1214   char *msg;
1215
1216   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1217
1218   msg = silc_calloc(message->len + 1, sizeof(char));
1219   memcpy(msg, message->data, message->len);
1220   client->ops->say(client, sock->user_data, msg);
1221   silc_free(msg);
1222
1223   SILC_SET_DISCONNECTED(sock);
1224   silc_client_close_connection(client, sock);
1225 }
1226
1227 /* Received error message from server. Display it on the screen. 
1228    We don't take any action what so ever of the error message. */
1229
1230 void silc_client_error_by_server(SilcClient client,
1231                                  SilcSocketConnection sock,
1232                                  SilcBuffer message)
1233 {
1234   char *msg;
1235
1236   msg = silc_calloc(message->len + 1, sizeof(char));
1237   memcpy(msg, message->data, message->len);
1238   client->ops->say(client, sock->user_data, msg);
1239   silc_free(msg);
1240 }
1241
1242 /* Received notify message from server */
1243
1244 void silc_client_notify_by_server(SilcClient client,
1245                                   SilcSocketConnection sock,
1246                                   SilcBuffer message)
1247 {
1248   char *msg;
1249
1250   msg = silc_calloc(message->len + 1, sizeof(char));
1251   memcpy(msg, message->data, message->len);
1252   client->ops->say(client, sock->user_data, msg);
1253   silc_free(msg);
1254 }
1255
1256 /* Processes the received new Client ID from server. Old Client ID is
1257    deleted from cache and new one is added. */
1258
1259 void silc_client_receive_new_id(SilcClient client,
1260                                 SilcSocketConnection sock,
1261                                 unsigned char *id_string)
1262 {
1263   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1264
1265   /* Delete old ID from ID cache */
1266   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1267   
1268   /* Save the new ID */
1269   if (conn->local_id)
1270     silc_free(conn->local_id);
1271   conn->local_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
1272   if (conn->local_id_data)
1273     silc_free(conn->local_id_data);
1274   conn->local_id_data = 
1275     silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1276   memcpy(conn->local_id_data, id_string, SILC_ID_CLIENT_LEN);
1277   conn->local_id_data_len = SILC_ID_CLIENT_LEN;
1278   if (!conn->local_entry)
1279     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1280   conn->local_entry->nickname = conn->nickname;
1281   conn->local_entry->id = conn->local_id;
1282   
1283   /* Put it to the ID cache */
1284   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1285                    conn->local_id, (void *)conn->local_entry, TRUE);
1286 }
1287
1288 /* Processed received Channel ID for a channel. This is called when client
1289    joins to channel and server replies with channel ID. The ID is cached. */
1290
1291 void silc_client_new_channel_id(SilcClient client,
1292                                 SilcSocketConnection sock,
1293                                 char *channel_name,
1294                                 unsigned int mode,
1295                                 unsigned char *id_string)
1296 {
1297   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1298   SilcChannelID *id;
1299   SilcChannelEntry channel;
1300
1301   SILC_LOG_DEBUG(("New channel ID"));
1302
1303   id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1304   channel = silc_calloc(1, sizeof(*channel));
1305   channel->channel_name = channel_name;
1306   channel->id = id;
1307   channel->mode = mode;
1308   conn->current_channel = channel;
1309   
1310   /* Put it to the ID cache */
1311   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1312                    (void *)id, (void *)channel, TRUE);
1313 }
1314
1315 /* Processes received key for channel. The received key will be used
1316    to protect the traffic on the channel for now on. Client must receive
1317    the key to the channel before talking on the channel is possible. 
1318    This is the key that server has generated, this is not the channel
1319    private key, it is entirely local setting. */
1320
1321 void silc_client_receive_channel_key(SilcClient client,
1322                                      SilcSocketConnection sock,
1323                                      SilcBuffer packet)
1324 {
1325   unsigned char *id_string, *key, *cipher;
1326   unsigned int key_len;
1327   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1328   SilcChannelID *id;
1329   SilcIDCacheEntry id_cache = NULL;
1330   SilcChannelEntry channel;
1331   SilcChannelKeyPayload payload;
1332
1333   SILC_LOG_DEBUG(("Received key for channel"));
1334   
1335   payload = silc_channel_key_parse_payload(packet);
1336   if (!payload)
1337     return;
1338
1339   id_string = silc_channel_key_get_id(payload, NULL);
1340   if (!id_string) {
1341     silc_channel_key_free_payload(payload);
1342     return;
1343   }
1344   id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
1345
1346   /* Find channel. */
1347   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1348                                    SILC_ID_CHANNEL, &id_cache))
1349     goto out;
1350   
1351   /* Save the key */
1352   key = silc_channel_key_get_key(payload, &key_len);
1353   cipher = silc_channel_key_get_cipher(payload, NULL);
1354
1355   channel = (SilcChannelEntry)id_cache->context;
1356   channel->key_len = key_len;
1357   channel->key = silc_calloc(key_len, sizeof(*channel->key));
1358   memcpy(channel->key, key, key_len);
1359
1360   silc_cipher_alloc(cipher, &channel->channel_key);
1361   if (!channel->channel_key) {
1362     client->ops->say(client, conn,
1363                      "Cannot talk to channel: unsupported cipher %s", cipher);
1364     goto out;
1365   }
1366   channel->channel_key->cipher->set_key(channel->channel_key->context, 
1367                                         key, key_len);
1368
1369   /* Client is now joined to the channel */
1370   channel->on_channel = TRUE;
1371
1372  out:
1373   silc_free(id);
1374   silc_channel_key_free_payload(payload);
1375 }
1376
1377 /* Process received message to a channel (or from a channel, really). This
1378    decrypts the channel message with channel specific key and parses the
1379    channel payload. Finally it displays the message on the screen. */
1380
1381 void silc_client_channel_message(SilcClient client, 
1382                                  SilcSocketConnection sock, 
1383                                  SilcPacketContext *packet)
1384 {
1385   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1386   SilcBuffer buffer = packet->buffer;
1387   SilcChannelPayload payload = NULL;
1388   SilcChannelID *id = NULL;
1389   SilcChannelEntry channel;
1390   SilcIDCacheEntry id_cache = NULL;
1391
1392   /* Sanity checks */
1393   if (packet->dst_id_type != SILC_ID_CHANNEL)
1394     goto out;
1395
1396   id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1397
1398   /* Find the channel entry from channels on this window */
1399   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1400                                    SILC_ID_CHANNEL, &id_cache))
1401     goto out;
1402
1403   channel = (SilcChannelEntry)id_cache->context;
1404
1405   /* Decrypt the channel message payload. Push the IV out of the way,
1406      since it is not encrypted (after pushing buffer->tail has the IV). */
1407   silc_buffer_push_tail(buffer, 16);
1408   channel->channel_key->cipher->decrypt(channel->channel_key->context,
1409                                         buffer->data, buffer->data,
1410                                         buffer->len, buffer->tail);
1411   silc_buffer_pull_tail(buffer, 16);
1412
1413   /* Parse the channel message payload */
1414   payload = silc_channel_parse_payload(buffer);
1415   if (!payload)
1416     goto out;
1417
1418   /* Pass the message to application */
1419   if (packet->src_id_type == SILC_ID_CLIENT) {
1420     client->ops->channel_message(client, conn, 
1421                                  silc_channel_get_nickname(payload, NULL),
1422                                  channel->channel_name,
1423                                  silc_channel_get_data(payload, NULL));
1424   } else {
1425     /* Message from server */
1426     /* XXX maybe this should be passed to app... */
1427     client->ops->say(client, conn, "%s", silc_channel_get_data(payload, NULL));
1428   }
1429
1430  out:
1431   if (id)
1432     silc_free(id);
1433   if (payload)
1434     silc_channel_free_payload(payload);
1435 }
1436
1437 /* Private message received. This processes the private message and
1438    finally displays it on the screen. */
1439
1440 void silc_client_private_message(SilcClient client, 
1441                                  SilcSocketConnection sock, 
1442                                  SilcPacketContext *packet)
1443 {
1444   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1445   SilcBuffer buffer = packet->buffer;
1446   unsigned short nick_len;
1447   unsigned char *nickname, *message;
1448
1449   /* Get nickname */
1450   silc_buffer_unformat(buffer, 
1451                        SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
1452                        SILC_STR_END);
1453   silc_buffer_pull(buffer, 2 + nick_len);
1454      
1455   message = silc_calloc(buffer->len + 1, sizeof(char));
1456   memcpy(message, buffer->data, buffer->len);
1457
1458   /* Pass the private message to application */
1459   client->ops->private_message(client, conn, nickname, message);
1460
1461   /* See if we are away (gone). If we are away we will reply to the
1462      sender with the set away message. */
1463   if (conn->away && conn->away->away) {
1464     SilcClientID *remote_id;
1465     SilcClientEntry remote_client;
1466     SilcIDCacheEntry id_cache;
1467
1468     if (packet->src_id_type != SILC_ID_CLIENT)
1469       goto out;
1470
1471     remote_id = silc_id_str2id(packet->src_id, SILC_ID_CLIENT);
1472     if (!remote_id)
1473       goto out;
1474
1475     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
1476       goto out;
1477
1478     /* Check whether we know this client already */
1479     if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
1480                                      SILC_ID_CLIENT, &id_cache))
1481       {
1482         /* Allocate client entry */
1483         remote_client = silc_calloc(1, sizeof(*remote_client));
1484         remote_client->id = remote_id;
1485         remote_client->nickname = strdup(nickname);
1486
1487         /* Save the client to cache */
1488         silc_idcache_add(conn->client_cache, remote_client->nickname,
1489                          SILC_ID_CLIENT, remote_client->id, remote_client, 
1490                          TRUE);
1491       } else {
1492         silc_free(remote_id);
1493         remote_client = (SilcClientEntry)id_cache->context;
1494       }
1495
1496     /* Send the away message */
1497     silc_client_packet_send_private_message(client, sock, remote_client,
1498                                             conn->away->away,
1499                                             strlen(conn->away->away), TRUE);
1500   }
1501
1502  out:
1503   memset(message, 0, buffer->len);
1504   silc_free(message);
1505   silc_free(nickname);
1506 }