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 - 2001 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 #include "client_internal.h"
24
25 /* Static task callback prototypes */
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
28 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
30 SILC_TASK_CALLBACK(silc_client_rekey_callback);
31 SILC_TASK_CALLBACK(silc_client_rekey_final);
32
33 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
34 static void silc_client_packet_parse_type(SilcClient client, 
35                                           SilcSocketConnection sock,
36                                           SilcPacketContext *packet);
37
38 /* Allocates new client object. This has to be done before client may
39    work. After calling this one must call silc_client_init to initialize
40    the client. The `application' is application specific user data pointer
41    and caller must free it. */
42
43 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
44 {
45   SilcClient new_client;
46
47   new_client = silc_calloc(1, sizeof(*new_client));
48   new_client->application = application;
49   new_client->ops = ops;
50
51   return new_client;
52 }
53
54 /* Frees client object and its internals. */
55
56 void silc_client_free(SilcClient client)
57 {
58   if (client) {
59     if (client->rng)
60       silc_rng_free(client->rng);
61
62     silc_free(client);
63   }
64 }
65
66 /* Initializes the client. This makes all the necessary steps to make
67    the client ready to be run. One must call silc_client_run to run the
68    client. Returns FALSE if error occured, TRUE otherwise. */
69
70 int silc_client_init(SilcClient client)
71 {
72   SILC_LOG_DEBUG(("Initializing client"));
73
74   /* Initialize hash functions for client to use */
75   silc_hash_alloc("md5", &client->md5hash);
76   silc_hash_alloc("sha1", &client->sha1hash);
77
78   /* Initialize none cipher */
79   silc_cipher_alloc("none", &client->none_cipher);
80
81   /* Initialize random number generator */
82   client->rng = silc_rng_alloc();
83   silc_rng_init(client->rng);
84   silc_rng_global_init(client->rng);
85
86   /* Register protocols */
87   silc_client_protocols_register();
88
89   /* Initialize the scheduler */
90   silc_schedule_init(&client->io_queue, &client->timeout_queue, 
91                      &client->generic_queue, 5000);
92
93   return TRUE;
94 }
95
96 /* Stops the client. This is called to stop the client and thus to stop
97    the program. */
98
99 void silc_client_stop(SilcClient client)
100 {
101   SILC_LOG_DEBUG(("Stopping client"));
102
103   /* Stop the scheduler, although it might be already stopped. This
104      doesn't hurt anyone. This removes all the tasks and task queues,
105      as well. */
106   silc_schedule_stop();
107   silc_schedule_uninit();
108
109   silc_client_protocols_unregister();
110
111   SILC_LOG_DEBUG(("Client stopped"));
112 }
113
114 /* Runs the client. This starts the scheduler from the utility library.
115    When this functions returns the execution of the appliation is over. */
116
117 void silc_client_run(SilcClient client)
118 {
119   SILC_LOG_DEBUG(("Running client"));
120
121   /* Start the scheduler, the heart of the SILC client. When this returns
122      the program will be terminated. */
123   silc_schedule();
124 }
125
126 /* Allocates and adds new connection to the client. This adds the allocated
127    connection to the connection table and returns a pointer to it. A client
128    can have multiple connections to multiple servers. Every connection must
129    be added to the client using this function. User data `context' may
130    be sent as argument. This function is normally used only if the 
131    application performed the connecting outside the library. The library
132    however may use this internally. */
133
134 SilcClientConnection silc_client_add_connection(SilcClient client,
135                                                 char *hostname,
136                                                 int port,
137                                                 void *context)
138 {
139   SilcClientConnection conn;
140   int i;
141
142   conn = silc_calloc(1, sizeof(*conn));
143
144   /* Initialize ID caches */
145   conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
146   conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
147   conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
148   conn->client = client;
149   conn->remote_host = strdup(hostname);
150   conn->remote_port = port;
151   conn->context = context;
152   conn->pending_commands = silc_dlist_init();
153
154   /* Add the connection to connections table */
155   for (i = 0; i < client->conns_count; i++)
156     if (client->conns && !client->conns[i]) {
157       client->conns[i] = conn;
158       return conn;
159     }
160
161   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
162                                * (client->conns_count + 1));
163   client->conns[client->conns_count] = conn;
164   client->conns_count++;
165
166   return conn;
167 }
168
169 /* Removes connection from client. Frees all memory. */
170
171 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
172 {
173   int i;
174
175   for (i = 0; i < client->conns_count; i++)
176     if (client->conns[i] == conn) {
177       if (conn->pending_commands)
178         silc_dlist_uninit(conn->pending_commands);
179       silc_free(conn);
180       client->conns[i] = NULL;
181     }
182 }
183
184 /* Adds listener socket to the listener sockets table. This function is
185    used to add socket objects that are listeners to the client.  This should
186    not be used to add other connection objects. */
187
188 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
189 {
190   int i;
191
192   if (!client->sockets) {
193     client->sockets = silc_calloc(1, sizeof(*client->sockets));
194     client->sockets[0] = silc_socket_dup(sock);
195     client->sockets_count = 1;
196     return;
197   }
198
199   for (i = 0; i < client->sockets_count; i++) {
200     if (client->sockets[i] == NULL) {
201       client->sockets[i] = silc_socket_dup(sock);
202       return;
203     }
204   }
205
206   client->sockets = silc_realloc(client->sockets, sizeof(*client->sockets) *
207                                  (client->sockets_count + 1));
208   client->sockets[client->sockets_count] = silc_socket_dup(sock);
209   client->sockets_count++;
210 }
211
212 /* Deletes listener socket from the listener sockets table. */
213
214 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
215 {
216   int i;
217
218   if (!client->sockets)
219     return;
220
221   for (i = 0; i < client->sockets_count; i++) {
222     if (client->sockets[i] == sock) {
223       silc_socket_free(sock);
224       client->sockets[i] = NULL;
225       return;
226     }
227   }
228 }
229
230 static int 
231 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
232 {
233   int sock;
234
235   /* XXX In the future we should give up this non-blocking connect all
236      together and use threads instead. */
237   /* Create connection to server asynchronously */
238   sock = silc_net_create_connection_async(ctx->port, ctx->host);
239   if (sock < 0)
240     return -1;
241
242   /* Register task that will receive the async connect and will
243      read the result. */
244   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
245                                  silc_client_connect_to_server_start,
246                                  (void *)ctx, 0, 0, 
247                                  SILC_TASK_FD,
248                                  SILC_TASK_PRI_NORMAL);
249   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
250   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
251
252   ctx->sock = sock;
253
254   return sock;
255 }
256
257 /* Connects to remote server. This is the main routine used to connect
258    to SILC server. Returns -1 on error and the created socket otherwise. 
259    The `context' is user context that is saved into the SilcClientConnection
260    that is created after the connection is created. Note that application
261    may handle the connecting process outside the library. If this is the
262    case then this function is not used at all. When the connecting is
263    done the `connect' client operation is called. */
264
265 int silc_client_connect_to_server(SilcClient client, int port,
266                                   char *host, void *context)
267 {
268   SilcClientInternalConnectContext *ctx;
269   SilcClientConnection conn;
270   int sock;
271
272   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
273                   port, host));
274
275   conn = silc_client_add_connection(client, host, port, context);
276
277   client->ops->say(client, conn, 
278                    "Connecting to port %d of server %s", port, host);
279
280   /* Allocate internal context for connection process. This is
281      needed as we are doing async connecting. */
282   ctx = silc_calloc(1, sizeof(*ctx));
283   ctx->client = client;
284   ctx->conn = conn;
285   ctx->host = strdup(host);
286   ctx->port = port;
287   ctx->tries = 0;
288
289   /* Do the actual connecting process */
290   sock = silc_client_connect_to_server_internal(ctx);
291   if (sock == -1)
292     silc_client_del_connection(client, conn);
293   return sock;
294 }
295
296 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
297    key material between client and server.  This function can be called
298    directly if application is performing its own connecting and does not
299    use the connecting provided by this library. This function is normally
300    used only if the application performed the connecting outside the library.
301    The library however may use this internally. */
302
303 int silc_client_start_key_exchange(SilcClient client,
304                                    SilcClientConnection conn,
305                                    int fd)
306 {
307   SilcProtocol protocol;
308   SilcClientKEInternalContext *proto_ctx;
309   void *context;
310
311   /* Allocate new socket connection object */
312   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
313
314   conn->nickname = strdup(client->username);
315   conn->sock->hostname = conn->remote_host;
316   conn->sock->ip = strdup(conn->remote_host);
317   conn->sock->port = conn->remote_port;
318
319   /* Allocate internal Key Exchange context. This is sent to the
320      protocol as context. */
321   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
322   proto_ctx->client = (void *)client;
323   proto_ctx->sock = silc_socket_dup(conn->sock);
324   proto_ctx->rng = client->rng;
325   proto_ctx->responder = FALSE;
326   proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
327   proto_ctx->verify = silc_client_protocol_ke_verify_key;
328
329   /* Perform key exchange protocol. silc_client_connect_to_server_final
330      will be called after the protocol is finished. */
331   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
332                       &protocol, (void *)proto_ctx,
333                       silc_client_connect_to_server_second);
334   if (!protocol) {
335     client->ops->say(client, conn, 
336                      "Error: Could not start authentication protocol");
337     return FALSE;
338   }
339   conn->sock->protocol = protocol;
340
341   /* Register the connection for network input and output. This sets
342      that scheduler will listen for incoming packets for this connection 
343      and sets that outgoing packets may be sent to this connection as well.
344      However, this doesn't set the scheduler for outgoing traffic, it will 
345      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
346      later when outgoing data is available. */
347   context = (void *)client;
348   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
349
350   /* Execute the protocol */
351   protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
352   return TRUE;
353 }
354
355 /* Start of the connection to the remote server. This is called after
356    succesful TCP/IP connection has been established to the remote host. */
357
358 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
359 {
360   SilcClientInternalConnectContext *ctx =
361     (SilcClientInternalConnectContext *)context;
362   SilcClient client = ctx->client;
363   SilcClientConnection conn = ctx->conn;
364   int opt, opt_len = sizeof(opt);
365
366   SILC_LOG_DEBUG(("Start"));
367
368   /* Check the socket status as it might be in error */
369   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
370   if (opt != 0) {
371     if (ctx->tries < 2) {
372       /* Connection failed but lets try again */
373       client->ops->say(client, conn, "Could not connect to server %s: %s",
374                        ctx->host, strerror(opt));
375       client->ops->say(client, conn, 
376                        "Connecting to port %d of server %s resumed", 
377                        ctx->port, ctx->host);
378
379       /* Unregister old connection try */
380       silc_schedule_unset_listen_fd(fd);
381       silc_net_close_connection(fd);
382       silc_task_unregister(client->io_queue, ctx->task);
383
384       /* Try again */
385       silc_client_connect_to_server_internal(ctx);
386       ctx->tries++;
387     } else {
388       /* Connection failed and we won't try anymore */
389       client->ops->say(client, conn, "Could not connect to server %s: %s",
390                        ctx->host, strerror(opt));
391       silc_schedule_unset_listen_fd(fd);
392       silc_net_close_connection(fd);
393       silc_task_unregister(client->io_queue, ctx->task);
394       silc_free(ctx);
395
396       /* Notify application of failure */
397       client->ops->connect(client, conn, FALSE);
398       silc_client_del_connection(client, conn);
399     }
400     return;
401   }
402
403   silc_schedule_unset_listen_fd(fd);
404   silc_task_unregister(client->io_queue, ctx->task);
405   silc_free(ctx);
406
407   if (!silc_client_start_key_exchange(client, conn, fd)) {
408     silc_net_close_connection(fd);
409     client->ops->connect(client, conn, FALSE);
410   }
411 }
412
413 /* Second part of the connecting to the server. This executed 
414    authentication protocol. */
415
416 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
417 {
418   SilcProtocol protocol = (SilcProtocol)context;
419   SilcClientKEInternalContext *ctx = 
420     (SilcClientKEInternalContext *)protocol->context;
421   SilcClient client = (SilcClient)ctx->client;
422   SilcSocketConnection sock = NULL;
423   SilcClientConnAuthInternalContext *proto_ctx;
424
425   SILC_LOG_DEBUG(("Start"));
426
427   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
428       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
429     /* Error occured during protocol */
430     SILC_LOG_DEBUG(("Error during KE protocol"));
431     silc_protocol_free(protocol);
432     silc_ske_free_key_material(ctx->keymat);
433     if (ctx->ske)
434       silc_ske_free(ctx->ske);
435     if (ctx->dest_id)
436       silc_free(ctx->dest_id);
437     ctx->sock->protocol = NULL;
438     silc_socket_free(ctx->sock);
439
440     /* Notify application of failure */
441     client->ops->connect(client, ctx->sock->user_data, FALSE);
442     silc_free(ctx);
443     return;
444   }
445
446   /* We now have the key material as the result of the key exchange
447      protocol. Take the key material into use. Free the raw key material
448      as soon as we've set them into use. */
449   silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
450                                    ctx->ske->prop->cipher,
451                                    ctx->ske->prop->pkcs,
452                                    ctx->ske->prop->hash,
453                                    ctx->ske->prop->hmac,
454                                    ctx->ske->prop->group);
455   silc_ske_free_key_material(ctx->keymat);
456
457   /* Allocate internal context for the authentication protocol. This
458      is sent as context for the protocol. */
459   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
460   proto_ctx->client = (void *)client;
461   proto_ctx->sock = sock = ctx->sock;
462   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
463   proto_ctx->dest_id_type = ctx->dest_id_type;
464   proto_ctx->dest_id = ctx->dest_id;
465
466   /* Resolve the authentication method to be used in this connection */
467   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
468                                     sock->port, &proto_ctx->auth_meth,
469                                     &proto_ctx->auth_data, 
470                                     &proto_ctx->auth_data_len)) {
471     client->ops->say(client, ctx->sock->user_data, 
472                      "Could not resolve authentication method to use, "
473                      "assume no authentication");
474     proto_ctx->auth_meth = SILC_AUTH_NONE;
475   }
476
477   /* Free old protocol as it is finished now */
478   silc_protocol_free(protocol);
479   if (ctx->packet)
480     silc_packet_context_free(ctx->packet);
481   silc_free(ctx);
482   sock->protocol = NULL;
483
484   /* Allocate the authenteication protocol and execute it. */
485   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
486                       &sock->protocol, (void *)proto_ctx, 
487                       silc_client_connect_to_server_final);
488
489   /* Execute the protocol */
490   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
491 }
492
493 /* Finalizes the connection to the remote SILC server. This is called
494    after authentication protocol has been completed. This send our
495    user information to the server to receive our client ID from
496    server. */
497
498 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
499 {
500   SilcProtocol protocol = (SilcProtocol)context;
501   SilcClientConnAuthInternalContext *ctx = 
502     (SilcClientConnAuthInternalContext *)protocol->context;
503   SilcClient client = (SilcClient)ctx->client;
504   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
505   SilcBuffer packet;
506
507   SILC_LOG_DEBUG(("Start"));
508
509   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
510       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
511     /* Error occured during protocol */
512     SILC_LOG_DEBUG(("Error during authentication protocol"));
513     silc_protocol_free(protocol);
514     if (ctx->auth_data)
515       silc_free(ctx->auth_data);
516     if (ctx->ske)
517       silc_ske_free(ctx->ske);
518     if (ctx->dest_id)
519       silc_free(ctx->dest_id);
520     conn->sock->protocol = NULL;
521     silc_socket_free(ctx->sock);
522
523     /* Notify application of failure */
524     client->ops->connect(client, ctx->sock->user_data, FALSE);
525     silc_free(ctx);
526     return;
527   }
528
529   /* Send NEW_CLIENT packet to the server. We will become registered
530      to the SILC network after sending this packet and we will receive
531      client ID from the server. */
532   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
533                              strlen(client->realname));
534   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
535   silc_buffer_format(packet,
536                      SILC_STR_UI_SHORT(strlen(client->username)),
537                      SILC_STR_UI_XNSTRING(client->username,
538                                           strlen(client->username)),
539                      SILC_STR_UI_SHORT(strlen(client->realname)),
540                      SILC_STR_UI_XNSTRING(client->realname,
541                                           strlen(client->realname)),
542                      SILC_STR_END);
543
544   /* Send the packet */
545   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
546                           NULL, 0, NULL, NULL, 
547                           packet->data, packet->len, TRUE);
548   silc_buffer_free(packet);
549
550   /* Save remote ID. */
551   conn->remote_id = ctx->dest_id;
552   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
553   conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
554
555   /* Register re-key timeout */
556   conn->rekey->timeout = 3600; /* XXX hardcoded */
557   conn->rekey->context = (void *)client;
558   silc_task_register(client->timeout_queue, conn->sock->sock, 
559                      silc_client_rekey_callback,
560                      (void *)conn->sock, conn->rekey->timeout, 0,
561                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
562
563   silc_protocol_free(protocol);
564   if (ctx->auth_data)
565     silc_free(ctx->auth_data);
566   if (ctx->ske)
567     silc_ske_free(ctx->ske);
568   silc_socket_free(ctx->sock);
569   silc_free(ctx);
570   conn->sock->protocol = NULL;
571 }
572
573 /* Internal routine that sends packet or marks packet to be sent. This
574    is used directly only in special cases. Normal cases should use
575    silc_server_packet_send. Returns < 0 on error. */
576
577 int silc_client_packet_send_real(SilcClient client,
578                                  SilcSocketConnection sock,
579                                  bool force_send,
580                                  bool flush)
581 {
582   int ret;
583
584   /* If rekey protocol is active we must assure that all packets are
585      sent through packet queue. */
586   if (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
587     force_send = FALSE;
588
589   /* Send the packet */
590   ret = silc_packet_send(sock, force_send);
591   if (ret != -2)
592     return ret;
593
594   /* Mark that there is some outgoing data available for this connection. 
595      This call sets the connection both for input and output (the input
596      is set always and this call keeps the input setting, actually). 
597      Actual data sending is performed by silc_client_packet_process. */
598   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
599
600   /* Mark to socket that data is pending in outgoing buffer. This flag
601      is needed if new data is added to the buffer before the earlier
602      put data is sent to the network. */
603   SILC_SET_OUTBUF_PENDING(sock);
604
605   return 0;
606 }
607
608 /* Packet processing callback. This is used to send and receive packets
609    from network. This is generic task. */
610
611 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
612 {
613   SilcClient client = (SilcClient)context;
614   SilcSocketConnection sock = NULL;
615   SilcClientConnection conn;
616   int ret;
617
618   SILC_LOG_DEBUG(("Processing packet"));
619
620   SILC_CLIENT_GET_SOCK(client, fd, sock);
621   if (sock == NULL)
622     return;
623
624   conn = (SilcClientConnection)sock->user_data;
625
626   /* Packet sending */
627   if (type == SILC_TASK_WRITE) {
628     SILC_LOG_DEBUG(("Writing data to connection"));
629
630     if (sock->outbuf->data - sock->outbuf->head)
631       silc_buffer_push(sock->outbuf, 
632                        sock->outbuf->data - sock->outbuf->head);
633
634     ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
635
636     /* If returned -2 could not write to connection now, will do
637        it later. */
638     if (ret == -2)
639       return;
640     
641     /* The packet has been sent and now it is time to set the connection
642        back to only for input. When there is again some outgoing data 
643        available for this connection it will be set for output as well. 
644        This call clears the output setting and sets it only for input. */
645     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
646     SILC_UNSET_OUTBUF_PENDING(sock);
647
648     silc_buffer_clear(sock->outbuf);
649     return;
650   }
651
652   /* Packet receiving */
653   if (type == SILC_TASK_READ) {
654     SILC_LOG_DEBUG(("Reading data from connection"));
655
656     /* Read data from network */
657     ret = silc_packet_receive(sock);
658     if (ret < 0)
659       return;
660     
661     /* EOF */
662     if (ret == 0) {
663       SILC_LOG_DEBUG(("Read EOF"));
664
665       /* If connection is disconnecting already we will finally
666          close the connection */
667       if (SILC_IS_DISCONNECTING(sock)) {
668         if (sock == conn->sock)
669           client->ops->disconnect(client, conn);
670         silc_client_close_connection(client, sock, conn);
671         return;
672       }
673       
674       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
675       if (sock == conn->sock)
676         client->ops->disconnect(client, conn);
677       silc_client_close_connection(client, sock, conn);
678       return;
679     }
680
681     /* Process the packet. This will call the parser that will then
682        decrypt and parse the packet. */
683     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
684       silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
685                                   silc_client_packet_parse, client);
686     else
687       silc_packet_receive_process(sock, NULL, NULL,
688                                   silc_client_packet_parse, client);
689   }
690 }
691
692 /* Callback function that the silc_packet_decrypt will call to make the
693    decision whether the packet is normal or special packet. We will 
694    return TRUE if it is normal and FALSE if it is special */
695
696 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
697                                             SilcBuffer buffer,
698                                             SilcPacketContext *packet,
699                                             void *context)
700 {
701
702   /* Packet is normal packet, if: 
703
704      1) packet is private message packet and does not have private key set
705      2) is other packet than channel message packet
706
707      all other packets are special packets 
708   */
709
710   if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
711       (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
712     return FALSE;
713
714   if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
715     return TRUE;
716
717   return FALSE;
718 }
719
720 /* Parses whole packet, received earlier. */
721
722 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
723 {
724   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
725   SilcClient client = (SilcClient)parse_ctx->context;
726   SilcPacketContext *packet = parse_ctx->packet;
727   SilcBuffer buffer = packet->buffer;
728   SilcSocketConnection sock = parse_ctx->sock;
729   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
730   int ret;
731
732   SILC_LOG_DEBUG(("Start"));
733
734   /* Decrypt the received packet */
735   if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
736     ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive, 
737                               buffer, packet,
738                               silc_client_packet_decrypt_check, parse_ctx);
739   else
740     ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
741                               silc_client_packet_decrypt_check, parse_ctx);
742
743   if (ret < 0)
744     goto out;
745
746   if (ret == 0) {
747     /* Parse the packet. Packet type is returned. */
748     ret = silc_packet_parse(packet);
749   } else {
750     /* Parse the packet header in special way as this is "special"
751        packet type. */
752     ret = silc_packet_parse_special(packet);
753   }
754
755   if (ret == SILC_PACKET_NONE)
756     goto out;
757
758   /* Parse the incoming packet type */
759   silc_client_packet_parse_type(client, sock, packet);
760
761  out:
762   /*  silc_buffer_clear(sock->inbuf); */
763   silc_packet_context_free(packet);
764   silc_free(parse_ctx);
765 }
766
767 /* Parser callback called by silc_packet_receive_process. Thie merely
768    registers timeout that will handle the actual parsing when appropriate. */
769
770 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
771 {
772   SilcClient client = (SilcClient)parser_context->context;
773
774   /* Parse the packet */
775   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
776                      silc_client_packet_parse_real,
777                      (void *)parser_context, 0, 1, 
778                      SILC_TASK_TIMEOUT,
779                      SILC_TASK_PRI_NORMAL);
780 }
781
782 /* Parses the packet type and calls what ever routines the packet type
783    requires. This is done for all incoming packets. */
784
785 void silc_client_packet_parse_type(SilcClient client, 
786                                    SilcSocketConnection sock,
787                                    SilcPacketContext *packet)
788 {
789   SilcBuffer buffer = packet->buffer;
790   SilcPacketType type = packet->type;
791
792   SILC_LOG_DEBUG(("Parsing packet type %d", type));
793
794   /* Parse the packet type */
795   switch(type) {
796   case SILC_PACKET_DISCONNECT:
797     silc_client_disconnected_by_server(client, sock, buffer);
798     break;
799   case SILC_PACKET_SUCCESS:
800     /*
801      * Success received for something. For now we can have only
802      * one protocol for connection executing at once hence this
803      * success message is for whatever protocol is executing currently.
804      */
805     if (sock->protocol) {
806       sock->protocol->execute(client->timeout_queue, 0,
807                               sock->protocol, sock->sock, 0, 0);
808     }
809     break;
810   case SILC_PACKET_FAILURE:
811     /*
812      * Failure received for some protocol. Set the protocol state to 
813      * error and call the protocol callback. This fill cause error on
814      * protocol and it will call the final callback.
815      */
816     silc_client_process_failure(client, sock, packet);
817     break;
818   case SILC_PACKET_REJECT:
819     break;
820
821   case SILC_PACKET_NOTIFY:
822     /*
823      * Received notify message 
824      */
825     silc_client_notify_by_server(client, sock, packet);
826     break;
827
828   case SILC_PACKET_ERROR:
829     /*
830      * Received error message
831      */
832     silc_client_error_by_server(client, sock, buffer);
833     break;
834
835   case SILC_PACKET_CHANNEL_MESSAGE:
836     /*
837      * Received message to (from, actually) a channel
838      */
839     silc_client_channel_message(client, sock, packet);
840     break;
841   case SILC_PACKET_CHANNEL_KEY:
842     /*
843      * Received key for a channel. By receiving this key the client will be
844      * able to talk to the channel it has just joined. This can also be
845      * a new key for existing channel as keys expire peridiocally.
846      */
847     silc_client_receive_channel_key(client, sock, buffer);
848     break;
849
850   case SILC_PACKET_PRIVATE_MESSAGE:
851     /*
852      * Received private message
853      */
854     silc_client_private_message(client, sock, packet);
855     break;
856   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
857     /*
858      * Received private message key
859      */
860     break;
861
862   case SILC_PACKET_COMMAND_REPLY:
863     /*
864      * Recived reply for a command
865      */
866     silc_client_command_reply_process(client, sock, packet);
867     break;
868
869   case SILC_PACKET_KEY_EXCHANGE:
870     if (sock->protocol && sock->protocol->protocol && 
871         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
872       SilcClientKEInternalContext *proto_ctx = 
873         (SilcClientKEInternalContext *)sock->protocol->context;
874
875       proto_ctx->packet = silc_packet_context_dup(packet);
876       proto_ctx->dest_id_type = packet->src_id_type;
877       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
878                                           packet->src_id_type);
879       if (!proto_ctx->dest_id)
880         break;
881
882       /* Let the protocol handle the packet */
883       sock->protocol->execute(client->timeout_queue, 0,
884                               sock->protocol, sock->sock, 0, 0);
885     } else {
886       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
887                       "protocol active, packet dropped."));
888     }
889     break;
890
891   case SILC_PACKET_KEY_EXCHANGE_1:
892     if (sock->protocol && sock->protocol->protocol && 
893         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
894          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
895
896       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
897         SilcClientRekeyInternalContext *proto_ctx = 
898           (SilcClientRekeyInternalContext *)sock->protocol->context;
899         
900         if (proto_ctx->packet)
901           silc_packet_context_free(proto_ctx->packet);
902         
903         proto_ctx->packet = silc_packet_context_dup(packet);
904
905         /* Let the protocol handle the packet */
906         sock->protocol->execute(client->timeout_queue, 0, 
907                                 sock->protocol, sock->sock, 0, 0);
908       } else {
909         SilcClientKEInternalContext *proto_ctx = 
910           (SilcClientKEInternalContext *)sock->protocol->context;
911         
912         if (proto_ctx->packet)
913           silc_packet_context_free(proto_ctx->packet);
914         
915         proto_ctx->packet = silc_packet_context_dup(packet);
916         proto_ctx->dest_id_type = packet->src_id_type;
917         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
918                                             packet->src_id_type);
919         if (!proto_ctx->dest_id)
920           break;
921         
922         /* Let the protocol handle the packet */
923         sock->protocol->execute(client->timeout_queue, 0,
924                                 sock->protocol, sock->sock, 0, 0);
925       }
926     } else {
927       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
928                       "protocol active, packet dropped."));
929     }
930     break;
931   case SILC_PACKET_KEY_EXCHANGE_2:
932     if (sock->protocol && sock->protocol->protocol && 
933         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
934          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
935
936       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
937         SilcClientRekeyInternalContext *proto_ctx = 
938           (SilcClientRekeyInternalContext *)sock->protocol->context;
939         
940         if (proto_ctx->packet)
941           silc_packet_context_free(proto_ctx->packet);
942         
943         proto_ctx->packet = silc_packet_context_dup(packet);
944
945         /* Let the protocol handle the packet */
946         sock->protocol->execute(client->timeout_queue, 0, 
947                                 sock->protocol, sock->sock, 0, 0);
948       } else {
949         SilcClientKEInternalContext *proto_ctx = 
950           (SilcClientKEInternalContext *)sock->protocol->context;
951         
952         if (proto_ctx->packet)
953           silc_packet_context_free(proto_ctx->packet);
954         
955         proto_ctx->packet = silc_packet_context_dup(packet);
956         proto_ctx->dest_id_type = packet->src_id_type;
957         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
958                                             packet->src_id_type);
959         if (!proto_ctx->dest_id)
960           break;
961         
962         /* Let the protocol handle the packet */
963         sock->protocol->execute(client->timeout_queue, 0,
964                                 sock->protocol, sock->sock, 0, 0);
965       }
966     } else {
967       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
968                       "protocol active, packet dropped."));
969     }
970     break;
971
972   case SILC_PACKET_NEW_ID:
973     {
974       /*
975        * Received new ID from server. This packet is received at
976        * the connection to the server.  New ID is also received when 
977        * user changes nickname but in that case the new ID is received
978        * as command reply and not as this packet type.
979        */
980       SilcIDPayload idp;
981
982       idp = silc_id_payload_parse(buffer);
983       if (!idp)
984         break;
985       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
986         break;
987
988       silc_client_receive_new_id(client, sock, idp);
989       silc_id_payload_free(idp);
990       break;
991     }
992
993   case SILC_PACKET_HEARTBEAT:
994     /*
995      * Received heartbeat packet
996      */
997     SILC_LOG_DEBUG(("Heartbeat packet"));
998     break;
999
1000   case SILC_PACKET_KEY_AGREEMENT:
1001     /*
1002      * Received key agreement packet
1003      */
1004     SILC_LOG_DEBUG(("Key agreement packet"));
1005     silc_client_key_agreement(client, sock, packet);
1006     break;
1007
1008   case SILC_PACKET_REKEY:
1009     SILC_LOG_DEBUG(("Re-key packet"));
1010     /* We ignore this for now */
1011     break;
1012
1013   case SILC_PACKET_REKEY_DONE:
1014     SILC_LOG_DEBUG(("Re-key done packet"));
1015
1016     if (sock->protocol && sock->protocol->protocol && 
1017         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1018
1019       SilcClientRekeyInternalContext *proto_ctx = 
1020         (SilcClientRekeyInternalContext *)sock->protocol->context;
1021       
1022       if (proto_ctx->packet)
1023         silc_packet_context_free(proto_ctx->packet);
1024       
1025       proto_ctx->packet = silc_packet_context_dup(packet);
1026
1027       /* Let the protocol handle the packet */
1028       if (proto_ctx->responder == FALSE)
1029         sock->protocol->execute(client->timeout_queue, 0, 
1030                                 sock->protocol, sock->sock, 0, 0);
1031       else
1032         /* Let the protocol handle the packet */
1033         sock->protocol->execute(client->timeout_queue, 0, 
1034                                 sock->protocol, sock->sock, 0, 100000);
1035     } else {
1036       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1037                       "protocol active, packet dropped."));
1038     }
1039     break;
1040
1041   default:
1042     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1043     break;
1044   }
1045 }
1046
1047 /* Sends packet. This doesn't actually send the packet instead it assembles
1048    it and marks it to be sent. However, if force_send is TRUE the packet
1049    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1050    will be derived from sock argument. Otherwise the valid arguments sent
1051    are used. */
1052
1053 void silc_client_packet_send(SilcClient client, 
1054                              SilcSocketConnection sock,
1055                              SilcPacketType type, 
1056                              void *dst_id,
1057                              SilcIdType dst_id_type,
1058                              SilcCipher cipher,
1059                              SilcHmac hmac,
1060                              unsigned char *data, 
1061                              uint32 data_len, 
1062                              int force_send)
1063 {
1064   SilcPacketContext packetdata;
1065
1066   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1067
1068   /* Get data used in the packet sending, keys and stuff */
1069   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1070     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1071       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1072
1073     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1074       hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1075
1076     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1077       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1078       dst_id_type = SILC_ID_SERVER;
1079     }
1080   }
1081
1082   /* Set the packet context pointers */
1083   packetdata.flags = 0;
1084   packetdata.type = type;
1085   if (sock->user_data && 
1086       ((SilcClientConnection)sock->user_data)->local_id_data) {
1087     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1088     packetdata.src_id_len = 
1089       silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1090                       SILC_ID_CLIENT);
1091   } else { 
1092     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1093     packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1094   }
1095   packetdata.src_id_type = SILC_ID_CLIENT;
1096   if (dst_id) {
1097     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1098     packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1099     packetdata.dst_id_type = dst_id_type;
1100   } else {
1101     packetdata.dst_id = NULL;
1102     packetdata.dst_id_len = 0;
1103     packetdata.dst_id_type = SILC_ID_NONE;
1104   }
1105   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1106     packetdata.src_id_len + packetdata.dst_id_len;
1107   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1108
1109   /* Prepare outgoing data buffer for packet sending */
1110   silc_packet_send_prepare(sock, 
1111                            SILC_PACKET_HEADER_LEN +
1112                            packetdata.src_id_len + 
1113                            packetdata.dst_id_len,
1114                            packetdata.padlen,
1115                            data_len);
1116
1117   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1118
1119   packetdata.buffer = sock->outbuf;
1120
1121   /* Put the data to the buffer */
1122   if (data && data_len)
1123     silc_buffer_put(sock->outbuf, data, data_len);
1124
1125   /* Create the outgoing packet */
1126   silc_packet_assemble(&packetdata);
1127
1128   /* Encrypt the packet */
1129   if (cipher)
1130     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1131
1132   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1133                    sock->outbuf->data, sock->outbuf->len);
1134
1135   /* Now actually send the packet */
1136   silc_client_packet_send_real(client, sock, force_send, FALSE);
1137 }
1138
1139 /* Closes connection to remote end. Free's all allocated data except
1140    for some information such as nickname etc. that are valid at all time. 
1141    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
1142    provided it will be checked whether the sock and `conn->sock' are the
1143    same (they can be different, ie. a socket can use `conn' as its
1144    connection but `conn->sock' might be actually a different connection
1145    than the `sock'). */
1146
1147 void silc_client_close_connection(SilcClient client,
1148                                   SilcSocketConnection sock,
1149                                   SilcClientConnection conn)
1150 {
1151   int del = FALSE;
1152
1153   if (!sock || (sock && conn->sock == sock))
1154     del = TRUE;
1155   if (!sock)
1156     sock = conn->sock;
1157
1158   /* We won't listen for this connection anymore */
1159   silc_schedule_unset_listen_fd(sock->sock);
1160
1161   /* Unregister all tasks */
1162   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1163   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1164
1165   /* Close the actual connection */
1166   silc_net_close_connection(sock->sock);
1167
1168   /* Free everything */
1169   if (del && sock->user_data) {
1170     /* XXX Free all client entries and channel entries. */
1171
1172     client->ops->say(client, sock->user_data,
1173                      "Closed connection to host %s", sock->hostname);
1174
1175     /* Clear ID caches */
1176     silc_idcache_del_all(conn->client_cache);
1177     silc_idcache_del_all(conn->channel_cache);
1178
1179     /* Free data */
1180     if (conn->remote_host)
1181       silc_free(conn->remote_host);
1182     if (conn->local_id)
1183       silc_free(conn->local_id);
1184     if (conn->local_id_data)
1185       silc_free(conn->local_id_data);
1186     if (conn->send_key)
1187       silc_cipher_free(conn->send_key);
1188     if (conn->receive_key)
1189       silc_cipher_free(conn->receive_key);
1190     if (conn->hmac_send)        /* conn->hmac_receive is same */
1191       silc_hmac_free(conn->hmac_send);
1192     if (conn->pending_commands)
1193       silc_dlist_uninit(conn->pending_commands);
1194     if (conn->rekey)
1195       silc_free(conn->rekey);
1196
1197     conn->sock = NULL;
1198     conn->remote_port = 0;
1199     conn->remote_type = 0;
1200     conn->send_key = NULL;
1201     conn->receive_key = NULL;
1202     conn->hmac_send = NULL;
1203     conn->hmac_receive = NULL;
1204     conn->local_id = NULL;
1205     conn->local_id_data = NULL;
1206     conn->remote_host = NULL;
1207     conn->current_channel = NULL;
1208     conn->pending_commands = NULL;
1209     conn->rekey = NULL;
1210
1211     silc_client_del_connection(client, conn);
1212   }
1213
1214   if (sock->protocol) {
1215     silc_protocol_free(sock->protocol);
1216     sock->protocol = NULL;
1217   }
1218   silc_socket_free(sock);
1219 }
1220
1221 /* Called when we receive disconnection packet from server. This 
1222    closes our end properly and displays the reason of the disconnection
1223    on the screen. */
1224
1225 void silc_client_disconnected_by_server(SilcClient client,
1226                                         SilcSocketConnection sock,
1227                                         SilcBuffer message)
1228 {
1229   char *msg;
1230
1231   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1232
1233   msg = silc_calloc(message->len + 1, sizeof(char));
1234   memcpy(msg, message->data, message->len);
1235   client->ops->say(client, sock->user_data, msg);
1236   silc_free(msg);
1237
1238   SILC_SET_DISCONNECTED(sock);
1239   silc_client_close_connection(client, sock, sock->user_data);
1240 }
1241
1242 /* Received error message from server. Display it on the screen. 
1243    We don't take any action what so ever of the error message. */
1244
1245 void silc_client_error_by_server(SilcClient client,
1246                                  SilcSocketConnection sock,
1247                                  SilcBuffer message)
1248 {
1249   char *msg;
1250
1251   msg = silc_calloc(message->len + 1, sizeof(char));
1252   memcpy(msg, message->data, message->len);
1253   client->ops->say(client, sock->user_data, msg);
1254   silc_free(msg);
1255 }
1256
1257 /* Processes the received new Client ID from server. Old Client ID is
1258    deleted from cache and new one is added. */
1259
1260 void silc_client_receive_new_id(SilcClient client,
1261                                 SilcSocketConnection sock,
1262                                 SilcIDPayload idp)
1263 {
1264   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1265   int connecting = FALSE;
1266
1267   if (!conn->local_entry)
1268     connecting = TRUE;
1269
1270   /* Delete old ID from ID cache */
1271   if (conn->local_id) {
1272     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1273     silc_free(conn->local_id);
1274   }
1275   
1276   /* Save the new ID */
1277
1278   if (conn->local_id_data)
1279     silc_free(conn->local_id_data);
1280
1281   conn->local_id = silc_id_payload_get_id(idp);
1282   conn->local_id_data = silc_id_payload_get_data(idp);
1283   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1284
1285   if (!conn->local_entry)
1286     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1287
1288   conn->local_entry->nickname = conn->nickname;
1289   if (!conn->local_entry->username) {
1290     conn->local_entry->username = 
1291       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1292                   sizeof(conn->local_entry->username));
1293     sprintf(conn->local_entry->username, "%s@%s", client->username,
1294             client->hostname);
1295   }
1296   conn->local_entry->server = strdup(conn->remote_host);
1297   conn->local_entry->id = conn->local_id;
1298   
1299   /* Put it to the ID cache */
1300   silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id, 
1301                    (void *)conn->local_entry, FALSE);
1302
1303   /* Notify application of successful connection. We do it here now that
1304      we've received the Client ID and are allowed to send traffic. */
1305   if (connecting)
1306     client->ops->connect(client, conn, TRUE);
1307 }
1308
1309 /* Processed received Channel ID for a channel. This is called when client
1310    joins to channel and server replies with channel ID. The ID is cached. 
1311    Returns the created channel entry. */
1312
1313 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1314                                             SilcSocketConnection sock,
1315                                             char *channel_name,
1316                                             uint32 mode, 
1317                                             SilcIDPayload idp)
1318 {
1319   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1320   SilcChannelEntry channel;
1321
1322   SILC_LOG_DEBUG(("New channel ID"));
1323
1324   channel = silc_calloc(1, sizeof(*channel));
1325   channel->channel_name = channel_name;
1326   channel->id = silc_id_payload_get_id(idp);
1327   channel->mode = mode;
1328   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1329
1330   conn->current_channel = channel;
1331
1332   /* Put it to the ID cache */
1333   silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id, 
1334                    (void *)channel, FALSE);
1335
1336   return channel;
1337 }
1338
1339 /* Removes a client entry from all channel it has joined. This really is
1340    a performance killer (client_entry should have pointers to channel 
1341    entry list). */
1342
1343 void silc_client_remove_from_channels(SilcClient client,
1344                                       SilcClientConnection conn,
1345                                       SilcClientEntry client_entry)
1346 {
1347   SilcIDCacheEntry id_cache;
1348   SilcIDCacheList list;
1349   SilcChannelEntry channel;
1350   SilcChannelUser chu;
1351
1352   if (!silc_idcache_get_all(conn->channel_cache, &list))
1353     return;
1354
1355   silc_idcache_list_first(list, &id_cache);
1356   channel = (SilcChannelEntry)id_cache->context;
1357   
1358   while (channel) {
1359     
1360     /* Remove client from channel */
1361     silc_list_start(channel->clients);
1362     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1363       if (chu->client == client_entry) {
1364         silc_list_del(channel->clients, chu);
1365         silc_free(chu);
1366         break;
1367       }
1368     }
1369
1370     if (!silc_idcache_list_next(list, &id_cache))
1371       break;
1372     
1373     channel = (SilcChannelEntry)id_cache->context;
1374   }
1375
1376   silc_idcache_list_free(list);
1377 }
1378
1379 /* Replaces `old' client entries from all channels to `new' client entry.
1380    This can be called for example when nickname changes and old ID entry
1381    is replaced from ID cache with the new one. If the old ID entry is only
1382    updated, then this fucntion needs not to be called. */
1383
1384 void silc_client_replace_from_channels(SilcClient client, 
1385                                        SilcClientConnection conn,
1386                                        SilcClientEntry old,
1387                                        SilcClientEntry new)
1388 {
1389   SilcIDCacheEntry id_cache;
1390   SilcIDCacheList list;
1391   SilcChannelEntry channel;
1392   SilcChannelUser chu;
1393
1394   if (!silc_idcache_get_all(conn->channel_cache, &list))
1395     return;
1396
1397   silc_idcache_list_first(list, &id_cache);
1398   channel = (SilcChannelEntry)id_cache->context;
1399   
1400   while (channel) {
1401     
1402     /* Replace client entry */
1403     silc_list_start(channel->clients);
1404     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1405       if (chu->client == old) {
1406         chu->client = new;
1407         break;
1408       }
1409     }
1410
1411     if (!silc_idcache_list_next(list, &id_cache))
1412       break;
1413     
1414     channel = (SilcChannelEntry)id_cache->context;
1415   }
1416
1417   silc_idcache_list_free(list);
1418 }
1419
1420 /* Parses mode mask and returns the mode as string. */
1421
1422 char *silc_client_chmode(uint32 mode, SilcChannelEntry channel)
1423 {
1424   char string[100];
1425
1426   if (!mode)
1427     return NULL;
1428
1429   memset(string, 0, sizeof(string));
1430
1431   if (mode & SILC_CHANNEL_MODE_PRIVATE)
1432     strncat(string, "p", 1);
1433
1434   if (mode & SILC_CHANNEL_MODE_SECRET)
1435     strncat(string, "s", 1);
1436
1437   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
1438     strncat(string, "k", 1);
1439
1440   if (mode & SILC_CHANNEL_MODE_INVITE)
1441     strncat(string, "i", 1);
1442
1443   if (mode & SILC_CHANNEL_MODE_TOPIC)
1444     strncat(string, "t", 1);
1445
1446   if (mode & SILC_CHANNEL_MODE_ULIMIT)
1447     strncat(string, "l", 1);
1448
1449   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
1450     strncat(string, "a", 1);
1451
1452   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
1453     strncat(string, "f", 1);
1454
1455   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1456     char cipher[30];
1457     memset(cipher, 0, sizeof(cipher));
1458     snprintf(cipher, sizeof(cipher), " c (%s)", 
1459              channel->channel_key->cipher->name);
1460     strncat(string, cipher, strlen(cipher));
1461   }
1462
1463   if (mode & SILC_CHANNEL_MODE_HMAC) {
1464     char hmac[30];
1465     memset(hmac, 0, sizeof(hmac));
1466     snprintf(hmac, sizeof(hmac), " h (%s)", 
1467              channel->hmac->hmac->name);
1468     strncat(string, hmac, strlen(hmac));
1469   }
1470
1471   /* Rest of mode is ignored */
1472
1473   return strdup(string);
1474 }
1475
1476 /* Parses channel user mode mask and returns te mode as string */
1477
1478 char *silc_client_chumode(uint32 mode)
1479 {
1480   char string[4];
1481
1482   if (!mode)
1483     return NULL;
1484
1485   memset(string, 0, sizeof(string));
1486
1487   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1488     strncat(string, "f", 1);
1489
1490   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1491     strncat(string, "o", 1);
1492
1493   return strdup(string);
1494 }
1495
1496 /* Parses channel user mode and returns it as special mode character. */
1497
1498 char *silc_client_chumode_char(uint32 mode)
1499 {
1500   char string[4];
1501
1502   if (!mode)
1503     return NULL;
1504
1505   memset(string, 0, sizeof(string));
1506
1507   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1508     strncat(string, "*", 1);
1509
1510   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1511     strncat(string, "@", 1);
1512
1513   return strdup(string);
1514 }
1515
1516 /* Registers failure timeout to process the received failure packet
1517    with timeout. */
1518
1519 void silc_client_process_failure(SilcClient client,
1520                                  SilcSocketConnection sock,
1521                                  SilcPacketContext *packet)
1522 {
1523   uint32 failure = 0;
1524
1525   if (sock->protocol) {
1526     if (packet->buffer->len >= 4)
1527       SILC_GET32_MSB(failure, packet->buffer->data);
1528
1529     /* Notify application */
1530     client->ops->failure(client, sock->user_data, sock->protocol,
1531                          (void *)failure);
1532   }
1533 }
1534
1535 /* A timeout callback for the re-key. We will be the initiator of the
1536    re-key protocol. */
1537
1538 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1539 {
1540   SilcSocketConnection sock = (SilcSocketConnection)context;
1541   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1542   SilcClient client = (SilcClient)conn->rekey->context;
1543   SilcProtocol protocol;
1544   SilcClientRekeyInternalContext *proto_ctx;
1545
1546   SILC_LOG_DEBUG(("Start"));
1547
1548   /* Allocate internal protocol context. This is sent as context
1549      to the protocol. */
1550   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1551   proto_ctx->client = (void *)client;
1552   proto_ctx->sock = silc_socket_dup(sock);
1553   proto_ctx->responder = FALSE;
1554   proto_ctx->pfs = conn->rekey->pfs;
1555       
1556   /* Perform rekey protocol. Will call the final callback after the
1557      protocol is over. */
1558   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1559                       &protocol, proto_ctx, silc_client_rekey_final);
1560   sock->protocol = protocol;
1561       
1562   /* Run the protocol */
1563   protocol->execute(client->timeout_queue, 0, protocol, 
1564                     sock->sock, 0, 0);
1565
1566   /* Re-register re-key timeout */
1567   silc_task_register(client->timeout_queue, sock->sock, 
1568                      silc_client_rekey_callback,
1569                      context, conn->rekey->timeout, 0,
1570                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1571 }
1572
1573 /* The final callback for the REKEY protocol. This will actually take the
1574    new key material into use. */
1575
1576 SILC_TASK_CALLBACK(silc_client_rekey_final)
1577 {
1578   SilcProtocol protocol = (SilcProtocol)context;
1579   SilcClientRekeyInternalContext *ctx =
1580     (SilcClientRekeyInternalContext *)protocol->context;
1581   SilcClient client = (SilcClient)ctx->client;
1582   SilcSocketConnection sock = ctx->sock;
1583
1584   SILC_LOG_DEBUG(("Start"));
1585
1586   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1587       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1588     /* Error occured during protocol */
1589     silc_protocol_cancel(client->timeout_queue, protocol);
1590     silc_protocol_free(protocol);
1591     sock->protocol = NULL;
1592     if (ctx->packet)
1593       silc_packet_context_free(ctx->packet);
1594     if (ctx->ske)
1595       silc_ske_free(ctx->ske);
1596     silc_socket_free(ctx->sock);
1597     silc_free(ctx);
1598     return;
1599   }
1600
1601   /* Cleanup */
1602   silc_protocol_free(protocol);
1603   sock->protocol = NULL;
1604   if (ctx->packet)
1605     silc_packet_context_free(ctx->packet);
1606   if (ctx->ske)
1607     silc_ske_free(ctx->ske);
1608   silc_socket_free(ctx->sock);
1609   silc_free(ctx);
1610 }