5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
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.
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.
22 #include "clientlibincludes.h"
23 #include "client_internal.h"
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);
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);
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. */
43 SilcClient silc_client_alloc(SilcClientOperations *ops,
44 SilcClientParams *params,
46 const char *silc_version)
48 SilcClient new_client;
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));
57 memcpy(new_client->params, params, sizeof(*params));
59 if (!new_client->params->rekey_secs)
60 new_client->params->rekey_secs = 3600;
65 /* Frees client object and its internals. */
67 void silc_client_free(SilcClient client)
71 silc_rng_free(client->rng);
73 silc_free(client->silc_client_version);
74 silc_free(client->params);
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. */
83 int silc_client_init(SilcClient client)
85 SILC_LOG_DEBUG(("Initializing client"));
87 /* Initialize hash functions for client to use */
88 silc_hash_alloc("md5", &client->md5hash);
89 silc_hash_alloc("sha1", &client->sha1hash);
91 /* Initialize none cipher */
92 silc_cipher_alloc("none", &client->none_cipher);
94 /* Initialize random number generator */
95 client->rng = silc_rng_alloc();
96 silc_rng_init(client->rng);
97 silc_rng_global_init(client->rng);
99 /* Register protocols */
100 silc_client_protocols_register();
102 /* Initialize the scheduler */
103 client->schedule = silc_schedule_init(client->params->task_max ?
104 client->params->task_max : 200);
105 if (!client->schedule)
111 /* Stops the client. This is called to stop the client and thus to stop
114 void silc_client_stop(SilcClient client)
116 SILC_LOG_DEBUG(("Stopping client"));
118 silc_schedule_stop(client->schedule);
119 silc_schedule_uninit(client->schedule);
121 silc_client_protocols_unregister();
123 SILC_LOG_DEBUG(("Client stopped"));
126 /* Runs the client. This starts the scheduler from the utility library.
127 When this functions returns the execution of the appliation is over. */
129 void silc_client_run(SilcClient client)
131 SILC_LOG_DEBUG(("Running client"));
133 /* Start the scheduler, the heart of the SILC client. When this returns
134 the program will be terminated. */
135 silc_schedule(client->schedule);
138 /* Allocates and adds new connection to the client. This adds the allocated
139 connection to the connection table and returns a pointer to it. A client
140 can have multiple connections to multiple servers. Every connection must
141 be added to the client using this function. User data `context' may
142 be sent as argument. This function is normally used only if the
143 application performed the connecting outside the library. The library
144 however may use this internally. */
146 SilcClientConnection silc_client_add_connection(SilcClient client,
151 SilcClientConnection conn;
154 conn = silc_calloc(1, sizeof(*conn));
156 /* Initialize ID caches */
157 conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
158 conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
159 conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
160 conn->client = client;
161 conn->remote_host = strdup(hostname);
162 conn->remote_port = port;
163 conn->context = context;
164 conn->pending_commands = silc_dlist_init();
166 /* Add the connection to connections table */
167 for (i = 0; i < client->conns_count; i++)
168 if (client->conns && !client->conns[i]) {
169 client->conns[i] = conn;
173 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
174 * (client->conns_count + 1));
175 client->conns[client->conns_count] = conn;
176 client->conns_count++;
181 /* Removes connection from client. Frees all memory. */
183 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
187 for (i = 0; i < client->conns_count; i++)
188 if (client->conns[i] == conn) {
189 if (conn->pending_commands)
190 silc_dlist_uninit(conn->pending_commands);
192 client->conns[i] = NULL;
196 /* Adds listener socket to the listener sockets table. This function is
197 used to add socket objects that are listeners to the client. This should
198 not be used to add other connection objects. */
200 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
204 if (!client->sockets) {
205 client->sockets = silc_calloc(1, sizeof(*client->sockets));
206 client->sockets[0] = silc_socket_dup(sock);
207 client->sockets_count = 1;
211 for (i = 0; i < client->sockets_count; i++) {
212 if (client->sockets[i] == NULL) {
213 client->sockets[i] = silc_socket_dup(sock);
218 client->sockets = silc_realloc(client->sockets, sizeof(*client->sockets) *
219 (client->sockets_count + 1));
220 client->sockets[client->sockets_count] = silc_socket_dup(sock);
221 client->sockets_count++;
224 /* Deletes listener socket from the listener sockets table. */
226 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
230 if (!client->sockets)
233 for (i = 0; i < client->sockets_count; i++) {
234 if (client->sockets[i] == sock) {
235 silc_socket_free(sock);
236 client->sockets[i] = NULL;
243 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
247 /* XXX In the future we should give up this non-blocking connect all
248 together and use threads instead. */
249 /* Create connection to server asynchronously */
250 sock = silc_net_create_connection_async(ctx->port, ctx->host);
254 /* Register task that will receive the async connect and will
256 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
257 silc_client_connect_to_server_start,
260 SILC_TASK_PRI_NORMAL);
261 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
268 /* Connects to remote server. This is the main routine used to connect
269 to SILC server. Returns -1 on error and the created socket otherwise.
270 The `context' is user context that is saved into the SilcClientConnection
271 that is created after the connection is created. Note that application
272 may handle the connecting process outside the library. If this is the
273 case then this function is not used at all. When the connecting is
274 done the `connect' client operation is called. */
276 int silc_client_connect_to_server(SilcClient client, int port,
277 char *host, void *context)
279 SilcClientInternalConnectContext *ctx;
280 SilcClientConnection conn;
283 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
286 conn = silc_client_add_connection(client, host, port, context);
288 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
289 "Connecting to port %d of server %s", port, host);
291 /* Allocate internal context for connection process. This is
292 needed as we are doing async connecting. */
293 ctx = silc_calloc(1, sizeof(*ctx));
294 ctx->client = client;
296 ctx->host = strdup(host);
300 /* Do the actual connecting process */
301 sock = silc_client_connect_to_server_internal(ctx);
303 silc_client_del_connection(client, conn);
307 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
308 key material between client and server. This function can be called
309 directly if application is performing its own connecting and does not
310 use the connecting provided by this library. This function is normally
311 used only if the application performed the connecting outside the library.
312 The library however may use this internally. */
314 int silc_client_start_key_exchange(SilcClient client,
315 SilcClientConnection conn,
318 SilcProtocol protocol;
319 SilcClientKEInternalContext *proto_ctx;
322 /* Allocate new socket connection object */
323 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
325 conn->nickname = strdup(client->username);
326 conn->sock->hostname = conn->remote_host;
327 conn->sock->ip = strdup(conn->remote_host);
328 conn->sock->port = conn->remote_port;
330 /* Allocate internal Key Exchange context. This is sent to the
331 protocol as context. */
332 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
333 proto_ctx->client = (void *)client;
334 proto_ctx->sock = silc_socket_dup(conn->sock);
335 proto_ctx->rng = client->rng;
336 proto_ctx->responder = FALSE;
337 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
338 proto_ctx->verify = silc_client_protocol_ke_verify_key;
340 /* Perform key exchange protocol. silc_client_connect_to_server_final
341 will be called after the protocol is finished. */
342 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
343 &protocol, (void *)proto_ctx,
344 silc_client_connect_to_server_second);
346 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
347 "Error: Could not start authentication protocol");
350 conn->sock->protocol = protocol;
352 /* Register the connection for network input and output. This sets
353 that scheduler will listen for incoming packets for this connection
354 and sets that outgoing packets may be sent to this connection as well.
355 However, this doesn't set the scheduler for outgoing traffic, it will
356 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
357 later when outgoing data is available. */
358 context = (void *)client;
359 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
361 /* Execute the protocol */
362 silc_protocol_execute(protocol, client->schedule, 0, 0);
366 /* Start of the connection to the remote server. This is called after
367 succesful TCP/IP connection has been established to the remote host. */
369 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
371 SilcClientInternalConnectContext *ctx =
372 (SilcClientInternalConnectContext *)context;
373 SilcClient client = ctx->client;
374 SilcClientConnection conn = ctx->conn;
375 int opt, opt_len = sizeof(opt);
377 SILC_LOG_DEBUG(("Start"));
379 /* Check the socket status as it might be in error */
380 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
382 if (ctx->tries < 2) {
383 /* Connection failed but lets try again */
384 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
385 "Could not connect to server %s: %s",
386 ctx->host, strerror(opt));
387 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
388 "Connecting to port %d of server %s resumed",
389 ctx->port, ctx->host);
391 /* Unregister old connection try */
392 silc_schedule_unset_listen_fd(client->schedule, fd);
393 silc_net_close_connection(fd);
394 silc_schedule_task_del(client->schedule, ctx->task);
397 silc_client_connect_to_server_internal(ctx);
400 /* Connection failed and we won't try anymore */
401 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
402 "Could not connect to server %s: %s",
403 ctx->host, strerror(opt));
404 silc_schedule_unset_listen_fd(client->schedule, fd);
405 silc_net_close_connection(fd);
406 silc_schedule_task_del(client->schedule, ctx->task);
409 /* Notify application of failure */
410 client->ops->connect(client, conn, FALSE);
411 silc_client_del_connection(client, conn);
416 silc_schedule_unset_listen_fd(client->schedule, fd);
417 silc_schedule_task_del(client->schedule, ctx->task);
420 if (!silc_client_start_key_exchange(client, conn, fd)) {
421 silc_net_close_connection(fd);
422 client->ops->connect(client, conn, FALSE);
426 /* Second part of the connecting to the server. This executed
427 authentication protocol. */
429 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
431 SilcProtocol protocol = (SilcProtocol)context;
432 SilcClientKEInternalContext *ctx =
433 (SilcClientKEInternalContext *)protocol->context;
434 SilcClient client = (SilcClient)ctx->client;
435 SilcSocketConnection sock = NULL;
436 SilcClientConnAuthInternalContext *proto_ctx;
438 SILC_LOG_DEBUG(("Start"));
440 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
441 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
442 /* Error occured during protocol */
443 SILC_LOG_DEBUG(("Error during KE protocol"));
444 silc_protocol_free(protocol);
445 silc_ske_free_key_material(ctx->keymat);
447 silc_ske_free(ctx->ske);
449 silc_free(ctx->dest_id);
450 ctx->sock->protocol = NULL;
451 silc_socket_free(ctx->sock);
453 /* Notify application of failure */
454 client->ops->connect(client, ctx->sock->user_data, FALSE);
459 /* We now have the key material as the result of the key exchange
460 protocol. Take the key material into use. Free the raw key material
461 as soon as we've set them into use. */
462 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
463 ctx->ske->prop->cipher,
464 ctx->ske->prop->pkcs,
465 ctx->ske->prop->hash,
466 ctx->ske->prop->hmac,
467 ctx->ske->prop->group);
468 silc_ske_free_key_material(ctx->keymat);
470 /* Allocate internal context for the authentication protocol. This
471 is sent as context for the protocol. */
472 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
473 proto_ctx->client = (void *)client;
474 proto_ctx->sock = sock = ctx->sock;
475 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
476 proto_ctx->dest_id_type = ctx->dest_id_type;
477 proto_ctx->dest_id = ctx->dest_id;
479 /* Resolve the authentication method to be used in this connection */
480 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
481 sock->port, &proto_ctx->auth_meth,
482 &proto_ctx->auth_data,
483 &proto_ctx->auth_data_len))
484 proto_ctx->auth_meth = SILC_AUTH_NONE;
486 /* Free old protocol as it is finished now */
487 silc_protocol_free(protocol);
489 silc_packet_context_free(ctx->packet);
491 sock->protocol = NULL;
493 /* Allocate the authenteication protocol and execute it. */
494 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
495 &sock->protocol, (void *)proto_ctx,
496 silc_client_connect_to_server_final);
498 /* Execute the protocol */
499 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
502 /* Finalizes the connection to the remote SILC server. This is called
503 after authentication protocol has been completed. This send our
504 user information to the server to receive our client ID from
507 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
509 SilcProtocol protocol = (SilcProtocol)context;
510 SilcClientConnAuthInternalContext *ctx =
511 (SilcClientConnAuthInternalContext *)protocol->context;
512 SilcClient client = (SilcClient)ctx->client;
513 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
516 SILC_LOG_DEBUG(("Start"));
518 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
519 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
520 /* Error occured during protocol */
521 SILC_LOG_DEBUG(("Error during authentication protocol"));
522 silc_protocol_free(protocol);
524 silc_free(ctx->auth_data);
526 silc_ske_free(ctx->ske);
528 silc_free(ctx->dest_id);
529 conn->sock->protocol = NULL;
530 silc_socket_free(ctx->sock);
532 /* Notify application of failure */
533 client->ops->connect(client, ctx->sock->user_data, FALSE);
538 /* Send NEW_CLIENT packet to the server. We will become registered
539 to the SILC network after sending this packet and we will receive
540 client ID from the server. */
541 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
542 strlen(client->realname));
543 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
544 silc_buffer_format(packet,
545 SILC_STR_UI_SHORT(strlen(client->username)),
546 SILC_STR_UI_XNSTRING(client->username,
547 strlen(client->username)),
548 SILC_STR_UI_SHORT(strlen(client->realname)),
549 SILC_STR_UI_XNSTRING(client->realname,
550 strlen(client->realname)),
553 /* Send the packet */
554 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
556 packet->data, packet->len, TRUE);
557 silc_buffer_free(packet);
559 /* Save remote ID. */
560 conn->remote_id = ctx->dest_id;
561 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
562 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
564 /* Register re-key timeout */
565 conn->rekey->timeout = client->params->rekey_secs;
566 conn->rekey->context = (void *)client;
567 silc_schedule_task_add(client->schedule, conn->sock->sock,
568 silc_client_rekey_callback,
569 (void *)conn->sock, conn->rekey->timeout, 0,
570 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
572 silc_protocol_free(protocol);
574 silc_free(ctx->auth_data);
576 silc_ske_free(ctx->ske);
577 silc_socket_free(ctx->sock);
579 conn->sock->protocol = NULL;
582 /* Internal routine that sends packet or marks packet to be sent. This
583 is used directly only in special cases. Normal cases should use
584 silc_server_packet_send. Returns < 0 on error. */
586 int silc_client_packet_send_real(SilcClient client,
587 SilcSocketConnection sock,
593 /* If rekey protocol is active we must assure that all packets are
594 sent through packet queue. */
595 if (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
598 /* Send the packet */
599 ret = silc_packet_send(sock, force_send);
603 /* Mark that there is some outgoing data available for this connection.
604 This call sets the connection both for input and output (the input
605 is set always and this call keeps the input setting, actually).
606 Actual data sending is performed by silc_client_packet_process. */
607 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
609 /* Mark to socket that data is pending in outgoing buffer. This flag
610 is needed if new data is added to the buffer before the earlier
611 put data is sent to the network. */
612 SILC_SET_OUTBUF_PENDING(sock);
617 /* Packet processing callback. This is used to send and receive packets
618 from network. This is generic task. */
620 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
622 SilcClient client = (SilcClient)context;
623 SilcSocketConnection sock = NULL;
624 SilcClientConnection conn;
627 SILC_LOG_DEBUG(("Processing packet"));
629 SILC_CLIENT_GET_SOCK(client, fd, sock);
633 conn = (SilcClientConnection)sock->user_data;
636 if (type == SILC_TASK_WRITE) {
637 SILC_LOG_DEBUG(("Writing data to connection"));
639 if (sock->outbuf->data - sock->outbuf->head)
640 silc_buffer_push(sock->outbuf,
641 sock->outbuf->data - sock->outbuf->head);
643 ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
645 /* If returned -2 could not write to connection now, will do
650 /* The packet has been sent and now it is time to set the connection
651 back to only for input. When there is again some outgoing data
652 available for this connection it will be set for output as well.
653 This call clears the output setting and sets it only for input. */
654 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
655 SILC_UNSET_OUTBUF_PENDING(sock);
657 silc_buffer_clear(sock->outbuf);
661 /* Packet receiving */
662 if (type == SILC_TASK_READ) {
663 SILC_LOG_DEBUG(("Reading data from connection"));
665 /* Read data from network */
666 ret = silc_packet_receive(sock);
672 SILC_LOG_DEBUG(("Read EOF"));
674 /* If connection is disconnecting already we will finally
675 close the connection */
676 if (SILC_IS_DISCONNECTING(sock)) {
677 if (sock == conn->sock)
678 client->ops->disconnect(client, conn);
679 silc_client_close_connection(client, sock, conn);
683 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
684 if (sock == conn->sock)
685 client->ops->disconnect(client, conn);
686 silc_client_close_connection(client, sock, conn);
690 /* Process the packet. This will call the parser that will then
691 decrypt and parse the packet. */
692 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
693 silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
694 silc_client_packet_parse, client);
696 silc_packet_receive_process(sock, NULL, NULL,
697 silc_client_packet_parse, client);
701 /* Callback function that the silc_packet_decrypt will call to make the
702 decision whether the packet is normal or special packet. We will
703 return TRUE if it is normal and FALSE if it is special */
705 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
707 SilcPacketContext *packet,
711 /* Packet is normal packet, if:
713 1) packet is private message packet and does not have private key set
714 2) is other packet than channel message packet
716 all other packets are special packets
719 if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
720 (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
723 if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
729 /* Parses whole packet, received earlier. */
731 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
733 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
734 SilcClient client = (SilcClient)parse_ctx->context;
735 SilcPacketContext *packet = parse_ctx->packet;
736 SilcBuffer buffer = packet->buffer;
737 SilcSocketConnection sock = parse_ctx->sock;
738 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
741 SILC_LOG_DEBUG(("Start"));
743 /* Decrypt the received packet */
744 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
745 ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive,
747 silc_client_packet_decrypt_check, parse_ctx);
749 ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
750 silc_client_packet_decrypt_check, parse_ctx);
756 /* Parse the packet. Packet type is returned. */
757 ret = silc_packet_parse(packet);
759 /* Parse the packet header in special way as this is "special"
761 ret = silc_packet_parse_special(packet);
764 if (ret == SILC_PACKET_NONE)
767 /* Parse the incoming packet type */
768 silc_client_packet_parse_type(client, sock, packet);
771 /* silc_buffer_clear(sock->inbuf); */
772 silc_packet_context_free(packet);
773 silc_free(parse_ctx);
776 /* Parser callback called by silc_packet_receive_process. Thie merely
777 registers timeout that will handle the actual parsing when appropriate. */
779 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
781 SilcClient client = (SilcClient)parser_context->context;
783 /* Parse the packet */
784 silc_schedule_task_add(client->schedule, parser_context->sock->sock,
785 silc_client_packet_parse_real,
786 (void *)parser_context, 0, 1,
788 SILC_TASK_PRI_NORMAL);
791 /* Parses the packet type and calls what ever routines the packet type
792 requires. This is done for all incoming packets. */
794 void silc_client_packet_parse_type(SilcClient client,
795 SilcSocketConnection sock,
796 SilcPacketContext *packet)
798 SilcBuffer buffer = packet->buffer;
799 SilcPacketType type = packet->type;
801 SILC_LOG_DEBUG(("Parsing packet type %d", type));
803 /* Parse the packet type */
805 case SILC_PACKET_DISCONNECT:
806 silc_client_disconnected_by_server(client, sock, buffer);
808 case SILC_PACKET_SUCCESS:
810 * Success received for something. For now we can have only
811 * one protocol for connection executing at once hence this
812 * success message is for whatever protocol is executing currently.
815 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
817 case SILC_PACKET_FAILURE:
819 * Failure received for some protocol. Set the protocol state to
820 * error and call the protocol callback. This fill cause error on
821 * protocol and it will call the final callback.
823 silc_client_process_failure(client, sock, packet);
825 case SILC_PACKET_REJECT:
828 case SILC_PACKET_NOTIFY:
830 * Received notify message
832 silc_client_notify_by_server(client, sock, packet);
835 case SILC_PACKET_ERROR:
837 * Received error message
839 silc_client_error_by_server(client, sock, buffer);
842 case SILC_PACKET_CHANNEL_MESSAGE:
844 * Received message to (from, actually) a channel
846 silc_client_channel_message(client, sock, packet);
848 case SILC_PACKET_CHANNEL_KEY:
850 * Received key for a channel. By receiving this key the client will be
851 * able to talk to the channel it has just joined. This can also be
852 * a new key for existing channel as keys expire peridiocally.
854 silc_client_receive_channel_key(client, sock, buffer);
857 case SILC_PACKET_PRIVATE_MESSAGE:
859 * Received private message
861 silc_client_private_message(client, sock, packet);
863 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
865 * Received private message key
869 case SILC_PACKET_COMMAND_REPLY:
871 * Recived reply for a command
873 silc_client_command_reply_process(client, sock, packet);
876 case SILC_PACKET_KEY_EXCHANGE:
877 if (sock->protocol && sock->protocol->protocol &&
878 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
879 SilcClientKEInternalContext *proto_ctx =
880 (SilcClientKEInternalContext *)sock->protocol->context;
882 proto_ctx->packet = silc_packet_context_dup(packet);
883 proto_ctx->dest_id_type = packet->src_id_type;
884 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
885 packet->src_id_type);
886 if (!proto_ctx->dest_id)
889 /* Let the protocol handle the packet */
890 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
892 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
893 "protocol active, packet dropped."));
897 case SILC_PACKET_KEY_EXCHANGE_1:
898 if (sock->protocol && sock->protocol->protocol &&
899 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
900 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
902 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
903 SilcClientRekeyInternalContext *proto_ctx =
904 (SilcClientRekeyInternalContext *)sock->protocol->context;
906 if (proto_ctx->packet)
907 silc_packet_context_free(proto_ctx->packet);
909 proto_ctx->packet = silc_packet_context_dup(packet);
911 /* Let the protocol handle the packet */
912 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
914 SilcClientKEInternalContext *proto_ctx =
915 (SilcClientKEInternalContext *)sock->protocol->context;
917 if (proto_ctx->packet)
918 silc_packet_context_free(proto_ctx->packet);
920 proto_ctx->packet = silc_packet_context_dup(packet);
921 proto_ctx->dest_id_type = packet->src_id_type;
922 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
923 packet->src_id_type);
924 if (!proto_ctx->dest_id)
927 /* Let the protocol handle the packet */
928 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
931 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
932 "protocol active, packet dropped."));
935 case SILC_PACKET_KEY_EXCHANGE_2:
936 if (sock->protocol && sock->protocol->protocol &&
937 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
938 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
940 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
941 SilcClientRekeyInternalContext *proto_ctx =
942 (SilcClientRekeyInternalContext *)sock->protocol->context;
944 if (proto_ctx->packet)
945 silc_packet_context_free(proto_ctx->packet);
947 proto_ctx->packet = silc_packet_context_dup(packet);
949 /* Let the protocol handle the packet */
950 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
952 SilcClientKEInternalContext *proto_ctx =
953 (SilcClientKEInternalContext *)sock->protocol->context;
955 if (proto_ctx->packet)
956 silc_packet_context_free(proto_ctx->packet);
958 proto_ctx->packet = silc_packet_context_dup(packet);
959 proto_ctx->dest_id_type = packet->src_id_type;
960 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
961 packet->src_id_type);
962 if (!proto_ctx->dest_id)
965 /* Let the protocol handle the packet */
966 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
969 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
970 "protocol active, packet dropped."));
974 case SILC_PACKET_NEW_ID:
977 * Received new ID from server. This packet is received at
978 * the connection to the server. New ID is also received when
979 * user changes nickname but in that case the new ID is received
980 * as command reply and not as this packet type.
984 idp = silc_id_payload_parse(buffer);
987 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
990 silc_client_receive_new_id(client, sock, idp);
991 silc_id_payload_free(idp);
995 case SILC_PACKET_HEARTBEAT:
997 * Received heartbeat packet
999 SILC_LOG_DEBUG(("Heartbeat packet"));
1002 case SILC_PACKET_KEY_AGREEMENT:
1004 * Received key agreement packet
1006 SILC_LOG_DEBUG(("Key agreement packet"));
1007 silc_client_key_agreement(client, sock, packet);
1010 case SILC_PACKET_REKEY:
1011 SILC_LOG_DEBUG(("Re-key packet"));
1012 /* We ignore this for now */
1015 case SILC_PACKET_REKEY_DONE:
1016 SILC_LOG_DEBUG(("Re-key done packet"));
1018 if (sock->protocol && sock->protocol->protocol &&
1019 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1021 SilcClientRekeyInternalContext *proto_ctx =
1022 (SilcClientRekeyInternalContext *)sock->protocol->context;
1024 if (proto_ctx->packet)
1025 silc_packet_context_free(proto_ctx->packet);
1027 proto_ctx->packet = silc_packet_context_dup(packet);
1029 /* Let the protocol handle the packet */
1030 if (proto_ctx->responder == FALSE)
1031 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1033 /* Let the protocol handle the packet */
1034 silc_protocol_execute(sock->protocol, client->schedule,
1037 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1038 "protocol active, packet dropped."));
1043 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1048 /* Sends packet. This doesn't actually send the packet instead it assembles
1049 it and marks it to be sent. However, if force_send is TRUE the packet
1050 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1051 will be derived from sock argument. Otherwise the valid arguments sent
1054 void silc_client_packet_send(SilcClient client,
1055 SilcSocketConnection sock,
1056 SilcPacketType type,
1058 SilcIdType dst_id_type,
1061 unsigned char *data,
1065 SilcPacketContext packetdata;
1070 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1072 /* Get data used in the packet sending, keys and stuff */
1073 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1074 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1075 cipher = ((SilcClientConnection)sock->user_data)->send_key;
1077 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1078 hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1080 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1081 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1082 dst_id_type = SILC_ID_SERVER;
1086 /* Set the packet context pointers */
1087 packetdata.flags = 0;
1088 packetdata.type = type;
1089 if (sock->user_data &&
1090 ((SilcClientConnection)sock->user_data)->local_id_data) {
1091 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1092 packetdata.src_id_len =
1093 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1096 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1097 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1099 packetdata.src_id_type = SILC_ID_CLIENT;
1101 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1102 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1103 packetdata.dst_id_type = dst_id_type;
1105 packetdata.dst_id = NULL;
1106 packetdata.dst_id_len = 0;
1107 packetdata.dst_id_type = SILC_ID_NONE;
1109 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1110 packetdata.src_id_len + packetdata.dst_id_len;
1111 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1113 /* Prepare outgoing data buffer for packet sending */
1114 silc_packet_send_prepare(sock,
1115 SILC_PACKET_HEADER_LEN +
1116 packetdata.src_id_len +
1117 packetdata.dst_id_len,
1121 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1123 packetdata.buffer = sock->outbuf;
1125 /* Put the data to the buffer */
1126 if (data && data_len)
1127 silc_buffer_put(sock->outbuf, data, data_len);
1129 /* Create the outgoing packet */
1130 silc_packet_assemble(&packetdata);
1132 /* Encrypt the packet */
1134 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1136 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1137 sock->outbuf->data, sock->outbuf->len);
1139 /* Now actually send the packet */
1140 silc_client_packet_send_real(client, sock, force_send, FALSE);
1143 /* Closes connection to remote end. Free's all allocated data except
1144 for some information such as nickname etc. that are valid at all time.
1145 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1146 provided it will be checked whether the sock and `conn->sock' are the
1147 same (they can be different, ie. a socket can use `conn' as its
1148 connection but `conn->sock' might be actually a different connection
1149 than the `sock'). */
1151 void silc_client_close_connection(SilcClient client,
1152 SilcSocketConnection sock,
1153 SilcClientConnection conn)
1157 if (!sock || (sock && conn->sock == sock))
1162 /* We won't listen for this connection anymore */
1163 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1165 /* Unregister all tasks */
1166 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1167 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1169 /* Close the actual connection */
1170 silc_net_close_connection(sock->sock);
1172 /* Cancel any active protocol */
1173 if (sock->protocol) {
1174 if (sock->protocol->protocol->type ==
1175 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1176 sock->protocol->protocol->type ==
1177 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1178 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1179 silc_protocol_execute_final(sock->protocol, client->schedule);
1180 sock->protocol = NULL;
1181 /* The application will recall this function with these protocols
1182 (the ops->connect client operation). */
1185 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1186 silc_protocol_execute_final(sock->protocol, client->schedule);
1187 sock->protocol = NULL;
1191 /* Free everything */
1192 if (del && sock->user_data) {
1193 /* Free all cache entries */
1194 SilcIDCacheList list;
1195 SilcIDCacheEntry entry;
1198 if (silc_idcache_get_all(conn->client_cache, &list)) {
1199 ret = silc_idcache_list_first(list, &entry);
1201 silc_client_del_client(client, conn, entry->context);
1202 ret = silc_idcache_list_next(list, &entry);
1204 silc_idcache_list_free(list);
1207 if (silc_idcache_get_all(conn->channel_cache, &list)) {
1208 ret = silc_idcache_list_first(list, &entry);
1210 silc_client_del_channel(client, conn, entry->context);
1211 ret = silc_idcache_list_next(list, &entry);
1213 silc_idcache_list_free(list);
1216 if (silc_idcache_get_all(conn->server_cache, &list)) {
1217 ret = silc_idcache_list_first(list, &entry);
1219 silc_client_del_server(client, conn, entry->context);
1220 ret = silc_idcache_list_next(list, &entry);
1222 silc_idcache_list_free(list);
1225 /* Clear ID caches */
1226 if (conn->client_cache)
1227 silc_idcache_del_all(conn->client_cache);
1228 if (conn->channel_cache)
1229 silc_idcache_del_all(conn->channel_cache);
1230 if (conn->server_cache)
1231 silc_idcache_del_all(conn->server_cache);
1234 if (conn->remote_host)
1235 silc_free(conn->remote_host);
1237 silc_free(conn->local_id);
1238 if (conn->local_id_data)
1239 silc_free(conn->local_id_data);
1241 silc_cipher_free(conn->send_key);
1242 if (conn->receive_key)
1243 silc_cipher_free(conn->receive_key);
1244 if (conn->hmac_send) /* conn->hmac_receive is same */
1245 silc_hmac_free(conn->hmac_send);
1246 if (conn->pending_commands)
1247 silc_dlist_uninit(conn->pending_commands);
1249 silc_free(conn->rekey);
1251 memset(conn, 0, sizeof(*conn));
1252 silc_client_del_connection(client, conn);
1255 silc_socket_free(sock);
1258 /* Called when we receive disconnection packet from server. This
1259 closes our end properly and displays the reason of the disconnection
1262 void silc_client_disconnected_by_server(SilcClient client,
1263 SilcSocketConnection sock,
1268 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1270 msg = silc_calloc(message->len + 1, sizeof(char));
1271 memcpy(msg, message->data, message->len);
1272 client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1275 SILC_SET_DISCONNECTED(sock);
1276 silc_client_close_connection(client, sock, sock->user_data);
1279 /* Received error message from server. Display it on the screen.
1280 We don't take any action what so ever of the error message. */
1282 void silc_client_error_by_server(SilcClient client,
1283 SilcSocketConnection sock,
1288 msg = silc_calloc(message->len + 1, sizeof(char));
1289 memcpy(msg, message->data, message->len);
1290 client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1294 /* Processes the received new Client ID from server. Old Client ID is
1295 deleted from cache and new one is added. */
1297 void silc_client_receive_new_id(SilcClient client,
1298 SilcSocketConnection sock,
1301 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1302 int connecting = FALSE;
1305 if (!conn->local_entry)
1308 /* Delete old ID from ID cache */
1309 if (conn->local_id) {
1310 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1311 silc_free(conn->local_id);
1314 /* Save the new ID */
1316 if (conn->local_id_data)
1317 silc_free(conn->local_id_data);
1319 conn->local_id = silc_id_payload_get_id(idp);
1320 conn->local_id_data = silc_id_payload_get_data(idp);
1321 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1323 if (!conn->local_entry)
1324 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1326 conn->local_entry->nickname = conn->nickname;
1327 if (!conn->local_entry->username) {
1328 conn->local_entry->username =
1329 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1330 sizeof(conn->local_entry->username));
1331 sprintf(conn->local_entry->username, "%s@%s", client->username,
1334 conn->local_entry->server = strdup(conn->remote_host);
1335 conn->local_entry->id = conn->local_id;
1337 /* Put it to the ID cache */
1338 silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id,
1339 (void *)conn->local_entry, FALSE);
1341 /* Issue INFO command to fetch the real server name and server information
1343 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1344 silc_client_send_command(client, conn, SILC_COMMAND_INFO,
1345 ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1346 silc_buffer_free(sidp);
1348 /* Notify application of successful connection. We do it here now that
1349 we've received the Client ID and are allowed to send traffic. */
1351 client->ops->connect(client, conn, TRUE);
1354 /* Processed received Channel ID for a channel. This is called when client
1355 joins to channel and server replies with channel ID. The ID is cached.
1356 Returns the created channel entry. This is also called when received
1357 channel ID in for example USERS command reply that we do not have. */
1359 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1360 SilcSocketConnection sock,
1365 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1366 SilcChannelEntry channel;
1368 SILC_LOG_DEBUG(("New channel ID"));
1370 channel = silc_calloc(1, sizeof(*channel));
1371 channel->channel_name = channel_name;
1372 channel->id = silc_id_payload_get_id(idp);
1373 channel->mode = mode;
1374 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1376 /* Put it to the ID cache */
1377 silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id,
1378 (void *)channel, FALSE);
1383 /* Removes a client entry from all channel it has joined. This really is
1384 a performance killer (client_entry should have pointers to channel
1387 void silc_client_remove_from_channels(SilcClient client,
1388 SilcClientConnection conn,
1389 SilcClientEntry client_entry)
1391 SilcIDCacheEntry id_cache;
1392 SilcIDCacheList list;
1393 SilcChannelEntry channel;
1394 SilcChannelUser chu;
1396 if (!silc_idcache_get_all(conn->channel_cache, &list))
1399 silc_idcache_list_first(list, &id_cache);
1400 channel = (SilcChannelEntry)id_cache->context;
1404 /* Remove client from channel */
1405 silc_list_start(channel->clients);
1406 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1407 if (chu->client == client_entry) {
1408 silc_list_del(channel->clients, chu);
1414 if (!silc_idcache_list_next(list, &id_cache))
1417 channel = (SilcChannelEntry)id_cache->context;
1420 silc_idcache_list_free(list);
1423 /* Replaces `old' client entries from all channels to `new' client entry.
1424 This can be called for example when nickname changes and old ID entry
1425 is replaced from ID cache with the new one. If the old ID entry is only
1426 updated, then this fucntion needs not to be called. */
1428 void silc_client_replace_from_channels(SilcClient client,
1429 SilcClientConnection conn,
1430 SilcClientEntry old,
1431 SilcClientEntry new)
1433 SilcIDCacheEntry id_cache;
1434 SilcIDCacheList list;
1435 SilcChannelEntry channel;
1436 SilcChannelUser chu;
1438 if (!silc_idcache_get_all(conn->channel_cache, &list))
1441 silc_idcache_list_first(list, &id_cache);
1442 channel = (SilcChannelEntry)id_cache->context;
1446 /* Replace client entry */
1447 silc_list_start(channel->clients);
1448 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1449 if (chu->client == old) {
1455 if (!silc_idcache_list_next(list, &id_cache))
1458 channel = (SilcChannelEntry)id_cache->context;
1461 silc_idcache_list_free(list);
1464 /* Registers failure timeout to process the received failure packet
1467 void silc_client_process_failure(SilcClient client,
1468 SilcSocketConnection sock,
1469 SilcPacketContext *packet)
1473 if (sock->protocol) {
1474 if (packet->buffer->len >= 4)
1475 SILC_GET32_MSB(failure, packet->buffer->data);
1477 /* Notify application */
1478 client->ops->failure(client, sock->user_data, sock->protocol,
1483 /* A timeout callback for the re-key. We will be the initiator of the
1486 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1488 SilcSocketConnection sock = (SilcSocketConnection)context;
1489 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1490 SilcClient client = (SilcClient)conn->rekey->context;
1491 SilcProtocol protocol;
1492 SilcClientRekeyInternalContext *proto_ctx;
1494 SILC_LOG_DEBUG(("Start"));
1496 /* Allocate internal protocol context. This is sent as context
1498 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1499 proto_ctx->client = (void *)client;
1500 proto_ctx->sock = silc_socket_dup(sock);
1501 proto_ctx->responder = FALSE;
1502 proto_ctx->pfs = conn->rekey->pfs;
1504 /* Perform rekey protocol. Will call the final callback after the
1505 protocol is over. */
1506 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1507 &protocol, proto_ctx, silc_client_rekey_final);
1508 sock->protocol = protocol;
1510 /* Run the protocol */
1511 silc_protocol_execute(protocol, client->schedule, 0, 0);
1513 /* Re-register re-key timeout */
1514 silc_schedule_task_add(client->schedule, sock->sock,
1515 silc_client_rekey_callback,
1516 context, conn->rekey->timeout, 0,
1517 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1520 /* The final callback for the REKEY protocol. This will actually take the
1521 new key material into use. */
1523 SILC_TASK_CALLBACK(silc_client_rekey_final)
1525 SilcProtocol protocol = (SilcProtocol)context;
1526 SilcClientRekeyInternalContext *ctx =
1527 (SilcClientRekeyInternalContext *)protocol->context;
1528 SilcClient client = (SilcClient)ctx->client;
1529 SilcSocketConnection sock = ctx->sock;
1531 SILC_LOG_DEBUG(("Start"));
1533 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1534 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1535 /* Error occured during protocol */
1536 silc_protocol_cancel(protocol, client->schedule);
1537 silc_protocol_free(protocol);
1538 sock->protocol = NULL;
1540 silc_packet_context_free(ctx->packet);
1542 silc_ske_free(ctx->ske);
1543 silc_socket_free(ctx->sock);
1549 silc_protocol_free(protocol);
1550 sock->protocol = NULL;
1552 silc_packet_context_free(ctx->packet);
1554 silc_ske_free(ctx->ske);
1555 silc_socket_free(ctx->sock);