summaryrefslogtreecommitdiff
path: root/libavformat/ftp.c
diff options
context:
space:
mode:
authorLukasz Marek <lukasz.m.luki2@gmail.com>2014-05-19 23:53:08 +0200
committerLukasz Marek <lukasz.m.luki2@gmail.com>2014-05-20 00:00:45 +0200
commitb9419b58826effc3d9afabd1a2e50d66391fbdbf (patch)
tree5c3f6bcb4af97ae11a630c0813360fa901422f96 /libavformat/ftp.c
parent37fa4b9bb9672520fa901b69234ac611bbbd133f (diff)
lavf/ftp: favour EPSV over PASV command
EPSV is newer version of PASV and allows to use IPv6. Signed-off-by: Lukasz Marek <lukasz.m.luki2@gmail.com>
Diffstat (limited to 'libavformat/ftp.c')
-rw-r--r--libavformat/ftp.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/libavformat/ftp.c b/libavformat/ftp.c
index dae8aa086d..60011650b5 100644
--- a/libavformat/ftp.c
+++ b/libavformat/ftp.c
@@ -227,6 +227,48 @@ static int ftp_auth(FTPContext *s)
return 0;
}
+static int ftp_passive_mode_epsv(FTPContext *s)
+{
+ char *res = NULL, *start = NULL, *end = NULL;
+ int i;
+ static const char d = '|';
+ static const char *command = "EPSV\r\n";
+ static const int epsv_codes[] = {229, 500, 501, 0}; /* 500, 501 are incorrect codes */
+
+ if (ftp_send_command(s, command, epsv_codes, &res) != 229 || !res)
+ goto fail;
+
+ for (i = 0; res[i]; ++i) {
+ if (res[i] == '(') {
+ start = res + i + 1;
+ } else if (res[i] == ')') {
+ end = res + i;
+ break;
+ }
+ }
+ if (!start || !end)
+ goto fail;
+
+ *end = '\0';
+ if (strlen(start) < 5)
+ goto fail;
+ if (start[0] != d || start[1] != d || start[2] != d || end[-1] != d)
+ goto fail;
+ start += 3;
+ end[-1] = '\0';
+
+ s->server_data_port = atoi(start);
+ av_dlog(s, "Server data port: %d\n", s->server_data_port);
+
+ av_free(res);
+ return 0;
+
+ fail:
+ av_free(res);
+ s->server_data_port = -1;
+ return AVERROR(ENOSYS);
+}
+
static int ftp_passive_mode(FTPContext *s)
{
char *res = NULL, *start = NULL, *end = NULL;
@@ -270,8 +312,6 @@ static int ftp_passive_mode(FTPContext *s)
fail:
av_free(res);
s->server_data_port = -1;
- av_log(s, AV_LOG_ERROR, "Set passive mode failed\n"
- "Your FTP server may use IPv6 which is not supported yet.\n");
return AVERROR(EIO);
}
@@ -439,8 +479,11 @@ static int ftp_connect_data_connection(URLContext *h)
if (!s->conn_data) {
/* Enter passive mode */
- if ((err = ftp_passive_mode(s)) < 0)
- return err;
+ if (ftp_passive_mode_epsv(s) < 0) {
+ /* Use PASV as fallback */
+ if ((err = ftp_passive_mode(s)) < 0)
+ return err;
+ }
/* Open data connection */
ff_url_join(buf, sizeof(buf), "tcp", NULL, s->hostname, s->server_data_port, NULL);
if (s->rw_timeout != -1) {