summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmpdemux/stream_ftp.c134
1 files changed, 68 insertions, 66 deletions
diff --git a/libmpdemux/stream_ftp.c b/libmpdemux/stream_ftp.c
index 7cc01004b6..2a23fd2d3d 100644
--- a/libmpdemux/stream_ftp.c
+++ b/libmpdemux/stream_ftp.c
@@ -71,6 +71,20 @@ static struct m_struct_st stream_opts = {
#define TELNET_IP 244 /* interrupt process--permanently */
#define TELNET_SYNCH 242 /* for telfunc calls */
+// Check if there is something to read on a fd. This avoid hanging
+// forever if the network stop responding.
+static int fd_can_read(int fd,int timeout) {
+ fd_set fds;
+ struct timeval tv;
+
+ FD_ZERO(&fds);
+ FD_SET(fd,&fds);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ return (select(fd+1, &fds, NULL, NULL, &tv) > 0);
+}
+
/*
* read a line of text
*
@@ -118,6 +132,13 @@ static int readline(char *buf,int max,struct stream_priv_s *ctl)
retval = -1;
break;
}
+
+ if(!fd_can_read(ctl->handle, 15)) {
+ mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] read timed out\n");
+ retval = -1;
+ break;
+ }
+
if ((x = recv(ctl->handle,ctl->cput,ctl->cleft,0)) == -1) {
mp_msg(MSGT_STREAM,MSGL_ERR, "[ftp] read error: %s\n",strerror(errno));
retval = -1;
@@ -174,7 +195,8 @@ static int FtpSendCmd(const char *cmd, struct stream_priv_s *nControl,char* rsp)
int l = strlen(cmd);
int hascrlf = cmd[l - 2] == '\r' && cmd[l - 1] == '\n';
- mp_msg(MSGT_STREAM,MSGL_V, "[ftp] > %s",cmd);
+ if(hascrlf && l == 2) mp_msg(MSGT_STREAM,MSGL_V, "\n");
+ else mp_msg(MSGT_STREAM,MSGL_V, "[ftp] > %s",cmd);
while(l > 0) {
int s = send(nControl->handle,cmd,l,0);
@@ -217,27 +239,52 @@ static int FtpOpenPort(struct stream_priv_s* p) {
snprintf(str,127,"%d.%d.%d.%d",num[0],num[1],num[2],num[3]);
fd = connect2Server(str,(num[4]<<8)+num[5],0);
- if(fd <= 0) {
+ if(fd < 0)
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] failed to create data connection\n");
+
+ return fd;
+}
+
+static int FtpOpenData(stream_t* s,size_t newpos) {
+ struct stream_priv_s* p = s->priv;
+ int resp;
+ char str[256],rsp_txt[256];
+
+ // Open a new connection
+ s->fd = FtpOpenPort(p);
+
+ if(s->fd < 0) return 0;
+
+ if(newpos > 0) {
+ snprintf(str,255,"REST %"PRId64, (int64_t)newpos);
+
+ resp = FtpSendCmd(str,p,rsp_txt);
+ if(resp != 3) {
+ mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+ newpos = 0;
+ }
+ }
+
+ // Get the file
+ snprintf(str,255,"RETR %s",p->filename);
+ resp = FtpSendCmd(str,p,rsp_txt);
+
+ if(resp != 1) {
+ mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
return 0;
}
- return fd;
+ s->pos = newpos;
+ return 1;
}
static int fill_buffer(stream_t *s, char* buffer, int max_len){
- fd_set fds;
- struct timeval tv;
int r;
- // Check if there is something to read. This avoid hang
- // forever if the network stop responding.
- FD_ZERO(&fds);
- FD_SET(s->fd,&fds);
- tv.tv_sec = 15;
- tv.tv_usec = 0;
-
- if(select(s->fd+1, &fds, NULL, NULL, &tv) < 1) {
+ if(s->fd < 0 && !FtpOpenData(s,s->pos))
+ return -1;
+
+ if(!fd_can_read(s->fd, 15)) {
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] read timed out\n");
return -1;
}
@@ -249,21 +296,15 @@ static int fill_buffer(stream_t *s, char* buffer, int max_len){
static int seek(stream_t *s,off_t newpos) {
struct stream_priv_s* p = s->priv;
int resp;
- char str[256],rsp_txt[256];
- fd_set fds;
- struct timeval tv;
+ char rsp_txt[256];
if(s->pos > s->end_pos) {
s->eof=1;
return 0;
}
- FD_ZERO(&fds);
- FD_SET(p->handle,&fds);
- tv.tv_sec = tv.tv_usec = 0;
-
// Check to see if the server doesn't alredy terminated the transfert
- if(select(p->handle+1, &fds, NULL, NULL, &tv) > 0) {
+ if(fd_can_read(p->handle, 0)) {
if(readresp(p,rsp_txt) != 2)
mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] Warning the server didn't finished the transfert correctly: %s\n",rsp_txt);
closesocket(s->fd);
@@ -304,33 +345,7 @@ static int seek(stream_t *s,off_t newpos) {
// Ignore the return code as sometimes it fail with "nothing to abort"
FtpSendCmd("ABOR",p,rsp_txt);
}
-
- // Open a new connection
- s->fd = FtpOpenPort(p);
-
- if(!s->fd) return 0;
-
- if(newpos > 0) {
- snprintf(str,255,"REST %"PRId64, (int64_t)newpos);
-
- resp = FtpSendCmd(str,p,rsp_txt);
- if(resp != 3) {
- mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
- newpos = 0;
- }
- }
-
- // Get the file
- snprintf(str,255,"RETR %s",p->filename);
- resp = FtpSendCmd(str,p,rsp_txt);
-
- if(resp != 1) {
- mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
- return 0;
- }
-
- s->pos = newpos;
- return 1;
+ return FtpOpenData(s,newpos);
}
@@ -427,29 +442,16 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
sscanf(rsp_txt,"%d %d",&dummy,&len);
}
- // Start the data connection
- stream->fd = FtpOpenPort(p);
- if(stream->fd <= 0) {
- close_f(stream);
- return STREAM_ERROR;
- }
-
- // Get the file
- snprintf(str,255,"RETR %s",p->filename);
- resp = FtpSendCmd(str,p,rsp_txt);
-
- if(resp != 1) {
- mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
- close_f(stream);
- return STREAM_ERROR;
- }
-
-
if(len > 0) {
stream->seek = seek;
stream->end_pos = len;
}
+ // The data connection is really opened only at the first
+ // read/seek. This must be done when the cache is used
+ // because the connection would stay open in the main process,
+ // preventing correct abort with many servers.
+ stream->fd = -1;
stream->priv = p;
stream->fill_buffer = fill_buffer;
stream->close = close_f;