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
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 /* Frees client object and its internals. */
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. Returns FALSE if error occured, TRUE otherwise. */
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. This starts the scheduler from the utility library.
113    When this functions returns the execution of the appliation is over. */
114
115 void silc_client_run(SilcClient client)
116 {
117   SILC_LOG_DEBUG(("Running client"));
118
119   /* Start the scheduler, the heart of the SILC client. When this returns
120      the program will be terminated. */
121   silc_schedule();
122 }
123
124 /* Allocates and adds new connection to the client. This adds the allocated
125    connection to the connection table and returns a pointer to it. A client
126    can have multiple connections to multiple servers. Every connection must
127    be added to the client using this function. User data `context' may
128    be sent as argument. This function is normally used only if the 
129    application performed the connecting outside the library. The library
130    however may use this internally. */
131
132 SilcClientConnection silc_client_add_connection(SilcClient client,
133                                                 char *hostname,
134                                                 int port,
135                                                 void *context)
136 {
137   SilcClientConnection conn;
138   int i;
139
140   conn = silc_calloc(1, sizeof(*conn));
141
142   /* Initialize ID caches */
143   conn->client_cache = silc_idcache_alloc(0);
144   conn->channel_cache = silc_idcache_alloc(0);
145   conn->server_cache = silc_idcache_alloc(0);
146   conn->client = client;
147   conn->remote_host = strdup(hostname);
148   conn->remote_port = port;
149   conn->context = context;
150   conn->pending_commands = silc_dlist_init();
151
152   /* Add the connection to connections table */
153   for (i = 0; i < client->conns_count; i++)
154     if (client->conns && !client->conns[i]) {
155       client->conns[i] = conn;
156       return conn;
157     }
158
159   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
160                                * (client->conns_count + 1));
161   client->conns[client->conns_count] = conn;
162   client->conns_count++;
163
164   return conn;
165 }
166
167 /* Removes connection from client. Frees all memory. */
168
169 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
170 {
171   int i;
172
173   for (i = 0; i < client->conns_count; i++)
174     if (client->conns[i] == conn) {
175       if (conn->pending_commands)
176         silc_dlist_uninit(conn->pending_commands);
177       silc_free(conn);
178       client->conns[i] = NULL;
179     }
180 }
181
182 static int 
183 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
184 {
185   int sock;
186
187   /* XXX In the future we should give up this non-blocking connect all
188      together and use threads instead. */
189   /* Create connection to server asynchronously */
190   sock = silc_net_create_connection_async(ctx->port, ctx->host);
191   if (sock < 0)
192     return -1;
193
194   /* Register task that will receive the async connect and will
195      read the result. */
196   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
197                                  silc_client_connect_to_server_start,
198                                  (void *)ctx, 0, 0, 
199                                  SILC_TASK_FD,
200                                  SILC_TASK_PRI_NORMAL);
201   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
202   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
203
204   ctx->sock = sock;
205
206   return sock;
207 }
208
209 /* Connects to remote server. This is the main routine used to connect
210    to SILC server. Returns -1 on error and the created socket otherwise. 
211    The `context' is user context that is saved into the SilcClientConnection
212    that is created after the connection is created. Note that application
213    may handle the connecting process outside the library. If this is the
214    case then this function is not used at all. When the connecting is
215    done the `connect' client operation is called. */
216
217 int silc_client_connect_to_server(SilcClient client, int port,
218                                   char *host, void *context)
219 {
220   SilcClientInternalConnectContext *ctx;
221   SilcClientConnection conn;
222   int sock;
223
224   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
225                   port, host));
226
227   conn = silc_client_add_connection(client, host, port, context);
228
229   client->ops->say(client, conn, 
230                    "Connecting to port %d of server %s", port, host);
231
232   /* Allocate internal context for connection process. This is
233      needed as we are doing async connecting. */
234   ctx = silc_calloc(1, sizeof(*ctx));
235   ctx->client = client;
236   ctx->conn = conn;
237   ctx->host = strdup(host);
238   ctx->port = port;
239   ctx->tries = 0;
240
241   /* Do the actual connecting process */
242   sock = silc_client_connect_to_server_internal(ctx);
243   if (sock == -1)
244     silc_client_del_connection(client, conn);
245   return sock;
246 }
247
248 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
249    key material between client and server.  This function can be called
250    directly if application is performing its own connecting and does not
251    use the connecting provided by this library. This function is normally
252    used only if the application performed the connecting outside the library.
253    The library however may use this internally. */
254
255 int silc_client_start_key_exchange(SilcClient client,
256                                    SilcClientConnection conn,
257                                    int fd)
258 {
259   SilcProtocol protocol;
260   SilcClientKEInternalContext *proto_ctx;
261   void *context;
262
263   /* Allocate new socket connection object */
264   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
265
266   conn->nickname = strdup(client->username);
267   conn->sock->hostname = conn->remote_host;
268   conn->sock->ip = strdup(conn->remote_host);
269   conn->sock->port = conn->remote_port;
270
271   /* Allocate internal Key Exchange context. This is sent to the
272      protocol as context. */
273   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
274   proto_ctx->client = (void *)client;
275   proto_ctx->sock = conn->sock;
276   proto_ctx->rng = client->rng;
277   proto_ctx->responder = FALSE;
278   proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
279
280   /* Perform key exchange protocol. silc_client_connect_to_server_final
281      will be called after the protocol is finished. */
282   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
283                       &protocol, (void *)proto_ctx,
284                       silc_client_connect_to_server_second);
285   if (!protocol) {
286     client->ops->say(client, conn, 
287                      "Error: Could not start authentication protocol");
288     return FALSE;
289   }
290   conn->sock->protocol = protocol;
291
292   /* Register the connection for network input and output. This sets
293      that scheduler will listen for incoming packets for this connection 
294      and sets that outgoing packets may be sent to this connection as well.
295      However, this doesn't set the scheduler for outgoing traffic, it will 
296      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
297      later when outgoing data is available. */
298   context = (void *)client;
299   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
300
301   /* Execute the protocol */
302   protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
303   return TRUE;
304 }
305
306 /* Start of the connection to the remote server. This is called after
307    succesful TCP/IP connection has been established to the remote host. */
308
309 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
310 {
311   SilcClientInternalConnectContext *ctx =
312     (SilcClientInternalConnectContext *)context;
313   SilcClient client = ctx->client;
314   SilcClientConnection conn = ctx->conn;
315   int opt, opt_len = sizeof(opt);
316
317   SILC_LOG_DEBUG(("Start"));
318
319   /* Check the socket status as it might be in error */
320   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
321   if (opt != 0) {
322     if (ctx->tries < 2) {
323       /* Connection failed but lets try again */
324       client->ops->say(client, conn, "Could not connect to server %s: %s",
325                        ctx->host, strerror(opt));
326       client->ops->say(client, conn, 
327                        "Connecting to port %d of server %s resumed", 
328                        ctx->port, ctx->host);
329
330       /* Unregister old connection try */
331       silc_schedule_unset_listen_fd(fd);
332       silc_net_close_connection(fd);
333       silc_task_unregister(client->io_queue, ctx->task);
334
335       /* Try again */
336       silc_client_connect_to_server_internal(ctx);
337       ctx->tries++;
338     } else {
339       /* Connection failed and we won't try anymore */
340       client->ops->say(client, conn, "Could not connect to server %s: %s",
341                        ctx->host, strerror(opt));
342       silc_schedule_unset_listen_fd(fd);
343       silc_net_close_connection(fd);
344       silc_task_unregister(client->io_queue, ctx->task);
345       silc_free(ctx);
346
347       /* Notify application of failure */
348       client->ops->connect(client, conn, FALSE);
349       silc_client_del_connection(client, conn);
350     }
351     return;
352   }
353
354   silc_schedule_unset_listen_fd(fd);
355   silc_task_unregister(client->io_queue, ctx->task);
356   silc_free(ctx);
357
358   if (!silc_client_start_key_exchange(client, conn, fd)) {
359     silc_net_close_connection(fd);
360     client->ops->connect(client, conn, FALSE);
361   }
362 }
363
364 /* Second part of the connecting to the server. This executed 
365    authentication protocol. */
366
367 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
368 {
369   SilcProtocol protocol = (SilcProtocol)context;
370   SilcClientKEInternalContext *ctx = 
371     (SilcClientKEInternalContext *)protocol->context;
372   SilcClient client = (SilcClient)ctx->client;
373   SilcSocketConnection sock = NULL;
374   SilcClientConnAuthInternalContext *proto_ctx;
375
376   SILC_LOG_DEBUG(("Start"));
377
378   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
379       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
380     /* Error occured during protocol */
381     SILC_LOG_DEBUG(("Error during KE protocol"));
382     silc_protocol_free(protocol);
383     silc_ske_free_key_material(ctx->keymat);
384     if (ctx->ske)
385       silc_ske_free(ctx->ske);
386     if (ctx->dest_id)
387       silc_free(ctx->dest_id);
388     ctx->sock->protocol = NULL;
389     silc_task_unregister_by_callback(client->timeout_queue,
390                                      silc_client_failure_callback);
391
392     /* Notify application of failure */
393     client->ops->connect(client, ctx->sock->user_data, FALSE);
394     silc_free(ctx);
395     return;
396   }
397
398   /* We now have the key material as the result of the key exchange
399      protocol. Take the key material into use. Free the raw key material
400      as soon as we've set them into use. */
401   silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
402                                    ctx->ske->prop->cipher,
403                                    ctx->ske->prop->pkcs,
404                                    ctx->ske->prop->hash,
405                                    ctx->ske->prop->hmac);
406   silc_ske_free_key_material(ctx->keymat);
407
408   /* Allocate internal context for the authentication protocol. This
409      is sent as context for the protocol. */
410   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
411   proto_ctx->client = (void *)client;
412   proto_ctx->sock = sock = ctx->sock;
413   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
414   proto_ctx->dest_id_type = ctx->dest_id_type;
415   proto_ctx->dest_id = ctx->dest_id;
416
417   /* Resolve the authentication method to be used in this connection */
418   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
419                                     sock->port, &proto_ctx->auth_meth,
420                                     &proto_ctx->auth_data, 
421                                     &proto_ctx->auth_data_len))
422     {
423       /* XXX do AUTH_REQUEST resolcing with server */
424       proto_ctx->auth_meth = SILC_AUTH_NONE;
425     }
426
427   /* Free old protocol as it is finished now */
428   silc_protocol_free(protocol);
429   if (ctx->packet)
430     silc_packet_context_free(ctx->packet);
431   silc_free(ctx);
432   /* silc_free(ctx->keymat....); */
433   sock->protocol = NULL;
434
435   /* Allocate the authentication protocol. This is allocated here
436      but we won't start it yet. We will be receiving party of this
437      protocol thus we will wait that connecting party will make
438      their first move. */
439   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
440                       &sock->protocol, (void *)proto_ctx, 
441                       silc_client_connect_to_server_final);
442
443   /* Execute the protocol */
444   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
445 }
446
447 /* Finalizes the connection to the remote SILC server. This is called
448    after authentication protocol has been completed. This send our
449    user information to the server to receive our client ID from
450    server. */
451
452 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
453 {
454   SilcProtocol protocol = (SilcProtocol)context;
455   SilcClientConnAuthInternalContext *ctx = 
456     (SilcClientConnAuthInternalContext *)protocol->context;
457   SilcClient client = (SilcClient)ctx->client;
458   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
459   SilcBuffer packet;
460
461   SILC_LOG_DEBUG(("Start"));
462
463   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
464       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
465     /* Error occured during protocol */
466     SILC_LOG_DEBUG(("Error during authentication protocol"));
467     silc_protocol_free(protocol);
468     if (ctx->auth_data)
469       silc_free(ctx->auth_data);
470     if (ctx->ske)
471       silc_ske_free(ctx->ske);
472     if (ctx->dest_id)
473       silc_free(ctx->dest_id);
474     conn->sock->protocol = NULL;
475     silc_task_unregister_by_callback(client->timeout_queue,
476                                      silc_client_failure_callback);
477
478     /* Notify application of failure */
479     client->ops->connect(client, ctx->sock->user_data, FALSE);
480     silc_free(ctx);
481     return;
482   }
483
484   /* Send NEW_CLIENT packet to the server. We will become registered
485      to the SILC network after sending this packet and we will receive
486      client ID from the server. */
487   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
488                              strlen(client->realname));
489   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
490   silc_buffer_format(packet,
491                      SILC_STR_UI_SHORT(strlen(client->username)),
492                      SILC_STR_UI_XNSTRING(client->username,
493                                           strlen(client->username)),
494                      SILC_STR_UI_SHORT(strlen(client->realname)),
495                      SILC_STR_UI_XNSTRING(client->realname,
496                                           strlen(client->realname)),
497                      SILC_STR_END);
498
499   /* Send the packet */
500   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
501                           NULL, 0, NULL, NULL, 
502                           packet->data, packet->len, TRUE);
503   silc_buffer_free(packet);
504
505   /* Save remote ID. */
506   conn->remote_id = ctx->dest_id;
507   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
508   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
509
510   silc_task_unregister_by_callback(client->timeout_queue,
511                                    silc_client_failure_callback);
512   silc_protocol_free(protocol);
513   if (ctx->auth_data)
514     silc_free(ctx->auth_data);
515   if (ctx->ske)
516     silc_ske_free(ctx->ske);
517   silc_free(ctx);
518   conn->sock->protocol = NULL;
519 }
520
521 /* Internal routine that sends packet or marks packet to be sent. This
522    is used directly only in special cases. Normal cases should use
523    silc_server_packet_send. Returns < 0 on error. */
524
525 int silc_client_packet_send_real(SilcClient client,
526                                  SilcSocketConnection sock,
527                                  int force_send)
528 {
529   int ret;
530
531   /* Send the packet */
532   ret = silc_packet_send(sock, force_send);
533   if (ret != -2)
534     return ret;
535
536   /* Mark that there is some outgoing data available for this connection. 
537      This call sets the connection both for input and output (the input
538      is set always and this call keeps the input setting, actually). 
539      Actual data sending is performed by silc_client_packet_process. */
540   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
541
542   /* Mark to socket that data is pending in outgoing buffer. This flag
543      is needed if new data is added to the buffer before the earlier
544      put data is sent to the network. */
545   SILC_SET_OUTBUF_PENDING(sock);
546
547   return 0;
548 }
549
550 /* Packet processing callback. This is used to send and receive packets
551    from network. This is generic task. */
552
553 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
554 {
555   SilcClient client = (SilcClient)context;
556   SilcSocketConnection sock = NULL;
557   SilcClientConnection conn;
558   int ret;
559
560   SILC_LOG_DEBUG(("Processing packet"));
561
562   SILC_CLIENT_GET_SOCK(client, fd, sock);
563   if (sock == NULL)
564     return;
565
566   conn = (SilcClientConnection)sock->user_data;
567
568   /* Packet sending */
569   if (type == SILC_TASK_WRITE) {
570     SILC_LOG_DEBUG(("Writing data to connection"));
571
572     if (sock->outbuf->data - sock->outbuf->head)
573       silc_buffer_push(sock->outbuf, 
574                        sock->outbuf->data - sock->outbuf->head);
575
576     ret = silc_client_packet_send_real(client, sock, TRUE);
577
578     /* If returned -2 could not write to connection now, will do
579        it later. */
580     if (ret == -2)
581       return;
582     
583     /* The packet has been sent and now it is time to set the connection
584        back to only for input. When there is again some outgoing data 
585        available for this connection it will be set for output as well. 
586        This call clears the output setting and sets it only for input. */
587     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
588     SILC_UNSET_OUTBUF_PENDING(sock);
589
590     silc_buffer_clear(sock->outbuf);
591     return;
592   }
593
594   /* Packet receiving */
595   if (type == SILC_TASK_READ) {
596     SILC_LOG_DEBUG(("Reading data from connection"));
597
598     /* Read data from network */
599     ret = silc_packet_receive(sock);
600     if (ret < 0)
601       return;
602     
603     /* EOF */
604     if (ret == 0) {
605       SILC_LOG_DEBUG(("Read EOF"));
606
607       /* If connection is disconnecting already we will finally
608          close the connection */
609       if (SILC_IS_DISCONNECTING(sock)) {
610         client->ops->disconnect(client, conn);
611         silc_client_close_connection(client, conn);
612         return;
613       }
614       
615       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
616       client->ops->disconnect(client, conn);
617       silc_client_close_connection(client, conn);
618       return;
619     }
620
621     /* Process the packet. This will call the parser that will then
622        decrypt and parse the packet. */
623     silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
624                                 silc_client_packet_parse, client);
625   }
626 }
627
628 /* Parses whole packet, received earlier. */
629
630 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
631 {
632   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
633   SilcClient client = (SilcClient)parse_ctx->context;
634   SilcPacketContext *packet = parse_ctx->packet;
635   SilcBuffer buffer = packet->buffer;
636   SilcSocketConnection sock = parse_ctx->sock;
637   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
638   int ret;
639
640   SILC_LOG_DEBUG(("Start"));
641
642   /* Decrypt the received packet */
643   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
644   if (ret < 0)
645     goto out;
646
647   if (ret == 0) {
648     /* Parse the packet. Packet type is returned. */
649     ret = silc_packet_parse(packet);
650   } else {
651     /* Parse the packet header in special way as this is "special"
652        packet type. */
653     ret = silc_packet_parse_special(packet);
654   }
655
656   if (ret == SILC_PACKET_NONE)
657     goto out;
658
659   /* Parse the incoming packet type */
660   silc_client_packet_parse_type(client, sock, packet);
661
662  out:
663   silc_buffer_clear(sock->inbuf);
664   silc_packet_context_free(packet);
665   silc_free(parse_ctx);
666 }
667
668 /* Parser callback called by silc_packet_receive_process. Thie merely
669    registers timeout that will handle the actual parsing when appropriate. */
670
671 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
672 {
673   SilcClient client = (SilcClient)parser_context->context;
674
675   /* Parse the packet */
676   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
677                      silc_client_packet_parse_real,
678                      (void *)parser_context, 0, 1, 
679                      SILC_TASK_TIMEOUT,
680                      SILC_TASK_PRI_NORMAL);
681 }
682   
683 /* Parses the packet type and calls what ever routines the packet type
684    requires. This is done for all incoming packets. */
685
686 void silc_client_packet_parse_type(SilcClient client, 
687                                    SilcSocketConnection sock,
688                                    SilcPacketContext *packet)
689 {
690   SilcBuffer buffer = packet->buffer;
691   SilcPacketType type = packet->type;
692
693   SILC_LOG_DEBUG(("Parsing packet type %d", type));
694
695   /* Parse the packet type */
696   switch(type) {
697   case SILC_PACKET_DISCONNECT:
698     silc_client_disconnected_by_server(client, sock, buffer);
699     break;
700   case SILC_PACKET_SUCCESS:
701     /*
702      * Success received for something. For now we can have only
703      * one protocol for connection executing at once hence this
704      * success message is for whatever protocol is executing currently.
705      */
706     if (sock->protocol) {
707       sock->protocol->execute(client->timeout_queue, 0,
708                               sock->protocol, sock->sock, 0, 0);
709     }
710     break;
711   case SILC_PACKET_FAILURE:
712     /*
713      * Failure received for some protocol. Set the protocol state to 
714      * error and call the protocol callback. This fill cause error on
715      * protocol and it will call the final callback.
716      */
717     silc_client_process_failure(client, sock, packet);
718     break;
719   case SILC_PACKET_REJECT:
720     break;
721
722   case SILC_PACKET_NOTIFY:
723     /*
724      * Received notify message 
725      */
726     silc_client_notify_by_server(client, sock, packet);
727     break;
728
729   case SILC_PACKET_ERROR:
730     /*
731      * Received error message
732      */
733     silc_client_error_by_server(client, sock, buffer);
734     break;
735
736   case SILC_PACKET_CHANNEL_MESSAGE:
737     /*
738      * Received message to (from, actually) a channel
739      */
740     silc_client_channel_message(client, sock, packet);
741     break;
742   case SILC_PACKET_CHANNEL_KEY:
743     /*
744      * Received key for a channel. By receiving this key the client will be
745      * able to talk to the channel it has just joined. This can also be
746      * a new key for existing channel as keys expire peridiocally.
747      */
748     silc_client_receive_channel_key(client, sock, buffer);
749     break;
750
751   case SILC_PACKET_PRIVATE_MESSAGE:
752     /*
753      * Received private message
754      */
755     silc_client_private_message(client, sock, packet);
756     break;
757   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
758     /*
759      * Received private message key
760      */
761     break;
762
763   case SILC_PACKET_COMMAND_REPLY:
764     /*
765      * Recived reply for a command
766      */
767     silc_client_command_reply_process(client, sock, packet);
768     break;
769
770   case SILC_PACKET_KEY_EXCHANGE:
771     if (sock->protocol) {
772       SilcClientKEInternalContext *proto_ctx = 
773         (SilcClientKEInternalContext *)sock->protocol->context;
774
775       proto_ctx->packet = silc_packet_context_dup(packet);
776       proto_ctx->dest_id_type = packet->src_id_type;
777       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
778                                           packet->src_id_type);
779       if (!proto_ctx->dest_id)
780         break;
781
782       /* Let the protocol handle the packet */
783       sock->protocol->execute(client->timeout_queue, 0,
784                               sock->protocol, sock->sock, 0, 0);
785     } else {
786       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
787                       "protocol active, packet dropped."));
788
789       /* XXX Trigger KE protocol?? Rekey actually! */
790     }
791     break;
792
793   case SILC_PACKET_KEY_EXCHANGE_1:
794     if (sock->protocol) {
795
796     } else {
797       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
798                       "protocol active, packet dropped."));
799     }
800     break;
801   case SILC_PACKET_KEY_EXCHANGE_2:
802     if (sock->protocol) {
803       SilcClientKEInternalContext *proto_ctx = 
804         (SilcClientKEInternalContext *)sock->protocol->context;
805
806       if (proto_ctx->packet)
807         silc_packet_context_free(proto_ctx->packet);
808
809       proto_ctx->packet = silc_packet_context_dup(packet);
810       proto_ctx->dest_id_type = packet->src_id_type;
811       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
812                                           packet->src_id_type);
813       if (!proto_ctx->dest_id)
814         break;
815
816       /* Let the protocol handle the packet */
817       sock->protocol->execute(client->timeout_queue, 0,
818                               sock->protocol, sock->sock, 0, 0);
819     } else {
820       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
821                       "protocol active, packet dropped."));
822     }
823     break;
824
825   case SILC_PACKET_NEW_ID:
826     {
827       /*
828        * Received new ID from server. This packet is received at
829        * the connection to the server.  New ID is also received when 
830        * user changes nickname but in that case the new ID is received
831        * as command reply and not as this packet type.
832        */
833       SilcIDPayload idp;
834
835       idp = silc_id_payload_parse(buffer);
836       if (!idp)
837         break;
838       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
839         break;
840
841       silc_client_receive_new_id(client, sock, idp);
842       silc_id_payload_free(idp);
843       break;
844     }
845
846   case SILC_PACKET_HEARTBEAT:
847     /*
848      * Received heartbeat packet
849      */
850     SILC_LOG_DEBUG(("Heartbeat packet"));
851     break;
852
853   case SILC_PACKET_KEY_AGREEMENT:
854     /*
855      * Received key agreement packet
856      */
857     SILC_LOG_DEBUG(("Key agreement packet"));
858     silc_client_key_agreement(client, sock, packet);
859     break;
860
861   default:
862     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
863     break;
864   }
865 }
866
867 /* Sends packet. This doesn't actually send the packet instead it assembles
868    it and marks it to be sent. However, if force_send is TRUE the packet
869    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
870    will be derived from sock argument. Otherwise the valid arguments sent
871    are used. */
872
873 void silc_client_packet_send(SilcClient client, 
874                              SilcSocketConnection sock,
875                              SilcPacketType type, 
876                              void *dst_id,
877                              SilcIdType dst_id_type,
878                              SilcCipher cipher,
879                              SilcHmac hmac,
880                              unsigned char *data, 
881                              unsigned int data_len, 
882                              int force_send)
883 {
884   SilcPacketContext packetdata;
885
886   SILC_LOG_DEBUG(("Sending packet, type %d", type));
887
888   /* Get data used in the packet sending, keys and stuff */
889   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
890     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
891       cipher = ((SilcClientConnection)sock->user_data)->send_key;
892
893     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
894       hmac = ((SilcClientConnection)sock->user_data)->hmac;
895
896     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
897       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
898       dst_id_type = SILC_ID_SERVER;
899     }
900   }
901
902   /* Set the packet context pointers */
903   packetdata.flags = 0;
904   packetdata.type = type;
905   if (((SilcClientConnection)sock->user_data)->local_id_data)
906     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
907   else 
908     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
909   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
910   packetdata.src_id_type = SILC_ID_CLIENT;
911   if (dst_id) {
912     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
913     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
914     packetdata.dst_id_type = dst_id_type;
915   } else {
916     packetdata.dst_id = NULL;
917     packetdata.dst_id_len = 0;
918     packetdata.dst_id_type = SILC_ID_NONE;
919   }
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 /* Closes connection to remote end. Free's all allocated data except
955    for some information such as nickname etc. that are valid at all time. */
956
957 void silc_client_close_connection(SilcClient client,
958                                   SilcClientConnection conn)
959 {
960   SilcSocketConnection sock = conn->sock;
961
962   /* We won't listen for this connection anymore */
963   silc_schedule_unset_listen_fd(sock->sock);
964
965   /* Unregister all tasks */
966   silc_task_unregister_by_fd(client->io_queue, sock->sock);
967   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
968
969   /* Close the actual connection */
970   silc_net_close_connection(sock->sock);
971
972   client->ops->say(client, sock->user_data,
973                    "Closed connection to host %s", sock->hostname);
974
975   /* Free everything */
976   if (sock->user_data) {
977     /* XXX Free all client entries and channel entries. */
978
979     /* Clear ID caches */
980     silc_idcache_del_all(conn->client_cache);
981     silc_idcache_del_all(conn->channel_cache);
982
983     /* Free data */
984     if (conn->remote_host)
985       silc_free(conn->remote_host);
986     if (conn->local_id)
987       silc_free(conn->local_id);
988     if (conn->local_id_data)
989       silc_free(conn->local_id_data);
990     if (conn->send_key)
991       silc_cipher_free(conn->send_key);
992     if (conn->receive_key)
993       silc_cipher_free(conn->receive_key);
994     if (conn->hmac)
995       silc_hmac_free(conn->hmac);
996     if (conn->hmac_key) {
997       memset(conn->hmac_key, 0, conn->hmac_key_len);
998       silc_free(conn->hmac_key);
999     }
1000     if (conn->pending_commands)
1001       silc_dlist_uninit(conn->pending_commands);
1002
1003     conn->sock = NULL;
1004     conn->remote_port = 0;
1005     conn->remote_type = 0;
1006     conn->send_key = NULL;
1007     conn->receive_key = NULL;
1008     conn->hmac = NULL;
1009     conn->hmac_key = NULL;
1010     conn->hmac_key_len = 0;
1011     conn->local_id = NULL;
1012     conn->local_id_data = NULL;
1013     conn->remote_host = NULL;
1014     conn->current_channel = NULL;
1015     conn->pending_commands = NULL;
1016
1017     silc_client_del_connection(client, conn);
1018   }
1019
1020   if (sock->protocol) {
1021     silc_protocol_free(sock->protocol);
1022     sock->protocol = NULL;
1023   }
1024   silc_socket_free(sock);
1025 }
1026
1027 /* Called when we receive disconnection packet from server. This 
1028    closes our end properly and displays the reason of the disconnection
1029    on the screen. */
1030
1031 void silc_client_disconnected_by_server(SilcClient client,
1032                                         SilcSocketConnection sock,
1033                                         SilcBuffer message)
1034 {
1035   char *msg;
1036
1037   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1038
1039   msg = silc_calloc(message->len + 1, sizeof(char));
1040   memcpy(msg, message->data, message->len);
1041   client->ops->say(client, sock->user_data, msg);
1042   silc_free(msg);
1043
1044   SILC_SET_DISCONNECTED(sock);
1045   silc_client_close_connection(client, sock->user_data);
1046 }
1047
1048 /* Received error message from server. Display it on the screen. 
1049    We don't take any action what so ever of the error message. */
1050
1051 void silc_client_error_by_server(SilcClient client,
1052                                  SilcSocketConnection sock,
1053                                  SilcBuffer message)
1054 {
1055   char *msg;
1056
1057   msg = silc_calloc(message->len + 1, sizeof(char));
1058   memcpy(msg, message->data, message->len);
1059   client->ops->say(client, sock->user_data, msg);
1060   silc_free(msg);
1061 }
1062
1063 /* Processes the received new Client ID from server. Old Client ID is
1064    deleted from cache and new one is added. */
1065
1066 void silc_client_receive_new_id(SilcClient client,
1067                                 SilcSocketConnection sock,
1068                                 SilcIDPayload idp)
1069 {
1070   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1071   int connecting = FALSE;
1072
1073   if (!conn->local_entry)
1074     connecting = TRUE;
1075
1076   /* Delete old ID from ID cache */
1077   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1078   
1079   /* Save the new ID */
1080   if (conn->local_id)
1081     silc_free(conn->local_id);
1082   if (conn->local_id_data)
1083     silc_free(conn->local_id_data);
1084
1085   conn->local_id = silc_id_payload_get_id(idp);
1086   conn->local_id_data = silc_id_payload_get_data(idp);
1087   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1088
1089   if (!conn->local_entry)
1090     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1091
1092   conn->local_entry->nickname = conn->nickname;
1093   if (!conn->local_entry->username) {
1094     conn->local_entry->username = 
1095       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1096                   sizeof(conn->local_entry->username));
1097     sprintf(conn->local_entry->username, "%s@%s", client->username,
1098             client->hostname);
1099   }
1100   conn->local_entry->server = strdup(conn->remote_host);
1101   conn->local_entry->id = conn->local_id;
1102   
1103   /* Put it to the ID cache */
1104   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1105                    conn->local_id, (void *)conn->local_entry, TRUE);
1106
1107   /* Notify application of successful connection. We do it here now that
1108      we've received the Client ID and are allowed to send traffic. */
1109   if (connecting)
1110     client->ops->connect(client, conn, TRUE);
1111 }
1112
1113 /* Processed received Channel ID for a channel. This is called when client
1114    joins to channel and server replies with channel ID. The ID is cached. 
1115    Returns the created channel entry. */
1116
1117 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1118                                             SilcSocketConnection sock,
1119                                             char *channel_name,
1120                                             unsigned int mode, 
1121                                             SilcIDPayload idp)
1122 {
1123   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1124   SilcChannelEntry channel;
1125
1126   SILC_LOG_DEBUG(("New channel ID"));
1127
1128   channel = silc_calloc(1, sizeof(*channel));
1129   channel->channel_name = channel_name;
1130   channel->id = silc_id_payload_get_id(idp);
1131   channel->mode = mode;
1132   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1133
1134   conn->current_channel = channel;
1135
1136   /* Put it to the ID cache */
1137   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1138                    (void *)channel->id, (void *)channel, TRUE);
1139
1140   return channel;
1141 }
1142
1143 /* Removes a client entry from all channel it has joined. This really is
1144    a performance killer (client_entry should have pointers to channel 
1145    entry list). */
1146
1147 void silc_client_remove_from_channels(SilcClient client,
1148                                       SilcClientConnection conn,
1149                                       SilcClientEntry client_entry)
1150 {
1151   SilcIDCacheEntry id_cache;
1152   SilcIDCacheList list;
1153   SilcChannelEntry channel;
1154   SilcChannelUser chu;
1155
1156   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
1157                                SILC_ID_CHANNEL, &list))
1158     return;
1159
1160   silc_idcache_list_first(list, &id_cache);
1161   channel = (SilcChannelEntry)id_cache->context;
1162   
1163   while (channel) {
1164     
1165     /* Remove client from channel */
1166     silc_list_start(channel->clients);
1167     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1168       if (chu->client == client_entry) {
1169         silc_list_del(channel->clients, chu);
1170         silc_free(chu);
1171         break;
1172       }
1173     }
1174
1175     if (!silc_idcache_list_next(list, &id_cache))
1176       break;
1177     
1178     channel = (SilcChannelEntry)id_cache->context;
1179   }
1180
1181   silc_idcache_list_free(list);
1182 }
1183
1184 /* Replaces `old' client entries from all channels to `new' client entry.
1185    This can be called for example when nickname changes and old ID entry
1186    is replaced from ID cache with the new one. If the old ID entry is only
1187    updated, then this fucntion needs not to be called. */
1188
1189 void silc_client_replace_from_channels(SilcClient client, 
1190                                        SilcClientConnection conn,
1191                                        SilcClientEntry old,
1192                                        SilcClientEntry new)
1193 {
1194   SilcIDCacheEntry id_cache;
1195   SilcIDCacheList list;
1196   SilcChannelEntry channel;
1197   SilcChannelUser chu;
1198
1199   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
1200                                SILC_ID_CHANNEL, &list))
1201     return;
1202
1203   silc_idcache_list_first(list, &id_cache);
1204   channel = (SilcChannelEntry)id_cache->context;
1205   
1206   while (channel) {
1207     
1208     /* Replace client entry */
1209     silc_list_start(channel->clients);
1210     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1211       if (chu->client == old) {
1212         chu->client = new;
1213         break;
1214       }
1215     }
1216
1217     if (!silc_idcache_list_next(list, &id_cache))
1218       break;
1219     
1220     channel = (SilcChannelEntry)id_cache->context;
1221   }
1222
1223   silc_idcache_list_free(list);
1224 }
1225
1226 /* Parses mode mask and returns the mode as string. */
1227
1228 char *silc_client_chmode(unsigned int mode)
1229 {
1230   char string[20];
1231
1232   if (!mode)
1233     return NULL;
1234
1235   memset(string, 0, sizeof(string));
1236
1237   if (mode & SILC_CHANNEL_MODE_PRIVATE)
1238     strncat(string, "p", 1);
1239
1240   if (mode & SILC_CHANNEL_MODE_SECRET)
1241     strncat(string, "s", 1);
1242
1243   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
1244     strncat(string, "k", 1);
1245
1246   if (mode & SILC_CHANNEL_MODE_INVITE)
1247     strncat(string, "i", 1);
1248
1249   if (mode & SILC_CHANNEL_MODE_TOPIC)
1250     strncat(string, "t", 1);
1251
1252   if (mode & SILC_CHANNEL_MODE_ULIMIT)
1253     strncat(string, "l", 1);
1254
1255   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
1256     strncat(string, "a", 1);
1257
1258   /* Rest of mode is ignored */
1259
1260   return strdup(string);
1261 }
1262
1263 /* Parses channel user mode mask and returns te mode as string */
1264
1265 char *silc_client_chumode(unsigned int mode)
1266 {
1267   char string[4];
1268
1269   if (!mode)
1270     return NULL;
1271
1272   memset(string, 0, sizeof(string));
1273
1274   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1275     strncat(string, "f", 1);
1276
1277   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1278     strncat(string, "o", 1);
1279
1280   return strdup(string);
1281 }
1282
1283 /* Parses channel user mode and returns it as special mode character. */
1284
1285 char *silc_client_chumode_char(unsigned int mode)
1286 {
1287   char string[4];
1288
1289   if (!mode)
1290     return NULL;
1291
1292   memset(string, 0, sizeof(string));
1293
1294   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1295     strncat(string, "*", 1);
1296
1297   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1298     strncat(string, "@", 1);
1299
1300   return strdup(string);
1301 }
1302
1303 /* Failure timeout callback. If this is called then we will immediately
1304    process the received failure. We always process the failure with timeout
1305    since we do not want to blindly trust to received failure packets. 
1306    This won't be called (the timeout is cancelled) if the failure was
1307    bogus (it is bogus if remote does not close the connection after sending
1308    the failure). */
1309
1310 SILC_TASK_CALLBACK_GLOBAL(silc_client_failure_callback)
1311 {
1312   SilcClientFailureContext *f = (SilcClientFailureContext *)context;
1313
1314   if (f->sock->protocol) {
1315     f->sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
1316     f->sock->protocol->execute(f->client->timeout_queue, 0,
1317                                f->sock->protocol, f->sock->sock, 0, 0);
1318     
1319     /* Notify application */
1320     f->client->ops->failure(f->client, f->sock->user_data, f->sock->protocol,
1321                             (void *)f->failure);
1322   }
1323
1324   silc_free(f);
1325 }
1326
1327 /* Registers failure timeout to process the received failure packet
1328    with timeout. */
1329
1330 void silc_client_process_failure(SilcClient client,
1331                                  SilcSocketConnection sock,
1332                                  SilcPacketContext *packet)
1333 {
1334   SilcClientFailureContext *f;
1335   unsigned int failure = 0;
1336
1337   if (sock->protocol) {
1338     if (packet->buffer->len >= 4)
1339       SILC_GET32_MSB(failure, packet->buffer->data);
1340
1341     f = silc_calloc(1, sizeof(*f));
1342     f->client = client;
1343     f->sock = sock;
1344     f->failure = failure;
1345
1346     /* We will wait 5 seconds to process this failure packet */
1347     silc_task_register(client->timeout_queue, sock->sock,
1348                        silc_client_failure_callback, (void *)f, 5, 0,
1349                        SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1350   }
1351 }