[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
+};