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