update.
[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   silc_packet_context_free(p);
1285 }
1286
1287 /* Received notify message from server */
1288
1289 void silc_client_notify_by_server(SilcClient client,
1290                                   SilcSocketConnection sock,
1291                                   SilcPacketContext *packet)
1292 {
1293   SilcBuffer buffer = packet->buffer;
1294   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1295   SilcNotifyPayload payload;
1296   SilcNotifyType type;
1297   SilcArgumentPayload args;
1298
1299   SilcClientID *client_id = NULL;
1300   SilcChannelID *channel_id = NULL;
1301   SilcClientEntry client_entry;
1302   SilcClientEntry client_entry2;
1303   SilcChannelEntry channel;
1304   SilcChannelUser chu;
1305   SilcIDCacheEntry id_cache = NULL;
1306   unsigned char *tmp;
1307   unsigned int tmp_len, mode;
1308
1309   payload = silc_notify_payload_parse(buffer);
1310   if (!payload)
1311     goto out;
1312
1313   type = silc_notify_get_type(payload);
1314   args = silc_notify_get_args(payload);
1315   if (!args)
1316     goto out;
1317
1318   switch(type) {
1319   case SILC_NOTIFY_TYPE_NONE:
1320     /* Notify application */
1321     client->ops->notify(client, conn, type, 
1322                         silc_argument_get_arg_type(args, 1, NULL));
1323     break;
1324
1325   case SILC_NOTIFY_TYPE_INVITE:
1326     /* 
1327      * Someone invited me to a channel. Find Client and Channel entries
1328      * for the application.
1329      */
1330     
1331     /* Get Client ID */
1332     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1333     if (!tmp)
1334       goto out;
1335
1336     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1337     if (!client_id)
1338       goto out;
1339
1340     /* Find Client entry and if not found query it */
1341     client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1342     if (!client_entry) {
1343       SilcPacketContext *p = silc_packet_context_dup(packet);
1344       p->context = (void *)client;
1345       p->sock = sock;
1346       silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
1347                                   silc_client_notify_by_server_pending, p);
1348       goto out;
1349     }
1350
1351     /* Get Channel ID */
1352     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1353     if (!tmp)
1354       goto out;
1355
1356     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1357     if (!channel_id)
1358       goto out;
1359
1360     /* XXX Will ALWAYS fail because currently we don't have way to resolve
1361        channel information for channel that we're not joined to. */
1362     /* XXX ways to fix: use (extended) LIST command, or define the channel
1363        name to the notfy type when name resolving is not mandatory. */
1364     /* Find channel entry */
1365     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1366                                      SILC_ID_CHANNEL, &id_cache))
1367       goto out;
1368
1369     channel = (SilcChannelEntry)id_cache->context;
1370
1371     /* Notify application */
1372     client->ops->notify(client, conn, type, client_entry, channel);
1373     break;
1374
1375   case SILC_NOTIFY_TYPE_JOIN:
1376     /*
1377      * Someone has joined to a channel. Get their ID and nickname and
1378      * cache them for later use.
1379      */
1380
1381     /* Get Client ID */
1382     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1383     if (!tmp)
1384       goto out;
1385
1386     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1387     if (!client_id)
1388       goto out;
1389
1390     /* Find Client entry and if not found query it */
1391     client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1392     if (!client_entry) {
1393       SilcPacketContext *p = silc_packet_context_dup(packet);
1394       p->context = (void *)client;
1395       p->sock = sock;
1396       silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT, 
1397                                   silc_client_notify_by_server_pending, p);
1398       goto out;
1399     }
1400
1401     /* If nickname or username hasn't been resolved, do so */
1402     if (!client_entry->nickname || !client_entry->username) {
1403       SilcPacketContext *p = silc_packet_context_dup(packet);
1404       SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1405       silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, 
1406                                SILC_IDLIST_IDENT, 1, 
1407                                3, idp->data, idp->len);
1408       p->context = (void *)client;
1409       p->sock = sock;
1410       silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT, 
1411                                   silc_client_notify_by_server_pending, p);
1412       goto out;
1413     }
1414
1415     /* Get channel entry */
1416     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1417                                 SILC_ID_CHANNEL);
1418     if (!channel_id)
1419       goto out;
1420     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1421                                      SILC_ID_CHANNEL, &id_cache))
1422       break;
1423
1424     channel = (SilcChannelEntry)id_cache->context;
1425
1426     /* Add client to channel */
1427     chu = silc_calloc(1, sizeof(*chu));
1428     chu->client = client_entry;
1429     silc_list_add(channel->clients, chu);
1430
1431     /* XXX add support for multiple same nicks on same channel. Check
1432        for them here */
1433
1434     /* Notify application. The channel entry is sent last as this notify
1435        is for channel but application don't know it from the arguments
1436        sent by server. */
1437     client->ops->notify(client, conn, type, client_entry, channel);
1438     break;
1439
1440   case SILC_NOTIFY_TYPE_LEAVE:
1441     /*
1442      * Someone has left a channel. We will remove it from the channel but
1443      * we'll keep it in the cache in case we'll need it later.
1444      */
1445     
1446     /* Get Client ID */
1447     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1448     if (!tmp)
1449       goto out;
1450
1451     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1452     if (!client_id)
1453       goto out;
1454
1455     /* Find Client entry */
1456     client_entry = 
1457       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1458     if (!client_entry)
1459       goto out;
1460
1461     /* Get channel entry */
1462     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1463                                 SILC_ID_CHANNEL);
1464     if (!channel_id)
1465       goto out;
1466     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1467                                      SILC_ID_CHANNEL, &id_cache))
1468       break;
1469
1470     channel = (SilcChannelEntry)id_cache->context;
1471
1472     /* Remove client from channel */
1473     silc_list_start(channel->clients);
1474     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1475       if (chu->client == client_entry) {
1476         silc_list_del(channel->clients, chu);
1477         silc_free(chu);
1478         break;
1479       }
1480     }
1481
1482     /* Notify application. The channel entry is sent last as this notify
1483        is for channel but application don't know it from the arguments
1484        sent by server. */
1485     client->ops->notify(client, conn, type, client_entry, channel);
1486     break;
1487
1488   case SILC_NOTIFY_TYPE_SIGNOFF:
1489     /*
1490      * Someone left SILC. We'll remove it from all channels and from cache.
1491      */
1492
1493     /* Get Client ID */
1494     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1495     if (!tmp)
1496       goto out;
1497
1498     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1499     if (!client_id)
1500       goto out;
1501
1502     /* Find Client entry */
1503     client_entry = 
1504       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1505     if (!client_entry)
1506       goto out;
1507
1508     /* Remove from all channels */
1509     silc_client_remove_from_channels(client, conn, client_entry);
1510
1511     /* Remove from cache */
1512     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1513                            client_entry->id);
1514
1515     /* Notify application */
1516     client->ops->notify(client, conn, type, client_entry);
1517
1518     /* Free data */
1519     if (client_entry->nickname)
1520       silc_free(client_entry->nickname);
1521     if (client_entry->server)
1522       silc_free(client_entry->server);
1523     if (client_entry->id)
1524       silc_free(client_entry->id);
1525     if (client_entry->send_key)
1526       silc_cipher_free(client_entry->send_key);
1527     if (client_entry->receive_key)
1528       silc_cipher_free(client_entry->receive_key);
1529     break;
1530
1531   case SILC_NOTIFY_TYPE_TOPIC_SET:
1532     /*
1533      * Someone set the topic on a channel.
1534      */
1535
1536     /* Get Client ID */
1537     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1538     if (!tmp)
1539       goto out;
1540
1541     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1542     if (!client_id)
1543       goto out;
1544
1545     /* Find Client entry */
1546     client_entry = 
1547       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1548     if (!client_entry)
1549       goto out;
1550
1551     /* Get topic */
1552     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1553     if (!tmp)
1554       goto out;
1555
1556     /* Get channel entry */
1557     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1558                                 SILC_ID_CHANNEL);
1559     if (!channel_id)
1560       goto out;
1561     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1562                                      SILC_ID_CHANNEL, &id_cache))
1563       break;
1564
1565     channel = (SilcChannelEntry)id_cache->context;
1566
1567     /* Notify application. The channel entry is sent last as this notify
1568        is for channel but application don't know it from the arguments
1569        sent by server. */
1570     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1571     break;
1572
1573   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1574     /*
1575      * Someone changed their nickname. If we don't have entry for the new
1576      * ID we will query it and return here after it's done. After we've
1577      * returned we fetch the old entry and free it and notify the 
1578      * application.
1579      */
1580
1581     /* Get new Client ID */
1582     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1583     if (!tmp)
1584       goto out;
1585
1586     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1587     if (!client_id)
1588       goto out;
1589
1590     /* Ignore my ID */
1591     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1592       break;
1593
1594     /* Find Client entry and if not found query it */
1595     client_entry2 = 
1596       silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1597     if (!client_entry2) {
1598       SilcPacketContext *p = silc_packet_context_dup(packet);
1599       p->context = (void *)client;
1600       p->sock = sock;
1601       silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
1602                                   silc_client_notify_by_server_pending, p);
1603       goto out;
1604     }
1605     silc_free(client_id);
1606
1607     /* Get old Client ID */
1608     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1609     if (!tmp)
1610       goto out;
1611
1612     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1613     if (!client_id)
1614       goto out;
1615
1616     /* Find old Client entry */
1617     client_entry = 
1618       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1619     if (!client_entry)
1620       goto out;
1621
1622     /* Remove the old from cache */
1623     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1624                            client_entry->id);
1625
1626     /* Replace old ID entry with new one on all channels. */
1627     silc_client_replace_from_channels(client, conn, client_entry,
1628                                       client_entry2);
1629
1630     /* Notify application */
1631     client->ops->notify(client, conn, type, client_entry, client_entry2);
1632
1633     /* Free data */
1634     if (client_entry->nickname)
1635       silc_free(client_entry->nickname);
1636     if (client_entry->server)
1637       silc_free(client_entry->server);
1638     if (client_entry->id)
1639       silc_free(client_entry->id);
1640     if (client_entry->send_key)
1641       silc_cipher_free(client_entry->send_key);
1642     if (client_entry->receive_key)
1643       silc_cipher_free(client_entry->receive_key);
1644     break;
1645
1646   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1647     /*
1648      * Someone changed a channel mode
1649      */
1650
1651     /* Get Client ID */
1652     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1653     if (!tmp)
1654       goto out;
1655
1656     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1657     if (!client_id)
1658       goto out;
1659
1660     /* Find Client entry */
1661     client_entry = 
1662       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1663     if (!client_entry)
1664       goto out;
1665
1666     /* Get the mode */
1667     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1668     if (!tmp)
1669       goto out;
1670
1671     SILC_GET32_MSB(mode, tmp);
1672
1673     /* Get channel entry */
1674     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1675                                 SILC_ID_CHANNEL);
1676     if (!channel_id)
1677       goto out;
1678     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1679                                      SILC_ID_CHANNEL, &id_cache))
1680       break;
1681
1682     channel = (SilcChannelEntry)id_cache->context;
1683
1684     /* Save the new mode */
1685     channel->mode = mode;
1686
1687     /* Notify application. The channel entry is sent last as this notify
1688        is for channel but application don't know it from the arguments
1689        sent by server. */
1690     client->ops->notify(client, conn, type, client_entry, mode, channel);
1691     break;
1692
1693   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1694     /*
1695      * Someone changed user's mode on a channel
1696      */
1697
1698     /* Get Client ID */
1699     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1700     if (!tmp)
1701       goto out;
1702
1703     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1704     if (!client_id)
1705       goto out;
1706
1707     /* Find Client entry */
1708     client_entry = 
1709       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1710     if (!client_entry)
1711       goto out;
1712
1713     /* Get the mode */
1714     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1715     if (!tmp)
1716       goto out;
1717
1718     SILC_GET32_MSB(mode, tmp);
1719
1720     /* Get target Client ID */
1721     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1722     if (!tmp)
1723       goto out;
1724
1725     silc_free(client_id);
1726     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1727     if (!client_id)
1728       goto out;
1729
1730     /* Find target Client entry */
1731     client_entry2 = 
1732       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1733     if (!client_entry2)
1734       goto out;
1735
1736     /* Get channel entry */
1737     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1738                                 SILC_ID_CHANNEL);
1739     if (!channel_id)
1740       goto out;
1741     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1742                                      SILC_ID_CHANNEL, &id_cache))
1743       break;
1744
1745     channel = (SilcChannelEntry)id_cache->context;
1746
1747     /* Save the mode */
1748     silc_list_start(channel->clients);
1749     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1750       if (chu->client == client_entry) {
1751         chu->mode = mode;
1752         break;
1753       }
1754     }
1755
1756     /* Notify application. The channel entry is sent last as this notify
1757        is for channel but application don't know it from the arguments
1758        sent by server. */
1759     client->ops->notify(client, conn, type, client_entry, mode, 
1760                         client_entry2, channel);
1761     break;
1762
1763   case SILC_NOTIFY_TYPE_MOTD:
1764     /*
1765      * Received Message of the day
1766      */
1767
1768     /* Get motd */
1769     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1770     if (!tmp)
1771       goto out;
1772     
1773     /* Notify application */
1774     client->ops->notify(client, conn, type, tmp);
1775     break;
1776
1777   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1778     /*
1779      * Router has enforced a new ID to a channel. Let's change the old
1780      * ID to the one provided here.
1781      */
1782
1783     /* Get the old ID */
1784     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1785     if (!tmp)
1786       goto out;
1787     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1788     if (!channel_id)
1789       goto out;
1790     
1791     /* Get the channel entry */
1792     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1793                                      SILC_ID_CHANNEL, &id_cache))
1794       break;
1795
1796     channel = (SilcChannelEntry)id_cache->context;
1797
1798     /* Free the old ID */
1799     silc_free(channel_id);
1800     silc_free(channel->id);
1801
1802     /* Get the new ID */
1803     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1804     if (!tmp)
1805       goto out;
1806     channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1807     if (!channel->id)
1808       goto out;
1809
1810     id_cache->id = (void *)channel->id;
1811
1812     /* Notify application */
1813     client->ops->notify(client, conn, type, channel, channel);
1814     break;
1815     
1816   default:
1817     break;
1818   }
1819
1820  out:
1821   silc_notify_payload_free(payload);
1822   if (client_id)
1823     silc_free(client_id);
1824   if (channel_id)
1825     silc_free(channel_id);
1826 }
1827
1828 /* Processes the received new Client ID from server. Old Client ID is
1829    deleted from cache and new one is added. */
1830
1831 void silc_client_receive_new_id(SilcClient client,
1832                                 SilcSocketConnection sock,
1833                                 SilcIDPayload idp)
1834 {
1835   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1836
1837   /* Delete old ID from ID cache */
1838   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1839   
1840   /* Save the new ID */
1841   if (conn->local_id)
1842     silc_free(conn->local_id);
1843   if (conn->local_id_data)
1844     silc_free(conn->local_id_data);
1845
1846   conn->local_id = silc_id_payload_get_id(idp);
1847   conn->local_id_data = silc_id_payload_get_data(idp);
1848   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1849
1850   if (!conn->local_entry)
1851     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1852
1853   conn->local_entry->nickname = conn->nickname;
1854   if (!conn->local_entry->username) {
1855     conn->local_entry->username = 
1856       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1857                   sizeof(conn->local_entry->username));
1858     sprintf(conn->local_entry->username, "%s@%s", client->username,
1859             client->hostname);
1860   }
1861   conn->local_entry->server = strdup(conn->remote_host);
1862   conn->local_entry->id = conn->local_id;
1863   
1864   /* Put it to the ID cache */
1865   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1866                    conn->local_id, (void *)conn->local_entry, TRUE);
1867
1868   /* Notify application of successful connection. We do it here now that
1869      we've received the Client ID and are allowed to send traffic. */
1870   client->ops->connect(client, conn, TRUE);
1871 }
1872
1873 /* Processed received Channel ID for a channel. This is called when client
1874    joins to channel and server replies with channel ID. The ID is cached. */
1875
1876 void silc_client_new_channel_id(SilcClient client,
1877                                 SilcSocketConnection sock,
1878                                 char *channel_name,
1879                                 unsigned int mode, SilcIDPayload idp)
1880 {
1881   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1882   SilcChannelEntry channel;
1883
1884   SILC_LOG_DEBUG(("New channel ID"));
1885
1886   channel = silc_calloc(1, sizeof(*channel));
1887   channel->channel_name = channel_name;
1888   channel->id = silc_id_payload_get_id(idp);
1889   channel->mode = mode;
1890   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1891
1892   conn->current_channel = channel;
1893
1894   /* Put it to the ID cache */
1895   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1896                    (void *)channel->id, (void *)channel, TRUE);
1897 }
1898
1899 /* Saves channel key from encoded `key_payload'. This is used when we
1900    receive Channel Key Payload and when we are processing JOIN command 
1901    reply. */
1902
1903 void silc_client_save_channel_key(SilcClientConnection conn,
1904                                   SilcBuffer key_payload, 
1905                                   SilcChannelEntry channel)
1906 {
1907   unsigned char *id_string, *key, *cipher;
1908   unsigned int tmp_len;
1909   SilcChannelID *id;
1910   SilcIDCacheEntry id_cache = NULL;
1911   SilcChannelKeyPayload payload;
1912
1913   payload = silc_channel_key_payload_parse(key_payload);
1914   if (!payload)
1915     return;
1916
1917   id_string = silc_channel_key_get_id(payload, &tmp_len);
1918   if (!id_string) {
1919     silc_channel_key_payload_free(payload);
1920     return;
1921   }
1922
1923   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
1924   if (!id) {
1925     silc_channel_key_payload_free(payload);
1926     return;
1927   }
1928
1929   /* Find channel. */
1930   if (!channel) {
1931     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1932                                      SILC_ID_CHANNEL, &id_cache))
1933       goto out;
1934     
1935     /* Get channel entry */
1936     channel = (SilcChannelEntry)id_cache->context;
1937   }
1938
1939   /* Save the key */
1940   key = silc_channel_key_get_key(payload, &tmp_len);
1941   cipher = silc_channel_key_get_cipher(payload, NULL);
1942   channel->key_len = tmp_len;
1943   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
1944   memcpy(channel->key, key, tmp_len);
1945
1946   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
1947     conn->client->ops->say(conn->client, conn,
1948                      "Cannot talk to channel: unsupported cipher %s", cipher);
1949     goto out;
1950   }
1951   channel->channel_key->cipher->set_key(channel->channel_key->context, 
1952                                         key, tmp_len);
1953
1954   /* Client is now joined to the channel */
1955   channel->on_channel = TRUE;
1956
1957  out:
1958   silc_free(id);
1959   silc_channel_key_payload_free(payload);
1960 }
1961
1962 /* Processes received key for channel. The received key will be used
1963    to protect the traffic on the channel for now on. Client must receive
1964    the key to the channel before talking on the channel is possible. 
1965    This is the key that server has generated, this is not the channel
1966    private key, it is entirely local setting. */
1967
1968 void silc_client_receive_channel_key(SilcClient client,
1969                                      SilcSocketConnection sock,
1970                                      SilcBuffer packet)
1971 {
1972   SILC_LOG_DEBUG(("Received key for channel"));
1973
1974   /* Save the key */
1975   silc_client_save_channel_key(sock->user_data, packet, NULL);
1976 }
1977
1978 /* Process received message to a channel (or from a channel, really). This
1979    decrypts the channel message with channel specific key and parses the
1980    channel payload. Finally it displays the message on the screen. */
1981
1982 void silc_client_channel_message(SilcClient client, 
1983                                  SilcSocketConnection sock, 
1984                                  SilcPacketContext *packet)
1985 {
1986   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1987   SilcBuffer buffer = packet->buffer;
1988   SilcChannelPayload payload = NULL;
1989   SilcChannelID *id = NULL;
1990   SilcChannelEntry channel;
1991   SilcChannelUser chu;
1992   SilcIDCacheEntry id_cache = NULL;
1993   SilcClientID *client_id = NULL;
1994   char *nickname;
1995
1996   /* Sanity checks */
1997   if (packet->dst_id_type != SILC_ID_CHANNEL)
1998     goto out;
1999
2000   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2001                              SILC_ID_CLIENT);
2002   if (!client_id)
2003     goto out;
2004   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2005   if (!id)
2006     goto out;
2007
2008   /* Find the channel entry from channels on this connection */
2009   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2010                                    SILC_ID_CHANNEL, &id_cache))
2011     goto out;
2012
2013   channel = (SilcChannelEntry)id_cache->context;
2014
2015   /* Decrypt the channel message payload. Push the IV out of the way,
2016      since it is not encrypted (after pushing buffer->tail has the IV). */
2017   silc_buffer_push_tail(buffer, 16);
2018   channel->channel_key->cipher->decrypt(channel->channel_key->context,
2019                                         buffer->data, buffer->data,
2020                                         buffer->len, buffer->tail);
2021   silc_buffer_pull_tail(buffer, 16);
2022
2023   /* Parse the channel message payload */
2024   payload = silc_channel_payload_parse(buffer);
2025   if (!payload)
2026     goto out;
2027
2028   /* Find nickname */
2029   nickname = "[unknown]";
2030   silc_list_start(channel->clients);
2031   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2032     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2033       nickname = chu->client->nickname;
2034       break;
2035     }
2036   }
2037
2038   /* Pass the message to application */
2039   client->ops->channel_message(client, conn, nickname,
2040                                channel->channel_name,
2041                                silc_channel_get_data(payload, NULL));
2042
2043  out:
2044   if (id)
2045     silc_free(id);
2046   if (client_id)
2047     silc_free(client_id);
2048   if (payload)
2049     silc_channel_payload_free(payload);
2050 }
2051
2052 /* Private message received. This processes the private message and
2053    finally displays it on the screen. */
2054
2055 void silc_client_private_message(SilcClient client, 
2056                                  SilcSocketConnection sock, 
2057                                  SilcPacketContext *packet)
2058 {
2059   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2060   SilcBuffer buffer = packet->buffer;
2061   unsigned short nick_len;
2062   unsigned char *nickname, *message;
2063   int ret;
2064
2065   /* Get nickname */
2066   ret = silc_buffer_unformat(buffer, 
2067                              SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2068                              SILC_STR_END);
2069   if (ret == -1)
2070     return;
2071
2072   silc_buffer_pull(buffer, 2 + nick_len);
2073
2074   message = silc_calloc(buffer->len + 1, sizeof(char));
2075   memcpy(message, buffer->data, buffer->len);
2076
2077   /* Pass the private message to application */
2078   client->ops->private_message(client, conn, nickname, message);
2079
2080   /* See if we are away (gone). If we are away we will reply to the
2081      sender with the set away message. */
2082   if (conn->away && conn->away->away) {
2083     SilcClientID *remote_id;
2084     SilcClientEntry remote_client;
2085     SilcIDCacheEntry id_cache;
2086
2087     if (packet->src_id_type != SILC_ID_CLIENT)
2088       goto out;
2089
2090     remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2091                                SILC_ID_CLIENT);
2092     if (!remote_id)
2093       goto out;
2094
2095     /* If it's me, ignore */
2096     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2097       goto out;
2098
2099     /* Check whether we know this client already */
2100     if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2101                                      SILC_ID_CLIENT, &id_cache))
2102       {
2103         /* Allocate client entry */
2104         remote_client = silc_calloc(1, sizeof(*remote_client));
2105         remote_client->id = remote_id;
2106         silc_parse_nickname(nickname, &remote_client->nickname, 
2107                             &remote_client->server, &remote_client->num);
2108
2109         /* Save the client to cache */
2110         silc_idcache_add(conn->client_cache, remote_client->nickname,
2111                          SILC_ID_CLIENT, remote_client->id, remote_client, 
2112                          TRUE);
2113       } else {
2114         silc_free(remote_id);
2115         remote_client = (SilcClientEntry)id_cache->context;
2116       }
2117
2118     /* Send the away message */
2119     silc_client_packet_send_private_message(client, sock, remote_client,
2120                                             conn->away->away,
2121                                             strlen(conn->away->away), TRUE);
2122   }
2123
2124  out:
2125   memset(message, 0, buffer->len);
2126   silc_free(message);
2127   silc_free(nickname);
2128 }
2129
2130 /* Removes a client entry from all channel it has joined. This really is
2131    a performance killer (client_entry should have pointers to channel 
2132    entry list). */
2133
2134 void silc_client_remove_from_channels(SilcClient client,
2135                                       SilcClientConnection conn,
2136                                       SilcClientEntry client_entry)
2137 {
2138   SilcIDCacheEntry id_cache;
2139   SilcIDCacheList list;
2140   SilcChannelEntry channel;
2141   SilcChannelUser chu;
2142
2143   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2144                                SILC_ID_CHANNEL, &list))
2145     return;
2146
2147   silc_idcache_list_first(list, &id_cache);
2148   channel = (SilcChannelEntry)id_cache->context;
2149   
2150   while (channel) {
2151     
2152     /* Remove client from channel */
2153     silc_list_start(channel->clients);
2154     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2155       if (chu->client == client_entry) {
2156         silc_list_del(channel->clients, chu);
2157         silc_free(chu);
2158         break;
2159       }
2160     }
2161
2162     if (!silc_idcache_list_next(list, &id_cache))
2163       break;
2164     
2165     channel = (SilcChannelEntry)id_cache->context;
2166   }
2167
2168   silc_idcache_list_free(list);
2169 }
2170
2171 /* Replaces `old' client entries from all channels to `new' client entry.
2172    This can be called for example when nickname changes and old ID entry
2173    is replaced from ID cache with the new one. If the old ID entry is only
2174    updated, then this fucntion needs not to be called. */
2175
2176 void silc_client_replace_from_channels(SilcClient client, 
2177                                        SilcClientConnection conn,
2178                                        SilcClientEntry old,
2179                                        SilcClientEntry new)
2180 {
2181   SilcIDCacheEntry id_cache;
2182   SilcIDCacheList list;
2183   SilcChannelEntry channel;
2184   SilcChannelUser chu;
2185
2186   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2187                                SILC_ID_CHANNEL, &list))
2188     return;
2189
2190   silc_idcache_list_first(list, &id_cache);
2191   channel = (SilcChannelEntry)id_cache->context;
2192   
2193   while (channel) {
2194     
2195     /* Replace client entry */
2196     silc_list_start(channel->clients);
2197     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2198       if (chu->client == old) {
2199         chu->client = new;
2200         break;
2201       }
2202     }
2203
2204     if (!silc_idcache_list_next(list, &id_cache))
2205       break;
2206     
2207     channel = (SilcChannelEntry)id_cache->context;
2208   }
2209
2210   silc_idcache_list_free(list);
2211 }
2212
2213 /* Parses mode mask and returns the mode as string. */
2214
2215 char *silc_client_chmode(unsigned int mode)
2216 {
2217   char string[20];
2218
2219   if (!mode)
2220     return NULL;
2221
2222   memset(string, 0, sizeof(string));
2223
2224   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2225     strncat(string, "p", 1);
2226
2227   if (mode & SILC_CHANNEL_MODE_SECRET)
2228     strncat(string, "s", 1);
2229
2230   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2231     strncat(string, "k", 1);
2232
2233   if (mode & SILC_CHANNEL_MODE_INVITE)
2234     strncat(string, "i", 1);
2235
2236   if (mode & SILC_CHANNEL_MODE_TOPIC)
2237     strncat(string, "t", 1);
2238
2239   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2240     strncat(string, "l", 1);
2241
2242   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2243     strncat(string, "a", 1);
2244
2245   /* Rest of mode is ignored */
2246
2247   return strdup(string);
2248 }
2249
2250 /* Parses channel user mode mask and returns te mode as string */
2251
2252 char *silc_client_chumode(unsigned int mode)
2253 {
2254   char string[4];
2255
2256   if (!mode)
2257     return NULL;
2258
2259   memset(string, 0, sizeof(string));
2260
2261   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2262     strncat(string, "f", 1);
2263
2264   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2265     strncat(string, "o", 1);
2266
2267   return strdup(string);
2268 }
2269
2270 /* Parses channel user mode and returns it as special mode character. */
2271
2272 char *silc_client_chumode_char(unsigned int mode)
2273 {
2274   char string[4];
2275
2276   if (!mode)
2277     return NULL;
2278
2279   memset(string, 0, sizeof(string));
2280
2281   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2282     strncat(string, "*", 1);
2283
2284   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2285     strncat(string, "@", 1);
2286
2287   return strdup(string);
2288 }