diff --git a/stream/Makefile b/stream/Makefile index 31872b2ada..84c8780459 100644 --- a/stream/Makefile +++ b/stream/Makefile @@ -86,6 +86,7 @@ SRCS += asf_streaming.c \ asf_mmst_streaming.c \ pnm.c \ rtp.c \ + udp.c \ stream_rtsp.c \ stream_rtp.c \ stream_udp.c \ diff --git a/stream/rtp.c b/stream/rtp.c index 507fc086d2..03073f2651 100644 --- a/stream/rtp.c +++ b/stream/rtp.c @@ -198,117 +198,6 @@ int read_rtp_from_server(int fd, char *buffer, int length) { return(length); } -// Start listening on a UDP port. If multicast, join the group. -int rtp_open_socket( URL_t *url ) { - int socket_server_fd, rxsockbufsz; - int err, err_len; - fd_set set; - struct sockaddr_in server_address; - struct ip_mreq mcast; - struct timeval tv; - struct hostent *hp; - - mp_msg(MSGT_NETWORK,MSGL_V,"Listening for traffic on %s:%d ...\n", url->hostname, url->port ); - - socket_server_fd = socket(AF_INET, SOCK_DGRAM, 0); -// fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); - if( socket_server_fd==-1 ) { - mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create socket\n"); - return -1; - } - - if( isalpha(url->hostname[0]) ) { -#ifndef HAVE_WINSOCK2 - hp =(struct hostent*)gethostbyname( url->hostname ); - if( hp==NULL ) { - mp_msg(MSGT_NETWORK,MSGL_ERR,"Counldn't resolve name: %s\n", url->hostname); - goto err_out; - } - memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr_list[0], hp->h_length ); -#else - server_address.sin_addr.s_addr = htonl(INADDR_ANY); -#endif - } else { -#ifndef HAVE_WINSOCK2 -#ifdef USE_ATON - inet_aton(url->hostname, &server_address.sin_addr); -#else - inet_pton(AF_INET, url->hostname, &server_address.sin_addr); -#endif -#else - server_address.sin_addr.s_addr = htonl(INADDR_ANY); -#endif - } - server_address.sin_family=AF_INET; - server_address.sin_port=htons(url->port); - - if( bind( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) { -#ifndef HAVE_WINSOCK2 - if( errno!=EINPROGRESS ) { -#else - if( WSAGetLastError() != WSAEINPROGRESS ) { -#endif - mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to connect to server\n"); - goto err_out; - } - } - -#ifdef HAVE_WINSOCK2 - if (isalpha(url->hostname[0])) { - hp =(struct hostent*)gethostbyname( url->hostname ); - if( hp==NULL ) { - mp_msg(MSGT_NETWORK,MSGL_ERR,"Counldn't resolve name: %s\n", url->hostname); - goto err_out; - } - memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length ); - } else { - unsigned int addr = inet_addr(url->hostname); - memcpy( (void*)&server_address.sin_addr, (void*)&addr, sizeof(addr) ); - } -#endif - - // Increase the socket rx buffer size to maximum -- this is UDP - rxsockbufsz = 240 * 1024; - if( setsockopt( socket_server_fd, SOL_SOCKET, SO_RCVBUF, &rxsockbufsz, sizeof(rxsockbufsz))) { - mp_msg(MSGT_NETWORK,MSGL_ERR,"Couldn't set receive socket buffer size\n"); - } - - if((ntohl(server_address.sin_addr.s_addr) >> 28) == 0xe) { - mcast.imr_multiaddr.s_addr = server_address.sin_addr.s_addr; - //mcast.imr_interface.s_addr = inet_addr("10.1.1.2"); - mcast.imr_interface.s_addr = 0; - if( setsockopt( socket_server_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast))) { - mp_msg(MSGT_NETWORK,MSGL_ERR,"IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n"); - goto err_out; - } - } - - tv.tv_sec = 0; - tv.tv_usec = (1 * 1000000); // 1 second timeout - FD_ZERO( &set ); - FD_SET( socket_server_fd, &set ); - err = select(socket_server_fd+1, &set, NULL, NULL, &tv); - if (err < 0) { - mp_msg(MSGT_NETWORK, MSGL_FATAL, "Select failed: %s\n", strerror(errno)); - goto err_out; - } - if (err == 0) { - mp_msg(MSGT_NETWORK,MSGL_ERR,"Timeout! No data from host %s\n", url->hostname ); - goto err_out; - } - err_len = sizeof( err ); - getsockopt( socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len ); - if( err ) { - mp_msg(MSGT_NETWORK,MSGL_DBG2,"Socket error: %d\n", err ); - goto err_out; - } - return socket_server_fd; - -err_out: - closesocket(socket_server_fd); - return -1; -} - static int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData) { static char buf[1600]; unsigned int intP; diff --git a/stream/rtp.h b/stream/rtp.h index f961553b3d..c244eff2f4 100644 --- a/stream/rtp.h +++ b/stream/rtp.h @@ -34,6 +34,5 @@ struct rtpheader { /* in network byte order */ static int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData); int read_rtp_from_server(int fd, char *buffer, int length); -int rtp_open_socket (URL_t *url); #endif diff --git a/stream/stream_rtp.c b/stream/stream_rtp.c index cf1635bf6a..214ebf2257 100644 --- a/stream/stream_rtp.c +++ b/stream/stream_rtp.c @@ -24,6 +24,7 @@ #include "stream.h" #include "url.h" +#include "udp.h" #include "rtp.h" static int @@ -47,7 +48,7 @@ rtp_streaming_start (stream_t *stream) if (fd < 0) { - fd = rtp_open_socket (streaming_ctrl->url); + fd = udp_open_socket (streaming_ctrl->url); if (fd < 0) return -1; stream->fd = fd; diff --git a/stream/stream_udp.c b/stream/stream_udp.c index 97b0e40f6c..466241c85d 100644 --- a/stream/stream_udp.c +++ b/stream/stream_udp.c @@ -24,7 +24,7 @@ #include "stream.h" #include "url.h" -#include "rtp.h" +#include "udp.h" static int udp_streaming_start (stream_t *stream) @@ -40,7 +40,7 @@ udp_streaming_start (stream_t *stream) if (fd < 0) { - fd = rtp_open_socket (streaming_ctrl->url); + fd = udp_open_socket (streaming_ctrl->url); if (fd < 0) return -1; stream->fd = fd; diff --git a/stream/udp.c b/stream/udp.c new file mode 100644 index 0000000000..d8cdc152fb --- /dev/null +++ b/stream/udp.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2006 Benjamin Zores + * Network helpers for UDP connections (originally borrowed from rtp.c). + * + * 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 + +#ifndef HAVE_WINSOCK2 +#include +#include +#include +#define closesocket close +#else +#include +#include +#endif + +#include "mp_msg.h" +#include "url.h" +#include "udp.h" + +/* Start listening on a UDP port. If multicast, join the group. */ +int +udp_open_socket (URL_t *url) +{ + int socket_server_fd, rxsockbufsz; + int err, err_len; + fd_set set; + struct sockaddr_in server_address; + struct ip_mreq mcast; + struct timeval tv; + struct hostent *hp; + + mp_msg (MSGT_NETWORK, MSGL_V, + "Listening for traffic on %s:%d ...\n", url->hostname, url->port); + + socket_server_fd = socket (AF_INET, SOCK_DGRAM, 0); + if (socket_server_fd == -1) + { + mp_msg (MSGT_NETWORK, MSGL_ERR, "Failed to create socket\n"); + return -1; + } + + if (isalpha (url->hostname[0])) + { +#ifndef HAVE_WINSOCK2 + hp = (struct hostent *) gethostbyname (url->hostname); + if (!hp) + { + mp_msg (MSGT_NETWORK, MSGL_ERR, + "Counldn't resolve name: %s\n", url->hostname); + closesocket (socket_server_fd); + return -1; + } + memcpy ((void *) &server_address.sin_addr.s_addr, + (void *) hp->h_addr_list[0], hp->h_length); +#else + server_address.sin_addr.s_addr = htonl (INADDR_ANY); +#endif /* HAVE_WINSOCK2 */ + } + else + { +#ifndef HAVE_WINSOCK2 +#ifdef USE_ATON + inet_aton (url->hostname, &server_address.sin_addr); +#else + inet_pton (AF_INET, url->hostname, &server_address.sin_addr); +#endif /* USE_ATON */ +#else + server_address.sin_addr.s_addr = htonl(INADDR_ANY); +#endif /* HAVE_WINSOCK2 */ + } + server_address.sin_family = AF_INET; + server_address.sin_port = htons (url->port); + + if (bind (socket_server_fd, (struct sockaddr *) &server_address, + sizeof (server_address)) == -1) + { +#ifndef HAVE_WINSOCK2 + if (errno != EINPROGRESS) +#else + if (WSAGetLastError () != WSAEINPROGRESS) +#endif /* HAVE_WINSOCK2 */ + { + mp_msg (MSGT_NETWORK, MSGL_ERR, "Failed to connect to server\n"); + closesocket (socket_server_fd); + return -1; + } + } + +#ifdef HAVE_WINSOCK2 + if (isalpha (url->hostname[0])) + { + hp = (struct hostent *) gethostbyname (url->hostname); + if (!hp) + { + mp_msg (MSGT_NETWORK, MSGL_ERR, + "Counldn't resolve name: %s\n", url->hostname); + closesocket (socket_server_fd); + return -1; + } + memcpy ((void *) &server_address.sin_addr.s_addr, + (void *) hp->h_addr, hp->h_length); + } + else + { + unsigned int addr = inet_addr (url->hostname); + memcpy ((void *) &server_address.sin_addr, (void *) &addr, sizeof (addr)); + } +#endif /* HAVE_WINSOCK2 */ + + /* Increase the socket rx buffer size to maximum -- this is UDP */ + rxsockbufsz = 240 * 1024; + if (setsockopt (socket_server_fd, SOL_SOCKET, SO_RCVBUF, + &rxsockbufsz, sizeof (rxsockbufsz))) + { + mp_msg (MSGT_NETWORK, MSGL_ERR, + "Couldn't set receive socket buffer size\n"); + } + + if ((ntohl (server_address.sin_addr.s_addr) >> 28) == 0xe) + { + mcast.imr_multiaddr.s_addr = server_address.sin_addr.s_addr; + mcast.imr_interface.s_addr = 0; + + if (setsockopt (socket_server_fd, IPPROTO_IP, + IP_ADD_MEMBERSHIP, &mcast, sizeof (mcast))) + { + mp_msg (MSGT_NETWORK, MSGL_ERR, "IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n"); + closesocket (socket_server_fd); + return -1; + } + } + + tv.tv_sec = 0; + tv.tv_usec = (1 * 1000000); /* 1 second timeout */ + + FD_ZERO (&set); + FD_SET (socket_server_fd, &set); + + err = select (socket_server_fd + 1, &set, NULL, NULL, &tv); + if (err < 0) + { + mp_msg (MSGT_NETWORK, MSGL_FATAL, + "Select failed: %s\n", strerror (errno)); + closesocket (socket_server_fd); + return -1; + } + + if (err == 0) + { + mp_msg (MSGT_NETWORK, MSGL_ERR, + "Timeout! No data from host %s\n", url->hostname); + closesocket (socket_server_fd); + return -1; + } + + err_len = sizeof (err); + getsockopt (socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len); + if (err) + { + mp_msg (MSGT_NETWORK, MSGL_DBG2, "Socket error: %d\n", err); + closesocket (socket_server_fd); + return -1; + } + + return socket_server_fd; +} diff --git a/stream/udp.h b/stream/udp.h new file mode 100644 index 0000000000..5bac18bbca --- /dev/null +++ b/stream/udp.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Benjamin Zores + * Network helpers for UDP connections (originally borrowed from rtp.c). + * + * 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 + */ + +int udp_open_socket (URL_t *url);