-SILC_TASK_CALLBACK(silc_client_ftp_connected)
-{
- SilcClientInternalConnectContext *ctx =
- (SilcClientInternalConnectContext *)context;
- SilcClient client = ctx->client;
- SilcClientConnection conn = ctx->conn;
- SilcClientFtpSession session = (SilcClientFtpSession)ctx->context;
- int opt, opt_len = sizeof(opt);
-
- SILC_LOG_DEBUG(("Start"));
-
- /* Check the socket status as it might be in error */
- silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
- if (opt != 0) {
- if (ctx->tries < 2) {
- /* Connection failed but lets try again */
- client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
- "Could not connect to client %s: %s",
- ctx->host, strerror(opt));
- client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
- "Connecting to port %d of client %s resumed",
- ctx->port, ctx->host);
-
- /* Unregister old connection try */
- silc_schedule_unset_listen_fd(client->schedule, fd);
- silc_net_close_connection(fd);
- silc_schedule_task_del(client->schedule, ctx->task);
-
- /* Try again */
- silc_client_connect_to_client_internal(ctx);
- ctx->tries++;
- } else {
- /* Connection failed and we won't try anymore */
- client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
- "Could not connect to client %s: %s",
- ctx->host, strerror(opt));
- silc_schedule_unset_listen_fd(client->schedule, fd);
- silc_net_close_connection(fd);
- silc_schedule_task_del(client->schedule, ctx->task);
- silc_free(ctx);
- silc_client_ftp_session_free(session);
- }
- return;
- }
-
- silc_schedule_unset_listen_fd(client->schedule, fd);
- silc_schedule_task_del(client->schedule, ctx->task);
-
- /* Start the key agreement */
- silc_client_ftp_start_key_agreement(session, fd);
-}
-
-static int
-silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
-{
- int sock;
-
- /* Create connection to server asynchronously */
- sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
- if (sock < 0)
- return -1;
-
- /* Register task that will receive the async connect and will
- read the result. */
- ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
- silc_client_ftp_connected,
- (void *)ctx, 0, 0,
- SILC_TASK_FD,
- SILC_TASK_PRI_NORMAL);
- silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
-
- ctx->sock = sock;
-
- return sock;
-}
-
-static int
-silc_client_connect_to_client(SilcClient client,
- SilcClientConnection conn, int port,
- char *host, void *context)
-{
- SilcClientInternalConnectContext *ctx;
-
- /* Allocate internal context for connection process. This is
- needed as we are doing async connecting. */
- ctx = silc_calloc(1, sizeof(*ctx));
- ctx->client = client;
- ctx->conn = conn;
- ctx->host = strdup(host);
- ctx->port = port;
- ctx->tries = 0;
- ctx->context = context;
-
- /* Do the actual connecting process */
- return silc_client_connect_to_client_internal(ctx);
-}
-
-/* Free session */
-
-void silc_client_ftp_session_free(SilcClientFtpSession session)
-{
- SilcClientConnection conn;
-
- silc_dlist_del(session->conn->ftp_sessions, session);
-
- if (session->sftp) {
- if (session->server)
- silc_sftp_server_shutdown(session->sftp);
- else
- silc_sftp_client_shutdown(session->sftp);
- }
-
- if (session->fs)
- silc_sftp_fs_memory_free(session->fs);
-
- if (session->listener) {
- silc_schedule_unset_listen_fd(session->client->schedule,
- session->listener);
- silc_net_close_connection(session->listener);
- }
-
- if (session->sock) {
- silc_schedule_unset_listen_fd(session->client->schedule,
- session->sock->sock);
- silc_net_close_connection(session->sock->sock);
-
- if (session->sock->user_data) {
- conn = (SilcClientConnection)session->sock->user_data;
-
- if (conn->active_session == session)
- conn->active_session = NULL;
-
- silc_client_close_connection(session->client, session->sock, conn);
- } else {
- silc_socket_free(session->sock);
- }
- }
-
- silc_free(session->hostname);
- silc_free(session->filepath);
- silc_free(session);
-}