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