implemented KICK command
[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)
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   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1032   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1033                                         payload->data, payload->data,
1034                                         payload->len - 16, /* -IV_LEN */
1035                                         channel->iv);
1036
1037   /* Put the actual encrypted payload data into the buffer. */
1038   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1039
1040   /* Create the outgoing packet */
1041   silc_packet_assemble(&packetdata);
1042
1043   /* Encrypt the header and padding of the packet. This is encrypted 
1044      with normal session key shared with our server. */
1045   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1046                       packetdata.src_id_len + packetdata.dst_id_len +
1047                       packetdata.padlen);
1048
1049   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1050                    sock->outbuf->data, sock->outbuf->len);
1051
1052   /* Now actually send the packet */
1053   silc_client_packet_send_real(client, sock, force_send);
1054   silc_buffer_free(payload);
1055   silc_free(id_string);
1056 }
1057
1058 /* Sends private message to remote client. If private message key has
1059    not been set with this client then the message will be encrypted using
1060    normal session keys. Private messages are special packets in SILC
1061    network hence we need this own function for them. This is similiar
1062    to silc_client_packet_send_to_channel except that we send private
1063    message. */
1064
1065 void silc_client_packet_send_private_message(SilcClient client,
1066                                              SilcSocketConnection sock,
1067                                              SilcClientEntry client_entry,
1068                                              unsigned char *data, 
1069                                              unsigned int data_len, 
1070                                              int force_send)
1071 {
1072   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1073   SilcBuffer buffer;
1074   SilcPacketContext packetdata;
1075   unsigned int nick_len;
1076   SilcCipher cipher;
1077   SilcHmac hmac;
1078
1079   SILC_LOG_DEBUG(("Sending private message"));
1080
1081   /* Create private message payload */
1082   nick_len = strlen(conn->nickname);
1083   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1084   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1085   silc_buffer_format(buffer,
1086                      SILC_STR_UI_SHORT(nick_len),
1087                      SILC_STR_UI_XNSTRING(conn->nickname,
1088                                           nick_len),
1089                      SILC_STR_UI_XNSTRING(data, data_len),
1090                      SILC_STR_END);
1091
1092   /* If we don't have private message specific key then private messages
1093      are just as any normal packet thus call normal packet sending.  If
1094      the key exist then the encryption process is a bit different and
1095      will be done in the rest of this function. */
1096   if (!client_entry->send_key) {
1097     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1098                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1099                             buffer->data, buffer->len, force_send);
1100     goto out;
1101   }
1102
1103   /* We have private message specific key */
1104
1105   /* Get data used in the encryption */
1106   cipher = client_entry->send_key;
1107   hmac = conn->hmac;
1108
1109   /* Set the packet context pointers. */
1110   packetdata.flags = 0;
1111   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1112   packetdata.src_id = conn->local_id_data;
1113   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1114   packetdata.src_id_type = SILC_ID_CLIENT;
1115   if (client_entry)
1116     packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1117   else
1118     packetdata.dst_id = conn->local_id_data;
1119   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1120   packetdata.dst_id_type = SILC_ID_CLIENT;
1121   packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1122     packetdata.src_id_len + packetdata.dst_id_len;
1123   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1124                                           packetdata.src_id_len +
1125                                           packetdata.dst_id_len));
1126
1127   /* Prepare outgoing data buffer for packet sending */
1128   silc_packet_send_prepare(sock, 
1129                            SILC_PACKET_HEADER_LEN +
1130                            packetdata.src_id_len + 
1131                            packetdata.dst_id_len,
1132                            packetdata.padlen,
1133                            buffer->len);
1134   
1135   packetdata.buffer = sock->outbuf;
1136
1137   /* Encrypt payload of the packet. Encrypt with private message specific
1138      key if it exist, otherwise with session key. */
1139   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1140                           buffer->len, cipher->iv);
1141       
1142   /* Put the actual encrypted payload data into the buffer. */
1143   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1144
1145   /* Create the outgoing packet */
1146   silc_packet_assemble(&packetdata);
1147
1148   /* Encrypt the header and padding of the packet. */
1149   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1150                       packetdata.src_id_len + packetdata.dst_id_len +
1151                       packetdata.padlen);
1152
1153   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1154                    sock->outbuf->data, sock->outbuf->len);
1155
1156   /* Now actually send the packet */
1157   silc_client_packet_send_real(client, sock, force_send);
1158   silc_free(packetdata.dst_id);
1159
1160  out:
1161   silc_free(buffer);
1162 }     
1163
1164 /* Closes connection to remote end. Free's all allocated data except
1165    for some information such as nickname etc. that are valid at all time. */
1166
1167 void silc_client_close_connection(SilcClient client,
1168                                   SilcSocketConnection sock)
1169 {
1170   SilcClientConnection conn;
1171
1172   /* We won't listen for this connection anymore */
1173   silc_schedule_unset_listen_fd(sock->sock);
1174
1175   /* Unregister all tasks */
1176   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1177   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1178
1179   /* Close the actual connection */
1180   silc_net_close_connection(sock->sock);
1181
1182   client->ops->say(client, sock->user_data,
1183                    "Closed connection to host %s", sock->hostname);
1184
1185   /* Free everything */
1186   if (sock->user_data) {
1187     conn = (SilcClientConnection)sock->user_data;
1188
1189     /* XXX Free all client entries and channel entries. */
1190
1191     /* Clear ID caches */
1192     silc_idcache_del_all(conn->client_cache);
1193     silc_idcache_del_all(conn->channel_cache);
1194
1195     /* Free data */
1196     if (conn->remote_host)
1197       silc_free(conn->remote_host);
1198     if (conn->local_id)
1199       silc_free(conn->local_id);
1200     if (conn->local_id_data)
1201       silc_free(conn->local_id_data);
1202     if (conn->send_key)
1203       silc_cipher_free(conn->send_key);
1204     if (conn->receive_key)
1205       silc_cipher_free(conn->receive_key);
1206     if (conn->hmac)
1207       silc_hmac_free(conn->hmac);
1208     if (conn->hmac_key) {
1209       memset(conn->hmac_key, 0, conn->hmac_key_len);
1210       silc_free(conn->hmac_key);
1211     }
1212     if (conn->pending_commands)
1213       silc_dlist_uninit(conn->pending_commands);
1214
1215     conn->sock = NULL;
1216     conn->remote_port = 0;
1217     conn->remote_type = 0;
1218     conn->send_key = NULL;
1219     conn->receive_key = NULL;
1220     conn->hmac = NULL;
1221     conn->hmac_key = NULL;
1222     conn->hmac_key_len = 0;
1223     conn->local_id = NULL;
1224     conn->local_id_data = NULL;
1225     conn->remote_host = NULL;
1226     conn->current_channel = NULL;
1227     conn->pending_commands = NULL;
1228
1229     silc_client_del_connection(client, conn);
1230   }
1231
1232   if (sock->protocol) {
1233     silc_protocol_free(sock->protocol);
1234     sock->protocol = NULL;
1235   }
1236   silc_socket_free(sock);
1237 }
1238
1239 /* Called when we receive disconnection packet from server. This 
1240    closes our end properly and displays the reason of the disconnection
1241    on the screen. */
1242
1243 void silc_client_disconnected_by_server(SilcClient client,
1244                                         SilcSocketConnection sock,
1245                                         SilcBuffer message)
1246 {
1247   char *msg;
1248
1249   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1250
1251   msg = silc_calloc(message->len + 1, sizeof(char));
1252   memcpy(msg, message->data, message->len);
1253   client->ops->say(client, sock->user_data, msg);
1254   silc_free(msg);
1255
1256   SILC_SET_DISCONNECTED(sock);
1257   silc_client_close_connection(client, sock);
1258 }
1259
1260 /* Received error message from server. Display it on the screen. 
1261    We don't take any action what so ever of the error message. */
1262
1263 void silc_client_error_by_server(SilcClient client,
1264                                  SilcSocketConnection sock,
1265                                  SilcBuffer message)
1266 {
1267   char *msg;
1268
1269   msg = silc_calloc(message->len + 1, sizeof(char));
1270   memcpy(msg, message->data, message->len);
1271   client->ops->say(client, sock->user_data, msg);
1272   silc_free(msg);
1273 }
1274
1275 /* Called when notify is received and some async operation (such as command)
1276    is required before processing the notify message. This calls again the
1277    silc_client_notify_by_server and reprocesses the original notify packet. */
1278
1279 static void silc_client_notify_by_server_pending(void *context)
1280 {
1281   SilcPacketContext *p = (SilcPacketContext *)context;
1282   silc_client_notify_by_server(p->context, p->sock, p);
1283 }
1284
1285 /* Destructor for the pending command callback */
1286
1287 static void silc_client_notify_by_server_destructor(void *context)
1288 {
1289   silc_packet_context_free((SilcPacketContext *)context);
1290 }
1291
1292 /* Resolve client information from server by Client ID. */
1293
1294 static void silc_client_notify_by_server_resolve(SilcClient client,
1295                                                  SilcClientConnection conn,
1296                                                  SilcPacketContext *packet,
1297                                                  SilcClientID *client_id)
1298 {
1299   SilcPacketContext *p = silc_packet_context_dup(packet);
1300   SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1301
1302   p->context = (void *)client;
1303   p->sock = conn->sock;
1304
1305   silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1306                            1, 3, idp->data, idp->len);
1307   silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1308                               silc_client_notify_by_server_destructor,
1309                               silc_client_notify_by_server_pending, p);
1310   silc_buffer_free(idp);
1311 }
1312
1313 /* Received notify message from server */
1314
1315 void silc_client_notify_by_server(SilcClient client,
1316                                   SilcSocketConnection sock,
1317                                   SilcPacketContext *packet)
1318 {
1319   SilcBuffer buffer = packet->buffer;
1320   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1321   SilcNotifyPayload payload;
1322   SilcNotifyType type;
1323   SilcArgumentPayload args;
1324
1325   SilcClientID *client_id = NULL;
1326   SilcChannelID *channel_id = NULL;
1327   SilcClientEntry client_entry;
1328   SilcClientEntry client_entry2;
1329   SilcChannelEntry channel;
1330   SilcChannelUser chu;
1331   SilcIDCacheEntry id_cache = NULL;
1332   unsigned char *tmp;
1333   unsigned int tmp_len, mode;
1334
1335   payload = silc_notify_payload_parse(buffer);
1336   if (!payload)
1337     goto out;
1338
1339   type = silc_notify_get_type(payload);
1340   args = silc_notify_get_args(payload);
1341   if (!args)
1342     goto out;
1343
1344   switch(type) {
1345   case SILC_NOTIFY_TYPE_NONE:
1346     /* Notify application */
1347     client->ops->notify(client, conn, type, 
1348                         silc_argument_get_arg_type(args, 1, NULL));
1349     break;
1350
1351   case SILC_NOTIFY_TYPE_INVITE:
1352     /* 
1353      * Someone invited me to a channel. Find Client and Channel entries
1354      * for the application.
1355      */
1356     
1357     /* Get Client ID */
1358     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1359     if (!tmp)
1360       goto out;
1361
1362     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1363     if (!client_id)
1364       goto out;
1365
1366     /* Find Client entry and if not found query it */
1367     client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
1368     if (!client_entry) {
1369       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1370       goto out;
1371     }
1372
1373     /* Get Channel ID */
1374     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1375     if (!tmp)
1376       goto out;
1377
1378     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1379     if (!channel_id)
1380       goto out;
1381
1382     /* XXX Will ALWAYS fail because currently we don't have way to resolve
1383        channel information for channel that we're not joined to. */
1384     /* XXX ways to fix: use (extended) LIST command, or define the channel
1385        name to the notfy type when name resolving is not mandatory. */
1386     /* Find channel entry */
1387     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1388                                      SILC_ID_CHANNEL, &id_cache))
1389       goto out;
1390
1391     channel = (SilcChannelEntry)id_cache->context;
1392
1393     /* Notify application */
1394     client->ops->notify(client, conn, type, client_entry, channel);
1395     break;
1396
1397   case SILC_NOTIFY_TYPE_JOIN:
1398     /*
1399      * Someone has joined to a channel. Get their ID and nickname and
1400      * cache them for later use.
1401      */
1402
1403     /* Get Client ID */
1404     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1405     if (!tmp)
1406       goto out;
1407
1408     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1409     if (!client_id)
1410       goto out;
1411
1412     /* Find Client entry and if not found query it */
1413     client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
1414     if (!client_entry) {
1415       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1416       goto out;
1417     }
1418
1419     /* If nickname or username hasn't been resolved, do so */
1420     if (!client_entry->nickname || !client_entry->username) {
1421       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1422       goto out;
1423     }
1424
1425     /* Get Channel ID */
1426     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1427     if (!tmp)
1428       goto out;
1429
1430     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1431     if (!channel_id)
1432       goto out;
1433
1434     /* Get channel entry */
1435     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1436                                      SILC_ID_CHANNEL, &id_cache))
1437       break;
1438
1439     channel = (SilcChannelEntry)id_cache->context;
1440
1441     /* Add client to channel */
1442     chu = silc_calloc(1, sizeof(*chu));
1443     chu->client = client_entry;
1444     silc_list_add(channel->clients, chu);
1445
1446     /* XXX add support for multiple same nicks on same channel. Check
1447        for them here */
1448
1449     /* Notify application. The channel entry is sent last as this notify
1450        is for channel but application don't know it from the arguments
1451        sent by server. */
1452     client->ops->notify(client, conn, type, client_entry, channel);
1453     break;
1454
1455   case SILC_NOTIFY_TYPE_LEAVE:
1456     /*
1457      * Someone has left a channel. We will remove it from the channel but
1458      * we'll keep it in the cache in case we'll need it later.
1459      */
1460     
1461     /* Get Client ID */
1462     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1463     if (!tmp)
1464       goto out;
1465
1466     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1467     if (!client_id)
1468       goto out;
1469
1470     /* Find Client entry */
1471     client_entry = 
1472       silc_idlist_get_client_by_id(client, conn, client_id);
1473     if (!client_entry)
1474       goto out;
1475
1476     /* Get channel entry */
1477     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1478                                 SILC_ID_CHANNEL);
1479     if (!channel_id)
1480       goto out;
1481     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1482                                      SILC_ID_CHANNEL, &id_cache))
1483       break;
1484
1485     channel = (SilcChannelEntry)id_cache->context;
1486
1487     /* Remove client from channel */
1488     silc_list_start(channel->clients);
1489     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1490       if (chu->client == client_entry) {
1491         silc_list_del(channel->clients, chu);
1492         silc_free(chu);
1493         break;
1494       }
1495     }
1496
1497     /* Notify application. The channel entry is sent last as this notify
1498        is for channel but application don't know it from the arguments
1499        sent by server. */
1500     client->ops->notify(client, conn, type, client_entry, channel);
1501     break;
1502
1503   case SILC_NOTIFY_TYPE_SIGNOFF:
1504     /*
1505      * Someone left SILC. We'll remove it from all channels and from cache.
1506      */
1507
1508     /* Get Client ID */
1509     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1510     if (!tmp)
1511       goto out;
1512
1513     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1514     if (!client_id)
1515       goto out;
1516
1517     /* Find Client entry */
1518     client_entry = 
1519       silc_idlist_get_client_by_id(client, conn, client_id);
1520     if (!client_entry)
1521       goto out;
1522
1523     /* Remove from all channels */
1524     silc_client_remove_from_channels(client, conn, client_entry);
1525
1526     /* Remove from cache */
1527     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1528                            client_entry->id);
1529
1530     /* Get signoff message */
1531     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1532     if (tmp_len > 128)
1533       tmp = NULL;
1534
1535     /* Notify application */
1536     client->ops->notify(client, conn, type, client_entry, tmp);
1537
1538     /* Free data */
1539     if (client_entry->nickname)
1540       silc_free(client_entry->nickname);
1541     if (client_entry->server)
1542       silc_free(client_entry->server);
1543     if (client_entry->id)
1544       silc_free(client_entry->id);
1545     if (client_entry->send_key)
1546       silc_cipher_free(client_entry->send_key);
1547     if (client_entry->receive_key)
1548       silc_cipher_free(client_entry->receive_key);
1549     break;
1550
1551   case SILC_NOTIFY_TYPE_TOPIC_SET:
1552     /*
1553      * Someone set the topic on a channel.
1554      */
1555
1556     /* Get Client ID */
1557     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1558     if (!tmp)
1559       goto out;
1560
1561     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1562     if (!client_id)
1563       goto out;
1564
1565     /* Find Client entry */
1566     client_entry = 
1567       silc_idlist_get_client_by_id(client, conn, client_id);
1568     if (!client_entry)
1569       goto out;
1570
1571     /* Get topic */
1572     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1573     if (!tmp)
1574       goto out;
1575
1576     /* Get channel entry */
1577     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1578                                 SILC_ID_CHANNEL);
1579     if (!channel_id)
1580       goto out;
1581     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1582                                      SILC_ID_CHANNEL, &id_cache))
1583       break;
1584
1585     channel = (SilcChannelEntry)id_cache->context;
1586
1587     /* Notify application. The channel entry is sent last as this notify
1588        is for channel but application don't know it from the arguments
1589        sent by server. */
1590     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1591     break;
1592
1593   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1594     /*
1595      * Someone changed their nickname. If we don't have entry for the new
1596      * ID we will query it and return here after it's done. After we've
1597      * returned we fetch the old entry and free it and notify the 
1598      * application.
1599      */
1600
1601     /* Get new Client ID */
1602     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1603     if (!tmp)
1604       goto out;
1605
1606     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1607     if (!client_id)
1608       goto out;
1609
1610     /* Ignore my ID */
1611     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1612       break;
1613
1614     /* Find Client entry and if not found query it */
1615     client_entry2 = 
1616       silc_idlist_get_client_by_id(client, conn, client_id);
1617     if (!client_entry2) {
1618       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1619       goto out;
1620     }
1621     silc_free(client_id);
1622
1623     /* Get old Client ID */
1624     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1625     if (!tmp)
1626       goto out;
1627
1628     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1629     if (!client_id)
1630       goto out;
1631
1632     /* Find old Client entry */
1633     client_entry = 
1634       silc_idlist_get_client_by_id(client, conn, client_id);
1635     if (!client_entry)
1636       goto out;
1637
1638     /* Remove the old from cache */
1639     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1640                            client_entry->id);
1641
1642     /* Replace old ID entry with new one on all channels. */
1643     silc_client_replace_from_channels(client, conn, client_entry,
1644                                       client_entry2);
1645
1646     /* Notify application */
1647     client->ops->notify(client, conn, type, client_entry, client_entry2);
1648
1649     /* Free data */
1650     if (client_entry->nickname)
1651       silc_free(client_entry->nickname);
1652     if (client_entry->server)
1653       silc_free(client_entry->server);
1654     if (client_entry->id)
1655       silc_free(client_entry->id);
1656     if (client_entry->send_key)
1657       silc_cipher_free(client_entry->send_key);
1658     if (client_entry->receive_key)
1659       silc_cipher_free(client_entry->receive_key);
1660     break;
1661
1662   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1663     /*
1664      * Someone changed a channel mode
1665      */
1666
1667     /* Get Client ID */
1668     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1669     if (!tmp)
1670       goto out;
1671
1672     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1673     if (!client_id)
1674       goto out;
1675
1676     /* Find Client entry */
1677     client_entry = 
1678       silc_idlist_get_client_by_id(client, conn, client_id);
1679     if (!client_entry)
1680       goto out;
1681
1682     /* Get the mode */
1683     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1684     if (!tmp)
1685       goto out;
1686
1687     SILC_GET32_MSB(mode, tmp);
1688
1689     /* Get channel entry */
1690     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1691                                 SILC_ID_CHANNEL);
1692     if (!channel_id)
1693       goto out;
1694     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1695                                      SILC_ID_CHANNEL, &id_cache))
1696       break;
1697
1698     channel = (SilcChannelEntry)id_cache->context;
1699
1700     /* Save the new mode */
1701     channel->mode = mode;
1702
1703     /* Notify application. The channel entry is sent last as this notify
1704        is for channel but application don't know it from the arguments
1705        sent by server. */
1706     client->ops->notify(client, conn, type, client_entry, mode, channel);
1707     break;
1708
1709   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1710     /*
1711      * Someone changed user's mode on a channel
1712      */
1713
1714     /* Get Client ID */
1715     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1716     if (!tmp)
1717       goto out;
1718
1719     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1720     if (!client_id)
1721       goto out;
1722
1723     /* Find Client entry */
1724     client_entry = 
1725       silc_idlist_get_client_by_id(client, conn, client_id);
1726     if (!client_entry)
1727       goto out;
1728
1729     /* Get the mode */
1730     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1731     if (!tmp)
1732       goto out;
1733
1734     SILC_GET32_MSB(mode, tmp);
1735
1736     /* Get target Client ID */
1737     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1738     if (!tmp)
1739       goto out;
1740
1741     silc_free(client_id);
1742     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1743     if (!client_id)
1744       goto out;
1745
1746     /* Find target Client entry */
1747     client_entry2 = 
1748       silc_idlist_get_client_by_id(client, conn, client_id);
1749     if (!client_entry2)
1750       goto out;
1751
1752     /* Get channel entry */
1753     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1754                                 SILC_ID_CHANNEL);
1755     if (!channel_id)
1756       goto out;
1757     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1758                                      SILC_ID_CHANNEL, &id_cache))
1759       break;
1760
1761     channel = (SilcChannelEntry)id_cache->context;
1762
1763     /* Save the mode */
1764     silc_list_start(channel->clients);
1765     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1766       if (chu->client == client_entry) {
1767         chu->mode = mode;
1768         break;
1769       }
1770     }
1771
1772     /* Notify application. The channel entry is sent last as this notify
1773        is for channel but application don't know it from the arguments
1774        sent by server. */
1775     client->ops->notify(client, conn, type, client_entry, mode, 
1776                         client_entry2, channel);
1777     break;
1778
1779   case SILC_NOTIFY_TYPE_MOTD:
1780     /*
1781      * Received Message of the day
1782      */
1783
1784     /* Get motd */
1785     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1786     if (!tmp)
1787       goto out;
1788     
1789     /* Notify application */
1790     client->ops->notify(client, conn, type, tmp);
1791     break;
1792
1793   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1794     /*
1795      * Router has enforced a new ID to a channel. Let's change the old
1796      * ID to the one provided here.
1797      */
1798
1799     /* Get the old ID */
1800     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1801     if (!tmp)
1802       goto out;
1803     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1804     if (!channel_id)
1805       goto out;
1806     
1807     /* Get the channel entry */
1808     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1809                                      SILC_ID_CHANNEL, &id_cache))
1810       break;
1811
1812     channel = (SilcChannelEntry)id_cache->context;
1813
1814     /* Free the old ID */
1815     silc_free(channel_id);
1816     silc_free(channel->id);
1817
1818     /* Get the new ID */
1819     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1820     if (!tmp)
1821       goto out;
1822     channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1823     if (!channel->id)
1824       goto out;
1825
1826     id_cache->id = (void *)channel->id;
1827
1828     /* Notify application */
1829     client->ops->notify(client, conn, type, channel, channel);
1830     break;
1831
1832   case SILC_NOTIFY_TYPE_KICKED:
1833     /*
1834      * A client (maybe me) was kicked from a channel
1835      */
1836
1837     /* Get Client ID */
1838     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1839     if (!tmp)
1840       goto out;
1841
1842     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1843     if (!client_id)
1844       goto out;
1845
1846     /* Find Client entry */
1847     client_entry = 
1848       silc_idlist_get_client_by_id(client, conn, client_id);
1849     if (!client_entry)
1850       goto out;
1851
1852     /* Get channel entry */
1853     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1854                                 SILC_ID_CHANNEL);
1855     if (!channel_id)
1856       goto out;
1857     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1858                                      SILC_ID_CHANNEL, &id_cache))
1859       break;
1860
1861     channel = (SilcChannelEntry)id_cache->context;
1862
1863     /* Get comment */
1864     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1865
1866     /* Notify application. The channel entry is sent last as this notify
1867        is for channel but application don't know it from the arguments
1868        sent by server. */
1869     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1870
1871     /* If I was kicked from channel, remove the channel */
1872     if (client_entry == conn->local_entry) {
1873       if (conn->current_channel == channel)
1874         conn->current_channel = NULL;
1875       silc_idcache_del_by_id(conn->channel_cache, 
1876                              SILC_ID_CHANNEL, channel->id);
1877       silc_free(channel->channel_name);
1878       silc_free(channel->id);
1879       silc_free(channel->key);
1880       silc_cipher_free(channel->channel_key);
1881       silc_free(channel);
1882     }
1883     break;
1884     
1885   default:
1886     break;
1887   }
1888
1889  out:
1890   silc_notify_payload_free(payload);
1891   if (client_id)
1892     silc_free(client_id);
1893   if (channel_id)
1894     silc_free(channel_id);
1895 }
1896
1897 /* Processes the received new Client ID from server. Old Client ID is
1898    deleted from cache and new one is added. */
1899
1900 void silc_client_receive_new_id(SilcClient client,
1901                                 SilcSocketConnection sock,
1902                                 SilcIDPayload idp)
1903 {
1904   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1905   int connecting = FALSE;
1906
1907   if (!conn->local_entry)
1908     connecting = TRUE;
1909
1910   /* Delete old ID from ID cache */
1911   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1912   
1913   /* Save the new ID */
1914   if (conn->local_id)
1915     silc_free(conn->local_id);
1916   if (conn->local_id_data)
1917     silc_free(conn->local_id_data);
1918
1919   conn->local_id = silc_id_payload_get_id(idp);
1920   conn->local_id_data = silc_id_payload_get_data(idp);
1921   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1922
1923   if (!conn->local_entry)
1924     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1925
1926   conn->local_entry->nickname = conn->nickname;
1927   if (!conn->local_entry->username) {
1928     conn->local_entry->username = 
1929       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1930                   sizeof(conn->local_entry->username));
1931     sprintf(conn->local_entry->username, "%s@%s", client->username,
1932             client->hostname);
1933   }
1934   conn->local_entry->server = strdup(conn->remote_host);
1935   conn->local_entry->id = conn->local_id;
1936   
1937   /* Put it to the ID cache */
1938   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1939                    conn->local_id, (void *)conn->local_entry, TRUE);
1940
1941   /* Notify application of successful connection. We do it here now that
1942      we've received the Client ID and are allowed to send traffic. */
1943   if (connecting)
1944     client->ops->connect(client, conn, TRUE);
1945 }
1946
1947 /* Processed received Channel ID for a channel. This is called when client
1948    joins to channel and server replies with channel ID. The ID is cached. */
1949
1950 void silc_client_new_channel_id(SilcClient client,
1951                                 SilcSocketConnection sock,
1952                                 char *channel_name,
1953                                 unsigned int mode, SilcIDPayload idp)
1954 {
1955   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1956   SilcChannelEntry channel;
1957
1958   SILC_LOG_DEBUG(("New channel ID"));
1959
1960   channel = silc_calloc(1, sizeof(*channel));
1961   channel->channel_name = channel_name;
1962   channel->id = silc_id_payload_get_id(idp);
1963   channel->mode = mode;
1964   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1965
1966   conn->current_channel = channel;
1967
1968   /* Put it to the ID cache */
1969   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1970                    (void *)channel->id, (void *)channel, TRUE);
1971 }
1972
1973 /* Saves channel key from encoded `key_payload'. This is used when we
1974    receive Channel Key Payload and when we are processing JOIN command 
1975    reply. */
1976
1977 void silc_client_save_channel_key(SilcClientConnection conn,
1978                                   SilcBuffer key_payload, 
1979                                   SilcChannelEntry channel)
1980 {
1981   unsigned char *id_string, *key, *cipher;
1982   unsigned int tmp_len;
1983   SilcChannelID *id;
1984   SilcIDCacheEntry id_cache = NULL;
1985   SilcChannelKeyPayload payload;
1986
1987   payload = silc_channel_key_payload_parse(key_payload);
1988   if (!payload)
1989     return;
1990
1991   id_string = silc_channel_key_get_id(payload, &tmp_len);
1992   if (!id_string) {
1993     silc_channel_key_payload_free(payload);
1994     return;
1995   }
1996
1997   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
1998   if (!id) {
1999     silc_channel_key_payload_free(payload);
2000     return;
2001   }
2002
2003   /* Find channel. */
2004   if (!channel) {
2005     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2006                                      SILC_ID_CHANNEL, &id_cache))
2007       goto out;
2008     
2009     /* Get channel entry */
2010     channel = (SilcChannelEntry)id_cache->context;
2011   }
2012
2013   /* Save the key */
2014   key = silc_channel_key_get_key(payload, &tmp_len);
2015   cipher = silc_channel_key_get_cipher(payload, NULL);
2016   channel->key_len = tmp_len;
2017   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
2018   memcpy(channel->key, key, tmp_len);
2019
2020   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
2021     conn->client->ops->say(conn->client, conn,
2022                      "Cannot talk to channel: unsupported cipher %s", cipher);
2023     goto out;
2024   }
2025   channel->channel_key->cipher->set_key(channel->channel_key->context, 
2026                                         key, tmp_len);
2027
2028   /* Client is now joined to the channel */
2029   channel->on_channel = TRUE;
2030
2031  out:
2032   silc_free(id);
2033   silc_channel_key_payload_free(payload);
2034 }
2035
2036 /* Processes received key for channel. The received key will be used
2037    to protect the traffic on the channel for now on. Client must receive
2038    the key to the channel before talking on the channel is possible. 
2039    This is the key that server has generated, this is not the channel
2040    private key, it is entirely local setting. */
2041
2042 void silc_client_receive_channel_key(SilcClient client,
2043                                      SilcSocketConnection sock,
2044                                      SilcBuffer packet)
2045 {
2046   SILC_LOG_DEBUG(("Received key for channel"));
2047
2048   /* Save the key */
2049   silc_client_save_channel_key(sock->user_data, packet, NULL);
2050 }
2051
2052 /* Process received message to a channel (or from a channel, really). This
2053    decrypts the channel message with channel specific key and parses the
2054    channel payload. Finally it displays the message on the screen. */
2055
2056 void silc_client_channel_message(SilcClient client, 
2057                                  SilcSocketConnection sock, 
2058                                  SilcPacketContext *packet)
2059 {
2060   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2061   SilcBuffer buffer = packet->buffer;
2062   SilcChannelPayload payload = NULL;
2063   SilcChannelID *id = NULL;
2064   SilcChannelEntry channel;
2065   SilcChannelUser chu;
2066   SilcIDCacheEntry id_cache = NULL;
2067   SilcClientID *client_id = NULL;
2068   int found = FALSE;
2069
2070   /* Sanity checks */
2071   if (packet->dst_id_type != SILC_ID_CHANNEL)
2072     goto out;
2073
2074   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2075                              SILC_ID_CLIENT);
2076   if (!client_id)
2077     goto out;
2078   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2079   if (!id)
2080     goto out;
2081
2082   /* Find the channel entry from channels on this connection */
2083   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2084                                    SILC_ID_CHANNEL, &id_cache))
2085     goto out;
2086
2087   channel = (SilcChannelEntry)id_cache->context;
2088
2089   /* Decrypt the channel message payload. Push the IV out of the way,
2090      since it is not encrypted (after pushing buffer->tail has the IV). */
2091   silc_buffer_push_tail(buffer, 16);
2092   channel->channel_key->cipher->decrypt(channel->channel_key->context,
2093                                         buffer->data, buffer->data,
2094                                         buffer->len, buffer->tail);
2095   silc_buffer_pull_tail(buffer, 16);
2096
2097   /* Parse the channel message payload */
2098   payload = silc_channel_payload_parse(buffer);
2099   if (!payload)
2100     goto out;
2101
2102   /* Find client entry */
2103   silc_list_start(channel->clients);
2104   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2105     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2106       found = TRUE;
2107       break;
2108     }
2109   }
2110
2111   /* Pass the message to application */
2112   client->ops->channel_message(client, conn, found ? chu->client : NULL,
2113                                channel, silc_channel_get_data(payload, NULL));
2114
2115  out:
2116   if (id)
2117     silc_free(id);
2118   if (client_id)
2119     silc_free(client_id);
2120   if (payload)
2121     silc_channel_payload_free(payload);
2122 }
2123
2124 /* Private message received. This processes the private message and
2125    finally displays it on the screen. */
2126
2127 void silc_client_private_message(SilcClient client, 
2128                                  SilcSocketConnection sock, 
2129                                  SilcPacketContext *packet)
2130 {
2131   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2132   SilcBuffer buffer = packet->buffer;
2133   SilcIDCacheEntry id_cache;
2134   SilcClientID *remote_id = NULL;
2135   SilcClientEntry remote_client;
2136   unsigned short nick_len;
2137   unsigned char *nickname, *message = NULL;
2138   int ret;
2139
2140   if (packet->src_id_type != SILC_ID_CLIENT)
2141     goto out;
2142
2143   /* Get nickname */
2144   ret = silc_buffer_unformat(buffer, 
2145                              SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2146                              SILC_STR_END);
2147   if (ret == -1)
2148     return;
2149
2150   silc_buffer_pull(buffer, 2 + nick_len);
2151
2152   message = silc_calloc(buffer->len + 1, sizeof(char));
2153   memcpy(message, buffer->data, buffer->len);
2154
2155   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2156                              SILC_ID_CLIENT);
2157   if (!remote_id)
2158     goto out;
2159
2160   /* Check whether we know this client already */
2161   if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2162                                    SILC_ID_CLIENT, &id_cache))
2163     {
2164       /* Allocate client entry */
2165       remote_client = silc_calloc(1, sizeof(*remote_client));
2166       remote_client->id = remote_id;
2167       silc_parse_nickname(nickname, &remote_client->nickname, 
2168                           &remote_client->server, &remote_client->num);
2169       
2170       /* Save the client to cache */
2171       silc_idcache_add(conn->client_cache, remote_client->nickname,
2172                        SILC_ID_CLIENT, remote_client->id, remote_client, 
2173                        TRUE);
2174     } else {
2175       remote_client = (SilcClientEntry)id_cache->context;
2176     }
2177
2178   /* Pass the private message to application */
2179   client->ops->private_message(client, conn, remote_client, message);
2180
2181   /* See if we are away (gone). If we are away we will reply to the
2182      sender with the set away message. */
2183   if (conn->away && conn->away->away) {
2184     /* If it's me, ignore */
2185     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2186       goto out;
2187
2188     /* Send the away message */
2189     silc_client_packet_send_private_message(client, sock, remote_client,
2190                                             conn->away->away,
2191                                             strlen(conn->away->away), TRUE);
2192   }
2193
2194  out:
2195   if (remote_id)
2196     silc_free(remote_id);
2197
2198   if (message) {
2199     memset(message, 0, buffer->len);
2200     silc_free(message);
2201   }
2202   silc_free(nickname);
2203 }
2204
2205 /* Removes a client entry from all channel it has joined. This really is
2206    a performance killer (client_entry should have pointers to channel 
2207    entry list). */
2208
2209 void silc_client_remove_from_channels(SilcClient client,
2210                                       SilcClientConnection conn,
2211                                       SilcClientEntry client_entry)
2212 {
2213   SilcIDCacheEntry id_cache;
2214   SilcIDCacheList list;
2215   SilcChannelEntry channel;
2216   SilcChannelUser chu;
2217
2218   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2219                                SILC_ID_CHANNEL, &list))
2220     return;
2221
2222   silc_idcache_list_first(list, &id_cache);
2223   channel = (SilcChannelEntry)id_cache->context;
2224   
2225   while (channel) {
2226     
2227     /* Remove client from channel */
2228     silc_list_start(channel->clients);
2229     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2230       if (chu->client == client_entry) {
2231         silc_list_del(channel->clients, chu);
2232         silc_free(chu);
2233         break;
2234       }
2235     }
2236
2237     if (!silc_idcache_list_next(list, &id_cache))
2238       break;
2239     
2240     channel = (SilcChannelEntry)id_cache->context;
2241   }
2242
2243   silc_idcache_list_free(list);
2244 }
2245
2246 /* Replaces `old' client entries from all channels to `new' client entry.
2247    This can be called for example when nickname changes and old ID entry
2248    is replaced from ID cache with the new one. If the old ID entry is only
2249    updated, then this fucntion needs not to be called. */
2250
2251 void silc_client_replace_from_channels(SilcClient client, 
2252                                        SilcClientConnection conn,
2253                                        SilcClientEntry old,
2254                                        SilcClientEntry new)
2255 {
2256   SilcIDCacheEntry id_cache;
2257   SilcIDCacheList list;
2258   SilcChannelEntry channel;
2259   SilcChannelUser chu;
2260
2261   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2262                                SILC_ID_CHANNEL, &list))
2263     return;
2264
2265   silc_idcache_list_first(list, &id_cache);
2266   channel = (SilcChannelEntry)id_cache->context;
2267   
2268   while (channel) {
2269     
2270     /* Replace client entry */
2271     silc_list_start(channel->clients);
2272     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2273       if (chu->client == old) {
2274         chu->client = new;
2275         break;
2276       }
2277     }
2278
2279     if (!silc_idcache_list_next(list, &id_cache))
2280       break;
2281     
2282     channel = (SilcChannelEntry)id_cache->context;
2283   }
2284
2285   silc_idcache_list_free(list);
2286 }
2287
2288 /* Parses mode mask and returns the mode as string. */
2289
2290 char *silc_client_chmode(unsigned int mode)
2291 {
2292   char string[20];
2293
2294   if (!mode)
2295     return NULL;
2296
2297   memset(string, 0, sizeof(string));
2298
2299   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2300     strncat(string, "p", 1);
2301
2302   if (mode & SILC_CHANNEL_MODE_SECRET)
2303     strncat(string, "s", 1);
2304
2305   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2306     strncat(string, "k", 1);
2307
2308   if (mode & SILC_CHANNEL_MODE_INVITE)
2309     strncat(string, "i", 1);
2310
2311   if (mode & SILC_CHANNEL_MODE_TOPIC)
2312     strncat(string, "t", 1);
2313
2314   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2315     strncat(string, "l", 1);
2316
2317   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2318     strncat(string, "a", 1);
2319
2320   /* Rest of mode is ignored */
2321
2322   return strdup(string);
2323 }
2324
2325 /* Parses channel user mode mask and returns te mode as string */
2326
2327 char *silc_client_chumode(unsigned int mode)
2328 {
2329   char string[4];
2330
2331   if (!mode)
2332     return NULL;
2333
2334   memset(string, 0, sizeof(string));
2335
2336   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2337     strncat(string, "f", 1);
2338
2339   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2340     strncat(string, "o", 1);
2341
2342   return strdup(string);
2343 }
2344
2345 /* Parses channel user mode and returns it as special mode character. */
2346
2347 char *silc_client_chumode_char(unsigned int mode)
2348 {
2349   char string[4];
2350
2351   if (!mode)
2352     return NULL;
2353
2354   memset(string, 0, sizeof(string));
2355
2356   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2357     strncat(string, "*", 1);
2358
2359   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2360     strncat(string, "@", 1);
2361
2362   return strdup(string);
2363 }