-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->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
- "Could not connect to client %s: %s",
- ctx->host, strerror(opt));
- client->internal->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->internal->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);
-}
-
-/* SFTP packet send callback. This will use preallocated buffer to avoid
- reallocation of outgoing data buffer everytime. */
-
-static void silc_client_ftp_send_packet(SilcSocketConnection sock,
- SilcBuffer packet, void *context)
-{
- SilcClientFtpSession session = (SilcClientFtpSession)context;
- SilcClient client = session->client;
-
- SILC_LOG_DEBUG(("Start"));
-
- /* Allocate outgoing packet */
- if (!session->packet)
- session->packet = silc_buffer_alloc(1 + packet->len);
-
- /* Enlarge outgoing packet if needed */
- if (session->packet->truelen < 1 + packet->len)
- session->packet = silc_buffer_realloc(session->packet, 1 + packet->len);
-
- /* Encode packet */
- silc_buffer_pull_tail(session->packet, 1 + packet->len);
- silc_buffer_format(session->packet,
- SILC_STR_UI_CHAR(1),
- SILC_STR_UI_XNSTRING(packet->data, packet->len),
- SILC_STR_END);