diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-07-18 01:40:37 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-07-18 01:40:49 +0200 |
commit | 1816f5509e4f0fd55d32b5dbf70c3be21c1b1515 (patch) | |
tree | 75ed13ca697c0a7ac8031726d1138d50c77c9e58 /libavformat | |
parent | 37ded53037196144eb712daa5decaca7f92ae3c6 (diff) | |
parent | 816c579cf3cbd079c1b14aaa063b61eed4c555ad (diff) | |
download | ffmpeg-1816f5509e4f0fd55d32b5dbf70c3be21c1b1515.tar.gz |
Merge https://github.com/lukaszmluki/ffmpeg
* https://github.com/lukaszmluki/ffmpeg:
ftp: warning about pure-ftp server used as and output
ftp: comments
ftp: remove unused headers
ftp: fix interrupt callback misuse
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/ftp.c | 132 |
1 files changed, 45 insertions, 87 deletions
diff --git a/libavformat/ftp.c b/libavformat/ftp.c index a256a25335..1a4708109b 100644 --- a/libavformat/ftp.c +++ b/libavformat/ftp.c @@ -18,15 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <stdlib.h> #include "libavutil/avstring.h" -#include "libavutil/time.h" #include "avformat.h" #include "internal.h" -#include "network.h" -#include "os_support.h" #include "url.h" #include "libavutil/opt.h" +#include "libavutil/bprint.h" #define CONTROL_BUFFER_SIZE 1024 #define CREDENTIALS_BUFFER_SIZE 128 @@ -42,8 +39,6 @@ typedef enum { typedef struct { const AVClass *class; URLContext *conn_control; /**< Control connection */ - int conn_control_block_flag; /**< Controls block/unblock mode of data connection */ - AVIOInterruptCB conn_control_interrupt_cb; /**< Controls block/unblock mode of data connection */ URLContext *conn_data; /**< Data connection, NULL when not connected */ uint8_t control_buffer[CONTROL_BUFFER_SIZE]; /**< Control connection buffer */ uint8_t *control_buf_ptr, *control_buf_end; @@ -77,18 +72,10 @@ static const AVClass ftp_context_class = { .version = LIBAVUTIL_VERSION_INT, }; -static int ftp_conn_control_block_control(void *data) -{ - FTPContext *s = data; - return s->conn_control_block_flag; -} - static int ftp_getc(FTPContext *s) { int len; if (s->control_buf_ptr >= s->control_buf_end) { - if (s->conn_control_block_flag) - return AVERROR_EXIT; len = ffurl_read(s->conn_control, s->control_buffer, CONTROL_BUFFER_SIZE); if (len < 0) { return len; @@ -106,12 +93,10 @@ static int ftp_get_line(FTPContext *s, char *line, int line_size) { int ch; char *q = line; - int ori_block_flag = s->conn_control_block_flag; for (;;) { ch = ftp_getc(s); if (ch < 0) { - s->conn_control_block_flag = ori_block_flag; return ch; } if (ch == '\n') { @@ -119,86 +104,61 @@ static int ftp_get_line(FTPContext *s, char *line, int line_size) if (q > line && q[-1] == '\r') q--; *q = '\0'; - - s->conn_control_block_flag = ori_block_flag; return 0; } else { - s->conn_control_block_flag = 0; /* line need to be finished */ if ((q - line) < line_size - 1) *q++ = ch; } } } -static int ftp_flush_control_input(FTPContext *s) -{ - char buf[CONTROL_BUFFER_SIZE]; - int err, ori_block_flag = s->conn_control_block_flag; - - s->conn_control_block_flag = 1; - do { - err = ftp_get_line(s, buf, sizeof(buf)); - } while (!err); - - s->conn_control_block_flag = ori_block_flag; - - if (err < 0 && err != AVERROR_EXIT) - return err; - - return 0; -} - /* * This routine returns ftp server response code. - * Server may send more than one response for a certain command, following priorities are used: - * - When pref_codes are set then pref_code is return if occurred. (expected result) - * - 0 is returned when no pref_codes or not occurred + * Server may send more than one response for a certain command. + * First expected code is returned. */ static int ftp_status(FTPContext *s, char **line, const int response_codes[]) { - int err, i, result = 0, pref_code_found = 0, wait_count = 100; + int err, i, dash = 0, result = 0, code_found = 0; char buf[CONTROL_BUFFER_SIZE]; + AVBPrint line_buffer; - /* Set blocking mode */ - s->conn_control_block_flag = 0; - for (;;) { + if (line) + av_bprint_init(&line_buffer, 0, AV_BPRINT_SIZE_AUTOMATIC); + + while (!code_found || dash) { if ((err = ftp_get_line(s, buf, sizeof(buf))) < 0) { - if (err == AVERROR_EXIT) { - if (!pref_code_found && wait_count--) { - av_usleep(10000); - continue; - } - } - return result; + av_bprint_finalize(&line_buffer, NULL); + return err; } av_log(s, AV_LOG_DEBUG, "%s\n", buf); - if (!pref_code_found) { - if (strlen(buf) < 3) - continue; - - err = 0; - for (i = 0; i < 3; ++i) { - if (buf[i] < '0' || buf[i] > '9') - continue; - err *= 10; - err += buf[i] - '0'; - } + if (strlen(buf) < 4) + continue; - for (i = 0; response_codes[i]; ++i) { - if (err == response_codes[i]) { - /* first code received. Now get all lines in non blocking mode */ - s->conn_control_block_flag = 1; - pref_code_found = 1; - result = err; - if (line) - *line = av_strdup(buf); - break; - } + err = 0; + for (i = 0; i < 3; ++i) { + if (buf[i] < '0' || buf[i] > '9') + continue; + err *= 10; + err += buf[i] - '0'; + } + dash = !!(buf[3] == '-'); + + for (i = 0; response_codes[i]; ++i) { + if (err == response_codes[i]) { + if (line) + av_bprintf(&line_buffer, "%s", buf); + code_found = 1; + result = err; + break; } } } + + if (line) + av_bprint_finalize(&line_buffer, line); return result; } @@ -207,12 +167,6 @@ static int ftp_send_command(FTPContext *s, const char *command, { int err; - /* Flush control connection input to get rid of non relevant responses if any */ - if ((err = ftp_flush_control_input(s)) < 0) - return err; - - /* send command in blocking mode */ - s->conn_control_block_flag = 0; if ((err = ffurl_write(s->conn_control, command, strlen(command))) < 0) return err; if (!err) @@ -428,14 +382,12 @@ static int ftp_restart(FTPContext *s, int64_t pos) static int ftp_connect_control_connection(URLContext *h) { - char buf[CONTROL_BUFFER_SIZE], opts_format[20]; + char buf[CONTROL_BUFFER_SIZE], opts_format[20], *response = NULL; int err; AVDictionary *opts = NULL; FTPContext *s = h->priv_data; const int connect_codes[] = {220, 0}; - s->conn_control_block_flag = 0; - if (!s->conn_control) { ff_url_join(buf, sizeof(buf), "tcp", NULL, s->hostname, s->server_control_port, NULL); @@ -444,19 +396,24 @@ static int ftp_connect_control_connection(URLContext *h) av_dict_set(&opts, "timeout", opts_format, 0); } /* if option is not given, don't pass it and let tcp use its own default */ err = ffurl_open(&s->conn_control, buf, AVIO_FLAG_READ_WRITE, - &s->conn_control_interrupt_cb, &opts); + &h->interrupt_callback, &opts); av_dict_free(&opts); if (err < 0) { av_log(h, AV_LOG_ERROR, "Cannot open control connection\n"); return err; } - /* consume all messages from server */ - if (ftp_status(s, NULL, connect_codes) != 220) { + /* check if server is ready */ + if (ftp_status(s, ((h->flags & AVIO_FLAG_WRITE) ? &response : NULL), connect_codes) != 220) { av_log(h, AV_LOG_ERROR, "FTP server not ready for new users\n"); return AVERROR(EACCES); } + if ((h->flags & AVIO_FLAG_WRITE) && av_stristr(response, "pure-ftpd")) { + av_log(h, AV_LOG_WARNING, "Pure-FTPd server is used as an output protocol. It is known issue this implementation may produce incorrect content and it cannot be fixed at this moment."); + } + av_free(response); + if ((err = ftp_auth(s)) < 0) { av_log(h, AV_LOG_ERROR, "FTP authentication failed\n"); return err; @@ -489,7 +446,7 @@ static int ftp_connect_data_connection(URLContext *h) snprintf(opts_format, sizeof(opts_format), "%d", s->rw_timeout); av_dict_set(&opts, "timeout", opts_format, 0); } /* if option is not given, don't pass it and let tcp use its own default */ - err = ffurl_open(&s->conn_data, buf, AVIO_FLAG_READ_WRITE, + err = ffurl_open(&s->conn_data, buf, h->flags, &h->interrupt_callback, &opts); av_dict_free(&opts); if (err < 0) @@ -553,8 +510,6 @@ static int ftp_open(URLContext *h, const char *url, int flags) s->state = DISCONNECTED; s->filesize = -1; s->position = 0; - s->conn_control_interrupt_cb.opaque = s; - s->conn_control_interrupt_cb.callback = ftp_conn_control_block_control; av_url_split(proto, sizeof(proto), s->credencials, sizeof(s->credencials), @@ -620,6 +575,7 @@ static int64_t ftp_seek(URLContext *h, int64_t pos, int whence) if (h->is_streamed) return AVERROR(EIO); + /* XXX: Simulate behaviour of lseek in file protocol, which could be treated as a reference */ new_pos = FFMAX(0, new_pos); fake_pos = s->filesize != -1 ? FFMIN(new_pos, s->filesize) : new_pos; @@ -639,6 +595,7 @@ static int ftp_read(URLContext *h, unsigned char *buf, int size) av_dlog(h, "ftp protocol read %d bytes\n", size); retry: if (s->state == DISCONNECTED) { + /* optimization */ if (s->position >= s->filesize) return 0; if ((err = ftp_connect_data_connection(h)) < 0) @@ -656,6 +613,7 @@ static int ftp_read(URLContext *h, unsigned char *buf, int size) s->position += read; if (s->position >= s->filesize) { /* server will terminate, but keep current position to avoid madness */ + /* save position to restart from it */ int64_t pos = s->position; if (ftp_abort(h) < 0) { s->position = pos; |