From 74f76ea788d9af5a37d668de0e53afe13a305aaa Mon Sep 17 00:00:00 2001 From: ben Date: Fri, 4 Aug 2006 19:31:53 +0000 Subject: removed udp socket creation code from rtp stack to a new dedicated udp helper file git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@19324 b3059339-0415-0410-9bf9-f77b7e298cf2 --- stream/udp.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 stream/udp.c (limited to 'stream/udp.c') 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; +} -- cgit v1.2.3