From 97cd1e6a44ca3b7cce2f8b6da351362ba78dcc9f Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 7 Nov 2002 18:05:07 +0000 Subject: [PATCH] Added -no-listener option to FILE SEND command in Irssi SILC client. Renamed FILE RECEIVE to FILE ACCEPT in Irssi SILC client. Added "do_not_bind" argument to silc_client_file_send. --- CHANGES | 12 +++++ apps/irssi/docs/help/in/file.in | 20 +++++---- apps/irssi/src/silc/core/client_ops.c | 25 ++++++++--- apps/irssi/src/silc/core/silc-servers.c | 31 +++++++++---- lib/silcclient/client_ftp.c | 60 ++++++++++++++++--------- lib/silcclient/silcclient.h | 10 +++-- 6 files changed, 107 insertions(+), 51 deletions(-) diff --git a/CHANGES b/CHANGES index ef180903..0f05c532 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,15 @@ +Thu Nov 7 19:21:10 EET 2002 Pekka Riikonen + + * Added "do_not_bind" argument to silc_client_file_send what + can be used to not bind locally but assume the file receiver + provides the point of connect. Usefull when sender is behind + NAT device. Affected file lib/silcclient/silcclient.h and + client_ftp.c. + + * Added -no-listener option to FILE SEND command in Irssi SILC + client. Affected file irssi/src/silc/core/silc-servers.c. + Renamed FILE RECEIVE to FILE ACCEPT. + Thu Nov 7 10:05:28 CET 2002 Pekka Riikonen * Move silc_client_packet_send back to internal, added diff --git a/apps/irssi/docs/help/in/file.in b/apps/irssi/docs/help/in/file.in index 4e85a92c..cb6ee86f 100644 --- a/apps/irssi/docs/help/in/file.in +++ b/apps/irssi/docs/help/in/file.in @@ -15,6 +15,7 @@ giving the FILE command without arguments. Commands: SEND [ []] + [-no-listener] Sends file transfer request to . This makes the available to . @@ -23,16 +24,18 @@ Commands: protocol listener will be bound to that address. If is defined it is bound to that port. If they are not defined then the local IP address - of your machine is used to bind the listener. If that - fails then the is assumed to provide the - listener. If you do not know whether you need to - provide or not, do not provide it. + of your machine is used to bind the listener. - RECEIVE [] + If the -no-listener option is used the client does not + bind locally but assumes that the will provide + the point of connect. This is usefull when the sender + is behind NAT device. - Accepts the file transfer request and starts - the file transfer session. If the is - omitted the last received request is used. + ACCEPT [] + + Accepts the file transfer request and starts the file + transfer session. If the is omitted the + last received request is used. CLOSE [] @@ -40,4 +43,3 @@ Commands: file transfer request. If this command is given during the file transfer process it will be cancelled. - diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index d8158bdd..1a539869 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -2247,18 +2247,29 @@ void silc_ftp(SilcClient client, SilcClientConnection conn, { SILC_SERVER_REC *server; char portstr[12]; - FtpSession ftp = silc_calloc(1, sizeof(*ftp)); + FtpSession ftp = NULL; SILC_LOG_DEBUG(("Start")); server = conn->context; - ftp->client_entry = client_entry; - ftp->session_id = session_id; - ftp->send = FALSE; - ftp->conn = conn; - silc_dlist_add(server->ftp_sessions, ftp); - server->current_session = ftp; + silc_dlist_start(server->ftp_sessions); + while ((ftp = silc_dlist_get(server->ftp_sessions)) != SILC_LIST_END) { + if (ftp->client_entry == client_entry && + ftp->session_id == session_id) { + server->current_session = ftp; + break; + } + } + if (ftp == SILC_LIST_END) { + ftp = silc_calloc(1, sizeof(*ftp)); + ftp->client_entry = client_entry; + ftp->session_id = session_id; + ftp->send = FALSE; + ftp->conn = conn; + silc_dlist_add(server->ftp_sessions, ftp); + server->current_session = ftp; + } if (hostname) snprintf(portstr, sizeof(portstr) - 1, "%d", port); diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index 198926c1..77ae7d8d 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -435,8 +435,8 @@ char *silc_server_get_channels(SILC_SERVER_REC *server) /* SYNTAX: PING */ /* SYNTAX: SCONNECT [] */ /* SYNTAX: USERS */ -/* SYNTAX: FILE SEND [ []] */ -/* SYNTAX: FILE RECEIVE [] */ +/* SYNTAX: FILE SEND [ []] [-no-listener]*/ +/* SYNTAX: FILE ACCEPT [] */ /* SYNTAX: FILE CLOSE [] */ /* SYNTAX: FILE */ /* SYNTAX: JOIN [] [-cipher ] [-hmac ] [-founder] */ @@ -666,6 +666,7 @@ static void command_file(const char *data, SILC_SERVER_REC *server, char *local_ip = NULL; SilcUInt32 local_port = 0; SilcUInt32 session_id; + bool do_not_bind = FALSE; CMD_SILC_SERVER(server); if (!server || !IS_SILC_SERVER(server) || !server->connected) @@ -675,7 +676,7 @@ static void command_file(const char *data, SILC_SERVER_REC *server, /* Now parse all arguments */ tmp = g_strconcat("FILE", " ", data, NULL); - silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 6); + silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7); g_free(tmp); if (argc == 1) @@ -684,7 +685,7 @@ static void command_file(const char *data, SILC_SERVER_REC *server, if (argc >= 2) { if (!strcasecmp(argv[1], "send")) type = 1; - if (!strcasecmp(argv[1], "receive")) + if (!strcasecmp(argv[1], "accept")) type = 2; if (!strcasecmp(argv[1], "close")) type = 3; @@ -721,14 +722,26 @@ static void command_file(const char *data, SILC_SERVER_REC *server, client_entry = entrys[0]; silc_free(entrys); - if (argc >= 5) - local_ip = argv[4]; - if (argc >= 6) - local_port = atoi(argv[5]); + if (argc >= 5) { + if (!strcasecmp(argv[4], "-no-listener")) + do_not_bind = TRUE; + else + local_ip = argv[4]; + } + if (argc >= 6) { + if (!strcasecmp(argv[5], "-no-listener")) + do_not_bind = TRUE; + else + local_port = atoi(argv[5]); + } + if (argc >= 7) { + if (!strcasecmp(argv[6], "-no-listener")) + do_not_bind = TRUE; + } ret = silc_client_file_send(silc_client, conn, silc_client_file_monitor, - server, local_ip, local_port, + server, local_ip, local_port, do_not_bind, client_entry, argv[2], &session_id); if (ret == SILC_CLIENT_FILE_OK) { ftp = silc_calloc(1, sizeof(*ftp)); diff --git a/lib/silcclient/client_ftp.c b/lib/silcclient/client_ftp.c index fb2891f8..ed9ca3bc 100644 --- a/lib/silcclient/client_ftp.c +++ b/lib/silcclient/client_ftp.c @@ -53,7 +53,8 @@ struct SilcClientFtpSessionStruct { SilcSFTP sftp; SilcSFTPFilesystem fs; - bool server; + unsigned int server : 1; + unsigned int bound : 1; SilcSFTPHandle dir_handle; SilcSFTPHandle read_handle; @@ -793,6 +794,7 @@ silc_client_file_send(SilcClient client, void *monitor_context, const char *local_ip, SilcUInt32 local_port, + bool do_not_bind, SilcClientEntry client_entry, const char *filepath, SilcUInt32 *session_id) @@ -826,11 +828,11 @@ silc_client_file_send(SilcClient client, 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->internal->ftp_sessions, session); path = silc_calloc(strlen(filepath) + 9, sizeof(*path)); @@ -850,27 +852,33 @@ silc_client_file_send(SilcClient client, 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); @@ -945,11 +953,13 @@ silc_client_file_receive(SilcClient client, 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) { @@ -965,6 +975,7 @@ silc_client_file_receive(SilcClient client, 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); @@ -1048,7 +1059,8 @@ static void silc_client_ftp_resolve_cb(SilcClient client, 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) + if (session->client_entry == client_entry && + (!session->server || !session->bound)) break; } @@ -1068,6 +1080,8 @@ static void silc_client_ftp_resolve_cb(SilcClient client, 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)); @@ -1093,6 +1107,8 @@ static void silc_client_ftp_resolve_cb(SilcClient client, 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 */ diff --git a/lib/silcclient/silcclient.h b/lib/silcclient/silcclient.h index ce6eb6e5..156cdf1d 100644 --- a/lib/silcclient/silcclient.h +++ b/lib/silcclient/silcclient.h @@ -2295,6 +2295,7 @@ typedef void (*SilcClientFileMonitor)(SilcClient client, * void *monitor_context, * const char *local_ip, * SilcUInt32 local_port, + * bool do_not_bind, * SilcClientEntry client_entry, * const char *filepath); * SilcUInt32 *session_id); @@ -2308,7 +2309,7 @@ typedef void (*SilcClientFileMonitor)(SilcClient client, * transmission of the file. * * This returns a file session ID for the file transmission to the - * `session_id' pointer.. It can be used to close the session (and + * `session_id' pointer. It can be used to close the session (and * abort the file transmission) by calling the silc_client_file_close * function. The session ID is also returned in the `monitor' callback. * @@ -2316,9 +2317,9 @@ typedef void (*SilcClientFileMonitor)(SilcClient client, * listener for key exchange protocol to that IP. If `local_port' is * non-zero that port is used. If `local_ip' is NULL then this will * automatically attempt to bind it to local IP address of the machine. - * If that fails then this does not bind to any address and port, and - * assume that the remote client will provide the listener for the - * key exchange protocol. + * If `do_not_bind' is TRUE then the `local_ip' and `local_port' are + * ignored and it is expected that the receiver will provide the + * point of contact. This is usefull if the sender is behind NAT. * * If error will occur during the file transfer process the error * status will be returned in the monitor callback. In this case @@ -2333,6 +2334,7 @@ silc_client_file_send(SilcClient client, void *monitor_context, const char *local_ip, SilcUInt32 local_port, + bool do_not_bind, SilcClientEntry client_entry, const char *filepath, SilcUInt32 *session_id); -- 2.24.0