diff -Naur libdvdcss-1.2.9/src/Makefile.am libdvdcss-1.2.9-network/src/Makefile.am --- libdvdcss-1.2.9/src/Makefile.am 2005-07-11 05:32:01.000000000 -0700 +++ libdvdcss-1.2.9-network/src/Makefile.am 2008-01-18 03:25:47.000000000 -0800 @@ -4,6 +4,7 @@ libdvdcss_la_SOURCES = \ libdvdcss.c libdvdcss.h \ + network.c network.h \ device.c device.h \ css.c css.h csstables.h \ ioctl.c ioctl.h \ diff -Naur libdvdcss-1.2.9/src/libdvdcss.c libdvdcss-1.2.9-network/src/libdvdcss.c --- libdvdcss-1.2.9/src/libdvdcss.c 2004-08-13 06:40:18.000000000 -0700 +++ libdvdcss-1.2.9-network/src/libdvdcss.c 2008-01-18 03:40:37.000000000 -0800 @@ -131,6 +131,9 @@ #include "libdvdcss.h" #include "ioctl.h" #include "device.h" +#include "network.h" + +#define MAX_ERR_MSG 300 /** * \brief Symbol for version checks. @@ -206,6 +209,10 @@ if( i >= 1 ) dvdcss->b_errors = 1; } + dvdcss->i_socket_fd = dvdcss_network_connect( dvdcss->psz_device ); + if( dvdcss->i_socket_fd != -1 ) + return dvdcss; + /* * Find method from DVDCSS_METHOD environment variable */ @@ -555,6 +562,16 @@ */ extern char * dvdcss_error ( dvdcss_t dvdcss ) { + if( dvdcss->i_socket_fd != -1 ) + { + static char buf[MAX_ERR_MSG]; + + if( dvdcss_network_command( dvdcss->i_socket_fd, buf, "dvd_error") < 0 ) + return "(network error)"; + else + return buf; + } + return dvdcss->psz_error; } @@ -584,6 +601,12 @@ */ extern int dvdcss_seek ( dvdcss_t dvdcss, int i_blocks, int i_flags ) { + if( dvdcss->i_socket_fd != -1 ) + { + return dvdcss_network_command( dvdcss->i_socket_fd, NULL, + "dvd_seek %d %d", i_blocks, i_flags); + } + /* title cracking method is too slow to be used at each seek */ if( ( ( i_flags & DVDCSS_SEEK_MPEG ) && ( dvdcss->i_method != DVDCSS_METHOD_TITLE ) ) @@ -628,6 +651,12 @@ { int i_ret, i_index; + if( dvdcss->i_socket_fd != -1 ) + { + return dvdcss_network_command( dvdcss->i_socket_fd, p_buffer, + "dvd_read %d %d", i_blocks, i_flags); + } + i_ret = dvdcss->pf_read( dvdcss, p_buffer, i_blocks ); if( i_ret <= 0 @@ -704,6 +733,12 @@ void *iov_base; size_t iov_len; + if( dvdcss->i_socket_fd != -1 ) + { + printf("error: network dvdcss_readv not implemented\n"); + return -1; + } + i_ret = dvdcss->pf_readv( dvdcss, _p_iovec, i_blocks ); if( i_ret <= 0 @@ -758,20 +793,27 @@ dvd_title_t *p_title; int i_ret; - /* Free our list of keys */ - p_title = dvdcss->p_titles; - while( p_title ) + if( dvdcss->i_socket_fd != -1 ) { - dvd_title_t *p_tmptitle = p_title->p_next; - free( p_title ); - p_title = p_tmptitle; + close(dvdcss->i_socket_fd); } + else + { + /* Free our list of keys */ + p_title = dvdcss->p_titles; + while( p_title ) + { + dvd_title_t *p_tmptitle = p_title->p_next; + free( p_title ); + p_title = p_tmptitle; + } - i_ret = _dvdcss_close( dvdcss ); + i_ret = _dvdcss_close( dvdcss ); - if( i_ret < 0 ) - { - return i_ret; + if( i_ret < 0 ) + { + return i_ret; + } } free( dvdcss->psz_device ); @@ -786,6 +828,11 @@ #undef dvdcss_title extern int dvdcss_title ( dvdcss_t dvdcss, int i_block ) { + if( dvdcss->i_socket_fd != -1 ) + { + return dvdcss_network_command( dvdcss->i_socket_fd, NULL, + "dvd_title %d", i_block); + } return _dvdcss_title( dvdcss, i_block ); } diff -Naur libdvdcss-1.2.9/src/libdvdcss.h libdvdcss-1.2.9-network/src/libdvdcss.h --- libdvdcss-1.2.9/src/libdvdcss.h 2004-02-24 07:46:49.000000000 -0800 +++ libdvdcss-1.2.9-network/src/libdvdcss.h 2008-01-18 03:41:56.000000000 -0800 @@ -34,6 +34,7 @@ int i_fd; int i_read_fd; int i_pos; + int i_socket_fd; /* File handling */ int ( * pf_seek ) ( dvdcss_t, int ); diff -Naur libdvdcss-1.2.9/src/network.c libdvdcss-1.2.9-network/src/network.c --- libdvdcss-1.2.9/src/network.c 1969-12-31 16:00:00.000000000 -0800 +++ libdvdcss-1.2.9-network/src/network.c 2008-01-18 03:44:44.000000000 -0800 @@ -0,0 +1,331 @@ +/*************************************************************************** + network.c - description + ------------------- + begin : Wed Mar 19 2003 + copyright : (C) 2003 by miguel + email : miguel@miguel + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define _BUFSIZ 300 + +static int host_connect_attempt (struct in_addr ia, int port) +{ + int s; + struct sockaddr_in sin; + + s=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (s==-1) { + printf("network: failed to open socket\n"); + return -1; + } + + sin.sin_family = AF_INET; + sin.sin_addr = ia; + sin.sin_port = htons(port); + + if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 && errno != EINPROGRESS) { + printf("network: cannot connect to host\n"); + close(s); + return -1; + } + + return s; +} + +static int host_connect (const char *host, int port) +{ + struct hostent *h; + int i; + int s; + + h=gethostbyname(host); + if (h==NULL) { + printf("network: unable to resolve >%s<\n", host); + return -1; + } + + for(i=0; h->h_addr_list[i]; i++) { + struct in_addr ia; + memcpy(&ia, h->h_addr_list[i], 4); + s=host_connect_attempt(ia, port); + if(s != -1) { + signal( SIGPIPE, SIG_IGN ); + return s; + } + } + + printf("network: unable to connect to >%s<\n", host); + return -1; +} + + +static int parse_url (char *urlbuf, char** host, int *port) { + char *start = NULL; + char *portcolon = NULL; + + if (host != NULL) + *host = NULL; + + if (port != NULL) + *port = 0; + + start = strstr(urlbuf, "://"); + if (start != NULL) + start += 3; + else + start = urlbuf; + + while( *start == '/' ) + start++; + + portcolon = strchr(start, ':'); + + if (host != NULL) + *host = start; + + if (portcolon != NULL) + { + *portcolon = '\0'; + + if (port != NULL) + *port = atoi(portcolon + 1); + } + + return 0; +} + +static int sock_check_opened(int socket) { + fd_set readfds, writefds, exceptfds; + int retval; + struct timeval timeout; + + for(;;) { + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + FD_SET(socket, &exceptfds); + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + retval = select(socket + 1, &readfds, &writefds, &exceptfds, &timeout); + + if(retval == -1 && (errno != EAGAIN && errno != EINTR)) + return 0; + + if (retval != -1) + return 1; + } + + return 0; +} + +/* + * read binary data from socket + */ +static int sock_data_read (int socket, char *buf, int nlen) { + int n, num_bytes; + + if((socket < 0) || (buf == NULL)) + return -1; + + if(!sock_check_opened(socket)) + return -1; + + num_bytes = 0; + + while (num_bytes < nlen) { + + n = read (socket, &buf[num_bytes], nlen - num_bytes); + + /* read errors */ + if (n < 0) { + if(errno == EAGAIN) { + fd_set rset; + struct timeval timeout; + + FD_ZERO (&rset); + FD_SET (socket, &rset); + + timeout.tv_sec = 30; + timeout.tv_usec = 0; + + if (select (socket+1, &rset, NULL, NULL, &timeout) <= 0) { + printf ("network: timeout on read\n"); + return 0; + } + continue; + } + printf ("network: read error %d\n", errno); + return 0; + } + + num_bytes += n; + + /* end of stream */ + if (!n) break; + } + + return num_bytes; +} + +/* + * read a line (\n-terminated) from socket + */ +static int sock_string_read(int socket, char *buf, int len) { + char *pbuf; + int r, rr; + void *nl; + + if((socket < 0) || (buf == NULL)) + return -1; + + if(!sock_check_opened(socket)) + return -1; + + if (--len < 1) + return(-1); + + pbuf = buf; + + do { + + if((r = recv(socket, pbuf, len, MSG_PEEK)) <= 0) + return -1; + + if((nl = memchr(pbuf, '\n', r)) != NULL) + r = ((char *) nl) - pbuf + 1; + + if((rr = read(socket, pbuf, r)) < 0) + return -1; + + pbuf += rr; + len -= rr; + + } while((nl == NULL) && len); + + if (pbuf > buf && *(pbuf-1) == '\n'){ + *(pbuf-1) = '\0'; + } + *pbuf = '\0'; + return (pbuf - buf); +} + +/* + * Write to socket. + */ +static int sock_data_write(int socket, char *buf, int len) { + ssize_t size; + int wlen = 0; + + if((socket < 0) || (buf == NULL)) + return -1; + + if(!sock_check_opened(socket)) + return -1; + + while(len) { + size = write(socket, buf, len); + + if(size <= 0) + return -1; + + len -= size; + wlen += size; + buf += size; + } + + return wlen; +} + +int dvdcss_network_command( int socket, char *data_buf, char *msg, ...) +{ + char buf[_BUFSIZ]; + va_list args; + int ret, n; + + va_start(args, msg); + vsnprintf(buf, _BUFSIZ - 1, msg, args); + va_end(args); + + /* Each line sent is '\n' terminated */ + if((buf[strlen(buf)] == '\0') && (buf[strlen(buf) - 1] != '\n')) + strcat(buf, "\n"); + + if( sock_data_write(socket, buf, strlen(buf)) < (int)strlen(buf) ) + { + printf("network: error writing to socket\n"); + return -1; + } + + if( sock_string_read(socket, buf, _BUFSIZ) <= 0 ) + { + printf("network: error reading from socket\n"); + return -1; + } + + sscanf(buf, "%d %d", &ret, &n ); + + if( n ) { + if( !data_buf ) { + printf("network: protocol error, data returned but no buffer provided.\n"); + return -1; + } + if( sock_data_read(socket, data_buf, n) < n ) + return -1; + } + + return ret; +} + +int dvdcss_network_connect( char *url ) +{ + char *host; + int port; + int fd; + + url = strdup(url); + parse_url(url, &host, &port); + + if( !host || !strlen(host) || !port ) + { + free(url); + return -1; + } + + fd = host_connect( host, port ); + free(url); + + if( fd != -1 ) { + if( dvdcss_network_command(fd, NULL, "dvd_open") < 0 ) { + close(fd); + return -1; + } + } + return fd; +} diff -Naur libdvdcss-1.2.9/src/network.h libdvdcss-1.2.9-network/src/network.h --- libdvdcss-1.2.9/src/network.h 1969-12-31 16:00:00.000000000 -0800 +++ libdvdcss-1.2.9-network/src/network.h 2008-01-18 03:44:44.000000000 -0800 @@ -0,0 +1,20 @@ +/*************************************************************************** + network.h - description + ------------------- + begin : Wed Mar 19 2003 + copyright : (C) 2003 by miguel + email : miguel@miguel + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +int dvdcss_network_connect( char *url ); + +int dvdcss_network_command( int socket, char *data_buf, char *msg, ...);