[PATCH] ftp port from g1 to g2 :)

Fabian Franz <[email protected]>
Newsgroups gmane.comp.video.mplayer.g2.devel
Message-ID <[email protected]>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

hi,

attached is the port from ftplib in g1 to g2 ...

what still strange is that g2 needs much more time, before it displays the 
video/audio, but then it works perfect (at least for me ;)).

Perhaps some cache-problem ?

cu

Fabian
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.0 (GNU/Linux)

iD8DBQE/O/veI0lSH7CXz7MRAoBBAJ9KHgJcqoJ95woJh6KJY082SaJp1wCfcDII
CpagrGESpA24EuN1VG4I0yQ=
=yh9q
-----END PGP SIGNATURE-----

_______________________________________________
MPlayer-G2-dev mailing list
[email protected]
http://mplayerhq.hu/mailman/listinfo/mplayer-g2-dev
g2-ftp-support-port.diff (text/x-diff, 13.2 KB)
diff -Nur g2.old/stream/Makefile g2/stream/Makefile
--- g2.old/stream/Makefile	2003-07-10 19:06:02.000000000 +0200
+++ g2/stream/Makefile	2003-08-14 22:17:53.000000000 +0200
@@ -6,7 +6,7 @@
 SRCS = stream.c cache2.c url.c stream_dvd.c stream_vcd.c stream_cdda.c stream_smb.c stream_cue.c
 
 ifeq ($(MPLAYER_NETWORK),yes)
-SRCS += http.c network.c stream_http.c stream_pnm.c pnm.c stream_mmst.c rtp.c stream_rtp.c stream_mms.c
+SRCS += http.c network.c stream_http.c stream_pnm.c pnm.c stream_mmst.c rtp.c stream_rtp.c stream_mms.c stream_ftp.c
 endif
 
 OBJS	= $(SRCS:.c=.o)
diff -Nur g2.old/stream/network.c g2/stream/network.c
--- g2.old/stream/network.c	2003-03-30 23:13:50.000000000 +0200
+++ g2/stream/network.c	2003-08-14 23:00:18.000000000 +0200
@@ -40,7 +40,7 @@
 // return -2 for fatal error, like unable to resolve name, connection timeout...
 // return -1 is unable to connect to a particular port
 int
-connect2Server(char *host, int port) {
+connect2Server(char *host, int port, int verb) {
 	int socket_server_fd;
 	int err, err_len;
 	int ret,count = 0;
@@ -71,9 +71,9 @@
 	
 	// Turn the socket as non blocking so we can timeout on the connection
 	if( isalpha(host[0]) && hp!=NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_STATUS,"Connecting to server %s[%d.%d.%d.%d]:%d ...\n", host, (hp->h_addr_list[0][0])&0xff, (hp->h_addr_list[0][1])&0xff, (hp->h_addr_list[0][2])&0xff, (hp->h_addr_list[0][3])&0xff, port );
+		if (verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,"Connecting to server %s[%d.%d.%d.%d]:%d ...\n", host, (hp->h_addr_list[0][0])&0xff, (hp->h_addr_list[0][1])&0xff, (hp->h_addr_list[0][2])&0xff, (hp->h_addr_list[0][3])&0xff, port );
 	} else {
-		mp_msg(MSGT_NETWORK,MSGL_STATUS,"Connecting to server %s:%d ...\n", host, port );
+		if (verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,"Connecting to server %s:%d ...\n", host, port );
 	}
 	fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK );
 	if( connect( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) {
@@ -197,11 +197,11 @@
 
 	if( proxy ) {
 		if( url->port==0 ) url->port = 8080;			// Default port for the proxy server
-		fd = connect2Server( url->hostname, url->port );
+		fd = connect2Server( url->hostname, url->port, 1);
 		url_free( server_url );
 	} else {
 		if( server_url->port==0 ) server_url->port = 80;	// Default port for the web server
-		fd = connect2Server( server_url->hostname, server_url->port );
+		fd = connect2Server( server_url->hostname, server_url->port, 1 );
 	}
 	if( fd<0 ) {
 		return -1; 
diff -Nur g2.old/stream/network.h g2/stream/network.h
--- g2.old/stream/network.h	2003-03-30 23:13:42.000000000 +0200
+++ g2/stream/network.h	2003-08-14 22:58:15.000000000 +0200
@@ -24,7 +24,7 @@
 	streaming_playing_e
 } streaming_status;
 
-int connect2Server(char *host, int port);
+int connect2Server(char *host, int port, int verb);
 
 int http_send_request(URL_t *url);
 HTTP_header_t *http_read_response(int fd);
diff -Nur g2.old/stream/stream.c g2/stream/stream.c
--- g2.old/stream/stream.c	2003-08-04 23:38:14.000000000 +0200
+++ g2/stream/stream.c	2003-08-14 22:19:05.000000000 +0200
@@ -39,6 +39,7 @@
 extern stream_driver_t stream_driver_rtp;
 extern stream_driver_t stream_driver_smb;
 extern stream_driver_t stream_driver_cue;
+extern stream_driver_t stream_driver_ftp;
 
 stream_driver_t* stream_driver_list[]= {
     &stream_driver_cue,
@@ -60,6 +61,7 @@
     &stream_driver_mmst,
     &stream_driver_mms,
     &stream_driver_rtp,
+    &stream_driver_ftp,
 #endif
     NULL
 };
diff -Nur g2.old/stream/stream_ftp.c g2/stream/stream_ftp.c
--- g2.old/stream/stream_ftp.c	1970-01-01 01:00:00.000000000 +0100
+++ g2/stream/stream_ftp.c	2003-08-14 23:11:48.000000000 +0200
@@ -0,0 +1,422 @@
+
+#include "../config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "../mp_msg.h"
+#include "stream.h"
+#include "network.h"
+#include "../help_mp.h"
+
+static struct stream_priv_s {
+  char *cput,*cget;
+  int handle;
+  int cavail,cleft;
+  char *buf;
+} ftp_priv_t;
+
+#define BUFSIZE 2048
+
+#define TELNET_IAC      255             /* interpret as command: */
+#define TELNET_IP       244             /* interrupt process--permanently */
+#define TELNET_SYNCH    242             /* for telfunc calls */
+
+/*
+ * read a line of text
+ *
+ * return -1 on error or bytecount
+ */
+static int readline(char *buf,int max,struct stream_priv_s *ctl)
+{
+    int x,retval = 0;
+    char *end,*bp=buf;
+    int eof = 0;
+ 
+    do {
+      if (ctl->cavail > 0) {
+	x = (max >= ctl->cavail) ? ctl->cavail : max-1;
+	end = memccpy(bp,ctl->cget,'\n',x);
+	if (end != NULL)
+	  x = end - bp;
+	retval += x;
+	bp += x;
+	*bp = '\0';
+	max -= x;
+	ctl->cget += x;
+	ctl->cavail -= x;
+	if (end != NULL) {
+	  bp -= 2;
+	  if (strcmp(bp,"\r\n") == 0) {
+	    *bp++ = '\n';
+	    *bp++ = '\0';
+	    --retval;
+	  }
+	  break;
+	}
+      }
+      if (max == 1) {
+	*buf = '\0';
+	break;
+      }
+      if (ctl->cput == ctl->cget) {
+	ctl->cput = ctl->cget = ctl->buf;
+	ctl->cavail = 0;
+	ctl->cleft = BUFSIZE;
+      }
+      if(eof) {
+	if (retval == 0)
+	  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;
+	break;
+      }
+      if (x == 0)
+	eof = 1;
+      ctl->cleft -= x;
+      ctl->cavail += x;
+      ctl->cput += x;
+    } while (1);
+    
+    return retval;
+}
+
+/*
+ * read a response from the server
+ *
+ * return 0 if first char doesn't match
+ * return 1 if first char matches
+ */
+static int readresp(struct stream_priv_s* ctl,char* rsp)
+{
+    static char response[256];
+    char match[5];
+    int r;
+
+    if (readline(response,256,ctl) == -1)
+      return 0;
+ 
+    r = atoi(response)/100;
+    if(rsp) strcpy(rsp,response);
+
+    mp_msg(MSGT_STREAM,MSGL_V, "[ftp] < %s",response);
+
+    if (response[3] == '-') {
+      strncpy(match,response,3);
+      match[3] = ' ';
+      match[4] = '\0';
+      do {
+	if (readline(response,256,ctl) == -1) {
+	  mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Control socket read failed\n");
+	  return 0;
+	}
+	mp_msg(MSGT_OPEN,MSGL_V, "[ftp] < %s",response);
+      }	while (strncmp(response,match,4));
+    }
+    return r;
+}
+
+
+static int FtpSendCmd(const char *cmd, struct stream_priv_s *nControl,char* rsp)
+{
+  int l = strlen(cmd);
+
+  mp_msg(MSGT_STREAM,MSGL_V, "[ftp] > %s",cmd);
+  while(l > 0) {
+    int s = send(nControl->handle,cmd,l,0);
+
+    if(s <= 0) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] write error: %s\n",strerror(errno));
+      return 0;
+    }
+    
+    cmd += s;
+    l -= s;
+  }
+    
+  return readresp(nControl,rsp);
+}
+
+static int FtpOpenPort(struct stream_priv_s* p) {
+  int resp,fd;
+  char rsp_txt[256];
+  char* par,str[128];
+  int num[6];
+
+  resp = FtpSendCmd("PASV\r\n",p,rsp_txt);
+  if(resp != 2) {
+    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command 'PASV' failed: %s\n",rsp_txt);
+    return 0;
+  }
+  
+  par = strchr(rsp_txt,'(');
+  
+  if(!par || !par[0] || !par[1]) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] invalid server response: %s ??\n",rsp_txt);
+    return 0;
+  }
+
+  sscanf(par+1,"%u,%u,%u,%u,%u,%u",&num[0],&num[1],&num[2],
+	 &num[3],&num[4],&num[5]);
+  sprintf(str,"%d.%d.%d.%d",num[0],num[1],num[2],num[3]);
+  fd = connect2Server(str,(num[4]<<8)+num[5],0);
+
+  if(fd <= 0) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] failed to create data connection\n");
+    return 0;
+  }
+
+  return fd;
+}
+
+static int fd_has_data(int fd) {
+  fd_set fds;
+  struct timeval tv;
+
+  FD_ZERO(&fds);
+  
+  
+  FD_SET(fd,&fds);
+  tv.tv_sec = tv.tv_usec = 0;
+  return select(fd+1, &fds, NULL, NULL, &tv);
+}
+
+// Begin of g2-specific part
+
+static int driver_free(stream_t *s);
+ 
+static int driver_open(stream_t *stream) {
+  int len = 0,resp;
+  struct stream_priv_s* p = (struct stream_priv_s*)malloc(sizeof(struct stream_priv_s));
+  URL_t* url = stream->url;
+  char str[256],rsp_txt[256];
+
+  // Sanity check for needed fields
+  if(!url || !url->file || !url->hostname) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Bad url\n");
+    free(p);
+    return 0;
+  }
+
+  // Set defaults
+  if (url->port == 0)
+      url->port=21;
+  if (url->username == NULL)
+      url->username="anonymous";
+  if (url->password == NULL)
+      url->password="no@spam";
+  
+  // Open the control connection
+  p->handle = connect2Server(url->hostname,url->port,1);
+  
+  if(p->handle <= 0) {
+    free(p);
+    return 0;
+  }
+
+  // We got a connection, let's start serious things
+  stream->fd = 0;
+  stream->priv = p;
+  p->buf = malloc(BUFSIZE);
+
+  if (readresp(p, NULL) == 0) {
+    driver_free(stream);
+    return 0;
+  }
+
+  // Login
+  
+  sprintf(str,"USER %s\r\n",url->username);
+  resp = FtpSendCmd(str,p,rsp_txt);
+
+  // password needed
+  if(resp == 3) {
+    sprintf(str,"PASS %s\r\n",url->password);
+    resp = FtpSendCmd(str,p,rsp_txt);
+    if(resp != 2) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+      driver_free(stream);
+      return 0;
+    }
+  } else if(resp != 2) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+    driver_free(stream);
+    return 0;
+  }
+    
+  // Set the transfer type
+  resp = FtpSendCmd("TYPE I\r\n",p,rsp_txt);
+  if(resp != 2) {
+    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command 'TYPE I' failed: %s\n",rsp_txt);
+    driver_free(stream);
+    return 0;
+  }
+
+  // Get the filesize
+  sprintf(str,"SIZE %s\r\n",url->file);
+  resp = FtpSendCmd(str,p,rsp_txt);
+  if(resp != 2) {
+    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+  } else {
+    int dummy;
+    sscanf(rsp_txt,"%d %d",&dummy,&len);
+  }
+
+  // Start the data connection
+  stream->fd = FtpOpenPort(p);
+  if(stream->fd <= 0) {
+    driver_free(stream);
+    return 0;
+  }
+
+  // Get the file
+  sprintf(str,"RETR %s\r\n",url->file);
+  resp = FtpSendCmd(str,p,rsp_txt);
+
+  if(resp != 1) {
+    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+    driver_free(stream);
+    return 0;
+  }
+  
+
+  if(len > 0) {
+    //stream->seek = seek;
+    stream->end_pos = len;
+  }
+
+  stream->priv = p;
+  stream->buf_size=BUFSIZE;
+  //stream->fill_buffer = fill_buffer;
+  //stream->close = close_f;
+
+  return 1;
+}
+
+static int driver_fill(stream_t *s){
+  int r = recv(s->fd,s->buffer,s->buf_size,0);
+  return (r <= 0) ? -1 : r;
+}
+
+static int driver_seek(stream_t *s,off_t newpos) {
+ struct stream_priv_s* p = s->priv;
+ int resp;
+ char str[256],rsp_txt[256];
+
+  if(s->fd <= 0 || s->pos > s->end_pos) {
+    s->eof=1;
+    return 0;
+  }
+
+  // Check to see if the server doesn't alredy terminated the transfert
+  if(fd_has_data(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);
+    close(s->fd);
+    s->fd = 0;
+  }
+
+  // Close current download
+  if(s->fd > 0) {
+    static const char pre_cmd[]={TELNET_IAC,TELNET_IP,TELNET_IAC,TELNET_SYNCH};
+    //int fl;
+    
+    // First close the fd
+    close(s->fd);
+    s->fd = 0;
+
+    // Send send the telnet sequence needed to make the server react
+
+    // Dunno if this is really needed, lftp have it. I let
+    // it here in case it turn out to be needed on some other OS
+    //fl=fcntl(p->handle,F_GETFL);
+    //fcntl(p->handle,F_SETFL,fl&~O_NONBLOCK);
+
+    // send only first byte as OOB due to OOB braindamage in many unices
+    send(p->handle,pre_cmd,1,MSG_OOB);
+    send(p->handle,pre_cmd+1,sizeof(pre_cmd)-1,0);
+    
+    //fcntl(p->handle,F_SETFL,fl);
+
+    // Get the 426 Transfer aborted
+    // Or the 226 Transfer complete
+    resp = readresp(p,rsp_txt);
+    if(resp != 4 && resp != 2) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Server didn't abort correctly: %s\n",rsp_txt);
+      s->eof = 1;
+      return 0;
+    }
+    // Send the ABOR command
+    // Ignore the return code as sometimes it fail with "nothing to abort"
+    FtpSendCmd("ABOR\n\r",p,rsp_txt);
+  }
+
+  // Open a new connection
+  s->fd = FtpOpenPort(p);
+
+  if(!s->fd) return 0;
+
+  if(newpos > 0) {
+#ifdef _LARGEFILE_SOURCE
+    sprintf(str,"REST %lld\r\n",(unsigned int)newpos);
+#else
+    sprintf(str,"REST %u\r\n",(unsigned int)newpos);
+#endif 
+
+    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
+  sprintf(str,"RETR %s\r\n",s->url->file);
+  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;
+}
+
+static int driver_free(stream_t *s) {
+  struct stream_priv_s* p = s->priv;
+
+  if(!p) return 0;
+
+  if(s->fd > 0) {
+    close(s->fd);
+    s->fd = 0;
+  }
+
+  FtpSendCmd("QUIT\r\n",p,NULL);
+
+  if(p->handle) close(p->handle);
+  if(p->buf) free(p->buf);
+  if (p) free(p);
+  return 1;
+}
+
+stream_driver_t stream_driver_ftp = {
+    "ftp",
+    "File Transfer Protokoll",
+    "by Albeu with help of ftplib, ported from g1 by Fabian Franz",
+    driver_open,
+    NULL, //reset,
+    driver_fill,
+    driver_seek, 
+    driver_free 
+};
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.