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 entry */
1430     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1431                                 SILC_ID_CHANNEL);
1432     if (!channel_id)
1433       goto out;
1434     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1435                                      SILC_ID_CHANNEL, &id_cache))
1436       break;
1437
1438     channel = (SilcChannelEntry)id_cache->context;
1439
1440     /* Add client to channel */
1441     chu = silc_calloc(1, sizeof(*chu));
1442     chu->client = client_entry;
1443     silc_list_add(channel->clients, chu);
1444
1445     /* XXX add support for multiple same nicks on same channel. Check
1446        for them here */
1447
1448     /* Notify application. The channel entry is sent last as this notify
1449        is for channel but application don't know it from the arguments
1450        sent by server. */
1451     client->ops->notify(client, conn, type, client_entry, channel);
1452     break;
1453
1454   case SILC_NOTIFY_TYPE_LEAVE:
1455     /*
1456      * Someone has left a channel. We will remove it from the channel but
1457      * we'll keep it in the cache in case we'll need it later.
1458      */
1459     
1460     /* Get Client ID */
1461     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1462     if (!tmp)
1463       goto out;
1464
1465     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1466     if (!client_id)
1467       goto out;
1468
1469     /* Find Client entry */
1470     client_entry = 
1471       silc_idlist_get_client_by_id(client, conn, client_id);
1472     if (!client_entry)
1473       goto out;
1474
1475     /* Get channel entry */
1476     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1477                                 SILC_ID_CHANNEL);
1478     if (!channel_id)
1479       goto out;
1480     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1481                                      SILC_ID_CHANNEL, &id_cache))
1482       break;
1483
1484     channel = (SilcChannelEntry)id_cache->context;
1485
1486     /* Remove client from channel */
1487     silc_list_start(channel->clients);
1488     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1489       if (chu->client == client_entry) {
1490         silc_list_del(channel->clients, chu);
1491         silc_free(chu);
1492         break;
1493       }
1494     }
1495
1496     /* Notify application. The channel entry is sent last as this notify
1497        is for channel but application don't know it from the arguments
1498        sent by server. */
1499     client->ops->notify(client, conn, type, client_entry, channel);
1500     break;
1501
1502   case SILC_NOTIFY_TYPE_SIGNOFF:
1503     /*
1504      * Someone left SILC. We'll remove it from all channels and from cache.
1505      */
1506
1507     /* Get Client ID */
1508     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1509     if (!tmp)
1510       goto out;
1511
1512     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1513     if (!client_id)
1514       goto out;
1515
1516     /* Find Client entry */
1517     client_entry = 
1518       silc_idlist_get_client_by_id(client, conn, client_id);
1519     if (!client_entry)
1520       goto out;
1521
1522     /* Remove from all channels */
1523     silc_client_remove_from_channels(client, conn, client_entry);
1524
1525     /* Remove from cache */
1526     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1527                            client_entry->id);
1528
1529     /* Notify application */
1530     client->ops->notify(client, conn, type, client_entry);
1531
1532     /* Free data */
1533     if (client_entry->nickname)
1534       silc_free(client_entry->nickname);
1535     if (client_entry->server)
1536       silc_free(client_entry->server);
1537     if (client_entry->id)
1538       silc_free(client_entry->id);
1539     if (client_entry->send_key)
1540       silc_cipher_free(client_entry->send_key);
1541     if (client_entry->receive_key)
1542       silc_cipher_free(client_entry->receive_key);
1543     break;
1544
1545   case SILC_NOTIFY_TYPE_TOPIC_SET:
1546     /*
1547      * Someone set the topic on a channel.
1548      */
1549
1550     /* Get Client ID */
1551     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1552     if (!tmp)
1553       goto out;
1554
1555     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1556     if (!client_id)
1557       goto out;
1558
1559     /* Find Client entry */
1560     client_entry = 
1561       silc_idlist_get_client_by_id(client, conn, client_id);
1562     if (!client_entry)
1563       goto out;
1564
1565     /* Get topic */
1566     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1567     if (!tmp)
1568       goto out;
1569
1570     /* Get channel entry */
1571     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1572                                 SILC_ID_CHANNEL);
1573     if (!channel_id)
1574       goto out;
1575     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1576                                      SILC_ID_CHANNEL, &id_cache))
1577       break;
1578
1579     channel = (SilcChannelEntry)id_cache->context;
1580
1581     /* Notify application. The channel entry is sent last as this notify
1582        is for channel but application don't know it from the arguments
1583        sent by server. */
1584     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1585     break;
1586
1587   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1588     /*
1589      * Someone changed their nickname. If we don't have entry for the new
1590      * ID we will query it and return here after it's done. After we've
1591      * returned we fetch the old entry and free it and notify the 
1592      * application.
1593      */
1594
1595     /* Get new Client ID */
1596     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1597     if (!tmp)
1598       goto out;
1599
1600     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1601     if (!client_id)
1602       goto out;
1603
1604     /* Ignore my ID */
1605     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1606       break;
1607
1608     /* Find Client entry and if not found query it */
1609     client_entry2 = 
1610       silc_idlist_get_client_by_id(client, conn, client_id);
1611     if (!client_entry2) {
1612       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1613       goto out;
1614     }
1615     silc_free(client_id);
1616
1617     /* Get old Client ID */
1618     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1619     if (!tmp)
1620       goto out;
1621
1622     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1623     if (!client_id)
1624       goto out;
1625
1626     /* Find old Client entry */
1627     client_entry = 
1628       silc_idlist_get_client_by_id(client, conn, client_id);
1629     if (!client_entry)
1630       goto out;
1631
1632     /* Remove the old from cache */
1633     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1634                            client_entry->id);
1635
1636     /* Replace old ID entry with new one on all channels. */
1637     silc_client_replace_from_channels(client, conn, client_entry,
1638                                       client_entry2);
1639
1640     /* Notify application */
1641     client->ops->notify(client, conn, type, client_entry, client_entry2);
1642
1643     /* Free data */
1644     if (client_entry->nickname)
1645       silc_free(client_entry->nickname);
1646     if (client_entry->server)
1647       silc_free(client_entry->server);
1648     if (client_entry->id)
1649       silc_free(client_entry->id);
1650     if (client_entry->send_key)
1651       silc_cipher_free(client_entry->send_key);
1652     if (client_entry->receive_key)
1653       silc_cipher_free(client_entry->receive_key);
1654     break;
1655
1656   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1657     /*
1658      * Someone changed a channel mode
1659      */
1660
1661     /* Get Client ID */
1662     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1663     if (!tmp)
1664       goto out;
1665
1666     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1667     if (!client_id)
1668       goto out;
1669
1670     /* Find Client entry */
1671     client_entry = 
1672       silc_idlist_get_client_by_id(client, conn, client_id);
1673     if (!client_entry)
1674       goto out;
1675
1676     /* Get the mode */
1677     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1678     if (!tmp)
1679       goto out;
1680
1681     SILC_GET32_MSB(mode, tmp);
1682
1683     /* Get channel entry */
1684     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1685                                 SILC_ID_CHANNEL);
1686     if (!channel_id)
1687       goto out;
1688     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1689                                      SILC_ID_CHANNEL, &id_cache))
1690       break;
1691
1692     channel = (SilcChannelEntry)id_cache->context;
1693
1694     /* Save the new mode */
1695     channel->mode = mode;
1696
1697     /* Notify application. The channel entry is sent last as this notify
1698        is for channel but application don't know it from the arguments
1699        sent by server. */
1700     client->ops->notify(client, conn, type, client_entry, mode, channel);
1701     break;
1702
1703   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1704     /*
1705      * Someone changed user's mode on a channel
1706      */
1707
1708     /* Get Client ID */
1709     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1710     if (!tmp)
1711       goto out;
1712
1713     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1714     if (!client_id)
1715       goto out;
1716
1717     /* Find Client entry */
1718     client_entry = 
1719       silc_idlist_get_client_by_id(client, conn, client_id);
1720     if (!client_entry)
1721       goto out;
1722
1723     /* Get the mode */
1724     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1725     if (!tmp)
1726       goto out;
1727
1728     SILC_GET32_MSB(mode, tmp);
1729
1730     /* Get target Client ID */
1731     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1732     if (!tmp)
1733       goto out;
1734
1735     silc_free(client_id);
1736     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1737     if (!client_id)
1738       goto out;
1739
1740     /* Find target Client entry */
1741     client_entry2 = 
1742       silc_idlist_get_client_by_id(client, conn, client_id);
1743     if (!client_entry2)
1744       goto out;
1745
1746     /* Get channel entry */
1747     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1748                                 SILC_ID_CHANNEL);
1749     if (!channel_id)
1750       goto out;
1751     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1752                                      SILC_ID_CHANNEL, &id_cache))
1753       break;
1754
1755     channel = (SilcChannelEntry)id_cache->context;
1756
1757     /* Save the mode */
1758     silc_list_start(channel->clients);
1759     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1760       if (chu->client == client_entry) {
1761         chu->mode = mode;
1762         break;
1763       }
1764     }
1765
1766     /* Notify application. The channel entry is sent last as this notify
1767        is for channel but application don't know it from the arguments
1768        sent by server. */
1769     client->ops->notify(client, conn, type, client_entry, mode, 
1770                         client_entry2, channel);
1771     break;
1772
1773   case SILC_NOTIFY_TYPE_MOTD:
1774     /*
1775      * Received Message of the day
1776      */
1777
1778     /* Get motd */
1779     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1780     if (!tmp)
1781       goto out;
1782     
1783     /* Notify application */
1784     client->ops->notify(client, conn, type, tmp);
1785     break;
1786
1787   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1788     /*
1789      * Router has enforced a new ID to a channel. Let's change the old
1790      * ID to the one provided here.
1791      */
1792
1793     /* Get the old ID */
1794     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1795     if (!tmp)
1796       goto out;
1797     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1798     if (!channel_id)
1799       goto out;
1800     
1801     /* Get the channel entry */
1802     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1803                                      SILC_ID_CHANNEL, &id_cache))
1804       break;
1805
1806     channel = (SilcChannelEntry)id_cache->context;
1807
1808     /* Free the old ID */
1809     silc_free(channel_id);
1810     silc_free(channel->id);
1811
1812     /* Get the new ID */
1813     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1814     if (!tmp)
1815       goto out;
1816     channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1817     if (!channel->id)
1818       goto out;
1819
1820     id_cache->id = (void *)channel->id;
1821
1822     /* Notify application */
1823     client->ops->notify(client, conn, type, channel, channel);
1824     break;
1825     
1826   default:
1827     break;
1828   }
1829
1830  out:
1831   silc_notify_payload_free(payload);
1832   if (client_id)
1833     silc_free(client_id);
1834   if (channel_id)
1835     silc_free(channel_id);
1836 }
1837
1838 /* Processes the received new Client ID from server. Old Client ID is
1839    deleted from cache and new one is added. */
1840
1841 void silc_client_receive_new_id(SilcClient client,
1842                                 SilcSocketConnection sock,
1843                                 SilcIDPayload idp)
1844 {
1845   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1846   int connecting = FALSE;
1847
1848   if (!conn->local_entry)
1849     connecting = TRUE;
1850
1851   /* Delete old ID from ID cache */
1852   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1853   
1854   /* Save the new ID */
1855   if (conn->local_id)
1856     silc_free(conn->local_id);
1857   if (conn->local_id_data)
1858     silc_free(conn->local_id_data);
1859
1860   conn->local_id = silc_id_payload_get_id(idp);
1861   conn->local_id_data = silc_id_payload_get_data(idp);
1862   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1863
1864   if (!conn->local_entry)
1865     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1866
1867   conn->local_entry->nickname = conn->nickname;
1868   if (!conn->local_entry->username) {
1869     conn->local_entry->username = 
1870       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1871                   sizeof(conn->local_entry->username));
1872     sprintf(conn->local_entry->username, "%s@%s", client->username,
1873             client->hostname);
1874   }
1875   conn->local_entry->server = strdup(conn->remote_host);
1876   conn->local_entry->id = conn->local_id;
1877   
1878   /* Put it to the ID cache */
1879   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1880                    conn->local_id, (void *)conn->local_entry, TRUE);
1881
1882   /* Notify application of successful connection. We do it here now that
1883      we've received the Client ID and are allowed to send traffic. */
1884   if (connecting)
1885     client->ops->connect(client, conn, TRUE);
1886 }
1887
1888 /* Processed received Channel ID for a channel. This is called when client
1889    joins to channel and server replies with channel ID. The ID is cached. */
1890
1891 void silc_client_new_channel_id(SilcClient client,
1892                                 SilcSocketConnection sock,
1893                                 char *channel_name,
1894                                 unsigned int mode, SilcIDPayload idp)
1895 {
1896   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1897   SilcChannelEntry channel;
1898
1899   SILC_LOG_DEBUG(("New channel ID"));
1900
1901   channel = silc_calloc(1, sizeof(*channel));
1902   channel->channel_name = channel_name;
1903   channel->id = silc_id_payload_get_id(idp);
1904   channel->mode = mode;
1905   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1906
1907   conn->current_channel = channel;
1908
1909   /* Put it to the ID cache */
1910   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1911                    (void *)channel->id, (void *)channel, TRUE);
1912 }
1913
1914 /* Saves channel key from encoded `key_payload'. This is used when we
1915    receive Channel Key Payload and when we are processing JOIN command 
1916    reply. */
1917
1918 void silc_client_save_channel_key(SilcClientConnection conn,
1919                                   SilcBuffer key_payload, 
1920                                   SilcChannelEntry channel)
1921 {
1922   unsigned char *id_string, *key, *cipher;
1923   unsigned int tmp_len;
1924   SilcChannelID *id;
1925   SilcIDCacheEntry id_cache = NULL;
1926   SilcChannelKeyPayload payload;
1927
1928   payload = silc_channel_key_payload_parse(key_payload);
1929   if (!payload)
1930     return;
1931
1932   id_string = silc_channel_key_get_id(payload, &tmp_len);
1933   if (!id_string) {
1934     silc_channel_key_payload_free(payload);
1935     return;
1936   }
1937
1938   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
1939   if (!id) {
1940     silc_channel_key_payload_free(payload);
1941     return;
1942   }
1943
1944   /* Find channel. */
1945   if (!channel) {
1946     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1947                                      SILC_ID_CHANNEL, &id_cache))
1948       goto out;
1949     
1950     /* Get channel entry */
1951     channel = (SilcChannelEntry)id_cache->context;
1952   }
1953
1954   /* Save the key */
1955   key = silc_channel_key_get_key(payload, &tmp_len);
1956   cipher = silc_channel_key_get_cipher(payload, NULL);
1957   channel->key_len = tmp_len;
1958   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
1959   memcpy(channel->key, key, tmp_len);
1960
1961   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
1962     conn->client->ops->say(conn->client, conn,
1963                      "Cannot talk to channel: unsupported cipher %s", cipher);
1964     goto out;
1965   }
1966   channel->channel_key->cipher->set_key(channel->channel_key->context, 
1967                                         key, tmp_len);
1968
1969   /* Client is now joined to the channel */
1970   channel->on_channel = TRUE;
1971
1972  out:
1973   silc_free(id);
1974   silc_channel_key_payload_free(payload);
1975 }
1976
1977 /* Processes received key for channel. The received key will be used
1978    to protect the traffic on the channel for now on. Client must receive
1979    the key to the channel before talking on the channel is possible. 
1980    This is the key that server has generated, this is not the channel
1981    private key, it is entirely local setting. */
1982
1983 void silc_client_receive_channel_key(SilcClient client,
1984                                      SilcSocketConnection sock,
1985                                      SilcBuffer packet)
1986 {
1987   SILC_LOG_DEBUG(("Received key for channel"));
1988
1989   /* Save the key */
1990   silc_client_save_channel_key(sock->user_data, packet, NULL);
1991 }
1992
1993 /* Process received message to a channel (or from a channel, really). This
1994    decrypts the channel message with channel specific key and parses the
1995    channel payload. Finally it displays the message on the screen. */
1996
1997 void silc_client_channel_message(SilcClient client, 
1998                                  SilcSocketConnection sock, 
1999                                  SilcPacketContext *packet)
2000 {
2001   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2002   SilcBuffer buffer = packet->buffer;
2003   SilcChannelPayload payload = NULL;
2004   SilcChannelID *id = NULL;
2005   SilcChannelEntry channel;
2006   SilcChannelUser chu;
2007   SilcIDCacheEntry id_cache = NULL;
2008   SilcClientID *client_id = NULL;
2009   int found = FALSE;
2010
2011   /* Sanity checks */
2012   if (packet->dst_id_type != SILC_ID_CHANNEL)
2013     goto out;
2014
2015   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2016                              SILC_ID_CLIENT);
2017   if (!client_id)
2018     goto out;
2019   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2020   if (!id)
2021     goto out;
2022
2023   /* Find the channel entry from channels on this connection */
2024   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2025                                    SILC_ID_CHANNEL, &id_cache))
2026     goto out;
2027
2028   channel = (SilcChannelEntry)id_cache->context;
2029
2030   /* Decrypt the channel message payload. Push the IV out of the way,
2031      since it is not encrypted (after pushing buffer->tail has the IV). */
2032   silc_buffer_push_tail(buffer, 16);
2033   channel->channel_key->cipher->decrypt(channel->channel_key->context,
2034                                         buffer->data, buffer->data,
2035                                         buffer->len, buffer->tail);
2036   silc_buffer_pull_tail(buffer, 16);
2037
2038   /* Parse the channel message payload */
2039   payload = silc_channel_payload_parse(buffer);
2040   if (!payload)
2041     goto out;
2042
2043   /* Find client entry */
2044   silc_list_start(channel->clients);
2045   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2046     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2047       found = TRUE;
2048       break;
2049     }
2050   }
2051
2052   /* Pass the message to application */
2053   client->ops->channel_message(client, conn, found ? chu->client : NULL,
2054                                channel, silc_channel_get_data(payload, NULL));
2055
2056  out:
2057   if (id)
2058     silc_free(id);
2059   if (client_id)
2060     silc_free(client_id);
2061   if (payload)
2062     silc_channel_payload_free(payload);
2063 }
2064
2065 /* Private message received. This processes the private message and
2066    finally displays it on the screen. */
2067
2068 void silc_client_private_message(SilcClient client, 
2069                                  SilcSocketConnection sock, 
2070                                  SilcPacketContext *packet)
2071 {
2072   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2073   SilcBuffer buffer = packet->buffer;
2074   SilcIDCacheEntry id_cache;
2075   SilcClientID *remote_id = NULL;
2076   SilcClientEntry remote_client;
2077   unsigned short nick_len;
2078   unsigned char *nickname, *message = NULL;
2079   int ret;
2080
2081   if (packet->src_id_type != SILC_ID_CLIENT)
2082     goto out;
2083
2084   /* Get nickname */
2085   ret = silc_buffer_unformat(buffer, 
2086                              SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2087                              SILC_STR_END);
2088   if (ret == -1)
2089     return;
2090
2091   silc_buffer_pull(buffer, 2 + nick_len);
2092
2093   message = silc_calloc(buffer->len + 1, sizeof(char));
2094   memcpy(message, buffer->data, buffer->len);
2095
2096   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2097                              SILC_ID_CLIENT);
2098   if (!remote_id)
2099     goto out;
2100
2101   /* Check whether we know this client already */
2102   if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2103                                    SILC_ID_CLIENT, &id_cache))
2104     {
2105       /* Allocate client entry */
2106       remote_client = silc_calloc(1, sizeof(*remote_client));
2107       remote_client->id = remote_id;
2108       silc_parse_nickname(nickname, &remote_client->nickname, 
2109                           &remote_client->server, &remote_client->num);
2110       
2111       /* Save the client to cache */
2112       silc_idcache_add(conn->client_cache, remote_client->nickname,
2113                        SILC_ID_CLIENT, remote_client->id, remote_client, 
2114                        TRUE);
2115     } else {
2116       remote_client = (SilcClientEntry)id_cache->context;
2117     }
2118
2119   /* Pass the private message to application */
2120   client->ops->private_message(client, conn, remote_client, message);
2121
2122   /* See if we are away (gone). If we are away we will reply to the
2123      sender with the set away message. */
2124   if (conn->away && conn->away->away) {
2125     /* If it's me, ignore */
2126     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2127       goto out;
2128
2129     /* Send the away message */
2130     silc_client_packet_send_private_message(client, sock, remote_client,
2131                                             conn->away->away,
2132                                             strlen(conn->away->away), TRUE);
2133   }
2134
2135  out:
2136   if (remote_id)
2137     silc_free(remote_id);
2138
2139   if (message) {
2140     memset(message, 0, buffer->len);
2141     silc_free(message);
2142   }
2143   silc_free(nickname);
2144 }
2145
2146 /* Removes a client entry from all channel it has joined. This really is
2147    a performance killer (client_entry should have pointers to channel 
2148    entry list). */
2149
2150 void silc_client_remove_from_channels(SilcClient client,
2151                                       SilcClientConnection conn,
2152                                       SilcClientEntry client_entry)
2153 {
2154   SilcIDCacheEntry id_cache;
2155   SilcIDCacheList list;
2156   SilcChannelEntry channel;
2157   SilcChannelUser chu;
2158
2159   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2160                                SILC_ID_CHANNEL, &list))
2161     return;
2162
2163   silc_idcache_list_first(list, &id_cache);
2164   channel = (SilcChannelEntry)id_cache->context;
2165   
2166   while (channel) {
2167     
2168     /* Remove client from channel */
2169     silc_list_start(channel->clients);
2170     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2171       if (chu->client == client_entry) {
2172         silc_list_del(channel->clients, chu);
2173         silc_free(chu);
2174         break;
2175       }
2176     }
2177
2178     if (!silc_idcache_list_next(list, &id_cache))
2179       break;
2180     
2181     channel = (SilcChannelEntry)id_cache->context;
2182   }
2183
2184   silc_idcache_list_free(list);
2185 }
2186
2187 /* Replaces `old' client entries from all channels to `new' client entry.
2188    This can be called for example when nickname changes and old ID entry
2189    is replaced from ID cache with the new one. If the old ID entry is only
2190    updated, then this fucntion needs not to be called. */
2191
2192 void silc_client_replace_from_channels(SilcClient client, 
2193                                        SilcClientConnection conn,
2194                                        SilcClientEntry old,
2195                                        SilcClientEntry new)
2196 {
2197   SilcIDCacheEntry id_cache;
2198   SilcIDCacheList list;
2199   SilcChannelEntry channel;
2200   SilcChannelUser chu;
2201
2202   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2203                                SILC_ID_CHANNEL, &list))
2204     return;
2205
2206   silc_idcache_list_first(list, &id_cache);
2207   channel = (SilcChannelEntry)id_cache->context;
2208   
2209   while (channel) {
2210     
2211     /* Replace client entry */
2212     silc_list_start(channel->clients);
2213     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2214       if (chu->client == old) {
2215         chu->client = new;
2216         break;
2217       }
2218     }
2219
2220     if (!silc_idcache_list_next(list, &id_cache))
2221       break;
2222     
2223     channel = (SilcChannelEntry)id_cache->context;
2224   }
2225
2226   silc_idcache_list_free(list);
2227 }
2228
2229 /* Parses mode mask and returns the mode as string. */
2230
2231 char *silc_client_chmode(unsigned int mode)
2232 {
2233   char string[20];
2234
2235   if (!mode)
2236     return NULL;
2237
2238   memset(string, 0, sizeof(string));
2239
2240   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2241     strncat(string, "p", 1);
2242
2243   if (mode & SILC_CHANNEL_MODE_SECRET)
2244     strncat(string, "s", 1);
2245
2246   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2247     strncat(string, "k", 1);
2248
2249   if (mode & SILC_CHANNEL_MODE_INVITE)
2250     strncat(string, "i", 1);
2251
2252   if (mode & SILC_CHANNEL_MODE_TOPIC)
2253     strncat(string, "t", 1);
2254
2255   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2256     strncat(string, "l", 1);
2257
2258   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2259     strncat(string, "a", 1);
2260
2261   /* Rest of mode is ignored */
2262
2263   return strdup(string);
2264 }
2265
2266 /* Parses channel user mode mask and returns te mode as string */
2267
2268 char *silc_client_chumode(unsigned int mode)
2269 {
2270   char string[4];
2271
2272   if (!mode)
2273     return NULL;
2274
2275   memset(string, 0, sizeof(string));
2276
2277   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2278     strncat(string, "f", 1);
2279
2280   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2281     strncat(string, "o", 1);
2282
2283   return strdup(string);
2284 }
2285
2286 /* Parses channel user mode and returns it as special mode character. */
2287
2288 char *silc_client_chumode_char(unsigned int mode)
2289 {
2290   char string[4];
2291
2292   if (!mode)
2293     return NULL;
2294
2295   memset(string, 0, sizeof(string));
2296
2297   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2298     strncat(string, "*", 1);
2299
2300   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2301     strncat(string, "@", 1);
2302
2303   return strdup(string);
2304 }