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