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       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
607       client->ops->disconnect(client, conn);
608       silc_client_close_connection(client, sock);
609       return;
610     }
611
612     /* Process the packet. This will call the parser that will then
613        decrypt and parse the packet. */
614     silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
615                                 silc_client_packet_parse, client);
616   }
617 }
618
619 /* Parses whole packet, received earlier. */
620
621 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
622 {
623   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
624   SilcClient client = (SilcClient)parse_ctx->context;
625   SilcPacketContext *packet = parse_ctx->packet;
626   SilcBuffer buffer = packet->buffer;
627   SilcSocketConnection sock = parse_ctx->sock;
628   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
629   int ret;
630
631   SILC_LOG_DEBUG(("Start"));
632
633   /* Decrypt the received packet */
634   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
635   if (ret < 0)
636     goto out;
637
638   if (ret == 0) {
639     /* Parse the packet. Packet type is returned. */
640     ret = silc_packet_parse(packet);
641   } else {
642     /* Parse the packet header in special way as this is "special"
643        packet type. */
644     ret = silc_packet_parse_special(packet);
645   }
646
647   if (ret == SILC_PACKET_NONE)
648     goto out;
649
650   /* Parse the incoming packet type */
651   silc_client_packet_parse_type(client, sock, packet);
652
653  out:
654   silc_buffer_clear(sock->inbuf);
655   silc_packet_context_free(packet);
656   silc_free(parse_ctx);
657 }
658
659 /* Parser callback called by silc_packet_receive_process. Thie merely
660    registers timeout that will handle the actual parsing when appropriate. */
661
662 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
663 {
664   SilcClient client = (SilcClient)parser_context->context;
665
666   /* Parse the packet */
667   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
668                      silc_client_packet_parse_real,
669                      (void *)parser_context, 0, 1, 
670                      SILC_TASK_TIMEOUT,
671                      SILC_TASK_PRI_NORMAL);
672 }
673   
674 /* Parses the packet type and calls what ever routines the packet type
675    requires. This is done for all incoming packets. */
676
677 void silc_client_packet_parse_type(SilcClient client, 
678                                    SilcSocketConnection sock,
679                                    SilcPacketContext *packet)
680 {
681   SilcBuffer buffer = packet->buffer;
682   SilcPacketType type = packet->type;
683
684   SILC_LOG_DEBUG(("Parsing packet type %d", type));
685
686   /* Parse the packet type */
687   switch(type) {
688   case SILC_PACKET_DISCONNECT:
689     silc_client_disconnected_by_server(client, sock, buffer);
690     break;
691   case SILC_PACKET_SUCCESS:
692     /*
693      * Success received for something. For now we can have only
694      * one protocol for connection executing at once hence this
695      * success message is for whatever protocol is executing currently.
696      */
697     if (sock->protocol) {
698       sock->protocol->execute(client->timeout_queue, 0,
699                               sock->protocol, sock->sock, 0, 0);
700     }
701     break;
702   case SILC_PACKET_FAILURE:
703     /*
704      * Failure received for some protocol. Set the protocol state to 
705      * error and call the protocol callback. This fill cause error on
706      * protocol and it will call the final callback.
707      */
708     if (sock->protocol) {
709       sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
710       sock->protocol->execute(client->timeout_queue, 0,
711                               sock->protocol, sock->sock, 0, 0);
712
713       /* XXX We have only two protocols currently thus we know what this
714          failure indication is. */
715       if (buffer->len >= 4) {
716         unsigned int failure;
717
718         SILC_GET32_MSB(failure, buffer->data);
719
720         /* Notify application */
721         client->ops->failure(client, sock->user_data, sock->protocol,
722                              (void *)failure);
723       }
724     }
725     break;
726   case SILC_PACKET_REJECT:
727     break;
728
729   case SILC_PACKET_NOTIFY:
730     /*
731      * Received notify message 
732      */
733     silc_client_notify_by_server(client, sock, packet);
734     break;
735
736   case SILC_PACKET_ERROR:
737     /*
738      * Received error message
739      */
740     silc_client_error_by_server(client, sock, buffer);
741     break;
742
743   case SILC_PACKET_CHANNEL_MESSAGE:
744     /*
745      * Received message to (from, actually) a channel
746      */
747     silc_client_channel_message(client, sock, packet);
748     break;
749   case SILC_PACKET_CHANNEL_KEY:
750     /*
751      * Received key for a channel. By receiving this key the client will be
752      * able to talk to the channel it has just joined. This can also be
753      * a new key for existing channel as keys expire peridiocally.
754      */
755     silc_client_receive_channel_key(client, sock, buffer);
756     break;
757
758   case SILC_PACKET_PRIVATE_MESSAGE:
759     /*
760      * Received private message
761      */
762     silc_client_private_message(client, sock, packet);
763     break;
764   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
765     /*
766      * Received private message key
767      */
768     break;
769
770   case SILC_PACKET_COMMAND_REPLY:
771     /*
772      * Recived reply for a command
773      */
774     silc_client_command_reply_process(client, sock, packet);
775     break;
776
777   case SILC_PACKET_KEY_EXCHANGE:
778     if (sock->protocol) {
779       SilcClientKEInternalContext *proto_ctx = 
780         (SilcClientKEInternalContext *)sock->protocol->context;
781
782       proto_ctx->packet = silc_packet_context_dup(packet);
783       proto_ctx->dest_id_type = packet->src_id_type;
784       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
785                                           packet->src_id_type);
786       if (!proto_ctx->dest_id)
787         break;
788
789       /* Let the protocol handle the packet */
790       sock->protocol->execute(client->timeout_queue, 0,
791                               sock->protocol, sock->sock, 0, 0);
792     } else {
793       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
794                       "protocol active, packet dropped."));
795
796       /* XXX Trigger KE protocol?? Rekey actually! */
797     }
798     break;
799
800   case SILC_PACKET_KEY_EXCHANGE_1:
801     if (sock->protocol) {
802
803     } else {
804       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
805                       "protocol active, packet dropped."));
806     }
807     break;
808   case SILC_PACKET_KEY_EXCHANGE_2:
809     if (sock->protocol) {
810       SilcClientKEInternalContext *proto_ctx = 
811         (SilcClientKEInternalContext *)sock->protocol->context;
812
813       if (proto_ctx->packet)
814         silc_packet_context_free(proto_ctx->packet);
815
816       proto_ctx->packet = silc_packet_context_dup(packet);
817       proto_ctx->dest_id_type = packet->src_id_type;
818       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
819                                           packet->src_id_type);
820       if (!proto_ctx->dest_id)
821         break;
822
823       /* Let the protocol handle the packet */
824       sock->protocol->execute(client->timeout_queue, 0,
825                               sock->protocol, sock->sock, 0, 0);
826     } else {
827       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
828                       "protocol active, packet dropped."));
829     }
830     break;
831
832   case SILC_PACKET_NEW_ID:
833     {
834       /*
835        * Received new ID from server. This packet is received at
836        * the connection to the server.  New ID is also received when 
837        * user changes nickname but in that case the new ID is received
838        * as command reply and not as this packet type.
839        */
840       SilcIDPayload idp;
841
842       idp = silc_id_payload_parse(buffer);
843       if (!idp)
844         break;
845       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
846         break;
847
848       silc_client_receive_new_id(client, sock, idp);
849       silc_id_payload_free(idp);
850       break;
851     }
852
853   case SILC_PACKET_HEARTBEAT:
854     /*
855      * Received heartbeat packet
856      */
857     SILC_LOG_DEBUG(("Heartbeat packet"));
858     break;
859
860   default:
861     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
862     break;
863   }
864 }
865
866 /* Sends packet. This doesn't actually send the packet instead it assembles
867    it and marks it to be sent. However, if force_send is TRUE the packet
868    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
869    will be derived from sock argument. Otherwise the valid arguments sent
870    are used. */
871
872 void silc_client_packet_send(SilcClient client, 
873                              SilcSocketConnection sock,
874                              SilcPacketType type, 
875                              void *dst_id,
876                              SilcIdType dst_id_type,
877                              SilcCipher cipher,
878                              SilcHmac hmac,
879                              unsigned char *data, 
880                              unsigned int data_len, 
881                              int force_send)
882 {
883   SilcPacketContext packetdata;
884
885   SILC_LOG_DEBUG(("Sending packet, type %d", type));
886
887   /* Get data used in the packet sending, keys and stuff */
888   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
889     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
890       cipher = ((SilcClientConnection)sock->user_data)->send_key;
891
892     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
893       hmac = ((SilcClientConnection)sock->user_data)->hmac;
894
895     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
896       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
897       dst_id_type = SILC_ID_SERVER;
898     }
899   }
900
901   /* Set the packet context pointers */
902   packetdata.flags = 0;
903   packetdata.type = type;
904   if (((SilcClientConnection)sock->user_data)->local_id_data)
905     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
906   else 
907     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
908   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
909   packetdata.src_id_type = SILC_ID_CLIENT;
910   if (dst_id) {
911     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
912     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
913     packetdata.dst_id_type = dst_id_type;
914   } else {
915     packetdata.dst_id = NULL;
916     packetdata.dst_id_len = 0;
917     packetdata.dst_id_type = SILC_ID_NONE;
918   }
919   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
920     packetdata.src_id_len + packetdata.dst_id_len;
921   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
922
923   /* Prepare outgoing data buffer for packet sending */
924   silc_packet_send_prepare(sock, 
925                            SILC_PACKET_HEADER_LEN +
926                            packetdata.src_id_len + 
927                            packetdata.dst_id_len,
928                            packetdata.padlen,
929                            data_len);
930
931   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
932
933   packetdata.buffer = sock->outbuf;
934
935   /* Put the data to the buffer */
936   if (data && data_len)
937     silc_buffer_put(sock->outbuf, data, data_len);
938
939   /* Create the outgoing packet */
940   silc_packet_assemble(&packetdata);
941
942   /* Encrypt the packet */
943   if (cipher)
944     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
945
946   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
947                    sock->outbuf->data, sock->outbuf->len);
948
949   /* Now actually send the packet */
950   silc_client_packet_send_real(client, sock, force_send);
951 }
952
953 /* Sends packet to a channel. Packet to channel is always encrypted
954    differently from "normal" packets. SILC header of the packet is 
955    encrypted with the next receiver's key and the rest of the packet is
956    encrypted with the channel specific key. Padding and HMAC is computed
957    with the next receiver's key. */
958
959 void silc_client_packet_send_to_channel(SilcClient client, 
960                                         SilcSocketConnection sock,
961                                         SilcChannelEntry channel,
962                                         unsigned char *data, 
963                                         unsigned int data_len, 
964                                         int force_send)
965 {
966   int i;
967   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
968   SilcBuffer payload;
969   SilcPacketContext packetdata;
970   SilcCipher cipher;
971   SilcHmac hmac;
972   unsigned char *id_string;
973
974   SILC_LOG_DEBUG(("Sending packet to channel"));
975
976   if (!channel || !channel->key) {
977     client->ops->say(client, conn, 
978                      "Cannot talk to channel: key does not exist");
979     return;
980   }
981
982   /* Generate IV */
983   if (channel->iv[0] == '\0')
984     for (i = 0; i < 16; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
985   else
986     silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
987
988   /* Encode the channel payload */
989   payload = silc_channel_payload_encode(data_len, data, 16, channel->iv, 
990                                         client->rng);
991   if (!payload) {
992     client->ops->say(client, conn, 
993                      "Error: Could not create packet to be sent to channel");
994     return;
995   }
996
997   /* Get data used in packet header encryption, keys and stuff. Rest
998      of the packet (the payload) is, however, encrypted with the 
999      specified channel key. */
1000   cipher = conn->send_key;
1001   hmac = conn->hmac;
1002   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1003
1004   /* Set the packet context pointers. The destination ID is always
1005      the Channel ID of the channel. Server and router will handle the
1006      distribution of the packet. */
1007   packetdata.flags = 0;
1008   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1009   packetdata.src_id = conn->local_id_data;
1010   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1011   packetdata.src_id_type = SILC_ID_CLIENT;
1012   packetdata.dst_id = id_string;
1013   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1014   packetdata.dst_id_type = SILC_ID_CHANNEL;
1015   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
1016     packetdata.src_id_len + packetdata.dst_id_len;
1017   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1018                                           packetdata.src_id_len +
1019                                           packetdata.dst_id_len));
1020
1021   /* Prepare outgoing data buffer for packet sending */
1022   silc_packet_send_prepare(sock, 
1023                            SILC_PACKET_HEADER_LEN +
1024                            packetdata.src_id_len + 
1025                            packetdata.dst_id_len,
1026                            packetdata.padlen,
1027                            payload->len);
1028
1029   packetdata.buffer = sock->outbuf;
1030
1031   SILC_LOG_HEXDUMP(("IV"), channel->iv, 16);
1032   SILC_LOG_HEXDUMP(("channel key"), channel->key, channel->key_len/8);
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.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1125     packetdata.src_id_len + packetdata.dst_id_len;
1126   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1127                                           packetdata.src_id_len +
1128                                           packetdata.dst_id_len));
1129
1130   /* Prepare outgoing data buffer for packet sending */
1131   silc_packet_send_prepare(sock, 
1132                            SILC_PACKET_HEADER_LEN +
1133                            packetdata.src_id_len + 
1134                            packetdata.dst_id_len,
1135                            packetdata.padlen,
1136                            buffer->len);
1137   
1138   packetdata.buffer = sock->outbuf;
1139
1140   /* Encrypt payload of the packet. Encrypt with private message specific
1141      key if it exist, otherwise with session key. */
1142   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1143                           buffer->len, cipher->iv);
1144       
1145   /* Put the actual encrypted payload data into the buffer. */
1146   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1147
1148   /* Create the outgoing packet */
1149   silc_packet_assemble(&packetdata);
1150
1151   /* Encrypt the header and padding of the packet. */
1152   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1153                       packetdata.src_id_len + packetdata.dst_id_len +
1154                       packetdata.padlen);
1155
1156   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1157                    sock->outbuf->data, sock->outbuf->len);
1158
1159   /* Now actually send the packet */
1160   silc_client_packet_send_real(client, sock, force_send);
1161   silc_free(packetdata.dst_id);
1162
1163  out:
1164   silc_free(buffer);
1165 }     
1166
1167 /* Closes connection to remote end. Free's all allocated data except
1168    for some information such as nickname etc. that are valid at all time. */
1169
1170 void silc_client_close_connection(SilcClient client,
1171                                   SilcSocketConnection sock)
1172 {
1173   SilcClientConnection conn;
1174
1175   /* We won't listen for this connection anymore */
1176   silc_schedule_unset_listen_fd(sock->sock);
1177
1178   /* Unregister all tasks */
1179   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1180   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1181
1182   /* Close the actual connection */
1183   silc_net_close_connection(sock->sock);
1184
1185   client->ops->say(client, sock->user_data,
1186                    "Closed connection to host %s", sock->hostname);
1187
1188   /* Free everything */
1189   if (sock->user_data) {
1190     conn = (SilcClientConnection)sock->user_data;
1191
1192     /* XXX Free all client entries and channel entries. */
1193
1194     /* Clear ID caches */
1195     silc_idcache_del_all(conn->client_cache);
1196     silc_idcache_del_all(conn->channel_cache);
1197
1198     /* Free data */
1199     if (conn->remote_host)
1200       silc_free(conn->remote_host);
1201     if (conn->local_id)
1202       silc_free(conn->local_id);
1203     if (conn->local_id_data)
1204       silc_free(conn->local_id_data);
1205     if (conn->send_key)
1206       silc_cipher_free(conn->send_key);
1207     if (conn->receive_key)
1208       silc_cipher_free(conn->receive_key);
1209     if (conn->hmac)
1210       silc_hmac_free(conn->hmac);
1211     if (conn->hmac_key) {
1212       memset(conn->hmac_key, 0, conn->hmac_key_len);
1213       silc_free(conn->hmac_key);
1214     }
1215     if (conn->pending_commands)
1216       silc_dlist_uninit(conn->pending_commands);
1217
1218     conn->sock = NULL;
1219     conn->remote_port = 0;
1220     conn->remote_type = 0;
1221     conn->send_key = NULL;
1222     conn->receive_key = NULL;
1223     conn->hmac = NULL;
1224     conn->hmac_key = NULL;
1225     conn->hmac_key_len = 0;
1226     conn->local_id = NULL;
1227     conn->local_id_data = NULL;
1228     conn->remote_host = NULL;
1229     conn->current_channel = NULL;
1230     conn->pending_commands = NULL;
1231
1232     silc_client_del_connection(client, conn);
1233   }
1234
1235   if (sock->protocol) {
1236     silc_protocol_free(sock->protocol);
1237     sock->protocol = NULL;
1238   }
1239   silc_socket_free(sock);
1240 }
1241
1242 /* Called when we receive disconnection packet from server. This 
1243    closes our end properly and displays the reason of the disconnection
1244    on the screen. */
1245
1246 void silc_client_disconnected_by_server(SilcClient client,
1247                                         SilcSocketConnection sock,
1248                                         SilcBuffer message)
1249 {
1250   char *msg;
1251
1252   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1253
1254   msg = silc_calloc(message->len + 1, sizeof(char));
1255   memcpy(msg, message->data, message->len);
1256   client->ops->say(client, sock->user_data, msg);
1257   silc_free(msg);
1258
1259   SILC_SET_DISCONNECTED(sock);
1260   silc_client_close_connection(client, sock);
1261 }
1262
1263 /* Received error message from server. Display it on the screen. 
1264    We don't take any action what so ever of the error message. */
1265
1266 void silc_client_error_by_server(SilcClient client,
1267                                  SilcSocketConnection sock,
1268                                  SilcBuffer message)
1269 {
1270   char *msg;
1271
1272   msg = silc_calloc(message->len + 1, sizeof(char));
1273   memcpy(msg, message->data, message->len);
1274   client->ops->say(client, sock->user_data, msg);
1275   silc_free(msg);
1276 }
1277
1278 /* Called when notify is received and some async operation (such as command)
1279    is required before processing the notify message. This calls again the
1280    silc_client_notify_by_server and reprocesses the original notify packet. */
1281
1282 static void silc_client_notify_by_server_pending(void *context)
1283 {
1284   SilcPacketContext *p = (SilcPacketContext *)context;
1285   silc_client_notify_by_server(p->context, p->sock, p);
1286 }
1287
1288 /* Destructor for the pending command callback */
1289
1290 static void silc_client_notify_by_server_destructor(void *context)
1291 {
1292   silc_packet_context_free((SilcPacketContext *)context);
1293 }
1294
1295 /* Resolve client information from server by Client ID. */
1296
1297 static void silc_client_notify_by_server_resolve(SilcClient client,
1298                                                  SilcClientConnection conn,
1299                                                  SilcPacketContext *packet,
1300                                                  SilcClientID *client_id)
1301 {
1302   SilcPacketContext *p = silc_packet_context_dup(packet);
1303   SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1304
1305   p->context = (void *)client;
1306   p->sock = conn->sock;
1307
1308   silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1309                            1, 3, idp->data, idp->len);
1310   silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1311                               silc_client_notify_by_server_destructor,
1312                               silc_client_notify_by_server_pending, p);
1313   silc_buffer_free(idp);
1314 }
1315
1316 /* Received notify message from server */
1317
1318 void silc_client_notify_by_server(SilcClient client,
1319                                   SilcSocketConnection sock,
1320                                   SilcPacketContext *packet)
1321 {
1322   SilcBuffer buffer = packet->buffer;
1323   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1324   SilcNotifyPayload payload;
1325   SilcNotifyType type;
1326   SilcArgumentPayload args;
1327
1328   SilcClientID *client_id = NULL;
1329   SilcChannelID *channel_id = NULL;
1330   SilcClientEntry client_entry;
1331   SilcClientEntry client_entry2;
1332   SilcChannelEntry channel;
1333   SilcChannelUser chu;
1334   SilcIDCacheEntry id_cache = NULL;
1335   unsigned char *tmp;
1336   unsigned int tmp_len, mode;
1337
1338   payload = silc_notify_payload_parse(buffer);
1339   if (!payload)
1340     goto out;
1341
1342   type = silc_notify_get_type(payload);
1343   args = silc_notify_get_args(payload);
1344   if (!args)
1345     goto out;
1346
1347   switch(type) {
1348   case SILC_NOTIFY_TYPE_NONE:
1349     /* Notify application */
1350     client->ops->notify(client, conn, type, 
1351                         silc_argument_get_arg_type(args, 1, NULL));
1352     break;
1353
1354   case SILC_NOTIFY_TYPE_INVITE:
1355     /* 
1356      * Someone invited me to a channel. Find Client and Channel entries
1357      * for the application.
1358      */
1359     
1360     /* Get Client ID */
1361     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1362     if (!tmp)
1363       goto out;
1364
1365     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1366     if (!client_id)
1367       goto out;
1368
1369     /* Find Client entry and if not found query it */
1370     client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
1371     if (!client_entry) {
1372       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1373       goto out;
1374     }
1375
1376     /* Get Channel ID */
1377     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1378     if (!tmp)
1379       goto out;
1380
1381     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1382     if (!channel_id)
1383       goto out;
1384
1385     /* XXX Will ALWAYS fail because currently we don't have way to resolve
1386        channel information for channel that we're not joined to. */
1387     /* XXX ways to fix: use (extended) LIST command, or define the channel
1388        name to the notfy type when name resolving is not mandatory. */
1389     /* Find channel entry */
1390     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1391                                      SILC_ID_CHANNEL, &id_cache))
1392       goto out;
1393
1394     channel = (SilcChannelEntry)id_cache->context;
1395
1396     /* Notify application */
1397     client->ops->notify(client, conn, type, client_entry, channel);
1398     break;
1399
1400   case SILC_NOTIFY_TYPE_JOIN:
1401     /*
1402      * Someone has joined to a channel. Get their ID and nickname and
1403      * cache them for later use.
1404      */
1405
1406     /* Get Client ID */
1407     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1408     if (!tmp)
1409       goto out;
1410
1411     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1412     if (!client_id)
1413       goto out;
1414
1415     /* Find Client entry and if not found query it */
1416     client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
1417     if (!client_entry) {
1418       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1419       goto out;
1420     }
1421
1422     /* If nickname or username hasn't been resolved, do so */
1423     if (!client_entry->nickname || !client_entry->username) {
1424       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1425       goto out;
1426     }
1427
1428     /* Get Channel ID */
1429     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1430     if (!tmp)
1431       goto out;
1432
1433     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1434     if (!channel_id)
1435       goto out;
1436
1437     /* Get channel entry */
1438     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1439                                      SILC_ID_CHANNEL, &id_cache))
1440       break;
1441
1442     channel = (SilcChannelEntry)id_cache->context;
1443
1444     /* Add client to channel */
1445     chu = silc_calloc(1, sizeof(*chu));
1446     chu->client = client_entry;
1447     silc_list_add(channel->clients, chu);
1448
1449     /* XXX add support for multiple same nicks on same channel. Check
1450        for them here */
1451
1452     /* Notify application. The channel entry is sent last as this notify
1453        is for channel but application don't know it from the arguments
1454        sent by server. */
1455     client->ops->notify(client, conn, type, client_entry, channel);
1456     break;
1457
1458   case SILC_NOTIFY_TYPE_LEAVE:
1459     /*
1460      * Someone has left a channel. We will remove it from the channel but
1461      * we'll keep it in the cache in case we'll need it later.
1462      */
1463     
1464     /* Get Client ID */
1465     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1466     if (!tmp)
1467       goto out;
1468
1469     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1470     if (!client_id)
1471       goto out;
1472
1473     /* Find Client entry */
1474     client_entry = 
1475       silc_idlist_get_client_by_id(client, conn, client_id);
1476     if (!client_entry)
1477       goto out;
1478
1479     /* Get channel entry */
1480     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1481                                 SILC_ID_CHANNEL);
1482     if (!channel_id)
1483       goto out;
1484     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1485                                      SILC_ID_CHANNEL, &id_cache))
1486       break;
1487
1488     channel = (SilcChannelEntry)id_cache->context;
1489
1490     /* Remove client from channel */
1491     silc_list_start(channel->clients);
1492     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1493       if (chu->client == client_entry) {
1494         silc_list_del(channel->clients, chu);
1495         silc_free(chu);
1496         break;
1497       }
1498     }
1499
1500     /* Notify application. The channel entry is sent last as this notify
1501        is for channel but application don't know it from the arguments
1502        sent by server. */
1503     client->ops->notify(client, conn, type, client_entry, channel);
1504     break;
1505
1506   case SILC_NOTIFY_TYPE_SIGNOFF:
1507     /*
1508      * Someone left SILC. We'll remove it from all channels and from cache.
1509      */
1510
1511     /* Get Client ID */
1512     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1513     if (!tmp)
1514       goto out;
1515
1516     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1517     if (!client_id)
1518       goto out;
1519
1520     /* Find Client entry */
1521     client_entry = 
1522       silc_idlist_get_client_by_id(client, conn, client_id);
1523     if (!client_entry)
1524       goto out;
1525
1526     /* Remove from all channels */
1527     silc_client_remove_from_channels(client, conn, client_entry);
1528
1529     /* Remove from cache */
1530     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1531                            client_entry->id);
1532
1533     /* Get signoff message */
1534     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1535     if (tmp_len > 128)
1536       tmp = NULL;
1537
1538     /* Notify application */
1539     client->ops->notify(client, conn, type, client_entry, tmp);
1540
1541     /* Free data */
1542     if (client_entry->nickname)
1543       silc_free(client_entry->nickname);
1544     if (client_entry->server)
1545       silc_free(client_entry->server);
1546     if (client_entry->id)
1547       silc_free(client_entry->id);
1548     if (client_entry->send_key)
1549       silc_cipher_free(client_entry->send_key);
1550     if (client_entry->receive_key)
1551       silc_cipher_free(client_entry->receive_key);
1552     break;
1553
1554   case SILC_NOTIFY_TYPE_TOPIC_SET:
1555     /*
1556      * Someone set the topic on a channel.
1557      */
1558
1559     /* Get Client ID */
1560     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1561     if (!tmp)
1562       goto out;
1563
1564     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1565     if (!client_id)
1566       goto out;
1567
1568     /* Find Client entry */
1569     client_entry = 
1570       silc_idlist_get_client_by_id(client, conn, client_id);
1571     if (!client_entry)
1572       goto out;
1573
1574     /* Get topic */
1575     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1576     if (!tmp)
1577       goto out;
1578
1579     /* Get channel entry */
1580     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1581                                 SILC_ID_CHANNEL);
1582     if (!channel_id)
1583       goto out;
1584     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1585                                      SILC_ID_CHANNEL, &id_cache))
1586       break;
1587
1588     channel = (SilcChannelEntry)id_cache->context;
1589
1590     /* Notify application. The channel entry is sent last as this notify
1591        is for channel but application don't know it from the arguments
1592        sent by server. */
1593     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1594     break;
1595
1596   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1597     /*
1598      * Someone changed their nickname. If we don't have entry for the new
1599      * ID we will query it and return here after it's done. After we've
1600      * returned we fetch the old entry and free it and notify the 
1601      * application.
1602      */
1603
1604     /* Get new Client ID */
1605     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1606     if (!tmp)
1607       goto out;
1608
1609     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1610     if (!client_id)
1611       goto out;
1612
1613     /* Ignore my ID */
1614     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1615       break;
1616
1617     /* Find Client entry and if not found query it */
1618     client_entry2 = 
1619       silc_idlist_get_client_by_id(client, conn, client_id);
1620     if (!client_entry2) {
1621       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1622       goto out;
1623     }
1624     silc_free(client_id);
1625
1626     /* Get old Client ID */
1627     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1628     if (!tmp)
1629       goto out;
1630
1631     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1632     if (!client_id)
1633       goto out;
1634
1635     /* Find old Client entry */
1636     client_entry = 
1637       silc_idlist_get_client_by_id(client, conn, client_id);
1638     if (!client_entry)
1639       goto out;
1640
1641     /* Remove the old from cache */
1642     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1643                            client_entry->id);
1644
1645     /* Replace old ID entry with new one on all channels. */
1646     silc_client_replace_from_channels(client, conn, client_entry,
1647                                       client_entry2);
1648
1649     /* Notify application */
1650     client->ops->notify(client, conn, type, client_entry, client_entry2);
1651
1652     /* Free data */
1653     if (client_entry->nickname)
1654       silc_free(client_entry->nickname);
1655     if (client_entry->server)
1656       silc_free(client_entry->server);
1657     if (client_entry->id)
1658       silc_free(client_entry->id);
1659     if (client_entry->send_key)
1660       silc_cipher_free(client_entry->send_key);
1661     if (client_entry->receive_key)
1662       silc_cipher_free(client_entry->receive_key);
1663     break;
1664
1665   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1666     /*
1667      * Someone changed a channel mode
1668      */
1669
1670     /* Get Client ID */
1671     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1672     if (!tmp)
1673       goto out;
1674
1675     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1676     if (!client_id)
1677       goto out;
1678
1679     /* Find Client entry */
1680     client_entry = 
1681       silc_idlist_get_client_by_id(client, conn, client_id);
1682     if (!client_entry)
1683       goto out;
1684
1685     /* Get the mode */
1686     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1687     if (!tmp)
1688       goto out;
1689
1690     SILC_GET32_MSB(mode, tmp);
1691
1692     /* Get channel entry */
1693     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1694                                 SILC_ID_CHANNEL);
1695     if (!channel_id)
1696       goto out;
1697     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1698                                      SILC_ID_CHANNEL, &id_cache))
1699       break;
1700
1701     channel = (SilcChannelEntry)id_cache->context;
1702
1703     /* Save the new mode */
1704     channel->mode = mode;
1705
1706     /* Notify application. The channel entry is sent last as this notify
1707        is for channel but application don't know it from the arguments
1708        sent by server. */
1709     client->ops->notify(client, conn, type, client_entry, mode, channel);
1710     break;
1711
1712   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1713     /*
1714      * Someone changed user's mode on a channel
1715      */
1716
1717     /* Get Client ID */
1718     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1719     if (!tmp)
1720       goto out;
1721
1722     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1723     if (!client_id)
1724       goto out;
1725
1726     /* Find Client entry */
1727     client_entry = 
1728       silc_idlist_get_client_by_id(client, conn, client_id);
1729     if (!client_entry)
1730       goto out;
1731
1732     /* Get the mode */
1733     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1734     if (!tmp)
1735       goto out;
1736
1737     SILC_GET32_MSB(mode, tmp);
1738
1739     /* Get target Client ID */
1740     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1741     if (!tmp)
1742       goto out;
1743
1744     silc_free(client_id);
1745     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1746     if (!client_id)
1747       goto out;
1748
1749     /* Find target Client entry */
1750     client_entry2 = 
1751       silc_idlist_get_client_by_id(client, conn, client_id);
1752     if (!client_entry2)
1753       goto out;
1754
1755     /* Get channel entry */
1756     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1757                                 SILC_ID_CHANNEL);
1758     if (!channel_id)
1759       goto out;
1760     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1761                                      SILC_ID_CHANNEL, &id_cache))
1762       break;
1763
1764     channel = (SilcChannelEntry)id_cache->context;
1765
1766     /* Save the mode */
1767     silc_list_start(channel->clients);
1768     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1769       if (chu->client == client_entry) {
1770         chu->mode = mode;
1771         break;
1772       }
1773     }
1774
1775     /* Notify application. The channel entry is sent last as this notify
1776        is for channel but application don't know it from the arguments
1777        sent by server. */
1778     client->ops->notify(client, conn, type, client_entry, mode, 
1779                         client_entry2, channel);
1780     break;
1781
1782   case SILC_NOTIFY_TYPE_MOTD:
1783     /*
1784      * Received Message of the day
1785      */
1786
1787     /* Get motd */
1788     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1789     if (!tmp)
1790       goto out;
1791     
1792     /* Notify application */
1793     client->ops->notify(client, conn, type, tmp);
1794     break;
1795
1796   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1797     /*
1798      * Router has enforced a new ID to a channel. Let's change the old
1799      * ID to the one provided here.
1800      */
1801
1802     /* Get the old ID */
1803     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1804     if (!tmp)
1805       goto out;
1806     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1807     if (!channel_id)
1808       goto out;
1809     
1810     /* Get the channel entry */
1811     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1812                                      SILC_ID_CHANNEL, &id_cache))
1813       break;
1814
1815     channel = (SilcChannelEntry)id_cache->context;
1816
1817     /* Free the old ID */
1818     silc_free(channel_id);
1819     silc_free(channel->id);
1820
1821     /* Get the new ID */
1822     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1823     if (!tmp)
1824       goto out;
1825     channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1826     if (!channel->id)
1827       goto out;
1828
1829     id_cache->id = (void *)channel->id;
1830
1831     /* Notify application */
1832     client->ops->notify(client, conn, type, channel, channel);
1833     break;
1834
1835   case SILC_NOTIFY_TYPE_KICKED:
1836     /*
1837      * A client (maybe me) was kicked from a channel
1838      */
1839
1840     /* Get Client ID */
1841     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1842     if (!tmp)
1843       goto out;
1844
1845     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1846     if (!client_id)
1847       goto out;
1848
1849     /* Find Client entry */
1850     client_entry = 
1851       silc_idlist_get_client_by_id(client, conn, client_id);
1852     if (!client_entry)
1853       goto out;
1854
1855     /* Get channel entry */
1856     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1857                                 SILC_ID_CHANNEL);
1858     if (!channel_id)
1859       goto out;
1860     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1861                                      SILC_ID_CHANNEL, &id_cache))
1862       break;
1863
1864     channel = (SilcChannelEntry)id_cache->context;
1865
1866     /* Get comment */
1867     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1868
1869     /* Notify application. The channel entry is sent last as this notify
1870        is for channel but application don't know it from the arguments
1871        sent by server. */
1872     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1873
1874     /* If I was kicked from channel, remove the channel */
1875     if (client_entry == conn->local_entry) {
1876       if (conn->current_channel == channel)
1877         conn->current_channel = NULL;
1878       silc_idcache_del_by_id(conn->channel_cache, 
1879                              SILC_ID_CHANNEL, channel->id);
1880       silc_free(channel->channel_name);
1881       silc_free(channel->id);
1882       silc_free(channel->key);
1883       silc_cipher_free(channel->channel_key);
1884       silc_free(channel);
1885     }
1886     break;
1887     
1888   default:
1889     break;
1890   }
1891
1892  out:
1893   silc_notify_payload_free(payload);
1894   if (client_id)
1895     silc_free(client_id);
1896   if (channel_id)
1897     silc_free(channel_id);
1898 }
1899
1900 /* Processes the received new Client ID from server. Old Client ID is
1901    deleted from cache and new one is added. */
1902
1903 void silc_client_receive_new_id(SilcClient client,
1904                                 SilcSocketConnection sock,
1905                                 SilcIDPayload idp)
1906 {
1907   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1908   int connecting = FALSE;
1909
1910   if (!conn->local_entry)
1911     connecting = TRUE;
1912
1913   /* Delete old ID from ID cache */
1914   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1915   
1916   /* Save the new ID */
1917   if (conn->local_id)
1918     silc_free(conn->local_id);
1919   if (conn->local_id_data)
1920     silc_free(conn->local_id_data);
1921
1922   conn->local_id = silc_id_payload_get_id(idp);
1923   conn->local_id_data = silc_id_payload_get_data(idp);
1924   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1925
1926   if (!conn->local_entry)
1927     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1928
1929   conn->local_entry->nickname = conn->nickname;
1930   if (!conn->local_entry->username) {
1931     conn->local_entry->username = 
1932       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1933                   sizeof(conn->local_entry->username));
1934     sprintf(conn->local_entry->username, "%s@%s", client->username,
1935             client->hostname);
1936   }
1937   conn->local_entry->server = strdup(conn->remote_host);
1938   conn->local_entry->id = conn->local_id;
1939   
1940   /* Put it to the ID cache */
1941   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1942                    conn->local_id, (void *)conn->local_entry, TRUE);
1943
1944   /* Notify application of successful connection. We do it here now that
1945      we've received the Client ID and are allowed to send traffic. */
1946   if (connecting)
1947     client->ops->connect(client, conn, TRUE);
1948 }
1949
1950 /* Processed received Channel ID for a channel. This is called when client
1951    joins to channel and server replies with channel ID. The ID is cached. */
1952
1953 void silc_client_new_channel_id(SilcClient client,
1954                                 SilcSocketConnection sock,
1955                                 char *channel_name,
1956                                 unsigned int mode, SilcIDPayload idp)
1957 {
1958   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1959   SilcChannelEntry channel;
1960
1961   SILC_LOG_DEBUG(("New channel ID"));
1962
1963   channel = silc_calloc(1, sizeof(*channel));
1964   channel->channel_name = channel_name;
1965   channel->id = silc_id_payload_get_id(idp);
1966   channel->mode = mode;
1967   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1968
1969   conn->current_channel = channel;
1970
1971   /* Put it to the ID cache */
1972   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1973                    (void *)channel->id, (void *)channel, TRUE);
1974 }
1975
1976 /* Saves channel key from encoded `key_payload'. This is used when we
1977    receive Channel Key Payload and when we are processing JOIN command 
1978    reply. */
1979
1980 void silc_client_save_channel_key(SilcClientConnection conn,
1981                                   SilcBuffer key_payload, 
1982                                   SilcChannelEntry channel)
1983 {
1984   unsigned char *id_string, *key, *cipher;
1985   unsigned int tmp_len;
1986   SilcChannelID *id;
1987   SilcIDCacheEntry id_cache = NULL;
1988   SilcChannelKeyPayload payload;
1989
1990   payload = silc_channel_key_payload_parse(key_payload);
1991   if (!payload)
1992     return;
1993
1994   id_string = silc_channel_key_get_id(payload, &tmp_len);
1995   if (!id_string) {
1996     silc_channel_key_payload_free(payload);
1997     return;
1998   }
1999
2000   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
2001   if (!id) {
2002     silc_channel_key_payload_free(payload);
2003     return;
2004   }
2005
2006   /* Find channel. */
2007   if (!channel) {
2008     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2009                                      SILC_ID_CHANNEL, &id_cache))
2010       goto out;
2011     
2012     /* Get channel entry */
2013     channel = (SilcChannelEntry)id_cache->context;
2014   }
2015
2016   /* Save the key */
2017   key = silc_channel_key_get_key(payload, &tmp_len);
2018   cipher = silc_channel_key_get_cipher(payload, NULL);
2019   channel->key_len = tmp_len * 8;
2020   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
2021   memcpy(channel->key, key, tmp_len);
2022
2023   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
2024     conn->client->ops->say(conn->client, conn,
2025                      "Cannot talk to channel: unsupported cipher %s", cipher);
2026     goto out;
2027   }
2028   channel->channel_key->cipher->set_key(channel->channel_key->context, 
2029                                         key, channel->key_len);
2030
2031   /* Client is now joined to the channel */
2032   channel->on_channel = TRUE;
2033
2034  out:
2035   silc_free(id);
2036   silc_channel_key_payload_free(payload);
2037 }
2038
2039 /* Processes received key for channel. The received key will be used
2040    to protect the traffic on the channel for now on. Client must receive
2041    the key to the channel before talking on the channel is possible. 
2042    This is the key that server has generated, this is not the channel
2043    private key, it is entirely local setting. */
2044
2045 void silc_client_receive_channel_key(SilcClient client,
2046                                      SilcSocketConnection sock,
2047                                      SilcBuffer packet)
2048 {
2049   SILC_LOG_DEBUG(("Received key for channel"));
2050
2051   /* Save the key */
2052   silc_client_save_channel_key(sock->user_data, packet, NULL);
2053 }
2054
2055 /* Process received message to a channel (or from a channel, really). This
2056    decrypts the channel message with channel specific key and parses the
2057    channel payload. Finally it displays the message on the screen. */
2058
2059 void silc_client_channel_message(SilcClient client, 
2060                                  SilcSocketConnection sock, 
2061                                  SilcPacketContext *packet)
2062 {
2063   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2064   SilcBuffer buffer = packet->buffer;
2065   SilcChannelPayload payload = NULL;
2066   SilcChannelID *id = NULL;
2067   SilcChannelEntry channel;
2068   SilcChannelUser chu;
2069   SilcIDCacheEntry id_cache = NULL;
2070   SilcClientID *client_id = NULL;
2071   int found = FALSE;
2072
2073   /* Sanity checks */
2074   if (packet->dst_id_type != SILC_ID_CHANNEL)
2075     goto out;
2076
2077   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2078                              SILC_ID_CLIENT);
2079   if (!client_id)
2080     goto out;
2081   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2082   if (!id)
2083     goto out;
2084
2085   /* Find the channel entry from channels on this connection */
2086   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2087                                    SILC_ID_CHANNEL, &id_cache))
2088     goto out;
2089
2090   channel = (SilcChannelEntry)id_cache->context;
2091
2092   SILC_LOG_HEXDUMP(("channel key"), channel->key, channel->key_len);
2093
2094   /* Decrypt the channel message payload. Push the IV out of the way,
2095      since it is not encrypted (after pushing buffer->tail has the IV). */
2096   SILC_LOG_HEXDUMP(("Packet"), buffer->data, buffer->len);
2097   silc_buffer_push_tail(buffer, channel->channel_key->cipher->block_len);
2098   SILC_LOG_HEXDUMP(("Packet"), buffer->data, buffer->len);
2099   SILC_LOG_HEXDUMP(("IV"), buffer->tail, 16);
2100   channel->channel_key->cipher->decrypt(channel->channel_key->context,
2101                                         buffer->data, buffer->data,
2102                                         buffer->len, buffer->tail);
2103   SILC_LOG_HEXDUMP(("Packet"), buffer->data, buffer->len);
2104   silc_buffer_pull_tail(buffer, channel->channel_key->cipher->block_len);
2105   SILC_LOG_HEXDUMP(("Packet"), buffer->data, buffer->len);
2106
2107   /* Parse the channel message payload */
2108   payload = silc_channel_payload_parse(buffer);
2109   if (!payload)
2110     goto out;
2111
2112   /* Find client entry */
2113   silc_list_start(channel->clients);
2114   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2115     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2116       found = TRUE;
2117       break;
2118     }
2119   }
2120
2121   /* Pass the message to application */
2122   client->ops->channel_message(client, conn, found ? chu->client : NULL,
2123                                channel, silc_channel_get_data(payload, NULL));
2124
2125  out:
2126   if (id)
2127     silc_free(id);
2128   if (client_id)
2129     silc_free(client_id);
2130   if (payload)
2131     silc_channel_payload_free(payload);
2132 }
2133
2134 /* Private message received. This processes the private message and
2135    finally displays it on the screen. */
2136
2137 void silc_client_private_message(SilcClient client, 
2138                                  SilcSocketConnection sock, 
2139                                  SilcPacketContext *packet)
2140 {
2141   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2142   SilcBuffer buffer = packet->buffer;
2143   SilcIDCacheEntry id_cache;
2144   SilcClientID *remote_id = NULL;
2145   SilcClientEntry remote_client;
2146   unsigned short nick_len;
2147   unsigned char *nickname, *message = NULL;
2148   int ret;
2149
2150   if (packet->src_id_type != SILC_ID_CLIENT)
2151     goto out;
2152
2153   /* Get nickname */
2154   ret = silc_buffer_unformat(buffer, 
2155                              SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2156                              SILC_STR_END);
2157   if (ret == -1)
2158     return;
2159
2160   silc_buffer_pull(buffer, 2 + nick_len);
2161
2162   message = silc_calloc(buffer->len + 1, sizeof(char));
2163   memcpy(message, buffer->data, buffer->len);
2164
2165   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2166                              SILC_ID_CLIENT);
2167   if (!remote_id)
2168     goto out;
2169
2170   /* Check whether we know this client already */
2171   if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2172                                    SILC_ID_CLIENT, &id_cache))
2173     {
2174       /* Allocate client entry */
2175       remote_client = silc_calloc(1, sizeof(*remote_client));
2176       remote_client->id = remote_id;
2177       silc_parse_nickname(nickname, &remote_client->nickname, 
2178                           &remote_client->server, &remote_client->num);
2179       
2180       /* Save the client to cache */
2181       silc_idcache_add(conn->client_cache, remote_client->nickname,
2182                        SILC_ID_CLIENT, remote_client->id, remote_client, 
2183                        TRUE);
2184     } else {
2185       remote_client = (SilcClientEntry)id_cache->context;
2186     }
2187
2188   /* Pass the private message to application */
2189   client->ops->private_message(client, conn, remote_client, message);
2190
2191   /* See if we are away (gone). If we are away we will reply to the
2192      sender with the set away message. */
2193   if (conn->away && conn->away->away) {
2194     /* If it's me, ignore */
2195     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2196       goto out;
2197
2198     /* Send the away message */
2199     silc_client_packet_send_private_message(client, sock, remote_client,
2200                                             conn->away->away,
2201                                             strlen(conn->away->away), TRUE);
2202   }
2203
2204  out:
2205   if (remote_id)
2206     silc_free(remote_id);
2207
2208   if (message) {
2209     memset(message, 0, buffer->len);
2210     silc_free(message);
2211   }
2212   silc_free(nickname);
2213 }
2214
2215 /* Removes a client entry from all channel it has joined. This really is
2216    a performance killer (client_entry should have pointers to channel 
2217    entry list). */
2218
2219 void silc_client_remove_from_channels(SilcClient client,
2220                                       SilcClientConnection conn,
2221                                       SilcClientEntry client_entry)
2222 {
2223   SilcIDCacheEntry id_cache;
2224   SilcIDCacheList list;
2225   SilcChannelEntry channel;
2226   SilcChannelUser chu;
2227
2228   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2229                                SILC_ID_CHANNEL, &list))
2230     return;
2231
2232   silc_idcache_list_first(list, &id_cache);
2233   channel = (SilcChannelEntry)id_cache->context;
2234   
2235   while (channel) {
2236     
2237     /* Remove client from channel */
2238     silc_list_start(channel->clients);
2239     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2240       if (chu->client == client_entry) {
2241         silc_list_del(channel->clients, chu);
2242         silc_free(chu);
2243         break;
2244       }
2245     }
2246
2247     if (!silc_idcache_list_next(list, &id_cache))
2248       break;
2249     
2250     channel = (SilcChannelEntry)id_cache->context;
2251   }
2252
2253   silc_idcache_list_free(list);
2254 }
2255
2256 /* Replaces `old' client entries from all channels to `new' client entry.
2257    This can be called for example when nickname changes and old ID entry
2258    is replaced from ID cache with the new one. If the old ID entry is only
2259    updated, then this fucntion needs not to be called. */
2260
2261 void silc_client_replace_from_channels(SilcClient client, 
2262                                        SilcClientConnection conn,
2263                                        SilcClientEntry old,
2264                                        SilcClientEntry new)
2265 {
2266   SilcIDCacheEntry id_cache;
2267   SilcIDCacheList list;
2268   SilcChannelEntry channel;
2269   SilcChannelUser chu;
2270
2271   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2272                                SILC_ID_CHANNEL, &list))
2273     return;
2274
2275   silc_idcache_list_first(list, &id_cache);
2276   channel = (SilcChannelEntry)id_cache->context;
2277   
2278   while (channel) {
2279     
2280     /* Replace client entry */
2281     silc_list_start(channel->clients);
2282     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2283       if (chu->client == old) {
2284         chu->client = new;
2285         break;
2286       }
2287     }
2288
2289     if (!silc_idcache_list_next(list, &id_cache))
2290       break;
2291     
2292     channel = (SilcChannelEntry)id_cache->context;
2293   }
2294
2295   silc_idcache_list_free(list);
2296 }
2297
2298 /* Parses mode mask and returns the mode as string. */
2299
2300 char *silc_client_chmode(unsigned int mode)
2301 {
2302   char string[20];
2303
2304   if (!mode)
2305     return NULL;
2306
2307   memset(string, 0, sizeof(string));
2308
2309   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2310     strncat(string, "p", 1);
2311
2312   if (mode & SILC_CHANNEL_MODE_SECRET)
2313     strncat(string, "s", 1);
2314
2315   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2316     strncat(string, "k", 1);
2317
2318   if (mode & SILC_CHANNEL_MODE_INVITE)
2319     strncat(string, "i", 1);
2320
2321   if (mode & SILC_CHANNEL_MODE_TOPIC)
2322     strncat(string, "t", 1);
2323
2324   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2325     strncat(string, "l", 1);
2326
2327   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2328     strncat(string, "a", 1);
2329
2330   /* Rest of mode is ignored */
2331
2332   return strdup(string);
2333 }
2334
2335 /* Parses channel user mode mask and returns te mode as string */
2336
2337 char *silc_client_chumode(unsigned int mode)
2338 {
2339   char string[4];
2340
2341   if (!mode)
2342     return NULL;
2343
2344   memset(string, 0, sizeof(string));
2345
2346   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2347     strncat(string, "f", 1);
2348
2349   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2350     strncat(string, "o", 1);
2351
2352   return strdup(string);
2353 }
2354
2355 /* Parses channel user mode and returns it as special mode character. */
2356
2357 char *silc_client_chumode_char(unsigned int mode)
2358 {
2359   char string[4];
2360
2361   if (!mode)
2362     return NULL;
2363
2364   memset(string, 0, sizeof(string));
2365
2366   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2367     strncat(string, "*", 1);
2368
2369   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2370     strncat(string, "@", 1);
2371
2372   return strdup(string);
2373 }