SilcSFTP sftp;
SilcSFTPFilesystem fs;
- bool server;
+ unsigned int server : 1;
+ unsigned int bound : 1;
SilcSFTPHandle dir_handle;
SilcSFTPHandle read_handle;
(void *)ctx, 0, 0,
SILC_TASK_FD,
SILC_TASK_PRI_NORMAL);
- silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
+ silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
+ FALSE);
ctx->sock = sock;
return sock;
}
}
/* Set this as active session */
- conn->active_session = session;
+ conn->internal->active_session = session;
out:
silc_ske_free_key_material(ctx->keymat);
void silc_client_ftp_free_sessions(SilcClient client,
SilcClientConnection conn)
{
- if (conn->ftp_sessions) {
+ if (conn->internal->ftp_sessions) {
SilcClientFtpSession session;
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->sock)
session->sock->user_data = NULL;
silc_client_ftp_session_free(session);
}
- silc_dlist_del(conn->ftp_sessions, session);
- silc_dlist_uninit(conn->ftp_sessions);
+ silc_dlist_del(conn->internal->ftp_sessions, session);
}
}
{
SilcClientFtpSession session;
- if (!conn->ftp_sessions)
+ if (!conn->internal->ftp_sessions)
return;
/* Get the session */
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
- if (session->client_entry == client_entry) {
- if (session->sock)
- session->sock->user_data = NULL;
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
+ if (session->client_entry == client_entry)
silc_client_ftp_session_free(session);
- }
}
}
SILC_LOG_DEBUG(("Free session"));
- silc_dlist_del(session->conn->ftp_sessions, session);
+ if (session->conn && session->conn->internal->ftp_sessions)
+ silc_dlist_del(session->conn->internal->ftp_sessions, session);
+
+ if (session->conn && session->conn->internal->active_session == session)
+ session->conn->internal->active_session = NULL;
if (session->sftp) {
if (session->server)
if (session->sock->user_data) {
conn = (SilcClientConnection)session->sock->user_data;
- if (conn->active_session == session)
- conn->active_session = NULL;
+ if (conn->internal->active_session == session)
+ conn->internal->active_session = NULL;
silc_client_close_connection_real(session->client, session->sock, conn);
} else {
silc_free(session->hostname);
silc_free(session->filepath);
+ silc_free(session->path);
+ memset(session, 'F', sizeof(*session));
silc_free(session);
}
void *monitor_context,
const char *local_ip,
SilcUInt32 local_port,
+ bool do_not_bind,
SilcClientEntry client_entry,
const char *filepath,
SilcUInt32 *session_id)
char *filename, *path;
int fd;
+ assert(client && conn && client_entry);
+
SILC_LOG_DEBUG(("Start"));
/* Check for existing session for `filepath'. */
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->filepath && !strcmp(session->filepath, filepath) &&
session->client_entry == client_entry)
return SILC_CLIENT_FILE_ALREADY_STARTED;
/* Add new session */
session = silc_calloc(1, sizeof(*session));
- session->session_id = ++conn->next_session_id;
+ session->session_id = ++conn->internal->next_session_id;
session->client = client;
session->conn = conn;
+ session->server = TRUE;
session->client_entry = client_entry;
session->monitor = monitor;
session->monitor_context = monitor_context;
session->filepath = strdup(filepath);
- session->server = TRUE;
- silc_dlist_add(conn->ftp_sessions, session);
+ silc_dlist_add(conn->internal->ftp_sessions, session);
- path = silc_calloc(strlen(filepath) + 8, sizeof(*path));
- strcat(path, "file://");
- strncat(path, filepath, strlen(filepath));
+ path = silc_calloc(strlen(filepath) + 9, sizeof(*path));
+ silc_strncat(path, strlen(filepath) + 9, "file://", 7);
+ silc_strncat(path, strlen(filepath) + 9, filepath, strlen(filepath));
/* Allocate memory filesystem and put the file to it */
if (strrchr(path, '/'))
session->filesize = silc_file_size(filepath);
/* Create the listener for incoming key exchange protocol. */
- if (local_ip)
- session->hostname = strdup(local_ip);
- else
- session->hostname = silc_net_localip();
- session->listener = silc_net_create_server(local_port, session->hostname);
- if (session->listener < 0) {
- /* Could not create listener. Do the second best thing; send empty
- key agreement packet and let the remote client provide the point
- for the key exchange. */
- SILC_LOG_DEBUG(("Could not create listener"));
- silc_free(session->hostname);
- session->hostname = NULL;
- session->port = 0;
- } else {
- /* Listener ready */
- session->port = silc_net_get_local_port(session->listener);
- silc_schedule_task_add(client->schedule, session->listener,
- silc_client_ftp_process_key_agreement, session,
- 0, 0, SILC_TASK_FD, SILC_TASK_PRI_NORMAL);
+ if (!do_not_bind) {
+ if (local_ip)
+ session->hostname = strdup(local_ip);
+ else
+ session->hostname = silc_net_localip();
+ session->listener = silc_net_create_server(local_port, session->hostname);
+ if (session->listener < 0) {
+ /* Could not create listener. Do the second best thing; send empty
+ key agreement packet and let the remote client provide the point
+ for the key exchange. */
+ SILC_LOG_DEBUG(("Could not create listener"));
+ silc_free(session->hostname);
+ session->hostname = NULL;
+ session->port = 0;
+ } else {
+ /* Listener ready */
+ SILC_LOG_DEBUG(("Bound listener"));
+ session->port = silc_net_get_local_port(session->listener);
+ silc_schedule_task_add(client->schedule, session->listener,
+ silc_client_ftp_process_key_agreement, session,
+ 0, 0, SILC_TASK_FD, SILC_TASK_PRI_NORMAL);
+ session->bound = TRUE;
+ }
}
+ SILC_LOG_DEBUG(("Sending key agreement for file transfer"));
+
/* Send the key agreement inside FTP packet */
keyagr = silc_key_agreement_payload_encode(session->hostname, session->port);
SilcClientFtpSession session;
SilcBuffer keyagr, ftp;
+ assert(client && conn);
+
SILC_LOG_DEBUG(("Start, Session ID: %d", session_id));
/* Get the session */
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->session_id == session_id) {
break;
}
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"));
if (silc_client_connect_to_client(client, conn, session->port,
session->hostname, session) < 0)
return SILC_CLIENT_FILE_ERROR;
} else {
/* Add the listener for the key agreement */
+ SILC_LOG_DEBUG(("Creating listener for file transfer"));
session->hostname = silc_net_localip();
session->listener = silc_net_create_server(0, session->hostname);
if (session->listener < 0) {
0, 0, SILC_TASK_FD, SILC_TASK_PRI_NORMAL);
/* Send the key agreement inside FTP packet */
+ SILC_LOG_DEBUG(("Sending key agreement for file transfer"));
keyagr = silc_key_agreement_payload_encode(session->hostname,
session->port);
ftp = silc_buffer_alloc(1 + keyagr->len);
{
SilcClientFtpSession session;
+ assert(client && conn);
+
SILC_LOG_DEBUG(("Start, Session ID: %d", session_id));
/* Get the session */
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->session_id == session_id) {
break;
}
client_entry = clients[0];
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
- if (session->client_entry == client_entry)
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
+ if (session->client_entry == client_entry &&
+ (!session->server || !session->bound))
break;
}
if (session == SILC_LIST_END || (!hostname && !port)) {
/* No session found, create one and let the application know about
incoming file transfer request. */
+ SILC_LOG_DEBUG(("New file transfer session ID: %d",
+ conn->internal->next_session_id + 1));
/* Add new session */
session = silc_calloc(1, sizeof(*session));
- session->session_id = ++conn->next_session_id;
+ session->session_id = ++conn->internal->next_session_id;
session->client = client;
session->conn = conn;
session->client_entry = client_entry;
- silc_dlist_add(conn->ftp_sessions, session);
+ silc_dlist_add(conn->internal->ftp_sessions, session);
/* Let the application know */
client->internal->ops->ftp(client, conn, client_entry,
session->port = port;
/* Session exists, continue with key agreement protocol. */
+ SILC_LOG_DEBUG(("Session ID %d exists, connecting to remote client",
+ session->session_id));
if (silc_client_connect_to_client(client, conn, port,
hostname, session) < 0) {
/* Call monitor callback */
/* If we have active FTP session then give the packet directly to the
protocol processor. */
- if (conn->active_session) {
+ if (conn->internal->active_session) {
/* Give it to the SFTP */
- if (conn->active_session->server)
- silc_sftp_server_receive_process(conn->active_session->sftp, sock,
- packet);
+ if (conn->internal->active_session->server)
+ silc_sftp_server_receive_process(conn->internal->active_session->sftp,
+ sock, packet);
else
- silc_sftp_client_receive_process(conn->active_session->sftp, sock,
- packet);
+ silc_sftp_client_receive_process(conn->internal->active_session->sftp,
+ sock, packet);
} else {
/* We don't have active session, resolve the remote client information
and then try to find the correct session. */
/* Resolve the client */
silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
- silc_client_ftp_resolve_cb,
+ NULL, silc_client_ftp_resolve_cb,
silc_packet_context_dup(packet));
silc_free(remote_id);
}