SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
-SILC_TASK_CALLBACK(silc_client_packet_parse_real);
SILC_TASK_CALLBACK(silc_client_rekey_callback);
SILC_TASK_CALLBACK(silc_client_rekey_final);
-static void silc_client_packet_parse(SilcPacketParserContext *parser_context,
+static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
void *context);
static void silc_client_packet_parse_type(SilcClient client,
SilcSocketConnection sock,
conn->remote_port = port;
conn->context = context;
conn->pending_commands = silc_dlist_init();
+ conn->ftp_sessions = silc_dlist_init();
/* Add the connection to connections table */
for (i = 0; i < client->conns_count; i++)
for (i = 0; i < client->conns_count; i++)
if (client->conns[i] == conn) {
+
+ silc_idcache_free(conn->client_cache);
+ silc_idcache_free(conn->channel_cache);
+ silc_idcache_free(conn->server_cache);
if (conn->pending_commands)
silc_dlist_uninit(conn->pending_commands);
+ silc_free(conn->remote_host);
+ silc_dlist_uninit(conn->ftp_sessions);
silc_free(conn);
+
client->conns[i] = NULL;
}
}
return TRUE;
}
+/* Callback called when error has occurred during connecting to the server.
+ The `connect' client operation will be called. */
+
+SILC_TASK_CALLBACK(silc_client_connect_failure)
+{
+ SilcClientKEInternalContext *ctx =
+ (SilcClientKEInternalContext *)context;
+ SilcClient client = (SilcClient)ctx->client;
+
+ client->ops->connect(client, ctx->sock->user_data, FALSE);
+ silc_free(ctx);
+}
+
/* Start of the connection to the remote server. This is called after
succesful TCP/IP connection has been established to the remote host. */
silc_socket_free(ctx->sock);
/* Notify application of failure */
- client->ops->connect(client, ctx->sock->user_data, FALSE);
- silc_free(ctx);
+ silc_schedule_task_add(client->schedule, ctx->sock->sock,
+ silc_client_connect_failure, ctx,
+ 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
return;
}
ctx->ske->prop->pkcs,
ctx->ske->prop->hash,
ctx->ske->prop->hmac,
- ctx->ske->prop->group);
+ ctx->ske->prop->group,
+ ctx->responder);
silc_ske_free_key_material(ctx->keymat);
/* Allocate internal context for the authentication protocol. This
silc_socket_free(ctx->sock);
/* Notify application of failure */
- client->ops->connect(client, ctx->sock->user_data, FALSE);
- silc_free(ctx);
+ silc_schedule_task_add(client->schedule, ctx->sock->sock,
+ silc_client_connect_failure, ctx,
+ 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
return;
}
/* If connection is disconnecting already we will finally
close the connection */
if (SILC_IS_DISCONNECTING(sock)) {
- if (sock == conn->sock)
+ if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
client->ops->disconnect(client, conn);
silc_client_close_connection(client, sock, conn);
return;
}
SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
- if (sock == conn->sock)
+ if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
client->ops->disconnect(client, conn);
silc_client_close_connection(client, sock, conn);
return;
}
}
-/* Parses whole packet, received earlier. */
+/* Parser callback called by silc_packet_receive_process. Thie merely
+ registers timeout that will handle the actual parsing when appropriate. */
-SILC_TASK_CALLBACK(silc_client_packet_parse_real)
+static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
+ void *context)
{
- SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
- SilcClient client = (SilcClient)parse_ctx->context;
- SilcPacketContext *packet = parse_ctx->packet;
- SilcSocketConnection sock = parse_ctx->sock;
+ SilcClient client = (SilcClient)context;
+ SilcSocketConnection sock = parser_context->sock;
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- int ret;
+ SilcPacketContext *packet = parser_context->packet;
+ SilcPacketType ret;
- SILC_LOG_DEBUG(("Start"));
+ if (conn && conn->hmac_receive && conn->sock == sock)
+ conn->psn_receive = parser_context->packet->sequence + 1;
- /* Parse the packet */
- if (parse_ctx->normal)
+ /* Parse the packet immediately */
+ if (parser_context->normal)
ret = silc_packet_parse(packet, conn->receive_key);
else
ret = silc_packet_parse_special(packet, conn->receive_key);
- if (ret == SILC_PACKET_NONE)
- goto out;
+ if (ret == SILC_PACKET_NONE) {
+ silc_packet_context_free(packet);
+ silc_free(parser_context);
+ return FALSE;
+ }
+
+ /* If protocol for this connection is key exchange or rekey then we'll
+ process all packets synchronously, since there might be packets in
+ queue that we are not able to decrypt without first processing the
+ packets before them. */
+ if ((ret == SILC_PACKET_REKEY || ret == SILC_PACKET_REKEY_DONE) ||
+ (sock->protocol && sock->protocol->protocol &&
+ (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
+ sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY))) {
+
+ /* Parse the incoming packet type */
+ silc_client_packet_parse_type(client, sock, packet);
+ silc_packet_context_free(packet);
+ silc_free(parser_context);
+
+ /* Reprocess the buffer since we'll return FALSE. This is because
+ the `conn->receive_key' might have become valid by processing
+ the previous packet */
+ if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
+ silc_packet_receive_process(sock, FALSE, conn->receive_key,
+ conn->hmac_receive, conn->psn_receive,
+ silc_client_packet_parse, client);
+ else
+ silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
+ silc_client_packet_parse, client);
+
+ return FALSE;
+ }
/* Parse the incoming packet type */
silc_client_packet_parse_type(client, sock, packet);
-
- out:
- /* silc_buffer_clear(sock->inbuf); */
silc_packet_context_free(packet);
- silc_free(parse_ctx);
-}
-
-/* Parser callback called by silc_packet_receive_process. Thie merely
- registers timeout that will handle the actual parsing when appropriate. */
-
-void silc_client_packet_parse(SilcPacketParserContext *parser_context,
- void *context)
-{
- SilcClient client = (SilcClient)context;
- SilcSocketConnection sock = parser_context->sock;
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
-
- if (conn && conn->hmac_receive)
- conn->psn_receive = parser_context->packet->sequence + 1;
-
- /* Parse the packet */
- silc_schedule_task_add(client->schedule, parser_context->sock->sock,
- silc_client_packet_parse_real,
- (void *)parser_context, 0, 1,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_free(parser_context);
+ return TRUE;
}
/* Parses the packet type and calls what ever routines the packet type
silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf,
sock->outbuf->len);
- SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
+ SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, sock->outbuf->len),
sock->outbuf->data, sock->outbuf->len);
/* Now actually send the packet */
{
int del = FALSE;
+ SILC_LOG_DEBUG(("Start"));
+
if (!sock || (sock && conn->sock == sock))
del = TRUE;
if (!sock)
if (conn->rekey)
silc_free(conn->rekey);
+ if (conn->active_session) {
+ sock->user_data = NULL;
+ silc_client_ftp_session_free(conn->active_session);
+ conn->active_session = NULL;
+ }
+
+ silc_client_ftp_free_sessions(client, conn);
+
memset(conn, 0, sizeof(*conn));
silc_client_del_connection(client, conn);
}
silc_socket_free(sock);
}
+/* Called when we receive disconnection packet from server. This
+ closes our end properly and displays the reason of the disconnection
+ on the screen. */
+
+SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
+{
+ SilcClient client = (SilcClient)context;
+ SilcSocketConnection sock;
+
+ SILC_CLIENT_GET_SOCK(client, fd, sock);
+ if (sock == NULL)
+ return;
+
+ silc_client_close_connection(client, sock, sock->user_data);
+}
+
/* Called when we receive disconnection packet from server. This
closes our end properly and displays the reason of the disconnection
on the screen. */
silc_free(msg);
SILC_SET_DISCONNECTED(sock);
- silc_client_close_connection(client, sock, sock->user_data);
+
+ /* Close connection through scheduler. */
+ silc_schedule_task_add(client->schedule, sock->sock,
+ silc_client_disconnected_by_server_later,
+ client, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
}
/* Received error message from server. Display it on the screen.
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
int connecting = FALSE;
+ SilcClientID *client_id = silc_id_payload_get_id(idp);
SilcBuffer sidp;
if (!conn->local_entry)
/* Delete old ID from ID cache */
if (conn->local_id) {
+ /* Check whether they are different */
+ if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
+ silc_free(client_id);
+ return;
+ }
+
silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
silc_free(conn->local_id);
}
if (conn->local_id_data)
silc_free(conn->local_id_data);
- conn->local_id = silc_id_payload_get_id(idp);
+ conn->local_id = client_id;
conn->local_id_data = silc_id_payload_get_data(idp);
conn->local_id_data_len = silc_id_payload_get_len(idp);;
silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
(void *)conn->local_entry, FALSE);
- /* Issue INFO command to fetch the real server name and server information
- and other stuff. */
- sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
- silc_client_send_command(client, conn, SILC_COMMAND_INFO,
- ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
- silc_buffer_free(sidp);
+ if (connecting) {
+ /* Issue INFO comqmand to fetch the real server name and server information
+ and other stuff. */
+ sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
+ silc_client_send_command(client, conn, SILC_COMMAND_INFO,
+ ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
+ silc_buffer_free(sidp);
- /* Notify application of successful connection. We do it here now that
- we've received the Client ID and are allowed to send traffic. */
- if (connecting)
+ /* Notify application of successful connection. We do it here now that
+ we've received the Client ID and are allowed to send traffic. */
client->ops->connect(client, conn, TRUE);
+ }
}
/* Processed received Channel ID for a channel. This is called when client
conn, client->params->connauth_request_secs, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
}
-
-/* Called when file transfer packet is received. This will parse the
- packet and give it to the file transfer protocol. */
-
-void silc_client_ftp(SilcClient client,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
-{
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- uint8 type;
- int ret;
-
- /* Parse the payload */
- ret = silc_buffer_unformat(packet->buffer,
- SILC_STR_UI_CHAR(&type),
- SILC_STR_END);
- if (ret == -1)
- return;
-
- /* We support only type number 1 (== SFTP) */
- if (type != 1)
- return;
-
- silc_buffer_pull(packet->buffer, 1);
-
- /* Give it to the file transfer protocol processor. */
- //silc_sftp_client_receive_process(xxx, sock, packet);
-}