aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/ftp.c
diff options
context:
space:
mode:
authorLukasz Marek <lukasz.m.luki@gmail.com>2013-05-27 20:53:27 +0200
committerLukasz Marek <lukasz.m.luki@gmail.com>2013-05-31 16:40:03 +0200
commit1931c2d2654fc6244232d4828ebfafeb414dbb26 (patch)
treea9b88a089cda524b5b7068b2f36b854c74c92b46 /libavformat/ftp.c
parentc84d6aa2f63f014a1c08f4adf67c462b98f68028 (diff)
downloadandroid_external_ffmpeg-1931c2d2654fc6244232d4828ebfafeb414dbb26.tar.gz
android_external_ffmpeg-1931c2d2654fc6244232d4828ebfafeb414dbb26.tar.bz2
android_external_ffmpeg-1931c2d2654fc6244232d4828ebfafeb414dbb26.zip
ftp: reconnect on read
FTP server may disconnect after some period of time when no transfer is done. FTP protocol should reconnect and seek to last position.
Diffstat (limited to 'libavformat/ftp.c')
-rw-r--r--libavformat/ftp.c125
1 files changed, 73 insertions, 52 deletions
diff --git a/libavformat/ftp.c b/libavformat/ftp.c
index da9408a2c3..e497c1a9de 100644
--- a/libavformat/ftp.c
+++ b/libavformat/ftp.c
@@ -38,7 +38,6 @@ typedef enum {
DISCONNECTED
} FTPState;
-
typedef struct {
const AVClass *class;
URLContext *conn_control; /**< Control connection */
@@ -499,57 +498,6 @@ static int ftp_open(URLContext *h, const char *url, int flags)
return err;
}
-static int ftp_read(URLContext *h, unsigned char *buf, int size)
-{
- FTPContext *s = h->priv_data;
- int read;
-
- av_dlog(h, "ftp protocol read %d bytes\n", size);
-
- if (s->state == READY) {
- ftp_retrieve(s);
- }
- if (s->conn_data && s->state == DOWNLOADING) {
- read = ffurl_read(s->conn_data, buf, size);
- if (read >= 0) {
- s->position += read;
- if (s->position >= s->filesize) {
- ffurl_closep(&s->conn_data);
- s->state = DISCONNECTED;
- if (ftp_status(s, NULL, NULL, NULL,NULL, 226) != 226)
- return AVERROR(EIO);
- }
- }
- return read;
- }
-
- av_log(h, AV_LOG_DEBUG, "FTP read failed\n");
- return AVERROR(EIO);
-}
-
-static int ftp_write(URLContext *h, const unsigned char *buf, int size)
-{
- FTPContext *s = h->priv_data;
- int written;
-
- av_dlog(h, "ftp protocol write %d bytes\n", size);
-
- if (s->state == READY) {
- ftp_store(s);
- }
- if (s->conn_data && s->state == UPLOADING) {
- written = ffurl_write(s->conn_data, buf, size);
- if (written > 0) {
- s->position += written;
- s->filesize = FFMAX(s->filesize, s->position);
- }
- return written;
- }
-
- av_log(h, AV_LOG_ERROR, "FTP write failed\n");
- return AVERROR(EIO);
-}
-
static int64_t ftp_seek(URLContext *h, int64_t pos, int whence)
{
FTPContext *s = h->priv_data;
@@ -618,6 +566,79 @@ static int64_t ftp_seek(URLContext *h, int64_t pos, int whence)
return new_pos;
}
+static int ftp_read(URLContext *h, unsigned char *buf, int size)
+{
+ FTPContext *s = h->priv_data;
+ int read, err, retry_done = 0;
+
+ av_dlog(h, "ftp protocol read %d bytes\n", size);
+ retry:
+ if (s->state == READY) {
+ ftp_retrieve(s);
+ }
+ if (s->conn_data && s->state == DOWNLOADING) {
+ read = ffurl_read(s->conn_data, buf, size);
+ if (read >= 0) {
+ s->position += read;
+ if (s->position >= s->filesize) {
+ ffurl_closep(&s->conn_data);
+ s->state = DISCONNECTED;
+ if (ftp_status(s, NULL, NULL, NULL,NULL, 226) != 226)
+ return AVERROR(EIO);
+ }
+ }
+ if (!read && s->position < s->filesize && !h->is_streamed) {
+ /* Server closed connection. Probably due to inactivity */
+ /* TODO: Consider retry before reconnect */
+ int64_t pos = s->position;
+ av_log(h, AV_LOG_INFO, "Reconnect to FTP server.\n");
+ ffurl_closep(&s->conn_control);
+ ffurl_closep(&s->conn_data);
+ s->position = 0;
+ s->state = DISCONNECTED;
+ if ((err = ftp_connect_control_connection(h)) < 0) {
+ av_log(h, AV_LOG_ERROR, "Reconnect failed\n");
+ return err;
+ }
+ if ((err = ftp_seek(h, pos, SEEK_SET)) < 0) {
+ av_dlog(h, "Seek failed after reconnect\n");
+ return err;
+ }
+ if (!retry_done) {
+ retry_done = 1;
+ goto retry;
+ }
+ }
+ return read;
+ }
+
+ av_log(h, AV_LOG_DEBUG, "FTP read failed\n");
+ return AVERROR(EIO);
+}
+
+static int ftp_write(URLContext *h, const unsigned char *buf, int size)
+{
+ FTPContext *s = h->priv_data;
+ int written;
+
+ av_dlog(h, "ftp protocol write %d bytes\n", size);
+
+ if (s->state == READY) {
+ ftp_store(s);
+ }
+ if (s->conn_data && s->state == UPLOADING) {
+ written = ffurl_write(s->conn_data, buf, size);
+ if (written > 0) {
+ s->position += written;
+ s->filesize = FFMAX(s->filesize, s->position);
+ }
+ return written;
+ }
+
+ av_log(h, AV_LOG_ERROR, "FTP write failed\n");
+ return AVERROR(EIO);
+}
+
static int ftp_close(URLContext *h)
{
FTPContext *s = h->priv_data;