⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 net_udp.c

📁 完整的RTP RTSP代码库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * FILE:     net_udp.c * AUTHOR:   Colin Perkins  * MODIFIED: Orion Hodson, Piers O'Hanlon, Kristian Hasler *  * Copyright (c) 1998-2000 University College London * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, is permitted provided that the following conditions  * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by the Computer Science *      Department at University College London * 4. Neither the name of the University nor of the Department may be used *    to endorse or promote products derived from this software without *    specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* If this machine supports IPv6 the symbol HAVE_IPv6 should *//* be defined in either config_unix.h or config_win32.h. The *//* appropriate system header files should also be included   *//* by those files.                                           */#include "config_unix.h"#include "config_win32.h"#include "debug.h"#include "memory.h"#include "inet_pton.h"#include "inet_ntop.h"#include "vsnprintf.h"#include "net_udp.h"#ifndef _WIN32//#include "mpeg4ip_config.h"#endif#ifdef NEED_ADDRINFO_H#include "addrinfo.h"#endif#define IPv4	4#define IPv6	6#if defined(WIN2K_IPV6) || defined(WINXP_IPV6)const struct	in6_addr	in6addr_any = {IN6ADDR_ANY_INIT};#endif/* This is pretty nasty but it's the simplest way to get round *//* the Detexis bug that means their MUSICA IPv6 stack uses     *//* IPPROTO_IP instead of IPPROTO_IPV6 in setsockopt calls      *//* We also need to define in6addr_any */#ifdef  MUSICA_IPV6#define	IPPROTO_IPV6	IPPROTO_IPstruct	in6_addr	in6addr_any = {IN6ADDR_ANY_INIT};/* These DEF's are required as MUSICA's winsock6.h causes a clash with some of the  * standard ws2tcpip.h definitions (eg struct in_addr6). * Note: winsock6.h defines AF_INET6 as 24 NOT 23 as in winsock2.h - I have left it * set to the MUSICA value as this is used in some of their function calls.  *///#define AF_INET6        23#define IP_MULTICAST_LOOP      11 /*set/get IP multicast loopback */#define	IP_MULTICAST_IF		9 /* set/get IP multicast i/f  */#define	IP_MULTICAST_TTL       10 /* set/get IP multicast ttl */#define	IP_MULTICAST_LOOP      11 /*set/get IP multicast loopback */#define	IP_ADD_MEMBERSHIP      12 /* add an IP group membership */#define	IP_DROP_MEMBERSHIP     13/* drop an IP group membership */#define IP_ADD_SOURCE_MEMBERSHIP 39#define IN6_IS_ADDR_UNSPECIFIED(a) (((a)->s6_addr32[0] == 0) && \									((a)->s6_addr32[1] == 0) && \									((a)->s6_addr32[2] == 0) && \									((a)->s6_addr32[3] == 0))struct ip_mreq {	struct in_addr imr_multiaddr;	/* IP multicast address of group */	struct in_addr imr_interface;	/* local IP address of interface */};#endif#ifndef INADDR_NONE#define INADDR_NONE 0xffffffff#endifstatic char G_Multicast_Src[256];static int G_IGMP_V3=0;struct socket_udp_ {	int	 	 mode;	/* IPv4 or IPv6 */        char	        *addr;	uint16_t	 rx_port;	uint16_t	 tx_port;	ttl_t	 	 ttl;	fd_t	 	 fd;	struct in_addr	 addr4;	struct in_addr	 iface4_addr;#ifdef HAVE_IPv6	struct in6_addr	 addr6;#endif /* HAVE_IPv6 */};#ifdef _WIN32/* Want to use both Winsock 1 and 2 socket options, but since* IPv6 support requires Winsock 2 we have to add own backwards* compatibility for Winsock 1.*/#define SETSOCKOPT winsock_versions_setsockopt#else#define SETSOCKOPT setsockopt#endif /* WIN32 *//*****************************************************************************//* Support functions...                                                      *//*****************************************************************************/static voidsocket_error(const char *msg, ...){	char		buffer[255];	uint32_t	blen = sizeof(buffer) / sizeof(buffer[0]);	va_list		ap;#ifdef WIN32#define WSERR(x) {#x,x}	struct wse {		char  errname[20];		int my_errno;	};	struct wse ws_errs[] = {		WSERR(WSANOTINITIALISED), WSERR(WSAENETDOWN),     WSERR(WSAEACCES),		WSERR(WSAEINVAL),         WSERR(WSAEINTR),        WSERR(WSAEINPROGRESS),		WSERR(WSAEFAULT),         WSERR(WSAENETRESET),    WSERR(WSAENOBUFS),		WSERR(WSAENOTCONN),       WSERR(WSAENOTSOCK),     WSERR(WSAEOPNOTSUPP),		WSERR(WSAESHUTDOWN),      WSERR(WSAEWOULDBLOCK),  WSERR(WSAEMSGSIZE),		WSERR(WSAEHOSTUNREACH),   WSERR(WSAECONNABORTED), WSERR(WSAECONNRESET),		WSERR(WSAEADDRNOTAVAIL),  WSERR(WSAEAFNOSUPPORT), WSERR(WSAEDESTADDRREQ),		WSERR(WSAENETUNREACH),    WSERR(WSAETIMEDOUT),    WSERR(0)	};		int i, e = WSAGetLastError();	i = 0;	while(ws_errs[i].my_errno && ws_errs[i].my_errno != e) {		i++;	}	va_start(ap, msg);	_vsnprintf(buffer, blen, msg, ap);	va_end(ap);	rtp_message(LOG_ALERT, "ERROR: %s, (%d - %s)\n", buffer, e, ws_errs[i].errname);#else	uint32_t retlen;	va_start(ap, msg);	retlen = vsnprintf(buffer, blen, msg, ap);	va_end(ap);	rtp_message(LOG_ALERT, "%s:%s", buffer, strerror(errno));#endif}#ifdef WIN32/* ws2tcpip.h defines these constants with different values from* winsock.h so files that use winsock 2 values but try to use * winsock 1 fail.  So what was the motivation in changing the* constants ?*/#define WS1_IP_MULTICAST_IF     2 /* set/get IP multicast interface   */#define WS1_IP_MULTICAST_TTL    3 /* set/get IP multicast timetolive  */#define WS1_IP_MULTICAST_LOOP   4 /* set/get IP multicast loopback    */#define WS1_IP_ADD_MEMBERSHIP   5 /* add  an IP group membership      */#define WS1_IP_DROP_MEMBERSHIP  6 /* drop an IP group membership      *//* winsock_versions_setsockopt tries 1 winsock version of option * optname and then winsock 2 version if that failed.* note: setting the TTL never fails, so we have to try both.*/static intwinsock_versions_setsockopt(SOCKET s, int level, int optname, const char FAR * optval, int optlen){	int success = -1;	switch (optname) {	case IP_MULTICAST_IF:		success = setsockopt(s, level, WS1_IP_MULTICAST_IF, optval, optlen);		break;	case IP_MULTICAST_TTL:		success = setsockopt(s, level, WS1_IP_MULTICAST_TTL, optval, optlen); 		success = setsockopt(s, level, optname, optval, optlen);		break;	case IP_MULTICAST_LOOP:		success = setsockopt(s, level, WS1_IP_MULTICAST_LOOP, optval, optlen);		break;	case IP_ADD_MEMBERSHIP: 		success = setsockopt(s, level, WS1_IP_ADD_MEMBERSHIP, optval, optlen);		break;	case IP_DROP_MEMBERSHIP: 		success = setsockopt(s, level, WS1_IP_DROP_MEMBERSHIP, optval, optlen);		break;	}	if (success != -1) {		return success;	}	return setsockopt(s, level, optname, optval, optlen);}#endif#if defined(NEED_INET_ATON) || !defined(HAVE_INET_ATON)#ifdef NEED_INET_ATON_STATICstatic #endifint inet_aton(const char *name, struct in_addr *addr){	addr->s_addr = inet_addr(name);	return (addr->s_addr != (in_addr_t) INADDR_NONE);}#endif#ifdef NEED_IN6_IS_ADDR_MULTICAST#define IN6_IS_ADDR_MULTICAST(addr) ((addr)->s6_addr[0] == 0xffU)#endif#if defined(NEED_IN6_IS_ADDR_UNSPECIFIED) && defined(MUSICA_IPV6)#define IN6_IS_ADDR_UNSPECIFIED(addr) IS_UNSPEC_IN6_ADDR(*addr)#endif/*****************************************************************************//* IPv4 specific functions...                                                *//*****************************************************************************/static int udp_addr_valid4(const char *dst){        struct in_addr addr4;	struct hostent *h;	if (inet_pton(AF_INET, dst, &addr4)) {		return TRUE;	} 	h = gethostbyname(dst);	if (h != NULL) {		return TRUE;	}	socket_error("Can't resolve IP address for %s", dst);        return FALSE;}static int have_recv_buf_size =#ifdef _WIN32     1#else     0#endif;static int recv_buf_size_value = 65536;static socket_udp *udp_init4 (const char *addr, const char *iface, 			      uint16_t rx_port, uint16_t tx_port, int ttl){  int                 	 reuse = 1;  struct sockaddr_in  	 s_in;  int recv_buf_size;  int test_buffer;  socklen_t test_buffer_size=sizeof(test_buffer);  socket_udp         	*s = (socket_udp *)malloc(sizeof(socket_udp));  s->mode    = IPv4;  s->addr    = NULL;  s->rx_port = rx_port;  s->tx_port = tx_port;  s->ttl     = ttl;  if (addr != NULL) {    if (inet_pton(AF_INET, addr, &s->addr4) != 1) {      struct hostent *h = gethostbyname(addr);      if (h == NULL) {	socket_error("Can't resolve IP address for %s", addr);	free(s);	return NULL;      }      memcpy(&(s->addr4), h->h_addr_list[0], sizeof(s->addr4));    }  } else {    s->addr4.s_addr = 0;  }  if (iface != NULL) {    if (inet_pton(AF_INET, iface, &s->iface4_addr) != 1) {      rtp_message(LOG_ERR, "Illegal interface specification");      free(s);      return NULL;    }  } else {    s->iface4_addr.s_addr = 0;  }  s->fd = socket(AF_INET, SOCK_DGRAM, 0);  if (s->fd < 0) {    socket_error("socket");    free(s);    return NULL;  }  if (have_recv_buf_size != 0) {    recv_buf_size = recv_buf_size_value;    if (SETSOCKOPT(s->fd, SOL_SOCKET, SO_RCVBUF, (char *)&recv_buf_size, sizeof(int)) != 0) {      socket_error("setsockopt SO_RCVBUF");      closesocket(s->fd);      free(s);      return NULL;    }    //Since setsockopt would not return the error if /proc/sys/net/core/rmem_max is smaller    //then the value you are trying to set. use sysctl -w net.core.rmem_max=new_val    //to set the value higher than what is desired in RCVBUF    if( getsockopt( s->fd, SOL_SOCKET, SO_RCVBUF, (void*)&test_buffer, &test_buffer_size ) == -1 )      {	socket_error("getsockopt SO_RCVBUF");      } else {	//See if we could set the desired value	if(test_buffer < recv_buf_size) {	  rtp_message(LOG_WARNING, "Failed to set the RCVBUF to %d, only could set %d\n. Check the Max kernel receive buffer size using \"sysctl net.core.rmem_max\"\n", recv_buf_size, test_buffer);	}      }  }	  if (SETSOCKOPT(s->fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse)) != 0) {    socket_error("setsockopt SO_REUSEADDR");    closesocket(s->fd);    free(s);    return NULL;  }#ifdef SO_REUSEPORT  if (SETSOCKOPT(s->fd, SOL_SOCKET, SO_REUSEPORT, (char *) &reuse, sizeof(reuse)) != 0) {    closesocket(s->fd);    free(s);    socket_error("setsockopt SO_REUSEPORT");    return NULL;  }#endif  s_in.sin_family      = AF_INET;  s_in.sin_addr.s_addr = INADDR_ANY;  s_in.sin_port        = htons(rx_port);  if (bind(s->fd, (struct sockaddr *) &s_in, sizeof(s_in)) != 0) {    socket_error("bind: port %d", rx_port);    closesocket(s->fd);    free(s);    return NULL;  }  if (IN_MULTICAST(ntohl(s->addr4.s_addr))) {    char            loop = 1;#ifndef HAVE_IGMP_V3    struct ip_mreq  imr;    imr.imr_multiaddr.s_addr = s->addr4.s_addr;    imr.imr_interface.s_addr = s->iface4_addr.s_addr;    if (SETSOCKOPT(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreq)) != 0) {      socket_error("setsockopt IP_ADD_MEMBERSHIP");      closesocket(s->fd);      free(s);      return NULL;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -