updates.
[silc.git] / lib / silcclient / client.c
1 /*
2
3   client.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "clientlibincludes.h"
23
24 /* Static task callback prototypes */
25 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
28 SILC_TASK_CALLBACK(silc_client_packet_process);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
30
31 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
32 static void silc_client_packet_parse_type(SilcClient client, 
33                                           SilcSocketConnection sock,
34                                           SilcPacketContext *packet);
35
36 /* Allocates new client object. This has to be done before client may
37    work. After calling this one must call silc_client_init to initialize
38    the client. The `application' is application specific user data pointer
39    and caller must free it. */
40
41 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
42 {
43   SilcClient new_client;
44
45   new_client = silc_calloc(1, sizeof(*new_client));
46   new_client->application = application;
47   new_client->ops = ops;
48
49   return new_client;
50 }
51
52 /* Free's client object */
53
54 void silc_client_free(SilcClient client)
55 {
56   if (client) {
57     if (client->rng)
58       silc_rng_free(client->rng);
59
60     silc_free(client);
61   }
62 }
63
64 /* Initializes the client. This makes all the necessary steps to make
65    the client ready to be run. One must call silc_client_run to run the
66    client. */
67
68 int silc_client_init(SilcClient client)
69 {
70   SILC_LOG_DEBUG(("Initializing client"));
71
72   /* Initialize hash functions for client to use */
73   silc_hash_alloc("md5", &client->md5hash);
74   silc_hash_alloc("sha1", &client->sha1hash);
75
76   /* Initialize none cipher */
77   silc_cipher_alloc("none", &client->none_cipher);
78
79   /* Initialize random number generator */
80   client->rng = silc_rng_alloc();
81   silc_rng_init(client->rng);
82   silc_rng_global_init(client->rng);
83
84   /* Register protocols */
85   silc_client_protocols_register();
86
87   /* Initialize the scheduler */
88   silc_schedule_init(&client->io_queue, &client->timeout_queue, 
89                      &client->generic_queue, 5000);
90
91   return TRUE;
92 }
93
94 /* Stops the client. This is called to stop the client and thus to stop
95    the program. */
96
97 void silc_client_stop(SilcClient client)
98 {
99   SILC_LOG_DEBUG(("Stopping client"));
100
101   /* Stop the scheduler, although it might be already stopped. This
102      doesn't hurt anyone. This removes all the tasks and task queues,
103      as well. */
104   silc_schedule_stop();
105   silc_schedule_uninit();
106
107   silc_client_protocols_unregister();
108
109   SILC_LOG_DEBUG(("Client stopped"));
110 }
111
112 /* Runs the client. */
113
114 void silc_client_run(SilcClient client)
115 {
116   SILC_LOG_DEBUG(("Running client"));
117
118   /* Start the scheduler, the heart of the SILC client. When this returns
119      the program will be terminated. */
120   silc_schedule();
121 }
122
123 /* Allocates and adds new connection to the client. This adds the allocated
124    connection to the connection table and returns a pointer to it. A client
125    can have multiple connections to multiple servers. Every connection must
126    be added to the client using this function. User data `context' may
127    be sent as argument. */
128
129 SilcClientConnection silc_client_add_connection(SilcClient client,
130                                                 char *hostname,
131                                                 int port,
132                                                 void *context)
133 {
134   SilcClientConnection conn;
135   int i;
136
137   conn = silc_calloc(1, sizeof(*conn));
138
139   /* Initialize ID caches */
140   conn->client_cache = silc_idcache_alloc(0);
141   conn->channel_cache = silc_idcache_alloc(0);
142   conn->server_cache = silc_idcache_alloc(0);
143   conn->client = client;
144   conn->remote_host = strdup(hostname);
145   conn->remote_port = port;
146   conn->context = context;
147   conn->pending_commands = silc_dlist_init();
148
149   /* Add the connection to connections table */
150   for (i = 0; i < client->conns_count; i++)
151     if (client->conns && !client->conns[i]) {
152       client->conns[i] = conn;
153       return conn;
154     }
155
156   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
157                                * (client->conns_count + 1));
158   client->conns[client->conns_count] = conn;
159   client->conns_count++;
160
161   return conn;
162 }
163
164 /* Removes connection from client. */
165
166 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
167 {
168   int i;
169
170   for (i = 0; i < client->conns_count; i++)
171     if (client->conns[i] == conn) {
172       if (conn->pending_commands)
173         silc_dlist_uninit(conn->pending_commands);
174       silc_free(conn);
175       client->conns[i] = NULL;
176     }
177 }
178
179 /* Internal context for connection process. This is needed as we
180    doing asynchronous connecting. */
181 typedef struct {
182   SilcClient client;
183   SilcClientConnection conn;
184   SilcTask task;
185   int sock;
186   char *host;
187   int port;
188   int tries;
189 } SilcClientInternalConnectContext;
190
191 static int 
192 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
193 {
194   int sock;
195
196   /* XXX In the future we should give up this non-blocking connect all
197      together and use threads instead. */
198   /* Create connection to server asynchronously */
199   sock = silc_net_create_connection_async(ctx->port, ctx->host);
200   if (sock < 0)
201     return -1;
202
203   /* Register task that will receive the async connect and will
204      read the result. */
205   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
206                                  silc_client_connect_to_server_start,
207                                  (void *)ctx, 0, 0, 
208                                  SILC_TASK_FD,
209                                  SILC_TASK_PRI_NORMAL);
210   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
211   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
212
213   ctx->sock = sock;
214
215   return sock;
216 }
217
218 /* Connects to remote server. This is the main routine used to connect
219    to SILC server. Returns -1 on error and the created socket otherwise. 
220    The `context' is user context that is saved into the SilcClientConnection
221    that is created after the connection is created. */
222
223 int silc_client_connect_to_server(SilcClient client, int port,
224                                   char *host, void *context)
225 {
226   SilcClientInternalConnectContext *ctx;
227   SilcClientConnection conn;
228   int sock;
229
230   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
231                   port, host));
232
233   conn = silc_client_add_connection(client, host, port, context);
234
235   client->ops->say(client, conn, 
236                    "Connecting to port %d of server %s", port, host);
237
238   /* Allocate internal context for connection process. This is
239      needed as we are doing async connecting. */
240   ctx = silc_calloc(1, sizeof(*ctx));
241   ctx->client = client;
242   ctx->conn = conn;
243   ctx->host = strdup(host);
244   ctx->port = port;
245   ctx->tries = 0;
246
247   /* Do the actual connecting process */
248   sock = silc_client_connect_to_server_internal(ctx);
249   if (sock == -1)
250     silc_client_del_connection(client, conn);
251   return sock;
252 }
253
254 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
255    key material between client and server.  This function can be called
256    directly if application is performing its own connecting and does not
257    use the connecting provided by this library. */
258
259 int silc_client_start_key_exchange(SilcClient client,
260                                    SilcClientConnection conn,
261                                    int fd)
262 {
263   SilcProtocol protocol;
264   SilcClientKEInternalContext *proto_ctx;
265   void *context;
266
267   /* Allocate new socket connection object */
268   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
269   if (conn->sock == NULL) {
270     client->ops->say(client, conn, 
271                      "Error: Could not allocate connection socket");
272     return FALSE;
273   }
274
275   conn->nickname = strdup(client->username);
276   conn->sock->hostname = conn->remote_host;
277   conn->sock->ip = strdup(conn->remote_host);
278   conn->sock->port = conn->remote_port;
279
280   /* Allocate internal Key Exchange context. This is sent to the
281      protocol as context. */
282   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
283   proto_ctx->client = (void *)client;
284   proto_ctx->sock = conn->sock;
285   proto_ctx->rng = client->rng;
286   proto_ctx->responder = FALSE;
287
288   /* Perform key exchange protocol. silc_client_connect_to_server_final
289      will be called after the protocol is finished. */
290   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
291                       &protocol, (void *)proto_ctx,
292                       silc_client_connect_to_server_second);
293   if (!protocol) {
294     client->ops->say(client, conn, 
295                      "Error: Could not start authentication protocol");
296     return FALSE;
297   }
298   conn->sock->protocol = protocol;
299
300   /* Register the connection for network input and output. This sets
301      that scheduler will listen for incoming packets for this connection 
302      and sets that outgoing packets may be sent to this connection as well.
303      However, this doesn't set the scheduler for outgoing traffic, it will 
304      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
305      later when outgoing data is available. */
306   context = (void *)client;
307   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
308
309   /* Execute the protocol */
310   protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
311   return TRUE;
312 }
313
314 /* Start of the connection to the remote server. This is called after
315    succesful TCP/IP connection has been established to the remote host. */
316
317 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
318 {
319   SilcClientInternalConnectContext *ctx =
320     (SilcClientInternalConnectContext *)context;
321   SilcClient client = ctx->client;
322   SilcClientConnection conn = ctx->conn;
323   int opt, opt_len = sizeof(opt);
324
325   SILC_LOG_DEBUG(("Start"));
326
327   /* Check the socket status as it might be in error */
328   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
329   if (opt != 0) {
330     if (ctx->tries < 2) {
331       /* Connection failed but lets try again */
332       client->ops->say(client, conn, "Could not connect to server %s: %s",
333                        ctx->host, strerror(opt));
334       client->ops->say(client, conn, 
335                        "Connecting to port %d of server %s resumed", 
336                        ctx->port, ctx->host);
337
338       /* Unregister old connection try */
339       silc_schedule_unset_listen_fd(fd);
340       silc_net_close_connection(fd);
341       silc_task_unregister(client->io_queue, ctx->task);
342
343       /* Try again */
344       silc_client_connect_to_server_internal(ctx);
345       ctx->tries++;
346     } else {
347       /* Connection failed and we won't try anymore */
348       client->ops->say(client, conn, "Could not connect to server %s: %s",
349                        ctx->host, strerror(opt));
350       silc_schedule_unset_listen_fd(fd);
351       silc_net_close_connection(fd);
352       silc_task_unregister(client->io_queue, ctx->task);
353       silc_free(ctx);
354
355       /* Notify application of failure */
356       client->ops->connect(client, conn, FALSE);
357       silc_client_del_connection(client, conn);
358     }
359     return;
360   }
361
362   silc_schedule_unset_listen_fd(fd);
363   silc_task_unregister(client->io_queue, ctx->task);
364   silc_free(ctx);
365
366   if (!silc_client_start_key_exchange(client, conn, fd)) {
367     silc_net_close_connection(fd);
368     client->ops->connect(client, conn, FALSE);
369   }
370 }
371
372 /* Second part of the connecting to the server. This executed 
373    authentication protocol. */
374
375 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
376 {
377   SilcProtocol protocol = (SilcProtocol)context;
378   SilcClientKEInternalContext *ctx = 
379     (SilcClientKEInternalContext *)protocol->context;
380   SilcClient client = (SilcClient)ctx->client;
381   SilcSocketConnection sock = NULL;
382   SilcClientConnAuthInternalContext *proto_ctx;
383
384   SILC_LOG_DEBUG(("Start"));
385
386   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
387       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
388     /* Error occured during protocol */
389     SILC_LOG_DEBUG(("Error during KE protocol"));
390     silc_protocol_free(protocol);
391     if (ctx->ske)
392       silc_ske_free(ctx->ske);
393     if (ctx->dest_id)
394       silc_free(ctx->dest_id);
395     ctx->sock->protocol = NULL;
396
397     /* Notify application of failure */
398     client->ops->connect(client, ctx->sock->user_data, FALSE);
399     silc_free(ctx);
400     return;
401   }
402
403   /* Allocate internal context for the authentication protocol. This
404      is sent as context for the protocol. */
405   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
406   proto_ctx->client = (void *)client;
407   proto_ctx->sock = sock = ctx->sock;
408   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
409   proto_ctx->dest_id_type = ctx->dest_id_type;
410   proto_ctx->dest_id = ctx->dest_id;
411
412   /* Resolve the authentication method to be used in this connection */
413   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
414                                     sock->port, &proto_ctx->auth_meth,
415                                     &proto_ctx->auth_data, 
416                                     &proto_ctx->auth_data_len))
417     {
418       /* XXX do AUTH_REQUEST resolcing with server */
419       proto_ctx->auth_meth = SILC_AUTH_NONE;
420     }
421
422   /* Free old protocol as it is finished now */
423   silc_protocol_free(protocol);
424   if (ctx->packet)
425     silc_packet_context_free(ctx->packet);
426   silc_free(ctx);
427   /* silc_free(ctx->keymat....); */
428   sock->protocol = NULL;
429
430   /* Allocate the authentication protocol. This is allocated here
431      but we won't start it yet. We will be receiving party of this
432      protocol thus we will wait that connecting party will make
433      their first move. */
434   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
435                       &sock->protocol, (void *)proto_ctx, 
436                       silc_client_connect_to_server_final);
437
438   /* Execute the protocol */
439   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
440 }
441
442 /* Finalizes the connection to the remote SILC server. This is called
443    after authentication protocol has been completed. This send our
444    user information to the server to receive our client ID from
445    server. */
446
447 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
448 {
449   SilcProtocol protocol = (SilcProtocol)context;
450   SilcClientConnAuthInternalContext *ctx = 
451     (SilcClientConnAuthInternalContext *)protocol->context;
452   SilcClient client = (SilcClient)ctx->client;
453   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
454   SilcBuffer packet;
455
456   SILC_LOG_DEBUG(("Start"));
457
458   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
459       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
460     /* Error occured during protocol */
461     SILC_LOG_DEBUG(("Error during authentication protocol"));
462     silc_protocol_free(protocol);
463     if (ctx->auth_data)
464       silc_free(ctx->auth_data);
465     if (ctx->ske)
466       silc_ske_free(ctx->ske);
467     if (ctx->dest_id)
468       silc_free(ctx->dest_id);
469     conn->sock->protocol = NULL;
470
471     /* Notify application of failure */
472     client->ops->connect(client, ctx->sock->user_data, FALSE);
473     silc_free(ctx);
474     return;
475   }
476
477   /* Send NEW_CLIENT packet to the server. We will become registered
478      to the SILC network after sending this packet and we will receive
479      client ID from the server. */
480   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
481                              strlen(client->realname));
482   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
483   silc_buffer_format(packet,
484                      SILC_STR_UI_SHORT(strlen(client->username)),
485                      SILC_STR_UI_XNSTRING(client->username,
486                                           strlen(client->username)),
487                      SILC_STR_UI_SHORT(strlen(client->realname)),
488                      SILC_STR_UI_XNSTRING(client->realname,
489                                           strlen(client->realname)),
490                      SILC_STR_END);
491
492   /* Send the packet */
493   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
494                           NULL, 0, NULL, NULL, 
495                           packet->data, packet->len, TRUE);
496   silc_buffer_free(packet);
497
498   /* Save remote ID. */
499   conn->remote_id = ctx->dest_id;
500   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
501   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
502
503   silc_protocol_free(protocol);
504   if (ctx->auth_data)
505     silc_free(ctx->auth_data);
506   if (ctx->ske)
507     silc_ske_free(ctx->ske);
508   silc_free(ctx);
509   conn->sock->protocol = NULL;
510 }
511
512 /* Internal routine that sends packet or marks packet to be sent. This
513    is used directly only in special cases. Normal cases should use
514    silc_server_packet_send. Returns < 0 on error. */
515
516 static int silc_client_packet_send_real(SilcClient client,
517                                         SilcSocketConnection sock,
518                                         int force_send)
519 {
520   int ret;
521
522   /* Send the packet */
523   ret = silc_packet_send(sock, force_send);
524   if (ret != -2)
525     return ret;
526
527   /* Mark that there is some outgoing data available for this connection. 
528      This call sets the connection both for input and output (the input
529      is set always and this call keeps the input setting, actually). 
530      Actual data sending is performed by silc_client_packet_process. */
531   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
532
533   /* Mark to socket that data is pending in outgoing buffer. This flag
534      is needed if new data is added to the buffer before the earlier
535      put data is sent to the network. */
536   SILC_SET_OUTBUF_PENDING(sock);
537
538   return 0;
539 }
540
541 /* Packet processing callback. This is used to send and receive packets
542    from network. This is generic task. */
543
544 SILC_TASK_CALLBACK(silc_client_packet_process)
545 {
546   SilcClient client = (SilcClient)context;
547   SilcSocketConnection sock = NULL;
548   SilcClientConnection conn;
549   int ret;
550
551   SILC_LOG_DEBUG(("Processing packet"));
552
553   SILC_CLIENT_GET_SOCK(client, fd, sock);
554   if (sock == NULL)
555     return;
556
557   conn = (SilcClientConnection)sock->user_data;
558
559   /* Packet sending */
560   if (type == SILC_TASK_WRITE) {
561     SILC_LOG_DEBUG(("Writing data to connection"));
562
563     if (sock->outbuf->data - sock->outbuf->head)
564       silc_buffer_push(sock->outbuf, 
565                        sock->outbuf->data - sock->outbuf->head);
566
567     ret = silc_client_packet_send_real(client, sock, TRUE);
568
569     /* If returned -2 could not write to connection now, will do
570        it later. */
571     if (ret == -2)
572       return;
573     
574     /* The packet has been sent and now it is time to set the connection
575        back to only for input. When there is again some outgoing data 
576        available for this connection it will be set for output as well. 
577        This call clears the output setting and sets it only for input. */
578     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
579     SILC_UNSET_OUTBUF_PENDING(sock);
580
581     silc_buffer_clear(sock->outbuf);
582     return;
583   }
584
585   /* Packet receiving */
586   if (type == SILC_TASK_READ) {
587     SILC_LOG_DEBUG(("Reading data from connection"));
588
589     /* Read data from network */
590     ret = silc_packet_receive(sock);
591     if (ret < 0)
592       return;
593     
594     /* EOF */
595     if (ret == 0) {
596       SILC_LOG_DEBUG(("Read EOF"));
597
598       /* If connection is disconnecting already we will finally
599          close the connection */
600       if (SILC_IS_DISCONNECTING(sock)) {
601         client->ops->disconnect(client, conn);
602         silc_client_close_connection(client, sock);
603         return;
604       }
605       
606       client->ops->say(client, conn, "Connection closed: premature EOF");
607       SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
608       client->ops->disconnect(client, conn);
609       silc_client_close_connection(client, sock);
610       return;
611     }
612
613     /* Process the packet. This will call the parser that will then
614        decrypt and parse the packet. */
615     silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
616                                 silc_client_packet_parse, client);
617   }
618 }
619
620 /* Parses whole packet, received earlier. */
621
622 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
623 {
624   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
625   SilcClient client = (SilcClient)parse_ctx->context;
626   SilcPacketContext *packet = parse_ctx->packet;
627   SilcBuffer buffer = packet->buffer;
628   SilcSocketConnection sock = parse_ctx->sock;
629   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
630   int ret;
631
632   SILC_LOG_DEBUG(("Start"));
633
634   /* Decrypt the received packet */
635   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
636   if (ret < 0)
637     goto out;
638
639   if (ret == 0) {
640     /* Parse the packet. Packet type is returned. */
641     ret = silc_packet_parse(packet);
642   } else {
643     /* Parse the packet header in special way as this is "special"
644        packet type. */
645     ret = silc_packet_parse_special(packet);
646   }
647
648   if (ret == SILC_PACKET_NONE)
649     goto out;
650
651   /* Parse the incoming packet type */
652   silc_client_packet_parse_type(client, sock, packet);
653
654  out:
655   silc_buffer_clear(sock->inbuf);
656   silc_packet_context_free(packet);
657   silc_free(parse_ctx);
658 }
659
660 /* Parser callback called by silc_packet_receive_process. Thie merely
661    registers timeout that will handle the actual parsing when appropriate. */
662
663 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
664 {
665   SilcClient client = (SilcClient)parser_context->context;
666
667   /* Parse the packet */
668   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
669                      silc_client_packet_parse_real,
670                      (void *)parser_context, 0, 1, 
671                      SILC_TASK_TIMEOUT,
672                      SILC_TASK_PRI_NORMAL);
673 }
674   
675 /* Parses the packet type and calls what ever routines the packet type
676    requires. This is done for all incoming packets. */
677
678 void silc_client_packet_parse_type(SilcClient client, 
679                                    SilcSocketConnection sock,
680                                    SilcPacketContext *packet)
681 {
682   SilcBuffer buffer = packet->buffer;
683   SilcPacketType type = packet->type;
684
685   SILC_LOG_DEBUG(("Parsing packet type %d", type));
686
687   /* Parse the packet type */
688   switch(type) {
689   case SILC_PACKET_DISCONNECT:
690     silc_client_disconnected_by_server(client, sock, buffer);
691     break;
692   case SILC_PACKET_SUCCESS:
693     /*
694      * Success received for something. For now we can have only
695      * one protocol for connection executing at once hence this
696      * success message is for whatever protocol is executing currently.
697      */
698     if (sock->protocol) {
699       sock->protocol->execute(client->timeout_queue, 0,
700                               sock->protocol, sock->sock, 0, 0);
701     }
702     break;
703   case SILC_PACKET_FAILURE:
704     /*
705      * Failure received for some protocol. Set the protocol state to 
706      * error and call the protocol callback. This fill cause error on
707      * protocol and it will call the final callback.
708      */
709     if (sock->protocol) {
710       sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
711       sock->protocol->execute(client->timeout_queue, 0,
712                               sock->protocol, sock->sock, 0, 0);
713
714       /* XXX We have only two protocols currently thus we know what this
715          failure indication is. */
716       if (buffer->len >= 4) {
717         unsigned int failure;
718
719         SILC_GET32_MSB(failure, buffer->data);
720
721         /* Notify application */
722         client->ops->failure(client, sock->user_data, sock->protocol,
723                              (void *)failure);
724       }
725     }
726     break;
727   case SILC_PACKET_REJECT:
728     break;
729
730   case SILC_PACKET_NOTIFY:
731     /*
732      * Received notify message 
733      */
734     silc_client_notify_by_server(client, sock, packet);
735     break;
736
737   case SILC_PACKET_ERROR:
738     /*
739      * Received error message
740      */
741     silc_client_error_by_server(client, sock, buffer);
742     break;
743
744   case SILC_PACKET_CHANNEL_MESSAGE:
745     /*
746      * Received message to (from, actually) a channel
747      */
748     silc_client_channel_message(client, sock, packet);
749     break;
750   case SILC_PACKET_CHANNEL_KEY:
751     /*
752      * Received key for a channel. By receiving this key the client will be
753      * able to talk to the channel it has just joined. This can also be
754      * a new key for existing channel as keys expire peridiocally.
755      */
756     silc_client_receive_channel_key(client, sock, buffer);
757     break;
758
759   case SILC_PACKET_PRIVATE_MESSAGE:
760     /*
761      * Received private message
762      */
763     silc_client_private_message(client, sock, packet);
764     break;
765   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
766     /*
767      * Received private message key
768      */
769     break;
770
771   case SILC_PACKET_COMMAND_REPLY:
772     /*
773      * Recived reply for a command
774      */
775     silc_client_command_reply_process(client, sock, packet);
776     break;
777
778   case SILC_PACKET_KEY_EXCHANGE:
779     if (sock->protocol) {
780       SilcClientKEInternalContext *proto_ctx = 
781         (SilcClientKEInternalContext *)sock->protocol->context;
782
783       proto_ctx->packet = silc_packet_context_dup(packet);
784       proto_ctx->dest_id_type = packet->src_id_type;
785       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
786                                           packet->src_id_type);
787       if (!proto_ctx->dest_id)
788         break;
789
790       /* Let the protocol handle the packet */
791       sock->protocol->execute(client->timeout_queue, 0,
792                               sock->protocol, sock->sock, 0, 0);
793     } else {
794       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
795                       "protocol active, packet dropped."));
796
797       /* XXX Trigger KE protocol?? Rekey actually! */
798     }
799     break;
800
801   case SILC_PACKET_KEY_EXCHANGE_1:
802     if (sock->protocol) {
803
804     } else {
805       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
806                       "protocol active, packet dropped."));
807     }
808     break;
809   case SILC_PACKET_KEY_EXCHANGE_2:
810     if (sock->protocol) {
811       SilcClientKEInternalContext *proto_ctx = 
812         (SilcClientKEInternalContext *)sock->protocol->context;
813
814       if (proto_ctx->packet)
815         silc_packet_context_free(proto_ctx->packet);
816
817       proto_ctx->packet = silc_packet_context_dup(packet);
818       proto_ctx->dest_id_type = packet->src_id_type;
819       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
820                                           packet->src_id_type);
821       if (!proto_ctx->dest_id)
822         break;
823
824       /* Let the protocol handle the packet */
825       sock->protocol->execute(client->timeout_queue, 0,
826                               sock->protocol, sock->sock, 0, 0);
827     } else {
828       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
829                       "protocol active, packet dropped."));
830     }
831     break;
832
833   case SILC_PACKET_NEW_ID:
834     {
835       /*
836        * Received new ID from server. This packet is received at
837        * the connection to the server.  New ID is also received when 
838        * user changes nickname but in that case the new ID is received
839        * as command reply and not as this packet type.
840        */
841       SilcIDPayload idp;
842
843       idp = silc_id_payload_parse(buffer);
844       if (!idp)
845         break;
846       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
847         break;
848
849       silc_client_receive_new_id(client, sock, idp);
850       silc_id_payload_free(idp);
851       break;
852     }
853
854   case SILC_PACKET_HEARTBEAT:
855     /*
856      * Received heartbeat packet
857      */
858     SILC_LOG_DEBUG(("Heartbeat packet"));
859     break;
860
861   default:
862     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
863     break;
864   }
865 }
866
867 /* Sends packet. This doesn't actually send the packet instead it assembles
868    it and marks it to be sent. However, if force_send is TRUE the packet
869    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
870    will be derived from sock argument. Otherwise the valid arguments sent
871    are used. */
872
873 void silc_client_packet_send(SilcClient client, 
874                              SilcSocketConnection sock,
875                              SilcPacketType type, 
876                              void *dst_id,
877                              SilcIdType dst_id_type,
878                              SilcCipher cipher,
879                              SilcHmac hmac,
880                              unsigned char *data, 
881                              unsigned int data_len, 
882                              int force_send)
883 {
884   SilcPacketContext packetdata;
885
886   SILC_LOG_DEBUG(("Sending packet, type %d", type));
887
888   /* Get data used in the packet sending, keys and stuff */
889   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
890     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
891       cipher = ((SilcClientConnection)sock->user_data)->send_key;
892
893     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
894       hmac = ((SilcClientConnection)sock->user_data)->hmac;
895
896     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
897       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
898       dst_id_type = SILC_ID_SERVER;
899     }
900   }
901
902   /* Set the packet context pointers */
903   packetdata.flags = 0;
904   packetdata.type = type;
905   if (((SilcClientConnection)sock->user_data)->local_id_data)
906     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
907   else 
908     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
909   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
910   packetdata.src_id_type = SILC_ID_CLIENT;
911   if (dst_id) {
912     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
913     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
914     packetdata.dst_id_type = dst_id_type;
915   } else {
916     packetdata.dst_id = NULL;
917     packetdata.dst_id_len = 0;
918     packetdata.dst_id_type = SILC_ID_NONE;
919   }
920   packetdata.rng = client->rng;
921   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
922     packetdata.src_id_len + packetdata.dst_id_len;
923   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
924
925   /* Prepare outgoing data buffer for packet sending */
926   silc_packet_send_prepare(sock, 
927                            SILC_PACKET_HEADER_LEN +
928                            packetdata.src_id_len + 
929                            packetdata.dst_id_len,
930                            packetdata.padlen,
931                            data_len);
932
933   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
934
935   packetdata.buffer = sock->outbuf;
936
937   /* Put the data to the buffer */
938   if (data && data_len)
939     silc_buffer_put(sock->outbuf, data, data_len);
940
941   /* Create the outgoing packet */
942   silc_packet_assemble(&packetdata);
943
944   /* Encrypt the packet */
945   if (cipher)
946     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
947
948   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
949                    sock->outbuf->data, sock->outbuf->len);
950
951   /* Now actually send the packet */
952   silc_client_packet_send_real(client, sock, force_send);
953 }
954
955 /* Sends packet to a channel. Packet to channel is always encrypted
956    differently from "normal" packets. SILC header of the packet is 
957    encrypted with the next receiver's key and the rest of the packet is
958    encrypted with the channel specific key. Padding and HMAC is computed
959    with the next receiver's key. */
960
961 void silc_client_packet_send_to_channel(SilcClient client, 
962                                         SilcSocketConnection sock,
963                                         SilcChannelEntry channel,
964                                         unsigned char *data, 
965                                         unsigned int data_len, 
966                                         int force_send)
967 {
968   int i;
969   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
970   SilcBuffer payload;
971   SilcPacketContext packetdata;
972   SilcCipher cipher;
973   SilcHmac hmac;
974   unsigned char *id_string;
975
976   SILC_LOG_DEBUG(("Sending packet to channel"));
977
978   if (!channel || !channel->key) {
979     client->ops->say(client, conn, 
980                      "Cannot talk to channel: key does not exist");
981     return;
982   }
983
984   /* Generate IV */
985   if (!channel->iv)
986     for (i = 0; i < 16; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
987   else
988     silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
989
990   /* Encode the channel payload */
991   payload = silc_channel_payload_encode(data_len, data, 16, channel->iv, 
992                                         client->rng);
993   if (!payload) {
994     client->ops->say(client, conn, 
995                      "Error: Could not create packet to be sent to channel");
996     return;
997   }
998
999   /* Get data used in packet header encryption, keys and stuff. Rest
1000      of the packet (the payload) is, however, encrypted with the 
1001      specified channel key. */
1002   cipher = conn->send_key;
1003   hmac = conn->hmac;
1004   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1005
1006   /* Set the packet context pointers. The destination ID is always
1007      the Channel ID of the channel. Server and router will handle the
1008      distribution of the packet. */
1009   packetdata.flags = 0;
1010   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1011   packetdata.src_id = conn->local_id_data;
1012   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1013   packetdata.src_id_type = SILC_ID_CLIENT;
1014   packetdata.dst_id = id_string;
1015   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1016   packetdata.dst_id_type = SILC_ID_CHANNEL;
1017   packetdata.rng = client->rng;
1018   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
1019     packetdata.src_id_len + packetdata.dst_id_len;
1020   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1021                                           packetdata.src_id_len +
1022                                           packetdata.dst_id_len));
1023
1024   /* Prepare outgoing data buffer for packet sending */
1025   silc_packet_send_prepare(sock, 
1026                            SILC_PACKET_HEADER_LEN +
1027                            packetdata.src_id_len + 
1028                            packetdata.dst_id_len,
1029                            packetdata.padlen,
1030                            payload->len);
1031
1032   packetdata.buffer = sock->outbuf;
1033
1034   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1035   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1036                                         payload->data, payload->data,
1037                                         payload->len - 16, /* -IV_LEN */
1038                                         channel->iv);
1039
1040   /* Put the actual encrypted payload data into the buffer. */
1041   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1042
1043   /* Create the outgoing packet */
1044   silc_packet_assemble(&packetdata);
1045
1046   /* Encrypt the header and padding of the packet. This is encrypted 
1047      with normal session key shared with our server. */
1048   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1049                       packetdata.src_id_len + packetdata.dst_id_len +
1050                       packetdata.padlen);
1051
1052   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1053                    sock->outbuf->data, sock->outbuf->len);
1054
1055   /* Now actually send the packet */
1056   silc_client_packet_send_real(client, sock, force_send);
1057   silc_buffer_free(payload);
1058   silc_free(id_string);
1059 }
1060
1061 /* Sends private message to remote client. If private message key has
1062    not been set with this client then the message will be encrypted using
1063    normal session keys. Private messages are special packets in SILC
1064    network hence we need this own function for them. This is similiar
1065    to silc_client_packet_send_to_channel except that we send private
1066    message. */
1067
1068 void silc_client_packet_send_private_message(SilcClient client,
1069                                              SilcSocketConnection sock,
1070                                              SilcClientEntry client_entry,
1071                                              unsigned char *data, 
1072                                              unsigned int data_len, 
1073                                              int force_send)
1074 {
1075   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1076   SilcBuffer buffer;
1077   SilcPacketContext packetdata;
1078   unsigned int nick_len;
1079   SilcCipher cipher;
1080   SilcHmac hmac;
1081
1082   SILC_LOG_DEBUG(("Sending private message"));
1083
1084   /* Create private message payload */
1085   nick_len = strlen(conn->nickname);
1086   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1087   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1088   silc_buffer_format(buffer,
1089                      SILC_STR_UI_SHORT(nick_len),
1090                      SILC_STR_UI_XNSTRING(conn->nickname,
1091                                           nick_len),
1092                      SILC_STR_UI_XNSTRING(data, data_len),
1093                      SILC_STR_END);
1094
1095   /* If we don't have private message specific key then private messages
1096      are just as any normal packet thus call normal packet sending.  If
1097      the key exist then the encryption process is a bit different and
1098      will be done in the rest of this function. */
1099   if (!client_entry->send_key) {
1100     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1101                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1102                             buffer->data, buffer->len, force_send);
1103     goto out;
1104   }
1105
1106   /* We have private message specific key */
1107
1108   /* Get data used in the encryption */
1109   cipher = client_entry->send_key;
1110   hmac = conn->hmac;
1111
1112   /* Set the packet context pointers. */
1113   packetdata.flags = 0;
1114   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1115   packetdata.src_id = conn->local_id_data;
1116   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1117   packetdata.src_id_type = SILC_ID_CLIENT;
1118   if (client_entry)
1119     packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1120   else
1121     packetdata.dst_id = conn->local_id_data;
1122   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1123   packetdata.dst_id_type = SILC_ID_CLIENT;
1124   packetdata.rng = client->rng;
1125   packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1126     packetdata.src_id_len + packetdata.dst_id_len;
1127   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1128                                           packetdata.src_id_len +
1129                                           packetdata.dst_id_len));
1130
1131   /* Prepare outgoing data buffer for packet sending */
1132   silc_packet_send_prepare(sock, 
1133                            SILC_PACKET_HEADER_LEN +
1134                            packetdata.src_id_len + 
1135                            packetdata.dst_id_len,
1136                            packetdata.padlen,
1137                            buffer->len);
1138   
1139   packetdata.buffer = sock->outbuf;
1140
1141   /* Encrypt payload of the packet. Encrypt with private message specific
1142      key if it exist, otherwise with session key. */
1143   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1144                           buffer->len, cipher->iv);
1145       
1146   /* Put the actual encrypted payload data into the buffer. */
1147   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1148
1149   /* Create the outgoing packet */
1150   silc_packet_assemble(&packetdata);
1151
1152   /* Encrypt the header and padding of the packet. */
1153   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1154                       packetdata.src_id_len + packetdata.dst_id_len +
1155                       packetdata.padlen);
1156
1157   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1158                    sock->outbuf->data, sock->outbuf->len);
1159
1160   /* Now actually send the packet */
1161   silc_client_packet_send_real(client, sock, force_send);
1162   silc_free(packetdata.dst_id);
1163
1164  out:
1165   silc_free(buffer);
1166 }     
1167
1168 /* Closes connection to remote end. Free's all allocated data except
1169    for some information such as nickname etc. that are valid at all time. */
1170
1171 void silc_client_close_connection(SilcClient client,
1172                                   SilcSocketConnection sock)
1173 {
1174   SilcClientConnection conn;
1175
1176   /* We won't listen for this connection anymore */
1177   silc_schedule_unset_listen_fd(sock->sock);
1178
1179   /* Unregister all tasks */
1180   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1181   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1182
1183   /* Close the actual connection */
1184   silc_net_close_connection(sock->sock);
1185
1186   client->ops->say(client, sock->user_data,
1187                    "Closed connection to host %s", sock->hostname);
1188
1189   /* Free everything */
1190   if (sock->user_data) {
1191     conn = (SilcClientConnection)sock->user_data;
1192
1193     /* XXX Free all client entries and channel entries. */
1194
1195     /* Clear ID caches */
1196     silc_idcache_del_all(conn->client_cache);
1197     silc_idcache_del_all(conn->channel_cache);
1198
1199     /* Free data */
1200     if (conn->remote_host)
1201       silc_free(conn->remote_host);
1202     if (conn->local_id)
1203       silc_free(conn->local_id);
1204     if (conn->local_id_data)
1205       silc_free(conn->local_id_data);
1206     if (conn->send_key)
1207       silc_cipher_free(conn->send_key);
1208     if (conn->receive_key)
1209       silc_cipher_free(conn->receive_key);
1210     if (conn->hmac)
1211       silc_hmac_free(conn->hmac);
1212     if (conn->hmac_key) {
1213       memset(conn->hmac_key, 0, conn->hmac_key_len);
1214       silc_free(conn->hmac_key);
1215     }
1216     if (conn->pending_commands)
1217       silc_dlist_uninit(conn->pending_commands);
1218
1219     conn->sock = NULL;
1220     conn->remote_port = 0;
1221     conn->remote_type = 0;
1222     conn->send_key = NULL;
1223     conn->receive_key = NULL;
1224     conn->hmac = NULL;
1225     conn->hmac_key = NULL;
1226     conn->hmac_key_len = 0;
1227     conn->local_id = NULL;
1228     conn->local_id_data = NULL;
1229     conn->remote_host = NULL;
1230     conn->current_channel = NULL;
1231     conn->pending_commands = NULL;
1232
1233     silc_client_del_connection(client, conn);
1234   }
1235
1236   if (sock->protocol) {
1237     silc_protocol_free(sock->protocol);
1238     sock->protocol = NULL;
1239   }
1240   silc_socket_free(sock);
1241 }
1242
1243 /* Called when we receive disconnection packet from server. This 
1244    closes our end properly and displays the reason of the disconnection
1245    on the screen. */
1246
1247 void silc_client_disconnected_by_server(SilcClient client,
1248                                         SilcSocketConnection sock,
1249                                         SilcBuffer message)
1250 {
1251   char *msg;
1252
1253   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1254
1255   msg = silc_calloc(message->len + 1, sizeof(char));
1256   memcpy(msg, message->data, message->len);
1257   client->ops->say(client, sock->user_data, msg);
1258   silc_free(msg);
1259
1260   SILC_SET_DISCONNECTED(sock);
1261   silc_client_close_connection(client, sock);
1262 }
1263
1264 /* Received error message from server. Display it on the screen. 
1265    We don't take any action what so ever of the error message. */
1266
1267 void silc_client_error_by_server(SilcClient client,
1268                                  SilcSocketConnection sock,
1269                                  SilcBuffer message)
1270 {
1271   char *msg;
1272
1273   msg = silc_calloc(message->len + 1, sizeof(char));
1274   memcpy(msg, message->data, message->len);
1275   client->ops->say(client, sock->user_data, msg);
1276   silc_free(msg);
1277 }
1278
1279 /* Called when notify is received and some async operation (such as command)
1280    is required before processing the notify message. This calls again the
1281    silc_client_notify_by_server and reprocesses the original notify packet. */
1282
1283 static void silc_client_notify_by_server_pending(void *context)
1284 {
1285   SilcPacketContext *p = (SilcPacketContext *)context;
1286   silc_client_notify_by_server(p->context, p->sock, p);
1287 }
1288
1289 /* Destructor for the pending command callback */
1290
1291 static void silc_client_notify_by_server_destructor(void *context)
1292 {
1293   silc_packet_context_free((SilcPacketContext *)context);
1294 }
1295
1296 /* Resolve client information from server by Client ID. */
1297
1298 static void silc_client_notify_by_server_resolve(SilcClient client,
1299                                                  SilcClientConnection conn,
1300                                                  SilcPacketContext *packet,
1301                                                  SilcClientID *client_id)
1302 {
1303   SilcPacketContext *p = silc_packet_context_dup(packet);
1304   SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1305
1306   p->context = (void *)client;
1307   p->sock = conn->sock;
1308
1309   silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1310                            1, 3, idp->data, idp->len);
1311   silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1312                               silc_client_notify_by_server_destructor,
1313                               silc_client_notify_by_server_pending, p);
1314   silc_buffer_free(idp);
1315 }
1316
1317 /* Received notify message from server */
1318
1319 void silc_client_notify_by_server(SilcClient client,
1320                                   SilcSocketConnection sock,
1321                                   SilcPacketContext *packet)
1322 {
1323   SilcBuffer buffer = packet->buffer;
1324   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1325   SilcNotifyPayload payload;
1326   SilcNotifyType type;
1327   SilcArgumentPayload args;
1328
1329   SilcClientID *client_id = NULL;
1330   SilcChannelID *channel_id = NULL;
1331   SilcClientEntry client_entry;
1332   SilcClientEntry client_entry2;
1333   SilcChannelEntry channel;
1334   SilcChannelUser chu;
1335   SilcIDCacheEntry id_cache = NULL;
1336   unsigned char *tmp;
1337   unsigned int tmp_len, mode;
1338
1339   payload = silc_notify_payload_parse(buffer);
1340   if (!payload)
1341     goto out;
1342
1343   type = silc_notify_get_type(payload);
1344   args = silc_notify_get_args(payload);
1345   if (!args)
1346     goto out;
1347
1348   switch(type) {
1349   case SILC_NOTIFY_TYPE_NONE:
1350     /* Notify application */
1351     client->ops->notify(client, conn, type, 
1352                         silc_argument_get_arg_type(args, 1, NULL));
1353     break;
1354
1355   case SILC_NOTIFY_TYPE_INVITE:
1356     /* 
1357      * Someone invited me to a channel. Find Client and Channel entries
1358      * for the application.
1359      */
1360     
1361     /* Get Client ID */
1362     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1363     if (!tmp)
1364       goto out;
1365
1366     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1367     if (!client_id)
1368       goto out;
1369
1370     /* Find Client entry and if not found query it */
1371     client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
1372     if (!client_entry) {
1373       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1374       goto out;
1375     }
1376
1377     /* Get Channel ID */
1378     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1379     if (!tmp)
1380       goto out;
1381
1382     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1383     if (!channel_id)
1384       goto out;
1385
1386     /* XXX Will ALWAYS fail because currently we don't have way to resolve
1387        channel information for channel that we're not joined to. */
1388     /* XXX ways to fix: use (extended) LIST command, or define the channel
1389        name to the notfy type when name resolving is not mandatory. */
1390     /* Find channel entry */
1391     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1392                                      SILC_ID_CHANNEL, &id_cache))
1393       goto out;
1394
1395     channel = (SilcChannelEntry)id_cache->context;
1396
1397     /* Notify application */
1398     client->ops->notify(client, conn, type, client_entry, channel);
1399     break;
1400
1401   case SILC_NOTIFY_TYPE_JOIN:
1402     /*
1403      * Someone has joined to a channel. Get their ID and nickname and
1404      * cache them for later use.
1405      */
1406
1407     /* Get Client ID */
1408     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1409     if (!tmp)
1410       goto out;
1411
1412     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1413     if (!client_id)
1414       goto out;
1415
1416     /* Find Client entry and if not found query it */
1417     client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
1418     if (!client_entry) {
1419       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1420       goto out;
1421     }
1422
1423     /* If nickname or username hasn't been resolved, do so */
1424     if (!client_entry->nickname || !client_entry->username) {
1425       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1426       goto out;
1427     }
1428
1429     /* Get Channel ID */
1430     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1431     if (!tmp)
1432       goto out;
1433
1434     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1435     if (!channel_id)
1436       goto out;
1437
1438     /* Get channel entry */
1439     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1440                                      SILC_ID_CHANNEL, &id_cache))
1441       break;
1442
1443     channel = (SilcChannelEntry)id_cache->context;
1444
1445     /* Add client to channel */
1446     chu = silc_calloc(1, sizeof(*chu));
1447     chu->client = client_entry;
1448     silc_list_add(channel->clients, chu);
1449
1450     /* XXX add support for multiple same nicks on same channel. Check
1451        for them here */
1452
1453     /* Notify application. The channel entry is sent last as this notify
1454        is for channel but application don't know it from the arguments
1455        sent by server. */
1456     client->ops->notify(client, conn, type, client_entry, channel);
1457     break;
1458
1459   case SILC_NOTIFY_TYPE_LEAVE:
1460     /*
1461      * Someone has left a channel. We will remove it from the channel but
1462      * we'll keep it in the cache in case we'll need it later.
1463      */
1464     
1465     /* Get Client ID */
1466     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1467     if (!tmp)
1468       goto out;
1469
1470     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1471     if (!client_id)
1472       goto out;
1473
1474     /* Find Client entry */
1475     client_entry = 
1476       silc_idlist_get_client_by_id(client, conn, client_id);
1477     if (!client_entry)
1478       goto out;
1479
1480     /* Get channel entry */
1481     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1482                                 SILC_ID_CHANNEL);
1483     if (!channel_id)
1484       goto out;
1485     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1486                                      SILC_ID_CHANNEL, &id_cache))
1487       break;
1488
1489     channel = (SilcChannelEntry)id_cache->context;
1490
1491     /* Remove client from channel */
1492     silc_list_start(channel->clients);
1493     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1494       if (chu->client == client_entry) {
1495         silc_list_del(channel->clients, chu);
1496         silc_free(chu);
1497         break;
1498       }
1499     }
1500
1501     /* Notify application. The channel entry is sent last as this notify
1502        is for channel but application don't know it from the arguments
1503        sent by server. */
1504     client->ops->notify(client, conn, type, client_entry, channel);
1505     break;
1506
1507   case SILC_NOTIFY_TYPE_SIGNOFF:
1508     /*
1509      * Someone left SILC. We'll remove it from all channels and from cache.
1510      */
1511
1512     /* Get Client ID */
1513     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1514     if (!tmp)
1515       goto out;
1516
1517     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1518     if (!client_id)
1519       goto out;
1520
1521     /* Find Client entry */
1522     client_entry = 
1523       silc_idlist_get_client_by_id(client, conn, client_id);
1524     if (!client_entry)
1525       goto out;
1526
1527     /* Remove from all channels */
1528     silc_client_remove_from_channels(client, conn, client_entry);
1529
1530     /* Remove from cache */
1531     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1532                            client_entry->id);
1533
1534     /* Notify application */
1535     client->ops->notify(client, conn, type, client_entry);
1536
1537     /* Free data */
1538     if (client_entry->nickname)
1539       silc_free(client_entry->nickname);
1540     if (client_entry->server)
1541       silc_free(client_entry->server);
1542     if (client_entry->id)
1543       silc_free(client_entry->id);
1544     if (client_entry->send_key)
1545       silc_cipher_free(client_entry->send_key);
1546     if (client_entry->receive_key)
1547       silc_cipher_free(client_entry->receive_key);
1548     break;
1549
1550   case SILC_NOTIFY_TYPE_TOPIC_SET:
1551     /*
1552      * Someone set the topic on a channel.
1553      */
1554
1555     /* Get Client ID */
1556     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1557     if (!tmp)
1558       goto out;
1559
1560     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1561     if (!client_id)
1562       goto out;
1563
1564     /* Find Client entry */
1565     client_entry = 
1566       silc_idlist_get_client_by_id(client, conn, client_id);
1567     if (!client_entry)
1568       goto out;
1569
1570     /* Get topic */
1571     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1572     if (!tmp)
1573       goto out;
1574
1575     /* Get channel entry */
1576     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1577                                 SILC_ID_CHANNEL);
1578     if (!channel_id)
1579       goto out;
1580     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1581                                      SILC_ID_CHANNEL, &id_cache))
1582       break;
1583
1584     channel = (SilcChannelEntry)id_cache->context;
1585
1586     /* Notify application. The channel entry is sent last as this notify
1587        is for channel but application don't know it from the arguments
1588        sent by server. */
1589     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1590     break;
1591
1592   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1593     /*
1594      * Someone changed their nickname. If we don't have entry for the new
1595      * ID we will query it and return here after it's done. After we've
1596      * returned we fetch the old entry and free it and notify the 
1597      * application.
1598      */
1599
1600     /* Get new Client ID */
1601     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1602     if (!tmp)
1603       goto out;
1604
1605     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1606     if (!client_id)
1607       goto out;
1608
1609     /* Ignore my ID */
1610     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1611       break;
1612
1613     /* Find Client entry and if not found query it */
1614     client_entry2 = 
1615       silc_idlist_get_client_by_id(client, conn, client_id);
1616     if (!client_entry2) {
1617       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1618       goto out;
1619     }
1620     silc_free(client_id);
1621
1622     /* Get old Client ID */
1623     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1624     if (!tmp)
1625       goto out;
1626
1627     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1628     if (!client_id)
1629       goto out;
1630
1631     /* Find old Client entry */
1632     client_entry = 
1633       silc_idlist_get_client_by_id(client, conn, client_id);
1634     if (!client_entry)
1635       goto out;
1636
1637     /* Remove the old from cache */
1638     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1639                            client_entry->id);
1640
1641     /* Replace old ID entry with new one on all channels. */
1642     silc_client_replace_from_channels(client, conn, client_entry,
1643                                       client_entry2);
1644
1645     /* Notify application */
1646     client->ops->notify(client, conn, type, client_entry, client_entry2);
1647
1648     /* Free data */
1649     if (client_entry->nickname)
1650       silc_free(client_entry->nickname);
1651     if (client_entry->server)
1652       silc_free(client_entry->server);
1653     if (client_entry->id)
1654       silc_free(client_entry->id);
1655     if (client_entry->send_key)
1656       silc_cipher_free(client_entry->send_key);
1657     if (client_entry->receive_key)
1658       silc_cipher_free(client_entry->receive_key);
1659     break;
1660
1661   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1662     /*
1663      * Someone changed a channel mode
1664      */
1665
1666     /* Get Client ID */
1667     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1668     if (!tmp)
1669       goto out;
1670
1671     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1672     if (!client_id)
1673       goto out;
1674
1675     /* Find Client entry */
1676     client_entry = 
1677       silc_idlist_get_client_by_id(client, conn, client_id);
1678     if (!client_entry)
1679       goto out;
1680
1681     /* Get the mode */
1682     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1683     if (!tmp)
1684       goto out;
1685
1686     SILC_GET32_MSB(mode, tmp);
1687
1688     /* Get channel entry */
1689     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1690                                 SILC_ID_CHANNEL);
1691     if (!channel_id)
1692       goto out;
1693     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1694                                      SILC_ID_CHANNEL, &id_cache))
1695       break;
1696
1697     channel = (SilcChannelEntry)id_cache->context;
1698
1699     /* Save the new mode */
1700     channel->mode = mode;
1701
1702     /* Notify application. The channel entry is sent last as this notify
1703        is for channel but application don't know it from the arguments
1704        sent by server. */
1705     client->ops->notify(client, conn, type, client_entry, mode, channel);
1706     break;
1707
1708   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1709     /*
1710      * Someone changed user's mode on a channel
1711      */
1712
1713     /* Get Client ID */
1714     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1715     if (!tmp)
1716       goto out;
1717
1718     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1719     if (!client_id)
1720       goto out;
1721
1722     /* Find Client entry */
1723     client_entry = 
1724       silc_idlist_get_client_by_id(client, conn, client_id);
1725     if (!client_entry)
1726       goto out;
1727
1728     /* Get the mode */
1729     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1730     if (!tmp)
1731       goto out;
1732
1733     SILC_GET32_MSB(mode, tmp);
1734
1735     /* Get target Client ID */
1736     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1737     if (!tmp)
1738       goto out;
1739
1740     silc_free(client_id);
1741     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1742     if (!client_id)
1743       goto out;
1744
1745     /* Find target Client entry */
1746     client_entry2 = 
1747       silc_idlist_get_client_by_id(client, conn, client_id);
1748     if (!client_entry2)
1749       goto out;
1750
1751     /* Get channel entry */
1752     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1753                                 SILC_ID_CHANNEL);
1754     if (!channel_id)
1755       goto out;
1756     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1757                                      SILC_ID_CHANNEL, &id_cache))
1758       break;
1759
1760     channel = (SilcChannelEntry)id_cache->context;
1761
1762     /* Save the mode */
1763     silc_list_start(channel->clients);
1764     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1765       if (chu->client == client_entry) {
1766         chu->mode = mode;
1767         break;
1768       }
1769     }
1770
1771     /* Notify application. The channel entry is sent last as this notify
1772        is for channel but application don't know it from the arguments
1773        sent by server. */
1774     client->ops->notify(client, conn, type, client_entry, mode, 
1775                         client_entry2, channel);
1776     break;
1777
1778   case SILC_NOTIFY_TYPE_MOTD:
1779     /*
1780      * Received Message of the day
1781      */
1782
1783     /* Get motd */
1784     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1785     if (!tmp)
1786       goto out;
1787     
1788     /* Notify application */
1789     client->ops->notify(client, conn, type, tmp);
1790     break;
1791
1792   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1793     /*
1794      * Router has enforced a new ID to a channel. Let's change the old
1795      * ID to the one provided here.
1796      */
1797
1798     /* Get the old ID */
1799     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1800     if (!tmp)
1801       goto out;
1802     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1803     if (!channel_id)
1804       goto out;
1805     
1806     /* Get the channel entry */
1807     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1808                                      SILC_ID_CHANNEL, &id_cache))
1809       break;
1810
1811     channel = (SilcChannelEntry)id_cache->context;
1812
1813     /* Free the old ID */
1814     silc_free(channel_id);
1815     silc_free(channel->id);
1816
1817     /* Get the new ID */
1818     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1819     if (!tmp)
1820       goto out;
1821     channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1822     if (!channel->id)
1823       goto out;
1824
1825     id_cache->id = (void *)channel->id;
1826
1827     /* Notify application */
1828     client->ops->notify(client, conn, type, channel, channel);
1829     break;
1830     
1831   default:
1832     break;
1833   }
1834
1835  out:
1836   silc_notify_payload_free(payload);
1837   if (client_id)
1838     silc_free(client_id);
1839   if (channel_id)
1840     silc_free(channel_id);
1841 }
1842
1843 /* Processes the received new Client ID from server. Old Client ID is
1844    deleted from cache and new one is added. */
1845
1846 void silc_client_receive_new_id(SilcClient client,
1847                                 SilcSocketConnection sock,
1848                                 SilcIDPayload idp)
1849 {
1850   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1851   int connecting = FALSE;
1852
1853   if (!conn->local_entry)
1854     connecting = TRUE;
1855
1856   /* Delete old ID from ID cache */
1857   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1858   
1859   /* Save the new ID */
1860   if (conn->local_id)
1861     silc_free(conn->local_id);
1862   if (conn->local_id_data)
1863     silc_free(conn->local_id_data);
1864
1865   conn->local_id = silc_id_payload_get_id(idp);
1866   conn->local_id_data = silc_id_payload_get_data(idp);
1867   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1868
1869   if (!conn->local_entry)
1870     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1871
1872   conn->local_entry->nickname = conn->nickname;
1873   if (!conn->local_entry->username) {
1874     conn->local_entry->username = 
1875       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1876                   sizeof(conn->local_entry->username));
1877     sprintf(conn->local_entry->username, "%s@%s", client->username,
1878             client->hostname);
1879   }
1880   conn->local_entry->server = strdup(conn->remote_host);
1881   conn->local_entry->id = conn->local_id;
1882   
1883   /* Put it to the ID cache */
1884   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1885                    conn->local_id, (void *)conn->local_entry, TRUE);
1886
1887   /* Notify application of successful connection. We do it here now that
1888      we've received the Client ID and are allowed to send traffic. */
1889   if (connecting)
1890     client->ops->connect(client, conn, TRUE);
1891 }
1892
1893 /* Processed received Channel ID for a channel. This is called when client
1894    joins to channel and server replies with channel ID. The ID is cached. */
1895
1896 void silc_client_new_channel_id(SilcClient client,
1897                                 SilcSocketConnection sock,
1898                                 char *channel_name,
1899                                 unsigned int mode, SilcIDPayload idp)
1900 {
1901   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1902   SilcChannelEntry channel;
1903
1904   SILC_LOG_DEBUG(("New channel ID"));
1905
1906   channel = silc_calloc(1, sizeof(*channel));
1907   channel->channel_name = channel_name;
1908   channel->id = silc_id_payload_get_id(idp);
1909   channel->mode = mode;
1910   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1911
1912   conn->current_channel = channel;
1913
1914   /* Put it to the ID cache */
1915   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1916                    (void *)channel->id, (void *)channel, TRUE);
1917 }
1918
1919 /* Saves channel key from encoded `key_payload'. This is used when we
1920    receive Channel Key Payload and when we are processing JOIN command 
1921    reply. */
1922
1923 void silc_client_save_channel_key(SilcClientConnection conn,
1924                                   SilcBuffer key_payload, 
1925                                   SilcChannelEntry channel)
1926 {
1927   unsigned char *id_string, *key, *cipher;
1928   unsigned int tmp_len;
1929   SilcChannelID *id;
1930   SilcIDCacheEntry id_cache = NULL;
1931   SilcChannelKeyPayload payload;
1932
1933   payload = silc_channel_key_payload_parse(key_payload);
1934   if (!payload)
1935     return;
1936
1937   id_string = silc_channel_key_get_id(payload, &tmp_len);
1938   if (!id_string) {
1939     silc_channel_key_payload_free(payload);
1940     return;
1941   }
1942
1943   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
1944   if (!id) {
1945     silc_channel_key_payload_free(payload);
1946     return;
1947   }
1948
1949   /* Find channel. */
1950   if (!channel) {
1951     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1952                                      SILC_ID_CHANNEL, &id_cache))
1953       goto out;
1954     
1955     /* Get channel entry */
1956     channel = (SilcChannelEntry)id_cache->context;
1957   }
1958
1959   /* Save the key */
1960   key = silc_channel_key_get_key(payload, &tmp_len);
1961   cipher = silc_channel_key_get_cipher(payload, NULL);
1962   channel->key_len = tmp_len;
1963   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
1964   memcpy(channel->key, key, tmp_len);
1965
1966   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
1967     conn->client->ops->say(conn->client, conn,
1968                      "Cannot talk to channel: unsupported cipher %s", cipher);
1969     goto out;
1970   }
1971   channel->channel_key->cipher->set_key(channel->channel_key->context, 
1972                                         key, tmp_len);
1973
1974   /* Client is now joined to the channel */
1975   channel->on_channel = TRUE;
1976
1977  out:
1978   silc_free(id);
1979   silc_channel_key_payload_free(payload);
1980 }
1981
1982 /* Processes received key for channel. The received key will be used
1983    to protect the traffic on the channel for now on. Client must receive
1984    the key to the channel before talking on the channel is possible. 
1985    This is the key that server has generated, this is not the channel
1986    private key, it is entirely local setting. */
1987
1988 void silc_client_receive_channel_key(SilcClient client,
1989                                      SilcSocketConnection sock,
1990                                      SilcBuffer packet)
1991 {
1992   SILC_LOG_DEBUG(("Received key for channel"));
1993
1994   /* Save the key */
1995   silc_client_save_channel_key(sock->user_data, packet, NULL);
1996 }
1997
1998 /* Process received message to a channel (or from a channel, really). This
1999    decrypts the channel message with channel specific key and parses the
2000    channel payload. Finally it displays the message on the screen. */
2001
2002 void silc_client_channel_message(SilcClient client, 
2003                                  SilcSocketConnection sock, 
2004                                  SilcPacketContext *packet)
2005 {
2006   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2007   SilcBuffer buffer = packet->buffer;
2008   SilcChannelPayload payload = NULL;
2009   SilcChannelID *id = NULL;
2010   SilcChannelEntry channel;
2011   SilcChannelUser chu;
2012   SilcIDCacheEntry id_cache = NULL;
2013   SilcClientID *client_id = NULL;
2014   int found = FALSE;
2015
2016   /* Sanity checks */
2017   if (packet->dst_id_type != SILC_ID_CHANNEL)
2018     goto out;
2019
2020   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2021                              SILC_ID_CLIENT);
2022   if (!client_id)
2023     goto out;
2024   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2025   if (!id)
2026     goto out;
2027
2028   /* Find the channel entry from channels on this connection */
2029   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2030                                    SILC_ID_CHANNEL, &id_cache))
2031     goto out;
2032
2033   channel = (SilcChannelEntry)id_cache->context;
2034
2035   /* Decrypt the channel message payload. Push the IV out of the way,
2036      since it is not encrypted (after pushing buffer->tail has the IV). */
2037   silc_buffer_push_tail(buffer, 16);
2038   channel->channel_key->cipher->decrypt(channel->channel_key->context,
2039                                         buffer->data, buffer->data,
2040                                         buffer->len, buffer->tail);
2041   silc_buffer_pull_tail(buffer, 16);
2042
2043   /* Parse the channel message payload */
2044   payload = silc_channel_payload_parse(buffer);
2045   if (!payload)
2046     goto out;
2047
2048   /* Find client entry */
2049   silc_list_start(channel->clients);
2050   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2051     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2052       found = TRUE;
2053       break;
2054     }
2055   }
2056
2057   /* Pass the message to application */
2058   client->ops->channel_message(client, conn, found ? chu->client : NULL,
2059                                channel, silc_channel_get_data(payload, NULL));
2060
2061  out:
2062   if (id)
2063     silc_free(id);
2064   if (client_id)
2065     silc_free(client_id);
2066   if (payload)
2067     silc_channel_payload_free(payload);
2068 }
2069
2070 /* Private message received. This processes the private message and
2071    finally displays it on the screen. */
2072
2073 void silc_client_private_message(SilcClient client, 
2074                                  SilcSocketConnection sock, 
2075                                  SilcPacketContext *packet)
2076 {
2077   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2078   SilcBuffer buffer = packet->buffer;
2079   SilcIDCacheEntry id_cache;
2080   SilcClientID *remote_id = NULL;
2081   SilcClientEntry remote_client;
2082   unsigned short nick_len;
2083   unsigned char *nickname, *message = NULL;
2084   int ret;
2085
2086   if (packet->src_id_type != SILC_ID_CLIENT)
2087     goto out;
2088
2089   /* Get nickname */
2090   ret = silc_buffer_unformat(buffer, 
2091                              SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2092                              SILC_STR_END);
2093   if (ret == -1)
2094     return;
2095
2096   silc_buffer_pull(buffer, 2 + nick_len);
2097
2098   message = silc_calloc(buffer->len + 1, sizeof(char));
2099   memcpy(message, buffer->data, buffer->len);
2100
2101   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2102                              SILC_ID_CLIENT);
2103   if (!remote_id)
2104     goto out;
2105
2106   /* Check whether we know this client already */
2107   if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2108                                    SILC_ID_CLIENT, &id_cache))
2109     {
2110       /* Allocate client entry */
2111       remote_client = silc_calloc(1, sizeof(*remote_client));
2112       remote_client->id = remote_id;
2113       silc_parse_nickname(nickname, &remote_client->nickname, 
2114                           &remote_client->server, &remote_client->num);
2115       
2116       /* Save the client to cache */
2117       silc_idcache_add(conn->client_cache, remote_client->nickname,
2118                        SILC_ID_CLIENT, remote_client->id, remote_client, 
2119                        TRUE);
2120     } else {
2121       remote_client = (SilcClientEntry)id_cache->context;
2122     }
2123
2124   /* Pass the private message to application */
2125   client->ops->private_message(client, conn, remote_client, message);
2126
2127   /* See if we are away (gone). If we are away we will reply to the
2128      sender with the set away message. */
2129   if (conn->away && conn->away->away) {
2130     /* If it's me, ignore */
2131     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2132       goto out;
2133
2134     /* Send the away message */
2135     silc_client_packet_send_private_message(client, sock, remote_client,
2136                                             conn->away->away,
2137                                             strlen(conn->away->away), TRUE);
2138   }
2139
2140  out:
2141   if (remote_id)
2142     silc_free(remote_id);
2143
2144   if (message) {
2145     memset(message, 0, buffer->len);
2146     silc_free(message);
2147   }
2148   silc_free(nickname);
2149 }
2150
2151 /* Removes a client entry from all channel it has joined. This really is
2152    a performance killer (client_entry should have pointers to channel 
2153    entry list). */
2154
2155 void silc_client_remove_from_channels(SilcClient client,
2156                                       SilcClientConnection conn,
2157                                       SilcClientEntry client_entry)
2158 {
2159   SilcIDCacheEntry id_cache;
2160   SilcIDCacheList list;
2161   SilcChannelEntry channel;
2162   SilcChannelUser chu;
2163
2164   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2165                                SILC_ID_CHANNEL, &list))
2166     return;
2167
2168   silc_idcache_list_first(list, &id_cache);
2169   channel = (SilcChannelEntry)id_cache->context;
2170   
2171   while (channel) {
2172     
2173     /* Remove client from channel */
2174     silc_list_start(channel->clients);
2175     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2176       if (chu->client == client_entry) {
2177         silc_list_del(channel->clients, chu);
2178         silc_free(chu);
2179         break;
2180       }
2181     }
2182
2183     if (!silc_idcache_list_next(list, &id_cache))
2184       break;
2185     
2186     channel = (SilcChannelEntry)id_cache->context;
2187   }
2188
2189   silc_idcache_list_free(list);
2190 }
2191
2192 /* Replaces `old' client entries from all channels to `new' client entry.
2193    This can be called for example when nickname changes and old ID entry
2194    is replaced from ID cache with the new one. If the old ID entry is only
2195    updated, then this fucntion needs not to be called. */
2196
2197 void silc_client_replace_from_channels(SilcClient client, 
2198                                        SilcClientConnection conn,
2199                                        SilcClientEntry old,
2200                                        SilcClientEntry new)
2201 {
2202   SilcIDCacheEntry id_cache;
2203   SilcIDCacheList list;
2204   SilcChannelEntry channel;
2205   SilcChannelUser chu;
2206
2207   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2208                                SILC_ID_CHANNEL, &list))
2209     return;
2210
2211   silc_idcache_list_first(list, &id_cache);
2212   channel = (SilcChannelEntry)id_cache->context;
2213   
2214   while (channel) {
2215     
2216     /* Replace client entry */
2217     silc_list_start(channel->clients);
2218     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2219       if (chu->client == old) {
2220         chu->client = new;
2221         break;
2222       }
2223     }
2224
2225     if (!silc_idcache_list_next(list, &id_cache))
2226       break;
2227     
2228     channel = (SilcChannelEntry)id_cache->context;
2229   }
2230
2231   silc_idcache_list_free(list);
2232 }
2233
2234 /* Parses mode mask and returns the mode as string. */
2235
2236 char *silc_client_chmode(unsigned int mode)
2237 {
2238   char string[20];
2239
2240   if (!mode)
2241     return NULL;
2242
2243   memset(string, 0, sizeof(string));
2244
2245   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2246     strncat(string, "p", 1);
2247
2248   if (mode & SILC_CHANNEL_MODE_SECRET)
2249     strncat(string, "s", 1);
2250
2251   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2252     strncat(string, "k", 1);
2253
2254   if (mode & SILC_CHANNEL_MODE_INVITE)
2255     strncat(string, "i", 1);
2256
2257   if (mode & SILC_CHANNEL_MODE_TOPIC)
2258     strncat(string, "t", 1);
2259
2260   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2261     strncat(string, "l", 1);
2262
2263   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2264     strncat(string, "a", 1);
2265
2266   /* Rest of mode is ignored */
2267
2268   return strdup(string);
2269 }
2270
2271 /* Parses channel user mode mask and returns te mode as string */
2272
2273 char *silc_client_chumode(unsigned int mode)
2274 {
2275   char string[4];
2276
2277   if (!mode)
2278     return NULL;
2279
2280   memset(string, 0, sizeof(string));
2281
2282   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2283     strncat(string, "f", 1);
2284
2285   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2286     strncat(string, "o", 1);
2287
2288   return strdup(string);
2289 }
2290
2291 /* Parses channel user mode and returns it as special mode character. */
2292
2293 char *silc_client_chumode_char(unsigned int mode)
2294 {
2295   char string[4];
2296
2297   if (!mode)
2298     return NULL;
2299
2300   memset(string, 0, sizeof(string));
2301
2302   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2303     strncat(string, "*", 1);
2304
2305   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2306     strncat(string, "@", 1);
2307
2308   return strdup(string);
2309 }