summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>2006-08-26 19:23:14 +0000
committerreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>2006-08-26 19:23:14 +0000
commitb5754c6044d7427edbac4f00ae782069fbf17710 (patch)
treed29201ad7d9a69027eb13267b019a070c8b57f72 /stream
parent69acfaa74b624508758d22fa8b21470b12ab001f (diff)
downloadmpv-b5754c6044d7427edbac4f00ae782069fbf17710.tar.bz2
mpv-b5754c6044d7427edbac4f00ae782069fbf17710.tar.xz
Recreate tcp.c as partial copy from network.c
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@19548 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'stream')
-rw-r--r--stream/tcp.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/stream/tcp.c b/stream/tcp.c
new file mode 100644
index 0000000000..0c3e39d42b
--- /dev/null
+++ b/stream/tcp.c
@@ -0,0 +1,242 @@
+/*
+ * Network layer for MPlayer
+ * by Bertrand BAUDET <bertrand_baudet@yahoo.com>
+ * (C) 2001, MPlayer team.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <errno.h>
+#include <ctype.h>
+
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#ifndef HAVE_WINSOCK2
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#define closesocket close
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+#include "tcp.h"
+
+/* IPv6 options */
+int network_prefer_ipv4 = 0;
+
+// 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
+
+
+}