Renamed FILE RECEIVE to FILE ACCEPT in Irssi SILC client.
Added "do_not_bind" argument to silc_client_file_send.
+Thu Nov 7 19:21:10 EET 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * 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 <priikone@silcnet.org>
* Move silc_client_packet_send back to internal, added
Commands:
SEND <filepath> <nickname> [<local IP> [<local port>]]
+ [-no-listener]
Sends file transfer request to <nickname>. This
makes the <filepath> available to <nickname>.
protocol listener will be bound to that address. If
<local port> 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 <nickname> is assumed to provide the
- listener. If you do not know whether you need to
- provide <local IP> or not, do not provide it.
+ of your machine is used to bind the listener.
- RECEIVE [<nickname>]
+ If the -no-listener option is used the client does not
+ bind locally but assumes that the <nickname> 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 <nickname> is
- omitted the last received request is used.
+ ACCEPT [<nickname>]
+
+ Accepts the file transfer request and starts the file
+ transfer session. If the <nickname> is omitted the
+ last received request is used.
CLOSE [<nickname>]
file transfer request. If this command is given
during the file transfer process it will be cancelled.
-
{
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);
/* SYNTAX: PING */
/* SYNTAX: SCONNECT <server> [<port>] */
/* SYNTAX: USERS <channel> */
-/* SYNTAX: FILE SEND <filepath> <nickname> [<local IP> [<local port>]] */
-/* SYNTAX: FILE RECEIVE [<nickname>] */
+/* SYNTAX: FILE SEND <filepath> <nickname> [<local IP> [<local port>]] [-no-listener]*/
+/* SYNTAX: FILE ACCEPT [<nickname>] */
/* SYNTAX: FILE CLOSE [<nickname>] */
/* SYNTAX: FILE */
/* SYNTAX: JOIN <channel> [<passphrase>] [-cipher <cipher>] [-hmac <hmac>] [-founder] */
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)
/* 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)
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;
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));
SilcSFTP sftp;
SilcSFTPFilesystem fs;
- bool server;
+ unsigned int server : 1;
+ unsigned int bound : 1;
SilcSFTPHandle dir_handle;
SilcSFTPHandle read_handle;
void *monitor_context,
const char *local_ip,
SilcUInt32 local_port,
+ bool do_not_bind,
SilcClientEntry client_entry,
const char *filepath,
SilcUInt32 *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->internal->ftp_sessions, session);
path = silc_calloc(strlen(filepath) + 9, sizeof(*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);
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);
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;
}
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->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 */
* void *monitor_context,
* const char *local_ip,
* SilcUInt32 local_port,
+ * bool do_not_bind,
* SilcClientEntry client_entry,
* const char *filepath);
* SilcUInt32 *session_id);
* 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.
*
* 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
void *monitor_context,
const char *local_ip,
SilcUInt32 local_port,
+ bool do_not_bind,
SilcClientEntry client_entry,
const char *filepath,
SilcUInt32 *session_id);