[MPlayer-cvslog] CVS: main/libmpdemux stream_ftp.c,1.8,1.9

Alban Bedel CVS syncmail at mplayerhq.hu
Mon Mar 13 17:56:15 CET 2006


CVS change done by Alban Bedel CVS

Update of /cvsroot/mplayer/main/libmpdemux
In directory mail:/var2/tmp/cvs-serv3699/libmpdemux

Modified Files:
	stream_ftp.c 
Log Message:
Fix seeking with cache enabled on systems using fork().
The first data connection was opened at open time which
happend in the main process. This prevented properly closing
the connection on later seeks as they happend in the child
process and the fd was still open in the parent process.
The fix delay opening the data connection upon the first
fill_buffer/seek.
Also remove some code duplication, add a timeout on read
from the control connection and a few other small fixes.


Index: stream_ftp.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/stream_ftp.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- stream_ftp.c	18 Nov 2005 14:39:20 -0000	1.8
+++ stream_ftp.c	13 Mar 2006 16:56:10 -0000	1.9
@@ -71,6 +71,20 @@
 #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 @@
 	  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 @@
   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 @@
   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 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 @@
     // 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 @@
     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;




More information about the MPlayer-cvslog mailing list