📄 extl_udp.c
字号:
/* eXosip - This is the eXtended osip library. Copyright (C) 2002,2003,2004,2005,2006,2007 Aymeric MOIZARD - jack@atosc.org eXosip 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. eXosip 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifdef ENABLE_MPATROL#include <mpatrol.h>#endif#include "eXosip2.h"#include "eXtransport.h"#ifdef _WIN32_WCE#include "inet_ntop.h"#elif WIN32#include "inet_ntop.h"#endifextern eXosip_t eXosip;#if defined(_WIN32_WCE)#define strerror(X) "-1"#endifstatic int udp_socket;static struct sockaddr_storage ai_addr;static char udp_firewall_ip[64];static char udp_firewall_port[10];static intudp_tl_init (void){ udp_socket = 0; memset (&ai_addr, 0, sizeof (struct sockaddr_storage)); memset (udp_firewall_ip, 0, sizeof (udp_firewall_ip)); memset (udp_firewall_port, 0, sizeof (udp_firewall_port)); return OSIP_SUCCESS;}static intudp_tl_free (void){ memset (udp_firewall_ip, 0, sizeof (udp_firewall_ip)); memset (udp_firewall_port, 0, sizeof (udp_firewall_port)); memset (&ai_addr, 0, sizeof (struct sockaddr_storage)); if (udp_socket > 0) close (udp_socket); return OSIP_SUCCESS;}static intudp_tl_open (void){ int res; struct addrinfo *addrinfo = NULL; struct addrinfo *curinfo; int sock = -1; if (eXtl_udp.proto_port < 0) eXtl_udp.proto_port = 5060; res = eXosip_get_addrinfo (&addrinfo, eXtl_udp.proto_ifs, eXtl_udp.proto_port, eXtl_udp.proto_num); if (res) return -1; for (curinfo = addrinfo; curinfo; curinfo = curinfo->ai_next) { socklen_t len; if (curinfo->ai_protocol && curinfo->ai_protocol != eXtl_udp.proto_num) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "eXosip: Skipping protocol %d\n", curinfo->ai_protocol)); continue; } sock = (int) socket (curinfo->ai_family, curinfo->ai_socktype, curinfo->ai_protocol); if (sock < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot create socket %s!\n", strerror (errno))); continue; } if (curinfo->ai_family == AF_INET6) {#ifdef IPV6_V6ONLY if (setsockopt_ipv6only (sock)) { close (sock); sock = -1; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot set socket option %s!\n", strerror (errno))); continue; }#endif /* IPV6_V6ONLY */ } res = bind (sock, curinfo->ai_addr, curinfo->ai_addrlen); if (res < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind socket node:%s family:%d %s\n", eXtl_udp.proto_ifs, curinfo->ai_family, strerror (errno))); close (sock); sock = -1; continue; } len = sizeof (ai_addr); res = getsockname (sock, (struct sockaddr *) &ai_addr, &len); if (res != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot get socket name (%s)\n", strerror (errno))); memcpy (&ai_addr, curinfo->ai_addr, curinfo->ai_addrlen); } if (eXtl_udp.proto_num != IPPROTO_UDP) { res = listen (sock, SOMAXCONN); if (res < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind socket node:%s family:%d %s\n", eXtl_udp.proto_ifs, curinfo->ai_family, strerror (errno))); close (sock); sock = -1; continue; } } break; } eXosip_freeaddrinfo (addrinfo); if (sock < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind on port: %i\n", eXtl_udp.proto_port)); return -1; } udp_socket = sock; if (eXtl_udp.proto_port == 0) { /* get port number from socket */ if (eXtl_udp.proto_family == AF_INET) eXtl_udp.proto_port = ntohs (((struct sockaddr_in *) &ai_addr)->sin_port); else eXtl_udp.proto_port = ntohs (((struct sockaddr_in6 *) &ai_addr)->sin6_port); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: Binding on port %i!\n", eXtl_udp.proto_port)); } snprintf (udp_firewall_port, sizeof (udp_firewall_port), "%i", eXtl_udp.proto_port); return OSIP_SUCCESS;}static intudp_tl_set_fdset (fd_set * osip_fdset, int *fd_max){ if (udp_socket <= 0) return -1; eXFD_SET (udp_socket, osip_fdset); if (udp_socket > *fd_max) *fd_max = udp_socket; return OSIP_SUCCESS;}voidudp_tl_learn_port_from_via (osip_message_t * sip){ /* EXOSIP_OPT_UDP_LEARN_PORT option set */ if (eXosip.learn_port > 0) { osip_via_t *via = NULL; osip_generic_param_t *br; osip_message_get_via (sip, 0, &via); if (via != NULL && via->protocol != NULL && (osip_strcasecmp (via->protocol, "udp") == 0 || osip_strcasecmp (via->protocol, "dtls-udp") == 0)) { osip_via_param_get_byname (via, "rport", &br); if (br != NULL && br->gvalue != NULL) { struct eXosip_account_info ainfo; memset (&ainfo, 0, sizeof (struct eXosip_account_info)); snprintf (udp_firewall_port, 20, "%s", br->gvalue); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "SIP port modified from rport in SIP answer\r\n")); osip_via_param_get_byname (via, "received", &br); if (br != NULL && br->gvalue != NULL && sip->from != NULL && sip->from->url != NULL && sip->from->url->host != NULL) { snprintf (ainfo.proxy, sizeof (ainfo.proxy), "%s", sip->from->url->host); ainfo.nat_port = atoi (udp_firewall_port); snprintf (ainfo.nat_ip, sizeof (ainfo.nat_ip), "%s", br->gvalue); eXosip_set_option (EXOSIP_OPT_ADD_ACCOUNT_INFO, &ainfo); } } } } return;}static intudp_tl_read_message (fd_set * osip_fdset){ char *buf; int i; if (udp_socket <= 0) return -1; if (FD_ISSET (udp_socket, osip_fdset)) { struct sockaddr_storage sa;#ifdef __linux socklen_t slen;#else int slen;#endif if (eXtl_udp.proto_family == AF_INET) slen = sizeof (struct sockaddr_in); else slen = sizeof (struct sockaddr_in6); buf = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH * sizeof (char) + 1); if (buf == NULL) return OSIP_NOMEM; i = recvfrom (udp_socket, buf, SIP_MESSAGE_MAX_LENGTH, 0, (struct sockaddr *) &sa, &slen); if (i > 5) { char src6host[NI_MAXHOST]; int recvport = 0; int err; osip_strncpy (buf + i, "\0", 1); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Received message: \n%s\n", buf)); memset (src6host, 0, sizeof (src6host)); if (eXtl_udp.proto_family == AF_INET) recvport = ntohs (((struct sockaddr_in *) &sa)->sin_port); else recvport = ntohs (((struct sockaddr_in6 *) &sa)->sin6_port);#if defined(__arc__) { struct sockaddr_in *fromsa = (struct sockaddr_in *) &sa; char *tmp; tmp = inet_ntoa (fromsa->sin_addr); if (tmp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Message received from: NULL:%i inet_ntoa failure\n", recvport)); } else { snprintf (src6host, sizeof (src6host), "%s", tmp); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message received from: %s:%i\n", src6host, recvport)); } }#else err = getnameinfo ((struct sockaddr *) &sa, slen, src6host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (err != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Message received from: NULL:%i getnameinfo failure\n", recvport)); snprintf (src6host, sizeof (src6host), "127.0.0.1"); } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message received from: %s:%i\n", src6host, recvport)); }#endif OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message received from: %s:%i\n", src6host, recvport)); _eXosip_handle_incoming_message (buf, i, udp_socket, src6host, recvport); }#ifndef MINISIZE else if (i < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not read socket\n")); } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Dummy SIP message received\n")); }#endif osip_free (buf); } return OSIP_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -