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