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

📄 rtpsession_inet.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack.  Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org  This library is free software; you can redistribute it and/or  modify it under the terms of the GNU Lesser General Public  License as published by the Free Software Foundation; either  version 2.1 of the License, or (at your option) any later version.  This library 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  Lesser General Public License for more details.  You should have received a copy of the GNU Lesser General Public  License along with this library; if not, write to the Free Software  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include "ortp/ortp.h"#include "utils.h"#include "ortp/rtpsession.h"#include "rtpsession_priv.h"#if defined(WIN32) || defined(_WIN32_WCE)#include "ortp-config-win32.h"#else#include "ortp-config.h" /*needed for HAVE_SYS_UIO_H */#endif#ifdef HAVE_SYS_UIO_H#include <sys/uio.h>#define USE_SENDMSG 1#endif#define can_connect(s)	( (s)->use_connect && !(s)->symmetric_rtp)static bool_t try_connect(int fd, const struct sockaddr *dest, socklen_t addrlen){	if (connect(fd,dest,addrlen)<0){		ortp_warning("Could not connect() socket: %s",getSocketError());		return FALSE;	}	return TRUE;}static ortp_socket_t create_and_bind(const char *addr, int port, int *sock_family, bool_t reuse_addr){	int err;	int optval = 1;	ortp_socket_t sock=-1;#ifdef ORTP_INET6	char num[8];	struct addrinfo hints, *res0, *res;#else	struct sockaddr_in saddr;#endif	#ifdef ORTP_INET6		memset(&hints, 0, sizeof(hints));	hints.ai_family = PF_UNSPEC;	hints.ai_socktype = SOCK_DGRAM;	snprintf(num, sizeof(num), "%d",port);	err = getaddrinfo(addr,num, &hints, &res0);	if (err!=0) {		ortp_warning ("Error in getaddrinfo on (addr=%s port=%i): %s", addr, port, gai_strerror(err));		return -1;	}		for (res = res0; res; res = res->ai_next) {		sock = socket(res->ai_family, res->ai_socktype, 0);		if (sock==-1)			continue;		if (reuse_addr){			err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,					(SOCKET_OPTION_VALUE)&optval, sizeof (optval));			if (err < 0)			{				ortp_warning ("Fail to set rtp address reusable: %s.", getSocketError());			}		}		*sock_family=res->ai_family;		err = bind (sock, res->ai_addr, res->ai_addrlen);		if (err != 0){			ortp_warning ("Fail to bind rtp socket to (addr=%s port=%i) : %s.", addr,port, getSocketError());			close_socket (sock);			sock=-1;			continue;		}#ifndef __hpux		switch (res->ai_family)		  {		    case AF_INET:		      if (IN_MULTICAST(ntohl(((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr)))			{		          struct ip_mreq mreq;			  mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr;			  mreq.imr_interface.s_addr = INADDR_ANY;			  err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (SOCKET_OPTION_VALUE) &mreq, sizeof(mreq));			  if (err < 0){				ortp_warning ("Fail to join address group: %s.", getSocketError());				close_socket (sock);				sock=-1;				continue;			    }			}		      break;		    case AF_INET6:		      if (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr)))			{			  struct ipv6_mreq mreq;			  mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;			  mreq.ipv6mr_interface = 0;			  err = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (SOCKET_OPTION_VALUE)&mreq, sizeof(mreq));			  if (err < 0)			    {			      ortp_warning ("Fail to join address group: %s.", getSocketError());			      close_socket (sock);			      sock=-1;			      continue;			    }			}		      break;		  }#endif /*hpux*/		break;	}	freeaddrinfo(res0);#else	saddr.sin_family = AF_INET;	*sock_family=AF_INET;	err = inet_aton (addr, &saddr.sin_addr);	if (err < 0)	{		ortp_warning ("Error in socket address:%s.", getSocketError());		return -1;	}	saddr.sin_port = htons (port);	sock = socket (PF_INET, SOCK_DGRAM, 0);	if (sock==-1) return -1;	if (reuse_addr){		err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,				(SOCKET_OPTION_VALUE)&optval, sizeof (optval));		if (err < 0)		{			ortp_warning ("Fail to set rtp address reusable: %s.",getSocketError());		}	}	err = bind (sock,		    (struct sockaddr *) &saddr,		    sizeof (saddr));	if (err != 0)	{		ortp_warning ("Fail to bind rtp socket to port %i: %s.", port, getSocketError());		close_socket (sock);		return -1;	}#endif	if (sock!=-1){		set_non_blocking_socket (sock);	}	return sock;}static void set_socket_sizes(int sock, unsigned int sndbufsz, unsigned int rcvbufsz){	int err;	bool_t done=FALSE;	if (sndbufsz>0){#ifdef SO_SNDBUFFORCE		err = setsockopt(sock, SOL_SOCKET, SO_SNDBUFFORCE, (void *)&sndbufsz, sizeof(sndbufsz)); 		if (err == -1) {			ortp_error("Fail to increase socket's send buffer size with SO_SNDBUFFORCE: %s.", getSocketError());		}else done=TRUE;#endif		if (!done){			err = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&sndbufsz, sizeof(sndbufsz)); 			if (err == -1) {				ortp_error("Fail to increase socket's send buffer size with SO_SNDBUF: %s.", getSocketError());			}		}	}	done=FALSE;	if (rcvbufsz>0){#ifdef SO_RCVBUFFORCE		err = setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE, (void *)&rcvbufsz, sizeof(rcvbufsz)); 		if (err == -1) {			ortp_error("Fail to increase socket's recv buffer size with SO_RCVBUFFORCE: %s.", getSocketError());		}#endif		if (!done){			err = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbufsz, sizeof(rcvbufsz)); 			if (err == -1) {				ortp_error("Fail to increase socket's recv buffer size with SO_RCVBUF: %s.", getSocketError());			}		}			}}static ortp_socket_t create_and_bind_random(const char *localip, int *sock_family, int *port){	int retry;	ortp_socket_t sock = -1;	for (retry=0;retry<100;retry++)	{		int localport;		do		{			localport = (rand () + 5000) & 0xfffe;		}		while ((localport < 5000) || (localport > 0xffff));		/*do not set REUSEADDR in case of random allocation */		sock = create_and_bind(localip, localport, sock_family,FALSE);		if (sock!=-1) {			*port=localport;			return sock;		}	}	ortp_warning("create_and_bind_random: Could not find a random port for %s !",localip);	return -1;}/** *rtp_session_set_local_addr: *@session:		a rtp session freshly created. *@addr:		a local IP address in the xxx.xxx.xxx.xxx form. *@port:		a local port or -1 to let oRTP choose the port randomly * *	Specify the local addr to be use to listen for rtp packets or to send rtp packet from. *	In case where the rtp session is send-only, then it is not required to call this function: *	when calling rtp_session_set_remote_addr(), if no local address has been set, then the  *	default INADRR_ANY (0.0.0.0) IP address with a random port will be used. Calling  *	rtp_sesession_set_local_addr() is mandatory when the session is recv-only or duplex. * *	Returns: 0 on success.**/intrtp_session_set_local_addr (RtpSession * session, const char * addr, int port){	ortp_socket_t sock;	int sockfamily;	if (session->rtp.socket>=0){		/* don't rebind, but close before*/		rtp_session_release_sockets(session);	}	/* try to bind the rtp port */	if (port>0)		sock=create_and_bind(addr,port,&sockfamily,TRUE);	else		sock=create_and_bind_random(addr,&sockfamily,&port);	if (sock!=-1){		set_socket_sizes(sock,session->rtp.snd_socket_size,session->rtp.rcv_socket_size);		session->rtp.sockfamily=sockfamily;		session->rtp.socket=sock;		session->rtp.loc_port=port;		/*try to bind rtcp port */		sock=create_and_bind(addr,port+1,&sockfamily,TRUE);		if (sock!=-1){			session->rtcp.sockfamily=sockfamily;			session->rtcp.socket=sock;		}else{			ortp_warning("Could not create and bind rtcp socket.");		}				/* set socket options (but don't change chosen states) */		rtp_session_set_dscp( session, -1 );		rtp_session_set_multicast_ttl( session, -1 );		rtp_session_set_multicast_loopback( session, -1 );		return 0;	}	return -1;}/** *rtp_session_set_multicast_ttl: *@session: a rtp session *@ttl: desired Multicast Time-To-Live * * Sets the TTL (Time-To-Live) for outgoing multicast packets. * * Returns: 0 on success. ***/int rtp_session_set_multicast_ttl(RtpSession *session, int ttl){    int retval;        // Store new TTL if one is specified    if (ttl>0) session->multicast_ttl = ttl;        // Don't do anything if socket hasn't been created yet    if (session->rtp.socket < 0) return 0;    switch (session->rtp.sockfamily) {        case AF_INET: { 			retval= setsockopt(session->rtp.socket, IPPROTO_IP, IP_MULTICAST_TTL,						 (SOCKET_OPTION_VALUE)  &session->multicast_ttl, sizeof(session->multicast_ttl));            			if (retval<0) break;			retval= setsockopt(session->rtcp.socket, IPPROTO_IP, IP_MULTICAST_TTL,					 (SOCKET_OPTION_VALUE)	   &session->multicast_ttl, sizeof(session->multicast_ttl)); 		} break;        case AF_INET6: {			retval= setsockopt(session->rtp.socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 					 (SOCKET_OPTION_VALUE)&session->multicast_ttl, sizeof(session->multicast_ttl));								if (retval<0) break;						retval= setsockopt(session->rtcp.socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 					 (SOCKET_OPTION_VALUE) &session->multicast_ttl, sizeof(session->multicast_ttl));        } break;        default:            retval=-1;    }    	if (retval<0)		ortp_warning("Failed to set multicast TTL on socket.");  	return retval;}/** *rtp_session_get_multicast_ttl: *@session: a rtp session * * Returns the TTL (Time-To-Live) for outgoing multicast packets. ***/int rtp_session_get_multicast_ttl(RtpSession *session){	return session->multicast_ttl;}/** *rtp_session_set_multicast_loopback: *@session: a rtp session *@ttl: desired Multicast Time-To-Live * * Sets the TTL (Time-To-Live) for outgoing multicast packets. * * Returns: 0 on success. ***/int rtp_session_set_multicast_loopback(RtpSession *session, int yesno){    int retval;        // Store new loopback state if one is specified    if (yesno==0) {    	// Don't loop back    	session->multicast_loopback = 0;    } else if (yesno>0) {    	// Do loop back    	session->multicast_loopback = 1;    }         // Don't do anything if socket hasn't been created yet    if (session->rtp.socket < 0) return 0;    switch (session->rtp.sockfamily) {        case AF_INET: { 			retval= setsockopt(session->rtp.socket, IPPROTO_IP, IP_MULTICAST_LOOP,						 (SOCKET_OPTION_VALUE)   &session->multicast_loopback, sizeof(session->multicast_loopback));            			if (retval<0) break;			retval= setsockopt(session->rtcp.socket, IPPROTO_IP, IP_MULTICAST_LOOP,						 (SOCKET_OPTION_VALUE)   &session->multicast_loopback, sizeof(session->multicast_loopback)); 		} break;        case AF_INET6: {			retval= setsockopt(session->rtp.socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 				 (SOCKET_OPTION_VALUE)	&session->multicast_loopback, sizeof(session->multicast_loopback));								if (retval<0) break;						retval= setsockopt(session->rtcp.socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 				 (SOCKET_OPTION_VALUE)	&session->multicast_loopback, sizeof(session->multicast_loopback));        } break;        default:            retval=-1;    }    	if (retval<0)		ortp_warning("Failed to set multicast loopback on socket.");  	return retval;}/** *rtp_session_get_multicast_loopback: *@session: a rtp session * * Returns the multicast loopback state of rtp session (true or false). ***/int rtp_session_get_multicast_loopback(RtpSession *session){	return session->multicast_loopback;}/** *rtp_session_set_dscp: *@session: a rtp session *@dscp: desired DSCP PHB value * * Sets the DSCP (Differentiated Services Code Point) for outgoing RTP packets. * * Returns: 0 on success. ***/int rtp_session_set_dscp(RtpSession *session, int dscp){	int retval=0;	int tos;	// Store new DSCP value if one is specified	if (dscp>=0) session->dscp = dscp;		// Don't do anything if socket hasn't been created yet	if (session->rtp.socket < 0) return 0;	// DSCP value is in the upper six bits of the TOS field	tos = (session->dscp << 2) & 0xFC;	switch (session->rtp.sockfamily) {		case AF_INET:		retval = setsockopt(session->rtp.socket, IPPROTO_IP, IP_TOS, (SOCKET_OPTION_VALUE)&tos, sizeof(tos));		break;#ifdef ORTP_INET6	case AF_INET6:#	ifdef IPV6_TCLASS /*seems not defined by my libc*/		retval = setsockopt(session->rtp.socket, IPPROTO_IPV6, IPV6_TCLASS,		 (SOCKET_OPTION_VALUE)&tos, sizeof(tos));#	else		/*in case that works:*/		retval = setsockopt(session->rtp.socket, IPPROTO_IPV6, IP_TOS,		 (SOCKET_OPTION_VALUE)&tos, sizeof(tos));#endif		break;#endif	default:		retval=-1;	}	if (retval<0)		ortp_warning("Failed to set DSCP value on socket.");	return retval;}/** *rtp_session_get_dscp: *@session: a rtp session * * Returns the DSCP (Differentiated Services Code Point) for outgoing RTP packets. ***/int rtp_session_get_dscp(const RtpSession *session){	return session->dscp;}/** *rtp_session_get_local_port: *@session:	a rtp session for which rtp_session_set_local_addr() or rtp_session_set_remote_addr() has been called * *	This function can be useful to retrieve the local port that was randomly choosen by  *	rtp_session_set_remote_addr() when rtp_session_set_local_addr() was not called. * *	Returns: the local port used to listen for rtp packets, -1 if not set.**/int rtp_session_get_local_port(const RtpSession *session){	return (session->rtp.loc_port>0) ? session->rtp.loc_port : -1;}static char * ortp_inet_ntoa(struct sockaddr *addr, int addrlen, char *dest, int destlen){#ifdef ORTP_INET6	int err;	dest[0]=0;	err=getnameinfo(addr,addrlen,dest,destlen,NULL,0,NI_NUMERICHOST);	if (err!=0){		ortp_warning("getnameinfo error: %s",gai_strerror(err));	}#else	char *tmp=inet_ntoa(((struct sockaddr_in*)addr)->sin_addr);	strncpy(dest,tmp,destlen);	dest[destlen-1]='\0';

⌨️ 快捷键说明

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