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 /* Callback function that the silc_packet_decrypt will call to make the
629    decision whether the packet is normal or special packet. We will 
630    return TRUE if it is normal and FALSE if it is special */
631
632 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
633                                             SilcBuffer buffer,
634                                             SilcPacketContext *packet,
635                                             void *context)
636 {
637
638   /* Packet is normal packet, if: 
639
640      1) packet is private message packet and does not have private key set
641      2) is other packet than channel message packet
642
643      all other packets are special packets 
644   */
645   if ((packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
646        !(buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY)) ||
647       packet_type != SILC_PACKET_CHANNEL_MESSAGE)
648     return TRUE;
649
650   return FALSE;
651 }
652
653 /* Parses whole packet, received earlier. */
654
655 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
656 {
657   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
658   SilcClient client = (SilcClient)parse_ctx->context;
659   SilcPacketContext *packet = parse_ctx->packet;
660   SilcBuffer buffer = packet->buffer;
661   SilcSocketConnection sock = parse_ctx->sock;
662   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
663   int ret;
664
665   SILC_LOG_DEBUG(("Start"));
666
667   /* Decrypt the received packet */
668   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet,
669                             silc_client_packet_decrypt_check, parse_ctx);
670   if (ret < 0)
671     goto out;
672
673   if (ret == 0) {
674     /* Parse the packet. Packet type is returned. */
675     ret = silc_packet_parse(packet);
676   } else {
677     /* Parse the packet header in special way as this is "special"
678        packet type. */
679     ret = silc_packet_parse_special(packet);
680   }
681
682   if (ret == SILC_PACKET_NONE)
683     goto out;
684
685   /* Parse the incoming packet type */
686   silc_client_packet_parse_type(client, sock, packet);
687
688  out:
689   silc_buffer_clear(sock->inbuf);
690   silc_packet_context_free(packet);
691   silc_free(parse_ctx);
692 }
693
694 /* Parser callback called by silc_packet_receive_process. Thie merely
695    registers timeout that will handle the actual parsing when appropriate. */
696
697 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
698 {
699   SilcClient client = (SilcClient)parser_context->context;
700
701   /* Parse the packet */
702   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
703                      silc_client_packet_parse_real,
704                      (void *)parser_context, 0, 1, 
705                      SILC_TASK_TIMEOUT,
706                      SILC_TASK_PRI_NORMAL);
707 }
708   
709 /* Parses the packet type and calls what ever routines the packet type
710    requires. This is done for all incoming packets. */
711
712 void silc_client_packet_parse_type(SilcClient client, 
713                                    SilcSocketConnection sock,
714                                    SilcPacketContext *packet)
715 {
716   SilcBuffer buffer = packet->buffer;
717   SilcPacketType type = packet->type;
718
719   SILC_LOG_DEBUG(("Parsing packet type %d", type));
720
721   /* Parse the packet type */
722   switch(type) {
723   case SILC_PACKET_DISCONNECT:
724     silc_client_disconnected_by_server(client, sock, buffer);
725     break;
726   case SILC_PACKET_SUCCESS:
727     /*
728      * Success received for something. For now we can have only
729      * one protocol for connection executing at once hence this
730      * success message is for whatever protocol is executing currently.
731      */
732     if (sock->protocol) {
733       sock->protocol->execute(client->timeout_queue, 0,
734                               sock->protocol, sock->sock, 0, 0);
735     }
736     break;
737   case SILC_PACKET_FAILURE:
738     /*
739      * Failure received for some protocol. Set the protocol state to 
740      * error and call the protocol callback. This fill cause error on
741      * protocol and it will call the final callback.
742      */
743     silc_client_process_failure(client, sock, packet);
744     break;
745   case SILC_PACKET_REJECT:
746     break;
747
748   case SILC_PACKET_NOTIFY:
749     /*
750      * Received notify message 
751      */
752     silc_client_notify_by_server(client, sock, packet);
753     break;
754
755   case SILC_PACKET_ERROR:
756     /*
757      * Received error message
758      */
759     silc_client_error_by_server(client, sock, buffer);
760     break;
761
762   case SILC_PACKET_CHANNEL_MESSAGE:
763     /*
764      * Received message to (from, actually) a channel
765      */
766     silc_client_channel_message(client, sock, packet);
767     break;
768   case SILC_PACKET_CHANNEL_KEY:
769     /*
770      * Received key for a channel. By receiving this key the client will be
771      * able to talk to the channel it has just joined. This can also be
772      * a new key for existing channel as keys expire peridiocally.
773      */
774     silc_client_receive_channel_key(client, sock, buffer);
775     break;
776
777   case SILC_PACKET_PRIVATE_MESSAGE:
778     /*
779      * Received private message
780      */
781     silc_client_private_message(client, sock, packet);
782     break;
783   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
784     /*
785      * Received private message key
786      */
787     break;
788
789   case SILC_PACKET_COMMAND_REPLY:
790     /*
791      * Recived reply for a command
792      */
793     silc_client_command_reply_process(client, sock, packet);
794     break;
795
796   case SILC_PACKET_KEY_EXCHANGE:
797     if (sock->protocol) {
798       SilcClientKEInternalContext *proto_ctx = 
799         (SilcClientKEInternalContext *)sock->protocol->context;
800
801       proto_ctx->packet = silc_packet_context_dup(packet);
802       proto_ctx->dest_id_type = packet->src_id_type;
803       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
804                                           packet->src_id_type);
805       if (!proto_ctx->dest_id)
806         break;
807
808       /* Let the protocol handle the packet */
809       sock->protocol->execute(client->timeout_queue, 0,
810                               sock->protocol, sock->sock, 0, 0);
811     } else {
812       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
813                       "protocol active, packet dropped."));
814
815       /* XXX Trigger KE protocol?? Rekey actually! */
816     }
817     break;
818
819   case SILC_PACKET_KEY_EXCHANGE_1:
820     if (sock->protocol) {
821
822     } else {
823       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
824                       "protocol active, packet dropped."));
825     }
826     break;
827   case SILC_PACKET_KEY_EXCHANGE_2:
828     if (sock->protocol) {
829       SilcClientKEInternalContext *proto_ctx = 
830         (SilcClientKEInternalContext *)sock->protocol->context;
831
832       if (proto_ctx->packet)
833         silc_packet_context_free(proto_ctx->packet);
834
835       proto_ctx->packet = silc_packet_context_dup(packet);
836       proto_ctx->dest_id_type = packet->src_id_type;
837       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
838                                           packet->src_id_type);
839       if (!proto_ctx->dest_id)
840         break;
841
842       /* Let the protocol handle the packet */
843       sock->protocol->execute(client->timeout_queue, 0,
844                               sock->protocol, sock->sock, 0, 0);
845     } else {
846       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
847                       "protocol active, packet dropped."));
848     }
849     break;
850
851   case SILC_PACKET_NEW_ID:
852     {
853       /*
854        * Received new ID from server. This packet is received at
855        * the connection to the server.  New ID is also received when 
856        * user changes nickname but in that case the new ID is received
857        * as command reply and not as this packet type.
858        */
859       SilcIDPayload idp;
860
861       idp = silc_id_payload_parse(buffer);
862       if (!idp)
863         break;
864       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
865         break;
866
867       silc_client_receive_new_id(client, sock, idp);
868       silc_id_payload_free(idp);
869       break;
870     }
871
872   case SILC_PACKET_HEARTBEAT:
873     /*
874      * Received heartbeat packet
875      */
876     SILC_LOG_DEBUG(("Heartbeat packet"));
877     break;
878
879   case SILC_PACKET_KEY_AGREEMENT:
880     /*
881      * Received key agreement packet
882      */
883     SILC_LOG_DEBUG(("Key agreement packet"));
884     silc_client_key_agreement(client, sock, packet);
885     break;
886
887   default:
888     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
889     break;
890   }
891 }
892
893 /* Sends packet. This doesn't actually send the packet instead it assembles
894    it and marks it to be sent. However, if force_send is TRUE the packet
895    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
896    will be derived from sock argument. Otherwise the valid arguments sent
897    are used. */
898
899 void silc_client_packet_send(SilcClient client, 
900                              SilcSocketConnection sock,
901                              SilcPacketType type, 
902                              void *dst_id,
903                              SilcIdType dst_id_type,
904                              SilcCipher cipher,
905                              SilcHmac hmac,
906                              unsigned char *data, 
907                              unsigned int data_len, 
908                              int force_send)
909 {
910   SilcPacketContext packetdata;
911
912   SILC_LOG_DEBUG(("Sending packet, type %d", type));
913
914   /* Get data used in the packet sending, keys and stuff */
915   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
916     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
917       cipher = ((SilcClientConnection)sock->user_data)->send_key;
918
919     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
920       hmac = ((SilcClientConnection)sock->user_data)->hmac;
921
922     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
923       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
924       dst_id_type = SILC_ID_SERVER;
925     }
926   }
927
928   /* Set the packet context pointers */
929   packetdata.flags = 0;
930   packetdata.type = type;
931   if (((SilcClientConnection)sock->user_data)->local_id_data)
932     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
933   else 
934     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
935   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
936   packetdata.src_id_type = SILC_ID_CLIENT;
937   if (dst_id) {
938     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
939     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
940     packetdata.dst_id_type = dst_id_type;
941   } else {
942     packetdata.dst_id = NULL;
943     packetdata.dst_id_len = 0;
944     packetdata.dst_id_type = SILC_ID_NONE;
945   }
946   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
947     packetdata.src_id_len + packetdata.dst_id_len;
948   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
949
950   /* Prepare outgoing data buffer for packet sending */
951   silc_packet_send_prepare(sock, 
952                            SILC_PACKET_HEADER_LEN +
953                            packetdata.src_id_len + 
954                            packetdata.dst_id_len,
955                            packetdata.padlen,
956                            data_len);
957
958   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
959
960   packetdata.buffer = sock->outbuf;
961
962   /* Put the data to the buffer */
963   if (data && data_len)
964     silc_buffer_put(sock->outbuf, data, data_len);
965
966   /* Create the outgoing packet */
967   silc_packet_assemble(&packetdata);
968
969   /* Encrypt the packet */
970   if (cipher)
971     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
972
973   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
974                    sock->outbuf->data, sock->outbuf->len);
975
976   /* Now actually send the packet */
977   silc_client_packet_send_real(client, sock, force_send);
978 }
979
980 /* Closes connection to remote end. Free's all allocated data except
981    for some information such as nickname etc. that are valid at all time. */
982
983 void silc_client_close_connection(SilcClient client,
984                                   SilcClientConnection conn)
985 {
986   SilcSocketConnection sock = conn->sock;
987
988   /* We won't listen for this connection anymore */
989   silc_schedule_unset_listen_fd(sock->sock);
990
991   /* Unregister all tasks */
992   silc_task_unregister_by_fd(client->io_queue, sock->sock);
993   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
994
995   /* Close the actual connection */
996   silc_net_close_connection(sock->sock);
997
998   client->ops->say(client, sock->user_data,
999                    "Closed connection to host %s", sock->hostname);
1000
1001   /* Free everything */
1002   if (sock->user_data) {
1003     /* XXX Free all client entries and channel entries. */
1004
1005     /* Clear ID caches */
1006     silc_idcache_del_all(conn->client_cache);
1007     silc_idcache_del_all(conn->channel_cache);
1008
1009     /* Free data */
1010     if (conn->remote_host)
1011       silc_free(conn->remote_host);
1012     if (conn->local_id)
1013       silc_free(conn->local_id);
1014     if (conn->local_id_data)
1015       silc_free(conn->local_id_data);
1016     if (conn->send_key)
1017       silc_cipher_free(conn->send_key);
1018     if (conn->receive_key)
1019       silc_cipher_free(conn->receive_key);
1020     if (conn->hmac)
1021       silc_hmac_free(conn->hmac);
1022     if (conn->hmac_key) {
1023       memset(conn->hmac_key, 0, conn->hmac_key_len);
1024       silc_free(conn->hmac_key);
1025     }
1026     if (conn->pending_commands)
1027       silc_dlist_uninit(conn->pending_commands);
1028
1029     conn->sock = NULL;
1030     conn->remote_port = 0;
1031     conn->remote_type = 0;
1032     conn->send_key = NULL;
1033     conn->receive_key = NULL;
1034     conn->hmac = NULL;
1035     conn->hmac_key = NULL;
1036     conn->hmac_key_len = 0;
1037     conn->local_id = NULL;
1038     conn->local_id_data = NULL;
1039     conn->remote_host = NULL;
1040     conn->current_channel = NULL;
1041     conn->pending_commands = NULL;
1042
1043     silc_client_del_connection(client, conn);
1044   }
1045
1046   if (sock->protocol) {
1047     silc_protocol_free(sock->protocol);
1048     sock->protocol = NULL;
1049   }
1050   silc_socket_free(sock);
1051 }
1052
1053 /* Called when we receive disconnection packet from server. This 
1054    closes our end properly and displays the reason of the disconnection
1055    on the screen. */
1056
1057 void silc_client_disconnected_by_server(SilcClient client,
1058                                         SilcSocketConnection sock,
1059                                         SilcBuffer message)
1060 {
1061   char *msg;
1062
1063   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1064
1065   msg = silc_calloc(message->len + 1, sizeof(char));
1066   memcpy(msg, message->data, message->len);
1067   client->ops->say(client, sock->user_data, msg);
1068   silc_free(msg);
1069
1070   SILC_SET_DISCONNECTED(sock);
1071   silc_client_close_connection(client, sock->user_data);
1072 }
1073
1074 /* Received error message from server. Display it on the screen. 
1075    We don't take any action what so ever of the error message. */
1076
1077 void silc_client_error_by_server(SilcClient client,
1078                                  SilcSocketConnection sock,
1079                                  SilcBuffer message)
1080 {
1081   char *msg;
1082
1083   msg = silc_calloc(message->len + 1, sizeof(char));
1084   memcpy(msg, message->data, message->len);
1085   client->ops->say(client, sock->user_data, msg);
1086   silc_free(msg);
1087 }
1088
1089 /* Processes the received new Client ID from server. Old Client ID is
1090    deleted from cache and new one is added. */
1091
1092 void silc_client_receive_new_id(SilcClient client,
1093                                 SilcSocketConnection sock,
1094                                 SilcIDPayload idp)
1095 {
1096   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1097   int connecting = FALSE;
1098
1099   if (!conn->local_entry)
1100     connecting = TRUE;
1101
1102   /* Delete old ID from ID cache */
1103   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1104   
1105   /* Save the new ID */
1106   if (conn->local_id)
1107     silc_free(conn->local_id);
1108   if (conn->local_id_data)
1109     silc_free(conn->local_id_data);
1110
1111   conn->local_id = silc_id_payload_get_id(idp);
1112   conn->local_id_data = silc_id_payload_get_data(idp);
1113   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1114
1115   if (!conn->local_entry)
1116     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1117
1118   conn->local_entry->nickname = conn->nickname;
1119   if (!conn->local_entry->username) {
1120     conn->local_entry->username = 
1121       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1122                   sizeof(conn->local_entry->username));
1123     sprintf(conn->local_entry->username, "%s@%s", client->username,
1124             client->hostname);
1125   }
1126   conn->local_entry->server = strdup(conn->remote_host);
1127   conn->local_entry->id = conn->local_id;
1128   
1129   /* Put it to the ID cache */
1130   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1131                    conn->local_id, (void *)conn->local_entry, TRUE);
1132
1133   /* Notify application of successful connection. We do it here now that
1134      we've received the Client ID and are allowed to send traffic. */
1135   if (connecting)
1136     client->ops->connect(client, conn, TRUE);
1137 }
1138
1139 /* Processed received Channel ID for a channel. This is called when client
1140    joins to channel and server replies with channel ID. The ID is cached. 
1141    Returns the created channel entry. */
1142
1143 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1144                                             SilcSocketConnection sock,
1145                                             char *channel_name,
1146                                             unsigned int mode, 
1147                                             SilcIDPayload idp)
1148 {
1149   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1150   SilcChannelEntry channel;
1151
1152   SILC_LOG_DEBUG(("New channel ID"));
1153
1154   channel = silc_calloc(1, sizeof(*channel));
1155   channel->channel_name = channel_name;
1156   channel->id = silc_id_payload_get_id(idp);
1157   channel->mode = mode;
1158   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1159
1160   conn->current_channel = channel;
1161
1162   /* Put it to the ID cache */
1163   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1164                    (void *)channel->id, (void *)channel, TRUE);
1165
1166   return channel;
1167 }
1168
1169 /* Removes a client entry from all channel it has joined. This really is
1170    a performance killer (client_entry should have pointers to channel 
1171    entry list). */
1172
1173 void silc_client_remove_from_channels(SilcClient client,
1174                                       SilcClientConnection conn,
1175                                       SilcClientEntry client_entry)
1176 {
1177   SilcIDCacheEntry id_cache;
1178   SilcIDCacheList list;
1179   SilcChannelEntry channel;
1180   SilcChannelUser chu;
1181
1182   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
1183                                SILC_ID_CHANNEL, &list))
1184     return;
1185
1186   silc_idcache_list_first(list, &id_cache);
1187   channel = (SilcChannelEntry)id_cache->context;
1188   
1189   while (channel) {
1190     
1191     /* Remove client from channel */
1192     silc_list_start(channel->clients);
1193     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1194       if (chu->client == client_entry) {
1195         silc_list_del(channel->clients, chu);
1196         silc_free(chu);
1197         break;
1198       }
1199     }
1200
1201     if (!silc_idcache_list_next(list, &id_cache))
1202       break;
1203     
1204     channel = (SilcChannelEntry)id_cache->context;
1205   }
1206
1207   silc_idcache_list_free(list);
1208 }
1209
1210 /* Replaces `old' client entries from all channels to `new' client entry.
1211    This can be called for example when nickname changes and old ID entry
1212    is replaced from ID cache with the new one. If the old ID entry is only
1213    updated, then this fucntion needs not to be called. */
1214
1215 void silc_client_replace_from_channels(SilcClient client, 
1216                                        SilcClientConnection conn,
1217                                        SilcClientEntry old,
1218                                        SilcClientEntry new)
1219 {
1220   SilcIDCacheEntry id_cache;
1221   SilcIDCacheList list;
1222   SilcChannelEntry channel;
1223   SilcChannelUser chu;
1224
1225   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
1226                                SILC_ID_CHANNEL, &list))
1227     return;
1228
1229   silc_idcache_list_first(list, &id_cache);
1230   channel = (SilcChannelEntry)id_cache->context;
1231   
1232   while (channel) {
1233     
1234     /* Replace client entry */
1235     silc_list_start(channel->clients);
1236     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1237       if (chu->client == old) {
1238         chu->client = new;
1239         break;
1240       }
1241     }
1242
1243     if (!silc_idcache_list_next(list, &id_cache))
1244       break;
1245     
1246     channel = (SilcChannelEntry)id_cache->context;
1247   }
1248
1249   silc_idcache_list_free(list);
1250 }
1251
1252 /* Parses mode mask and returns the mode as string. */
1253
1254 char *silc_client_chmode(unsigned int mode)
1255 {
1256   char string[20];
1257
1258   if (!mode)
1259     return NULL;
1260
1261   memset(string, 0, sizeof(string));
1262
1263   if (mode & SILC_CHANNEL_MODE_PRIVATE)
1264     strncat(string, "p", 1);
1265
1266   if (mode & SILC_CHANNEL_MODE_SECRET)
1267     strncat(string, "s", 1);
1268
1269   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
1270     strncat(string, "k", 1);
1271
1272   if (mode & SILC_CHANNEL_MODE_INVITE)
1273     strncat(string, "i", 1);
1274
1275   if (mode & SILC_CHANNEL_MODE_TOPIC)
1276     strncat(string, "t", 1);
1277
1278   if (mode & SILC_CHANNEL_MODE_ULIMIT)
1279     strncat(string, "l", 1);
1280
1281   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
1282     strncat(string, "a", 1);
1283
1284   /* Rest of mode is ignored */
1285
1286   return strdup(string);
1287 }
1288
1289 /* Parses channel user mode mask and returns te mode as string */
1290
1291 char *silc_client_chumode(unsigned int mode)
1292 {
1293   char string[4];
1294
1295   if (!mode)
1296     return NULL;
1297
1298   memset(string, 0, sizeof(string));
1299
1300   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1301     strncat(string, "f", 1);
1302
1303   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1304     strncat(string, "o", 1);
1305
1306   return strdup(string);
1307 }
1308
1309 /* Parses channel user mode and returns it as special mode character. */
1310
1311 char *silc_client_chumode_char(unsigned int mode)
1312 {
1313   char string[4];
1314
1315   if (!mode)
1316     return NULL;
1317
1318   memset(string, 0, sizeof(string));
1319
1320   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1321     strncat(string, "*", 1);
1322
1323   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1324     strncat(string, "@", 1);
1325
1326   return strdup(string);
1327 }
1328
1329 /* Failure timeout callback. If this is called then we will immediately
1330    process the received failure. We always process the failure with timeout
1331    since we do not want to blindly trust to received failure packets. 
1332    This won't be called (the timeout is cancelled) if the failure was
1333    bogus (it is bogus if remote does not close the connection after sending
1334    the failure). */
1335
1336 SILC_TASK_CALLBACK_GLOBAL(silc_client_failure_callback)
1337 {
1338   SilcClientFailureContext *f = (SilcClientFailureContext *)context;
1339
1340   if (f->sock->protocol) {
1341     f->sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
1342     f->sock->protocol->execute(f->client->timeout_queue, 0,
1343                                f->sock->protocol, f->sock->sock, 0, 0);
1344     
1345     /* Notify application */
1346     f->client->ops->failure(f->client, f->sock->user_data, f->sock->protocol,
1347                             (void *)f->failure);
1348   }
1349
1350   silc_free(f);
1351 }
1352
1353 /* Registers failure timeout to process the received failure packet
1354    with timeout. */
1355
1356 void silc_client_process_failure(SilcClient client,
1357                                  SilcSocketConnection sock,
1358                                  SilcPacketContext *packet)
1359 {
1360   SilcClientFailureContext *f;
1361   unsigned int failure = 0;
1362
1363   if (sock->protocol) {
1364     if (packet->buffer->len >= 4)
1365       SILC_GET32_MSB(failure, packet->buffer->data);
1366
1367     f = silc_calloc(1, sizeof(*f));
1368     f->client = client;
1369     f->sock = sock;
1370     f->failure = failure;
1371
1372     /* We will wait 5 seconds to process this failure packet */
1373     silc_task_register(client->timeout_queue, sock->sock,
1374                        silc_client_failure_callback, (void *)f, 5, 0,
1375                        SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1376   }
1377 }