+ session->ask_name = ask_name;
+ session->ask_name_context = ask_name_context;
+ session->path = path ? strdup(path) : NULL;
+
+ /* If the hostname and port already exists then the remote client did
+ provide the connection point to us and we won't create listener, but
+ create the connection ourselves. */
+ if (session->hostname && session->port) {
+ SILC_LOG_DEBUG(("Connecting to remote client"));
+ /* Connect to the remote client. Performs key exchange automatically. */
+ session->op =
+ silc_client_connect_to_client(client, params, public_key, private_key,
+ session->hostname, session->port,
+ silc_client_ftp_connect_completion,
+ session);
+ if (!session->op) {
+ silc_free(session);
+ return SILC_CLIENT_FILE_ERROR;
+ }
+ } else {
+ /* Add the listener for the key agreement */
+ SILC_LOG_DEBUG(("Creating listener for file transfer"));
+ if (!params || (!params->local_ip && !params->bind_ip)) {
+ session->client->internal->ops->say(session->client, session->conn,
+ SILC_CLIENT_MESSAGE_ERROR,
+ "Cannot create listener for file "
+ "transfer; IP address and/or port "
+ "not provided");
+ silc_free(session);
+ return SILC_CLIENT_FILE_ERROR;
+ }
+ session->listener =
+ silc_client_listener_add(client, conn->internal->schedule, params,
+ public_key, private_key,
+ silc_client_ftp_connect_completion,
+ session);
+ if (!session->listener) {
+ client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+ "Cannot create listener for file transfer: "
+ "%s", silc_errno_string(silc_errno));
+
+ silc_free(session);
+ return SILC_CLIENT_FILE_NO_MEMORY;
+ }
+ session->hostname = (params->bind_ip ? strdup(params->bind_ip) :
+ strdup(params->local_ip));
+ session->port = silc_client_listener_get_local_port(session->listener);
+
+ /* Send the key agreement inside FTP packet */
+ SILC_LOG_DEBUG(("Sending key agreement for file transfer"));
+ keyagr = silc_key_agreement_payload_encode(session->hostname, 0,
+ session->port);
+ if (!keyagr) {
+ silc_client_listener_free(session->listener);
+ silc_free(session);
+ return SILC_CLIENT_FILE_NO_MEMORY;
+ }
+ silc_packet_send_va_ext(conn->stream, SILC_PACKET_FTP, 0, 0, NULL,
+ SILC_ID_CLIENT, &session->client_entry->id,
+ NULL, NULL,
+ SILC_STR_UI_CHAR(1),
+ SILC_STR_DATA(silc_buffer_data(keyagr),
+ silc_buffer_len(keyagr)),
+ SILC_STR_END);
+ silc_buffer_free(keyagr);
+
+ /* Add session request timeout */
+ if (params && params->timeout_secs)
+ silc_schedule_task_add_timeout(client->schedule,
+ silc_client_ftp_timeout, session,
+ params->timeout_secs, 0);