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