From d7b460956a351157b59a551a8c21cfc18bf11e69 Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 5 Aug 2006 10:30:06 +0000 Subject: isolated tcp socket code from network.c to a dedicated file git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@19341 b3059339-0415-0410-9bf9-f77b7e298cf2 --- stream/Makefile | 1 + stream/asf_mmst_streaming.c | 1 + stream/asf_streaming.c | 1 + stream/network.c | 208 +------------------------------ stream/network.h | 2 - stream/pnm.c | 1 + stream/stream_ftp.c | 1 + stream/stream_netstream.c | 1 + stream/stream_rtsp.c | 1 + stream/stream_vstream.c | 1 + stream/tcp.c | 290 ++++++++++++++++++++++++++++++++++++++++++++ stream/tcp.h | 32 +++++ 12 files changed, 331 insertions(+), 209 deletions(-) create mode 100644 stream/tcp.c create mode 100644 stream/tcp.h (limited to 'stream') diff --git a/stream/Makefile b/stream/Makefile index 84c8780459..a6370d312d 100644 --- a/stream/Makefile +++ b/stream/Makefile @@ -87,6 +87,7 @@ SRCS += asf_streaming.c \ pnm.c \ rtp.c \ udp.c \ + tcp.c \ stream_rtsp.c \ stream_rtp.c \ stream_udp.c \ diff --git a/stream/asf_mmst_streaming.c b/stream/asf_mmst_streaming.c index baad3c9493..b9f342de7c 100644 --- a/stream/asf_mmst_streaming.c +++ b/stream/asf_mmst_streaming.c @@ -42,6 +42,7 @@ #include "stream.h" #include "network.h" +#include "tcp.h" #define BUF_SIZE 102400 #define HDR_BUF_SIZE 8192 diff --git a/stream/asf_streaming.c b/stream/asf_streaming.c index 1446c44f6d..bc9d082f38 100644 --- a/stream/asf_streaming.c +++ b/stream/asf_streaming.c @@ -23,6 +23,7 @@ #include "libmpdemux/demuxer.h" #include "network.h" +#include "tcp.h" #ifdef ARCH_X86 #define ASF_LOAD_GUID_PREFIX(guid) (*(uint32_t *)(guid)) diff --git a/stream/network.c b/stream/network.c index 4b0e0966db..4b8856d4b4 100644 --- a/stream/network.c +++ b/stream/network.c @@ -31,6 +31,7 @@ #include "m_config.h" #include "network.h" +#include "tcp.h" #include "http.h" #include "cookies.h" #include "url.h" @@ -51,7 +52,6 @@ int network_cookies_enabled = 0; char *network_useragent=NULL; /* IPv6 options */ -int network_prefer_ipv4 = 0; int network_ipv4_only_proxy = 0; @@ -114,212 +114,6 @@ streaming_ctrl_free( streaming_ctrl_t *streaming_ctrl ) { free( streaming_ctrl ); } - -// Converts an address family constant to a string - -const char *af2String(int af) { - switch (af) { - case AF_INET: return "AF_INET"; - -#ifdef HAVE_AF_INET6 - case AF_INET6: return "AF_INET6"; -#endif - default: return "Unknown address family!"; - } -} - - - -// Connect to a server using a TCP connection, with specified address family -// return -2 for fatal error, like unable to resolve name, connection timeout... -// return -1 is unable to connect to a particular port - -int -connect2Server_with_af(char *host, int port, int af,int verb) { - int socket_server_fd; - int err; - socklen_t err_len; - int ret,count = 0; - fd_set set; - struct timeval tv; - union { - struct sockaddr_in four; -#ifdef HAVE_AF_INET6 - struct sockaddr_in6 six; -#endif - } server_address; - size_t server_address_size; - void *our_s_addr; // Pointer to sin_addr or sin6_addr - struct hostent *hp=NULL; - char buf[255]; - -#ifdef HAVE_WINSOCK2 - u_long val; -#endif - - socket_server_fd = socket(af, SOCK_STREAM, 0); - - - if( socket_server_fd==-1 ) { -// mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create %s socket:\n", af2String(af)); - return -2; - } - - switch (af) { - case AF_INET: our_s_addr = (void *) &server_address.four.sin_addr; break; -#ifdef HAVE_AF_INET6 - case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break; -#endif - default: - mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); - return -2; - } - - - memset(&server_address, 0, sizeof(server_address)); - -#ifndef HAVE_WINSOCK2 -#ifdef USE_ATON - if (inet_aton(host, our_s_addr)!=1) -#else - if (inet_pton(af, host, our_s_addr)!=1) -#endif -#else - if ( inet_addr(host)==INADDR_NONE ) -#endif - { - if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ResolvingHostForAF, host, af2String(af)); - -#ifdef HAVE_GETHOSTBYNAME2 - hp=(struct hostent*)gethostbyname2( host, af ); -#else - hp=(struct hostent*)gethostbyname( host ); -#endif - if( hp==NULL ) { - if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantResolv, af2String(af), host); - return -2; - } - - memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length ); - } -#ifdef HAVE_WINSOCK2 - else { - unsigned long addr = inet_addr(host); - memcpy( our_s_addr, (void*)&addr, sizeof(addr) ); - } -#endif - - switch (af) { - case AF_INET: - server_address.four.sin_family=af; - server_address.four.sin_port=htons(port); - server_address_size = sizeof(server_address.four); - break; -#ifdef HAVE_AF_INET6 - case AF_INET6: - server_address.six.sin6_family=af; - server_address.six.sin6_port=htons(port); - server_address_size = sizeof(server_address.six); - break; -#endif - default: - mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); - return -2; - } - -#if defined(USE_ATON) || defined(HAVE_WINSOCK2) - strncpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); -#else - inet_ntop(af, our_s_addr, buf, 255); -#endif - if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); - - // Turn the socket as non blocking so we can timeout on the connection -#ifndef HAVE_WINSOCK2 - fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); -#else - val = 1; - ioctlsocket( socket_server_fd, FIONBIO, &val ); -#endif - if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) { -#ifndef HAVE_WINSOCK2 - if( errno!=EINPROGRESS ) { -#else - if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { -#endif - if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); - closesocket(socket_server_fd); - return -1; - } - } - tv.tv_sec = 0; - tv.tv_usec = 500000; - FD_ZERO( &set ); - FD_SET( socket_server_fd, &set ); - // When the connection will be made, we will have a writable fd - while((ret = select(socket_server_fd+1, NULL, &set, NULL, &tv)) == 0) { - if( ret<0 ) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed); - else if(ret > 0) break; - else if(count > 30 || mp_input_check_interrupt(500)) { - if(count > 30) - mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout); - else - mp_msg(MSGT_NETWORK,MSGL_V,"Connection interuppted by user\n"); - return -3; - } - count++; - FD_ZERO( &set ); - FD_SET( socket_server_fd, &set ); - tv.tv_sec = 0; - tv.tv_usec = 500000; - } - - // Turn back the socket as blocking -#ifndef HAVE_WINSOCK2 - fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK ); -#else - val = 0; - ioctlsocket( socket_server_fd, FIONBIO, &val ); -#endif - // Check if there were any error - err_len = sizeof(int); - ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); - if(ret < 0) { - mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_GetSockOptFailed,strerror(errno)); - return -2; - } - if(err > 0) { - mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnectError,strerror(err)); - return -1; - } - - return socket_server_fd; -} - -// Connect to a server using a TCP connection -// 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, int verb) { -#ifdef HAVE_AF_INET6 - int r; - int s = -2; - - r = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET:AF_INET6,verb); - if (r > -1) return r; - - s = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET6:AF_INET,verb); - if (s == -2) return r; - return s; -#else - return connect2Server_with_af(host, port, AF_INET,verb); -#endif - - -} - URL_t* check4proxies( URL_t *url ) { URL_t *url_out = NULL; diff --git a/stream/network.h b/stream/network.h index bb659fa6ba..8591fa32dc 100644 --- a/stream/network.h +++ b/stream/network.h @@ -57,8 +57,6 @@ int nop_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream int nop_streaming_seek( int fd, off_t pos, streaming_ctrl_t *stream_ctrl ); void streaming_ctrl_free( streaming_ctrl_t *streaming_ctrl ); -int connect2Server(char *host, int port,int verb); - int http_send_request(URL_t *url, off_t pos); HTTP_header_t *http_read_response(int fd); diff --git a/stream/pnm.c b/stream/pnm.c index b3c0b35279..31c049fc3c 100644 --- a/stream/pnm.c +++ b/stream/pnm.c @@ -50,6 +50,7 @@ #include "osdep/timer.h" #include "pnm.h" +#include "tcp.h" //#include "libreal/rmff.h" extern int network_bandwidth; diff --git a/stream/stream_ftp.c b/stream/stream_ftp.c index 2f82aa2210..3f1830ac35 100644 --- a/stream/stream_ftp.c +++ b/stream/stream_ftp.c @@ -21,6 +21,7 @@ #include "help_mp.h" #include "m_option.h" #include "m_struct.h" +#include "tcp.h" static struct stream_priv_s { char* user; diff --git a/stream/stream_netstream.c b/stream/stream_netstream.c index 753b9d7320..a9a789eb9c 100644 --- a/stream/stream_netstream.c +++ b/stream/stream_netstream.c @@ -63,6 +63,7 @@ #include "bswap.h" #include "netstream.h" +#include "tcp.h" static struct stream_priv_s { char* host; diff --git a/stream/stream_rtsp.c b/stream/stream_rtsp.c index d39294c8b9..ba2a440f5a 100644 --- a/stream/stream_rtsp.c +++ b/stream/stream_rtsp.c @@ -37,6 +37,7 @@ #include #include "stream.h" +#include "tcp.h" #include "librtsp/rtsp.h" #include "librtsp/rtsp_session.h" diff --git a/stream/stream_vstream.c b/stream/stream_vstream.c index 180700a2fe..8ee017a29a 100644 --- a/stream/stream_vstream.c +++ b/stream/stream_vstream.c @@ -51,6 +51,7 @@ #include "help_mp.h" #include "m_option.h" #include "m_struct.h" +#include "tcp.h" #include diff --git a/stream/tcp.c b/stream/tcp.c new file mode 100644 index 0000000000..e34efbd412 --- /dev/null +++ b/stream/tcp.c @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2001 Bertrand BAUDET, 2006 Benjamin Zores + * Network helpers for TCP connections + * (originally borrowed from network.c, + * by Bertrand BAUDET ). + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef HAVE_WINSOCK2 +#include +#include +#include +#define closesocket close +#else +#include +#include +#endif + +#include "mp_msg.h" +#include "help_mp.h" +#include "tcp.h" + +/* IPv6 options */ +int network_prefer_ipv4 = 0; + +/* Converts an address family constant to a string */ +static const char * +af2String (int af) +{ + switch (af) + { + case AF_INET: + return "AF_INET"; +#ifdef HAVE_AF_INET6 + case AF_INET6: + return "AF_INET6"; +#endif + default: + return "Unknown address family!"; + } +} + +static int +connect2Server_with_af (char *host, int port, int af ,int verb) +{ + int socket_server_fd; + int err; + socklen_t err_len; + int ret, count = 0; + fd_set set; + struct timeval tv; + + union { + struct sockaddr_in four; +#ifdef HAVE_AF_INET6 + struct sockaddr_in6 six; +#endif + } server_address; + + size_t server_address_size; + void *our_s_addr; /* Pointer to sin_addr or sin6_addr */ + struct hostent *hp = NULL; + char buf[255]; + +#ifdef HAVE_WINSOCK2 + u_long val; +#endif + + socket_server_fd = socket (af, SOCK_STREAM, 0); + if (socket_server_fd == -1) + return TCP_ERROR_FATAL; + + switch (af) + { + case AF_INET: + our_s_addr = (void *) &server_address.four.sin_addr; + break; +#ifdef HAVE_AF_INET6 + case AF_INET6: + our_s_addr = (void *) &server_address.six.sin6_addr; + break; +#endif + default: + mp_msg (MSGT_NETWORK, MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); + return TCP_ERROR_FATAL; + } + + memset (&server_address, 0, sizeof (server_address)); + +#ifndef HAVE_WINSOCK2 +#ifdef USE_ATON + if (inet_aton (host, our_s_addr) !=1) +#else + if (inet_pton (af, host, our_s_addr) !=1) +#endif /* USE_ATON */ +#else + if (inet_addr (host) == INADDR_NONE) +#endif /* HAVE_WINSOCK2 */ + { + if (verb) + mp_msg (MSGT_NETWORK, MSGL_STATUS, + MSGTR_MPDEMUX_NW_ResolvingHostForAF, host, af2String (af)); + +#ifdef HAVE_GETHOSTBYNAME2 + hp = (struct hostent *) gethostbyname2 (host, af); +#else + hp = (struct hostent *) gethostbyname (host); +#endif /* HAVE_GETHOSTBYNAME2 */ + + if (!hp) + { + if (verb) + mp_msg (MSGT_NETWORK, MSGL_ERR, + MSGTR_MPDEMUX_NW_CantResolv, af2String (af), host); + return TCP_ERROR_FATAL; + } + + memcpy (our_s_addr, (void *) hp->h_addr_list[0], hp->h_length); + } +#ifdef HAVE_WINSOCK2 + else + { + unsigned long addr = inet_addr (host); + memcpy (our_s_addr, (void *) &addr, sizeof (addr)); + } +#endif /* HAVE_WINSOCK2 */ + + switch (af) + { + case AF_INET: + server_address.four.sin_family = af; + server_address.four.sin_port = htons (port); + server_address_size = sizeof (server_address.four); + break; +#ifdef HAVE_AF_INET6 + case AF_INET6: + server_address.six.sin6_family = af; + server_address.six.sin6_port = htons (port); + server_address_size = sizeof (server_address.six); + break; +#endif /* HAVE_AF_INET6 */ + default: + mp_msg (MSGT_NETWORK, MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); + return TCP_ERROR_FATAL; + } + +#if defined(USE_ATON) || defined(HAVE_WINSOCK2) + strncpy (buf, inet_ntoa (*((struct in_addr *) our_s_addr)), 255); +#else + inet_ntop (af, our_s_addr, buf, 255); +#endif /* USE_ATON || HAVE_WINSOCK2 */ + + if (verb) + mp_msg (MSGT_NETWORK, MSGL_STATUS, + MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf, port); + + /* Turn the socket as non blocking so we can timeout on the connection */ +#ifndef HAVE_WINSOCK2 + fcntl (socket_server_fd, F_SETFL, + fcntl (socket_server_fd, F_GETFL) | O_NONBLOCK); +#else + val = 1; + ioctlsocket (socket_server_fd, FIONBIO, &val); +#endif /* HAVE_WINSOCK2 */ + + if (connect (socket_server_fd, (struct sockaddr *) &server_address, + server_address_size) == -1) + { +#ifndef HAVE_WINSOCK2 + if (errno != EINPROGRESS) +#else + if ((WSAGetLastError () != WSAEINPROGRESS) + && (WSAGetLastError () != WSAEWOULDBLOCK)) +#endif /* HAVE_WINSOCK2 */ + { + if (verb) + mp_msg (MSGT_NETWORK, MSGL_ERR, + MSGTR_MPDEMUX_NW_CantConnect2Server, af2String (af)); + + closesocket (socket_server_fd); + return TCP_ERROR_PORT; + } + } + + tv.tv_sec = 0; + tv.tv_usec = 500000; + + FD_ZERO (&set); + FD_SET (socket_server_fd, &set); + + /* When the connection will be made, we will have a writable fd */ + while ((ret = select (socket_server_fd + 1, NULL, &set, NULL, &tv)) == 0) + { + if (ret < 0) + mp_msg (MSGT_NETWORK, MSGL_ERR, MSGTR_MPDEMUX_NW_SelectFailed); + else if (ret > 0) + break; + else if (count > 30 || mp_input_check_interrupt (500)) + { + if (count > 30) + mp_msg (MSGT_NETWORK, MSGL_ERR, MSGTR_MPDEMUX_NW_ConnTimeout); + else + mp_msg (MSGT_NETWORK, MSGL_V, "Connection interuppted by user\n"); + return TCP_ERROR_TIMEOUT; + } + + count++; + FD_ZERO (&set); + FD_SET (socket_server_fd, &set); + tv.tv_sec = 0; + tv.tv_usec = 500000; + } + + /* Turn back the socket as blocking */ +#ifndef HAVE_WINSOCK2 + fcntl (socket_server_fd, F_SETFL, + fcntl (socket_server_fd, F_GETFL) & ~O_NONBLOCK); +#else + val = 0; + ioctlsocket (socket_server_fd, FIONBIO, &val); +#endif /* HAVE_WINSOCK2 */ + + /* Check if there were any error */ + err_len = sizeof (int); + ret = getsockopt (socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len); + if (ret < 0) + { + mp_msg (MSGT_NETWORK, MSGL_ERR, + MSGTR_MPDEMUX_NW_GetSockOptFailed, strerror (errno)); + return TCP_ERROR_FATAL; + } + + if (err > 0) + { + mp_msg (MSGT_NETWORK, MSGL_ERR, + MSGTR_MPDEMUX_NW_ConnectError, strerror (err)); + return TCP_ERROR_PORT; + } + + return socket_server_fd; +} + +int +connect2Server (char *host, int port, int verb) +{ +#ifdef HAVE_AF_INET6 + int r; + int s = TCP_ERROR_FATAL; + + r = connect2Server_with_af (host, port, + network_prefer_ipv4 ? AF_INET:AF_INET6, verb); + if (r > TCP_ERROR_PORT) + return r; + + s = connect2Server_with_af (host, port, + network_prefer_ipv4 ? AF_INET6:AF_INET, verb); + if (s == TCP_ERROR_FATAL) + return r; + + return s; +#else + return connect2Server_with_af (host, port, AF_INET,verb); +#endif /* HAVE_AF_INET6 */ +} diff --git a/stream/tcp.h b/stream/tcp.h new file mode 100644 index 0000000000..77aac33acc --- /dev/null +++ b/stream/tcp.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2001 Bertrand BAUDET, 2006 Benjamin Zores + * Network helpers for TCP connections + * (originally borrowed from network.c, + * by Bertrand BAUDET ). + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _TCP_H_ +#define _TCP_H_ + +/* Connect to a server using a TCP connection */ +int connect2Server (char *host, int port, int verb); + +#define TCP_ERROR_TIMEOUT -3 /* connection timeout */ +#define TCP_ERROR_FATAL -2 /* unable to resolve name */ +#define TCP_ERROR_PORT -1 /* unable to connect to a particular port */ + +#endif /* _TCP_H_ */ -- cgit v1.2.3