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