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->port = conn->remote_port;
275
276   /* Allocate internal Key Exchange context. This is sent to the
277      protocol as context. */
278   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
279   proto_ctx->client = (void *)client;
280   proto_ctx->sock = conn->sock;
281   proto_ctx->rng = client->rng;
282   proto_ctx->responder = FALSE;
283
284   /* Perform key exchange protocol. silc_client_connect_to_server_final
285      will be called after the protocol is finished. */
286   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
287                       &protocol, (void *)proto_ctx,
288                       silc_client_connect_to_server_second);
289   if (!protocol) {
290     client->ops->say(client, conn, 
291                      "Error: Could not start authentication protocol");
292     return FALSE;
293   }
294   conn->sock->protocol = protocol;
295
296   /* Register the connection for network input and output. This sets
297      that scheduler will listen for incoming packets for this connection 
298      and sets that outgoing packets may be sent to this connection as well.
299      However, this doesn't set the scheduler for outgoing traffic, it will 
300      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
301      later when outgoing data is available. */
302   context = (void *)client;
303   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
304
305   /* Execute the protocol */
306   protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
307   return TRUE;
308 }
309
310 /* Start of the connection to the remote server. This is called after
311    succesful TCP/IP connection has been established to the remote host. */
312
313 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
314 {
315   SilcClientInternalConnectContext *ctx =
316     (SilcClientInternalConnectContext *)context;
317   SilcClient client = ctx->client;
318   SilcClientConnection conn = ctx->conn;
319   int opt, opt_len = sizeof(opt);
320
321   SILC_LOG_DEBUG(("Start"));
322
323   /* Check the socket status as it might be in error */
324   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
325   if (opt != 0) {
326     if (ctx->tries < 2) {
327       /* Connection failed but lets try again */
328       client->ops->say(client, conn, "Could not connect to server %s: %s",
329                        ctx->host, strerror(opt));
330       client->ops->say(client, conn, 
331                        "Connecting to port %d of server %s resumed", 
332                        ctx->port, ctx->host);
333
334       /* Unregister old connection try */
335       silc_schedule_unset_listen_fd(fd);
336       silc_net_close_connection(fd);
337       silc_task_unregister(client->io_queue, ctx->task);
338
339       /* Try again */
340       silc_client_connect_to_server_internal(ctx);
341       ctx->tries++;
342     } else {
343       /* Connection failed and we won't try anymore */
344       client->ops->say(client, conn, "Could not connect to server %s: %s",
345                        ctx->host, strerror(opt));
346       silc_schedule_unset_listen_fd(fd);
347       silc_net_close_connection(fd);
348       silc_task_unregister(client->io_queue, ctx->task);
349       silc_free(ctx);
350
351       /* Notify application of failure */
352       client->ops->connect(client, conn, FALSE);
353       silc_client_del_connection(client, conn);
354     }
355     return;
356   }
357
358   silc_schedule_unset_listen_fd(fd);
359   silc_task_unregister(client->io_queue, ctx->task);
360   silc_free(ctx);
361
362   if (!silc_client_start_key_exchange(client, conn, fd)) {
363     silc_net_close_connection(fd);
364     client->ops->connect(client, conn, FALSE);
365   }
366 }
367
368 /* Second part of the connecting to the server. This executed 
369    authentication protocol. */
370
371 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
372 {
373   SilcProtocol protocol = (SilcProtocol)context;
374   SilcClientKEInternalContext *ctx = 
375     (SilcClientKEInternalContext *)protocol->context;
376   SilcClient client = (SilcClient)ctx->client;
377   SilcSocketConnection sock = NULL;
378   SilcClientConnAuthInternalContext *proto_ctx;
379
380   SILC_LOG_DEBUG(("Start"));
381
382   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
383       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
384     /* Error occured during protocol */
385     SILC_LOG_DEBUG(("Error during KE protocol"));
386     silc_protocol_free(protocol);
387     if (ctx->ske)
388       silc_ske_free(ctx->ske);
389     if (ctx->dest_id)
390       silc_free(ctx->dest_id);
391     ctx->sock->protocol = NULL;
392
393     /* Notify application of failure */
394     client->ops->connect(client, ctx->sock->user_data, FALSE);
395     silc_free(ctx);
396     return;
397   }
398
399   /* Allocate internal context for the authentication protocol. This
400      is sent as context for the protocol. */
401   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
402   proto_ctx->client = (void *)client;
403   proto_ctx->sock = sock = ctx->sock;
404   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
405   proto_ctx->dest_id_type = ctx->dest_id_type;
406   proto_ctx->dest_id = ctx->dest_id;
407
408   /* Resolve the authentication method to be used in this connection */
409   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
410                                     sock->port, &proto_ctx->auth_meth,
411                                     &proto_ctx->auth_data, 
412                                     &proto_ctx->auth_data_len))
413     {
414       /* XXX do AUTH_REQUEST resolcing with server */
415       proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
416     }
417
418   /* Free old protocol as it is finished now */
419   silc_protocol_free(protocol);
420   if (ctx->packet)
421     silc_packet_context_free(ctx->packet);
422   silc_free(ctx);
423   /* silc_free(ctx->keymat....); */
424   sock->protocol = NULL;
425
426   /* Allocate the authentication protocol. This is allocated here
427      but we won't start it yet. We will be receiving party of this
428      protocol thus we will wait that connecting party will make
429      their first move. */
430   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
431                       &sock->protocol, (void *)proto_ctx, 
432                       silc_client_connect_to_server_final);
433
434   /* Execute the protocol */
435   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
436 }
437
438 /* Finalizes the connection to the remote SILC server. This is called
439    after authentication protocol has been completed. This send our
440    user information to the server to receive our client ID from
441    server. */
442
443 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
444 {
445   SilcProtocol protocol = (SilcProtocol)context;
446   SilcClientConnAuthInternalContext *ctx = 
447     (SilcClientConnAuthInternalContext *)protocol->context;
448   SilcClient client = (SilcClient)ctx->client;
449   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
450   SilcBuffer packet;
451
452   SILC_LOG_DEBUG(("Start"));
453
454   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
455       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
456     /* Error occured during protocol */
457     SILC_LOG_DEBUG(("Error during authentication protocol"));
458     silc_protocol_free(protocol);
459     if (ctx->auth_data)
460       silc_free(ctx->auth_data);
461     if (ctx->ske)
462       silc_ske_free(ctx->ske);
463     if (ctx->dest_id)
464       silc_free(ctx->dest_id);
465     conn->sock->protocol = NULL;
466
467     /* Notify application of failure */
468     client->ops->connect(client, ctx->sock->user_data, FALSE);
469     silc_free(ctx);
470     return;
471   }
472
473   /* Send NEW_CLIENT packet to the server. We will become registered
474      to the SILC network after sending this packet and we will receive
475      client ID from the server. */
476   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
477                              strlen(client->realname));
478   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
479   silc_buffer_format(packet,
480                      SILC_STR_UI_SHORT(strlen(client->username)),
481                      SILC_STR_UI_XNSTRING(client->username,
482                                           strlen(client->username)),
483                      SILC_STR_UI_SHORT(strlen(client->realname)),
484                      SILC_STR_UI_XNSTRING(client->realname,
485                                           strlen(client->realname)),
486                      SILC_STR_END);
487
488   /* Send the packet */
489   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
490                           NULL, 0, NULL, NULL, 
491                           packet->data, packet->len, TRUE);
492   silc_buffer_free(packet);
493
494   /* Save remote ID. */
495   conn->remote_id = ctx->dest_id;
496   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
497   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
498
499   silc_protocol_free(protocol);
500   if (ctx->auth_data)
501     silc_free(ctx->auth_data);
502   if (ctx->ske)
503     silc_ske_free(ctx->ske);
504   silc_free(ctx);
505   conn->sock->protocol = NULL;
506 }
507
508 /* Internal routine that sends packet or marks packet to be sent. This
509    is used directly only in special cases. Normal cases should use
510    silc_server_packet_send. Returns < 0 on error. */
511
512 static int silc_client_packet_send_real(SilcClient client,
513                                         SilcSocketConnection sock,
514                                         int force_send)
515 {
516   int ret;
517
518   /* Send the packet */
519   ret = silc_packet_send(sock, force_send);
520   if (ret != -2)
521     return ret;
522
523   /* Mark that there is some outgoing data available for this connection. 
524      This call sets the connection both for input and output (the input
525      is set always and this call keeps the input setting, actually). 
526      Actual data sending is performed by silc_client_packet_process. */
527   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
528
529   /* Mark to socket that data is pending in outgoing buffer. This flag
530      is needed if new data is added to the buffer before the earlier
531      put data is sent to the network. */
532   SILC_SET_OUTBUF_PENDING(sock);
533
534   return 0;
535 }
536
537 /* Packet processing callback. This is used to send and receive packets
538    from network. This is generic task. */
539
540 SILC_TASK_CALLBACK(silc_client_packet_process)
541 {
542   SilcClient client = (SilcClient)context;
543   SilcSocketConnection sock = NULL;
544   SilcClientConnection conn;
545   int ret;
546
547   SILC_LOG_DEBUG(("Processing packet"));
548
549   SILC_CLIENT_GET_SOCK(client, fd, sock);
550   if (sock == NULL)
551     return;
552
553   conn = (SilcClientConnection)sock->user_data;
554
555   /* Packet sending */
556   if (type == SILC_TASK_WRITE) {
557     SILC_LOG_DEBUG(("Writing data to connection"));
558
559     if (sock->outbuf->data - sock->outbuf->head)
560       silc_buffer_push(sock->outbuf, 
561                        sock->outbuf->data - sock->outbuf->head);
562
563     ret = silc_client_packet_send_real(client, sock, TRUE);
564
565     /* If returned -2 could not write to connection now, will do
566        it later. */
567     if (ret == -2)
568       return;
569     
570     /* The packet has been sent and now it is time to set the connection
571        back to only for input. When there is again some outgoing data 
572        available for this connection it will be set for output as well. 
573        This call clears the output setting and sets it only for input. */
574     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
575     SILC_UNSET_OUTBUF_PENDING(sock);
576
577     silc_buffer_clear(sock->outbuf);
578     return;
579   }
580
581   /* Packet receiving */
582   if (type == SILC_TASK_READ) {
583     SILC_LOG_DEBUG(("Reading data from connection"));
584
585     /* Read data from network */
586     ret = silc_packet_receive(sock);
587     if (ret < 0)
588       return;
589     
590     /* EOF */
591     if (ret == 0) {
592       SILC_LOG_DEBUG(("Read EOF"));
593
594       /* If connection is disconnecting already we will finally
595          close the connection */
596       if (SILC_IS_DISCONNECTING(sock)) {
597         client->ops->disconnect(client, conn);
598         silc_client_close_connection(client, sock);
599         return;
600       }
601       
602       client->ops->say(client, conn, "Connection closed: premature EOF");
603       SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
604       client->ops->disconnect(client, conn);
605       silc_client_close_connection(client, sock);
606       return;
607     }
608
609     /* Process the packet. This will call the parser that will then
610        decrypt and parse the packet. */
611     silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
612                                 silc_client_packet_parse, client);
613   }
614 }
615
616 /* Parses whole packet, received earlier. */
617
618 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
619 {
620   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
621   SilcClient client = (SilcClient)parse_ctx->context;
622   SilcPacketContext *packet = parse_ctx->packet;
623   SilcBuffer buffer = packet->buffer;
624   SilcSocketConnection sock = parse_ctx->sock;
625   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
626   int ret;
627
628   SILC_LOG_DEBUG(("Start"));
629
630   /* Decrypt the received packet */
631   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
632   if (ret < 0)
633     goto out;
634
635   if (ret == 0) {
636     /* Parse the packet. Packet type is returned. */
637     ret = silc_packet_parse(packet);
638   } else {
639     /* Parse the packet header in special way as this is "special"
640        packet type. */
641     ret = silc_packet_parse_special(packet);
642   }
643
644   if (ret == SILC_PACKET_NONE)
645     goto out;
646
647   /* Parse the incoming packet type */
648   silc_client_packet_parse_type(client, sock, packet);
649
650  out:
651   silc_buffer_clear(sock->inbuf);
652   silc_packet_context_free(packet);
653   silc_free(parse_ctx);
654 }
655
656 /* Parser callback called by silc_packet_receive_process. Thie merely
657    registers timeout that will handle the actual parsing when appropriate. */
658
659 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
660 {
661   SilcClient client = (SilcClient)parser_context->context;
662
663   /* Parse the packet */
664   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
665                      silc_client_packet_parse_real,
666                      (void *)parser_context, 0, 1, 
667                      SILC_TASK_TIMEOUT,
668                      SILC_TASK_PRI_NORMAL);
669 }
670   
671 /* Parses the packet type and calls what ever routines the packet type
672    requires. This is done for all incoming packets. */
673
674 void silc_client_packet_parse_type(SilcClient client, 
675                                    SilcSocketConnection sock,
676                                    SilcPacketContext *packet)
677 {
678   SilcBuffer buffer = packet->buffer;
679   SilcPacketType type = packet->type;
680
681   SILC_LOG_DEBUG(("Parsing packet type %d", type));
682
683   /* Parse the packet type */
684   switch(type) {
685   case SILC_PACKET_DISCONNECT:
686     silc_client_disconnected_by_server(client, sock, buffer);
687     break;
688   case SILC_PACKET_SUCCESS:
689     /*
690      * Success received for something. For now we can have only
691      * one protocol for connection executing at once hence this
692      * success message is for whatever protocol is executing currently.
693      */
694     if (sock->protocol) {
695       sock->protocol->execute(client->timeout_queue, 0,
696                               sock->protocol, sock->sock, 0, 0);
697     }
698     break;
699   case SILC_PACKET_FAILURE:
700     /*
701      * Failure received for some protocol. Set the protocol state to 
702      * error and call the protocol callback. This fill cause error on
703      * protocol and it will call the final callback.
704      */
705     if (sock->protocol) {
706       sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
707       sock->protocol->execute(client->timeout_queue, 0,
708                               sock->protocol, sock->sock, 0, 0);
709
710       /* XXX We have only two protocols currently thus we know what this
711          failure indication is. */
712       if (buffer->len >= 4) {
713         unsigned int failure;
714
715         SILC_GET32_MSB(failure, buffer->data);
716
717         /* Notify application */
718         client->ops->failure(client, sock->user_data, sock->protocol,
719                              (void *)failure);
720       }
721     }
722     break;
723   case SILC_PACKET_REJECT:
724     break;
725
726   case SILC_PACKET_NOTIFY:
727     /*
728      * Received notify message 
729      */
730     silc_client_notify_by_server(client, sock, packet);
731     break;
732
733   case SILC_PACKET_ERROR:
734     /*
735      * Received error message
736      */
737     silc_client_error_by_server(client, sock, buffer);
738     break;
739
740   case SILC_PACKET_CHANNEL_MESSAGE:
741     /*
742      * Received message to (from, actually) a channel
743      */
744     silc_client_channel_message(client, sock, packet);
745     break;
746   case SILC_PACKET_CHANNEL_KEY:
747     /*
748      * Received key for a channel. By receiving this key the client will be
749      * able to talk to the channel it has just joined. This can also be
750      * a new key for existing channel as keys expire peridiocally.
751      */
752     silc_client_receive_channel_key(client, sock, buffer);
753     break;
754
755   case SILC_PACKET_PRIVATE_MESSAGE:
756     /*
757      * Received private message
758      */
759     silc_client_private_message(client, sock, packet);
760     break;
761   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
762     /*
763      * Received private message key
764      */
765     break;
766
767   case SILC_PACKET_COMMAND_REPLY:
768     /*
769      * Recived reply for a command
770      */
771     silc_client_command_reply_process(client, sock, packet);
772     break;
773
774   case SILC_PACKET_KEY_EXCHANGE:
775     if (sock->protocol) {
776       SilcClientKEInternalContext *proto_ctx = 
777         (SilcClientKEInternalContext *)sock->protocol->context;
778
779       proto_ctx->packet = silc_packet_context_dup(packet);
780       proto_ctx->dest_id_type = packet->src_id_type;
781       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
782                                           packet->src_id_type);
783       if (!proto_ctx->dest_id)
784         break;
785
786       /* Let the protocol handle the packet */
787       sock->protocol->execute(client->timeout_queue, 0,
788                               sock->protocol, sock->sock, 0, 0);
789     } else {
790       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
791                       "protocol active, packet dropped."));
792
793       /* XXX Trigger KE protocol?? Rekey actually! */
794     }
795     break;
796
797   case SILC_PACKET_KEY_EXCHANGE_1:
798     if (sock->protocol) {
799
800     } else {
801       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
802                       "protocol active, packet dropped."));
803     }
804     break;
805   case SILC_PACKET_KEY_EXCHANGE_2:
806     if (sock->protocol) {
807       SilcClientKEInternalContext *proto_ctx = 
808         (SilcClientKEInternalContext *)sock->protocol->context;
809
810       if (proto_ctx->packet)
811         silc_packet_context_free(proto_ctx->packet);
812
813       proto_ctx->packet = silc_packet_context_dup(packet);
814       proto_ctx->dest_id_type = packet->src_id_type;
815       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
816                                           packet->src_id_type);
817       if (!proto_ctx->dest_id)
818         break;
819
820       /* Let the protocol handle the packet */
821       sock->protocol->execute(client->timeout_queue, 0,
822                               sock->protocol, sock->sock, 0, 0);
823     } else {
824       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
825                       "protocol active, packet dropped."));
826     }
827     break;
828
829   case SILC_PACKET_NEW_ID:
830     {
831       /*
832        * Received new ID from server. This packet is received at
833        * the connection to the server.  New ID is also received when 
834        * user changes nickname but in that case the new ID is received
835        * as command reply and not as this packet type.
836        */
837       SilcIDPayload idp;
838
839       idp = silc_id_payload_parse(buffer);
840       if (!idp)
841         break;
842       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
843         break;
844
845       silc_client_receive_new_id(client, sock, idp);
846       silc_id_payload_free(idp);
847       break;
848     }
849
850   case SILC_PACKET_HEARTBEAT:
851     /*
852      * Received heartbeat packet
853      */
854     SILC_LOG_DEBUG(("Heartbeat packet"));
855     break;
856
857   default:
858     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
859     break;
860   }
861 }
862
863 /* Sends packet. This doesn't actually send the packet instead it assembles
864    it and marks it to be sent. However, if force_send is TRUE the packet
865    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
866    will be derived from sock argument. Otherwise the valid arguments sent
867    are used. */
868
869 void silc_client_packet_send(SilcClient client, 
870                              SilcSocketConnection sock,
871                              SilcPacketType type, 
872                              void *dst_id,
873                              SilcIdType dst_id_type,
874                              SilcCipher cipher,
875                              SilcHmac hmac,
876                              unsigned char *data, 
877                              unsigned int data_len, 
878                              int force_send)
879 {
880   SilcPacketContext packetdata;
881
882   SILC_LOG_DEBUG(("Sending packet, type %d", type));
883
884   /* Get data used in the packet sending, keys and stuff */
885   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
886     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
887       cipher = ((SilcClientConnection)sock->user_data)->send_key;
888
889     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
890       hmac = ((SilcClientConnection)sock->user_data)->hmac;
891
892     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
893       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
894       dst_id_type = SILC_ID_SERVER;
895     }
896   }
897
898   /* Set the packet context pointers */
899   packetdata.flags = 0;
900   packetdata.type = type;
901   if (((SilcClientConnection)sock->user_data)->local_id_data)
902     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
903   else 
904     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
905   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
906   packetdata.src_id_type = SILC_ID_CLIENT;
907   if (dst_id) {
908     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
909     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
910     packetdata.dst_id_type = dst_id_type;
911   } else {
912     packetdata.dst_id = NULL;
913     packetdata.dst_id_len = 0;
914     packetdata.dst_id_type = SILC_ID_NONE;
915   }
916   packetdata.rng = client->rng;
917   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
918     packetdata.src_id_len + packetdata.dst_id_len;
919   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
920
921   /* Prepare outgoing data buffer for packet sending */
922   silc_packet_send_prepare(sock, 
923                            SILC_PACKET_HEADER_LEN +
924                            packetdata.src_id_len + 
925                            packetdata.dst_id_len,
926                            packetdata.padlen,
927                            data_len);
928
929   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
930
931   packetdata.buffer = sock->outbuf;
932
933   /* Put the data to the buffer */
934   if (data && data_len)
935     silc_buffer_put(sock->outbuf, data, data_len);
936
937   /* Create the outgoing packet */
938   silc_packet_assemble(&packetdata);
939
940   /* Encrypt the packet */
941   if (cipher)
942     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
943
944   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
945                    sock->outbuf->data, sock->outbuf->len);
946
947   /* Now actually send the packet */
948   silc_client_packet_send_real(client, sock, force_send);
949 }
950
951 /* Sends packet to a channel. Packet to channel is always encrypted
952    differently from "normal" packets. SILC header of the packet is 
953    encrypted with the next receiver's key and the rest of the packet is
954    encrypted with the channel specific key. Padding and HMAC is computed
955    with the next receiver's key. */
956
957 void silc_client_packet_send_to_channel(SilcClient client, 
958                                         SilcSocketConnection sock,
959                                         SilcChannelEntry channel,
960                                         unsigned char *data, 
961                                         unsigned int data_len, 
962                                         int force_send)
963 {
964   int i;
965   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
966   SilcBuffer payload;
967   SilcPacketContext packetdata;
968   SilcCipher cipher;
969   SilcHmac hmac;
970   unsigned char *id_string;
971
972   SILC_LOG_DEBUG(("Sending packet to channel"));
973
974   if (!channel || !channel->key) {
975     client->ops->say(client, conn, 
976                      "Cannot talk to channel: key does not exist");
977     return;
978   }
979
980   /* Generate IV */
981   if (!channel->iv)
982     for (i = 0; i < 16; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
983   else
984     silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
985
986   /* Encode the channel payload */
987   payload = silc_channel_payload_encode(data_len, data, 16, channel->iv, 
988                                         client->rng);
989   if (!payload) {
990     client->ops->say(client, conn, 
991                      "Error: Could not create packet to be sent to channel");
992     return;
993   }
994
995   /* Get data used in packet header encryption, keys and stuff. Rest
996      of the packet (the payload) is, however, encrypted with the 
997      specified channel key. */
998   cipher = conn->send_key;
999   hmac = conn->hmac;
1000   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1001
1002   /* Set the packet context pointers. The destination ID is always
1003      the Channel ID of the channel. Server and router will handle the
1004      distribution of the packet. */
1005   packetdata.flags = 0;
1006   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1007   packetdata.src_id = conn->local_id_data;
1008   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1009   packetdata.src_id_type = SILC_ID_CLIENT;
1010   packetdata.dst_id = id_string;
1011   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1012   packetdata.dst_id_type = SILC_ID_CHANNEL;
1013   packetdata.rng = client->rng;
1014   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
1015     packetdata.src_id_len + packetdata.dst_id_len;
1016   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1017                                           packetdata.src_id_len +
1018                                           packetdata.dst_id_len));
1019
1020   /* Prepare outgoing data buffer for packet sending */
1021   silc_packet_send_prepare(sock, 
1022                            SILC_PACKET_HEADER_LEN +
1023                            packetdata.src_id_len + 
1024                            packetdata.dst_id_len,
1025                            packetdata.padlen,
1026                            payload->len);
1027
1028   packetdata.buffer = sock->outbuf;
1029
1030   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1031   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1032                                         payload->data, payload->data,
1033                                         payload->len - 16, /* -IV_LEN */
1034                                         channel->iv);
1035
1036   /* Put the actual encrypted payload data into the buffer. */
1037   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1038
1039   /* Create the outgoing packet */
1040   silc_packet_assemble(&packetdata);
1041
1042   /* Encrypt the header and padding of the packet. This is encrypted 
1043      with normal session key shared with our server. */
1044   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1045                       packetdata.src_id_len + packetdata.dst_id_len +
1046                       packetdata.padlen);
1047
1048   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1049                    sock->outbuf->data, sock->outbuf->len);
1050
1051   /* Now actually send the packet */
1052   silc_client_packet_send_real(client, sock, force_send);
1053   silc_buffer_free(payload);
1054   silc_free(id_string);
1055 }
1056
1057 /* Sends private message to remote client. If private message key has
1058    not been set with this client then the message will be encrypted using
1059    normal session keys. Private messages are special packets in SILC
1060    network hence we need this own function for them. This is similiar
1061    to silc_client_packet_send_to_channel except that we send private
1062    message. */
1063
1064 void silc_client_packet_send_private_message(SilcClient client,
1065                                              SilcSocketConnection sock,
1066                                              SilcClientEntry client_entry,
1067                                              unsigned char *data, 
1068                                              unsigned int data_len, 
1069                                              int force_send)
1070 {
1071   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1072   SilcBuffer buffer;
1073   SilcPacketContext packetdata;
1074   unsigned int nick_len;
1075   SilcCipher cipher;
1076   SilcHmac hmac;
1077
1078   SILC_LOG_DEBUG(("Sending private message"));
1079
1080   /* Create private message payload */
1081   nick_len = strlen(conn->nickname);
1082   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1083   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1084   silc_buffer_format(buffer,
1085                      SILC_STR_UI_SHORT(nick_len),
1086                      SILC_STR_UI_XNSTRING(conn->nickname,
1087                                           nick_len),
1088                      SILC_STR_UI_XNSTRING(data, data_len),
1089                      SILC_STR_END);
1090
1091   /* If we don't have private message specific key then private messages
1092      are just as any normal packet thus call normal packet sending.  If
1093      the key exist then the encryption process is a bit different and
1094      will be done in the rest of this function. */
1095   if (!client_entry->send_key) {
1096     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1097                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1098                             buffer->data, buffer->len, force_send);
1099     goto out;
1100   }
1101
1102   /* We have private message specific key */
1103
1104   /* Get data used in the encryption */
1105   cipher = client_entry->send_key;
1106   hmac = conn->hmac;
1107
1108   /* Set the packet context pointers. */
1109   packetdata.flags = 0;
1110   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1111   packetdata.src_id = conn->local_id_data;
1112   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1113   packetdata.src_id_type = SILC_ID_CLIENT;
1114   if (client_entry)
1115     packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1116   else
1117     packetdata.dst_id = conn->local_id_data;
1118   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1119   packetdata.dst_id_type = SILC_ID_CLIENT;
1120   packetdata.rng = client->rng;
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                    sock->hostname : sock->ip);
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 }