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