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

📄 udp.c

📁 用于linux环境下的SIP服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  The udp plugin is a GPL plugin for partysip.  Copyright (C) 2002,2003  WellX Telecom   - <partysip@wellx.com>  Copyright (C) 2002,2003  Aymeric MOIZARD - <jack@atosc.org>    The udp plugin 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.    The udp plugin 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 Foobar; if not, write to the Free Software  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include <partysip/partysip.h>#include <ppl/ppl_dns.h>#include <ppl/ppl_socket.h>#include "udp.h"#include <fcntl.h>/* to avoid warnings on WIN32 setsockopt calls */#ifdef WIN32#define OPTVALCAST (const char*)#else#define OPTVALCAST #endiflocal_ctx_t *ctx = NULL;static int ipv6_enable = 0;intlocal_ctx_init (int in_port, int out_port){#ifdef MULTICAST_SUPPORT  char *multicast;#endif  int option;  int atry;  int i;  struct sockaddr_in6 raddr6;  struct sockaddr_in raddr;  ctx = (local_ctx_t *) osip_malloc (sizeof (local_ctx_t));  if (ctx == NULL)    return -1;  ctx->mcast_socket = -1; /* if unused */  ctx->in_port = in_port;  /* not used by now */  ctx->out_port = out_port;  {    char *atmp = psp_config_get_element ("ipv6_enable");    if (atmp!=NULL && 0==osip_strncasecmp(atmp, "on", 2))      ipv6_enable = 1;  }  if (ipv6_enable==1)    ctx->in_socket = ppl_socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP);  else    ctx->in_socket = ppl_socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);  if (ctx->in_socket == -1)    {      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,			      "udp plugin: cannot create descriptor for port %i!\n",			      ctx->in_port));      goto lci_error1;    }  option = 1;  i = setsockopt (ctx->in_socket, SOL_SOCKET, SO_REUSEADDR,		  OPTVALCAST &option, sizeof option);  if (i!=0)    {      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_WARNING, NULL,		   "upd plugin; UDP listener SO_REUSE_ADDR failed %i (%i)!\n",		   ctx->in_port, i));    }  if (out_port == in_port)    ctx->out_socket = ctx->in_socket;  else    {      if (ipv6_enable==1)	ctx->out_socket = ppl_socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP);      else	ctx->out_socket = ppl_socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);      if (ctx->out_socket == -1)	{	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,				  "udp plugin: cannot create descriptor for port %i!\n",				  ctx->out_port));	  goto lci_error2;	}      i = (-1);      atry = 0;      while (i < 0 && atry < 40)	{	  atry++;	  if (ipv6_enable==1)	    {	      raddr6.sin6_addr = in6addr_any;	      raddr6.sin6_port = htons ((short) ctx->out_port);	      raddr6.sin6_family = AF_INET6;	      i = ppl_socket_bind (ctx->out_socket,				   (struct sockaddr *) &raddr6, sizeof (raddr6));	    }	  else	    {	      raddr.sin_addr.s_addr = htons (INADDR_ANY);	      raddr.sin_port = htons ((short) ctx->out_port);	      raddr.sin_family = AF_INET;	      i = ppl_socket_bind (ctx->out_socket,				   (struct sockaddr *) &raddr, sizeof (raddr));	    }	  if (i < 0)	    {	      OSIP_TRACE (osip_trace			  (__FILE__, __LINE__, OSIP_WARNING, NULL,			   "udp plugin: cannot bind on port %i!\n",			   ctx->out_port));	      ctx->out_port++;	    }	}      if (i != 0)	goto lci_error3;    }  if (ipv6_enable==1)    {      raddr6.sin6_addr = in6addr_any;      raddr6.sin6_port = htons ((short) ctx->in_port);      raddr6.sin6_family = AF_INET6;      i = ppl_socket_bind (ctx->in_socket,			   (struct sockaddr *) &raddr6, sizeof (raddr6));    }  else    {      raddr.sin_addr.s_addr = htons (INADDR_ANY);      raddr.sin_port = htons ((short) ctx->in_port);      raddr.sin_family = AF_INET;      i = ppl_socket_bind (ctx->in_socket,			   (struct sockaddr *) &raddr, sizeof (raddr));    }    if (i < 0)    {      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_WARNING, NULL,		   "udp plugin: cannot bind on port %i!\n",		   ctx->in_port));      return -1;    }#ifdef MULTICAST_SUPPORT  multicast = psp_config_get_element ("multicast");  if (multicast == NULL)    {      ctx->mcast_socket = -1; /* disabled */    }  else if (0 == osip_strncasecmp (multicast, "on", 2))    {      struct ip_mreq mreq;      struct ipv6_mreq mreq6;      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,			      "udp plugin: Multicast is enabled!\n"));#ifdef __linux      /* linux has support for listening on specific interface. */      {	char *if_mcast = psp_config_get_element ("if_mcast");	char *if_ipmcast = psp_config_get_element ("if_ipmcast");	if (if_mcast==NULL&&if_ipmcast==NULL)	  {	    if (ipv6_enable==1)	      memcpy ((void *)mreq6.ipv6mr_multiaddr.s6_addr, (void const *)&in6_addr_any, 16);	    else	      mreq.imr_interface.s_addr = htonl(INADDR_ANY);	  }	else if (if_mcast!=NULL)	  {	    char *tmp_name;	    char *tmp_ip;	    char *tmp_mask;	    if (ipv6_enable==1)	      {		if (0 != ppl_dns_get_local_fqdn (&tmp_name, &tmp_ip, &tmp_mask,if_mcast, 0, AF_INET6))		  {		    OSIP_TRACE (osip_trace				(__FILE__, __LINE__, OSIP_ERROR, NULL,				 "udp plugin: error while looking for %s interface!\n",				 if_mcast));		    goto lci_error5;		  }	      }	    else	      {		if (0 != ppl_dns_get_local_fqdn (&tmp_name, &tmp_ip, &tmp_mask,if_mcast, 0, AF_INET))		  {		    OSIP_TRACE (osip_trace				(__FILE__, __LINE__, OSIP_ERROR, NULL,				 "udp plugin: error while looking for %s interface!\n",				 if_mcast));		    goto lci_error5;		  }	      }	      	    if (ipv6_enable==1)	      ppl_inet_pton ((const char *)tmp_ip, (void *)&mreq6.ipv6mr_multiaddr.s6_addr);	    else	      mreq.imr_interface.s_addr = inet_addr(tmp_ip);	    OSIP_TRACE (osip_trace			(__FILE__, __LINE__, OSIP_INFO1, NULL,			 "udp plugin: Enabling multicast on %s interface!\n",			 if_mcast));	    OSIP_TRACE (osip_trace			(__FILE__, __LINE__, OSIP_INFO1, NULL,			 "udp plugin: %s %s %s!\n",			 tmp_name, tmp_ip, tmp_mask));	    	    osip_free(tmp_name);	    osip_free(tmp_ip);	    osip_free(tmp_mask);	  }	else if (if_ipmcast!=NULL)	  {	    if (ipv6_enable==1)	      ppl_inet_pton ((const char *)if_ipmcast, (void *)&mreq6.ipv6mr_multiaddr.s6_addr);	    else	      mreq.imr_interface.s_addr = inet_addr(if_ipmcast);	  }      }#else /* non __linux */      {	char *if_ipmcast = psp_config_get_element ("if_ipmcast");	if (if_ipmcast==NULL)	  {	    if (ipv6_enable==1)	      memcpy ((void *)mreq6.ipv6mr_multiaddr.s6_addr, (void const *)&in6_addr_any, 16);	    else	      mreq.imr_interface.s_addr = htonl(INADDR_ANY);	  }	else	  {	    if (ipv6_enable==1)	      ppl_inet_pton ((const char *)if_ipmcast, (void *)&mreq6.ipv6mr_multiaddr.s6_addr);	    else	      mreq.imr_interface.s_addr = inet_addr(if_ipmcast);	  }      }#endif /* __linux */      if (ipv6_enable==0)	{	  /* For IPv4, sip.mcast.org is the well-known IPv4 multicast IP address*/	  /* 224.0.1.75 is the multicast IP address of sip.mcast.org */	  mreq.imr_multiaddr.s_addr = inet_addr("224.0.1.75");      	  if (ctx->in_port==5060)	    ctx->mcast_socket = ctx->in_socket; /* reuse the same socket */	  else	    { /* open a new socket on 5060 for multicast */	      raddr.sin_addr.s_addr = htons (INADDR_ANY);	      raddr.sin_port = htons ((short) 5060); /* always 5060 */	      raddr.sin_family = AF_INET;	      	      ctx->mcast_socket = ppl_socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);	      if (ctx->mcast_socket<0)		{		  OSIP_TRACE (osip_trace			      (__FILE__, __LINE__, OSIP_WARNING, NULL,			       "upd plugin; Cannot create socket for multicast!\n"));		  ctx->mcast_socket = -1;		  goto skip_multicast;		}	      	      option = 1;	      i = setsockopt (ctx->mcast_socket, SOL_SOCKET, SO_REUSEADDR,			      OPTVALCAST &option, sizeof option);	      if (i!=0)		{		  OSIP_TRACE (osip_trace			      (__FILE__, __LINE__, OSIP_WARNING, NULL,			       "upd plugin; UDP listener SO_REUSE_ADDR failed %i (%i)!\n",			       5060, i));		  ppl_socket_close(ctx->mcast_socket);		  ctx->mcast_socket = -1;		  goto skip_multicast;		}	      	      i = ppl_socket_bind (ctx->mcast_socket,				   (struct sockaddr *) &raddr, sizeof (raddr));	      if (i < 0)		{		  OSIP_TRACE (osip_trace			      (__FILE__, __LINE__, OSIP_WARNING, NULL,			       "udp plugin: disabling multicast support %i (%s)!\n",			       5060, strerror (errno)));		  ppl_socket_close(ctx->mcast_socket);		  ctx->mcast_socket = -1;		  goto skip_multicast;		}	    }	  	  option=0;	  if(0 != setsockopt(ctx->mcast_socket, IPPROTO_IP, IP_MULTICAST_LOOP,			     OPTVALCAST &option, sizeof(option)))	    {	      OSIP_TRACE (osip_trace			  (__FILE__, __LINE__, OSIP_WARNING, NULL,			   "udp plugin; cannot disable loopback for multicast socket. (%i)!\n",			   5060));	      if (ctx->in_port!=5060)		ppl_socket_close(ctx->mcast_socket);	      ctx->mcast_socket = -1;	      goto skip_multicast;	    }	  	  /* Enable Multicast support */	  option=1;	  if (0 != setsockopt(ctx->mcast_socket, IPPROTO_IP, IP_MULTICAST_TTL,			      OPTVALCAST &option, sizeof(option)))	    {	      OSIP_TRACE (osip_trace			  (__FILE__, __LINE__, OSIP_WARNING, NULL,			   "udp plugin: cannot set multicast ttl value. (%i)!\n",			   5060));	      if (ctx->in_port!=5060)		ppl_socket_close(ctx->mcast_socket);	      ctx->mcast_socket = -1;	      goto skip_multicast;	    }	  	  if (0 != setsockopt (ctx->mcast_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,			       OPTVALCAST &mreq, sizeof(mreq)))	    {	      OSIP_TRACE (osip_trace			  (__FILE__, __LINE__, OSIP_WARNING, NULL,			   "udp plugin; cannot set multicast ttl value. (%i)!\n",			   5060));	      if (ctx->in_port!=5060)		ppl_socket_close(ctx->mcast_socket);	      ctx->mcast_socket = -1;	      goto skip_multicast;	    }	}    skip_multicast:    }#endif /* !MULTICAST_SUPPORT */  /* set the socket to never block on recv() calls */#ifndef WIN32  if (0 != fcntl (ctx->in_socket, F_SETFL, O_NONBLOCK))    {      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_ERROR, NULL,		   "udp plugin; cannot set O_NONBLOCK to the file desciptor (%i)!\n",		   ctx->in_port));      goto lci_error5;    }  if (0 != fcntl (ctx->out_socket, F_SETFL, O_NONBLOCK))    {      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_ERROR, NULL,		   "udp plugin; cannot set O_NONBLOCK to the file desciptor (%i)!\n",		   ctx->out_port));      goto lci_error5;    }#else  {    int timeout = 0;    int err;    err = setsockopt (ctx->in_socket,		      SOL_SOCKET,		      SO_RCVTIMEO, OPTVALCAST &timeout, sizeof (timeout));    if (err != NO_ERROR)      {	/* failed for some reason... */	OSIP_TRACE (osip_trace		    (__FILE__, __LINE__, OSIP_ERROR, NULL,		     "udp plugin; cannot set O_NONBLOCK to the file desciptor (%i)!\n",		     ctx->in_port));	goto lci_error5;      }    err = setsockopt (ctx->out_socket,		      SOL_SOCKET,		      SO_RCVTIMEO, OPTVALCAST &timeout, sizeof (timeout));    if (err != NO_ERROR)      {	/* failed for some reason... */	OSIP_TRACE (osip_trace		    (__FILE__, __LINE__, OSIP_ERROR, NULL,		     "udp plugin; cannot set O_NONBLOCK to the file desciptor (%i)!\n",		     ctx->out_port));	goto lci_error5;      }  }#endif  return 0;lci_error5:lci_error3:  ppl_socket_close (ctx->out_socket);lci_error2:  ppl_socket_close (ctx->in_socket);lci_error1:  osip_free (ctx);  ctx = NULL;  return -1;}voidlocal_ctx_free (){  if (ctx == NULL)    return;  if (ctx->in_socket != -1)    {      ppl_socket_close (ctx->in_socket);      ctx->in_socket = -1;    }  if (ctx->in_port == ctx->out_port)    ctx->out_socket = (-1);  else if (ctx->out_socket != -1)    ppl_socket_close (ctx->out_socket);  osip_free (ctx);  ctx = NULL;}#ifdef MULTICAST_SUPPORT#ifndef IN_MULTICAST#   define IN_MULTICAST(a)         IN_CLASSD(a)#endif#endif/* max_analysed = maximum number of message when this method can parse   messages whithout returning.   This method returns:   -1 on error   0  on no message available   1  on max_analysed reached*/intcb_rcv_udp_message (int max){  fd_set memo_fdset;  fd_set osip_fdset;  int max_fd;  struct sockaddr_in6 sa6;  struct sockaddr_in sa4;  struct sockaddr *sa;  char *buf;  int i;  struct timeval tv;#ifdef __linux  socklen_t slen;#else  int slen;#endif  if (ctx == NULL)    return -1;  tv.tv_sec = 0;  tv.tv_usec = 0;  FD_ZERO (&memo_fdset);  FD_SET (ctx->in_socket, &memo_fdset);  if (ctx->out_socket>0      &&ctx->out_socket!=ctx->in_socket)

⌨️ 快捷键说明

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