exutils.c
来自「libosip2-3版本的osip源代码」· C语言 代码 · 共 1,103 行 · 第 1/2 页
C
1,103 行
if (size > 256) size = 256;#endif if (eXosip.forced_localip) { if (size > sizeof (eXosip.net_interfaces[0].net_firewall_ip)) size = sizeof (eXosip.net_interfaces[0].net_firewall_ip); strncpy (loc, eXosip.net_interfaces[0].net_firewall_ip, size); return 0; } strcpy (loc, "127.0.0.1"); /* always fallback to local loopback */ memset (&hints, 0, sizeof (hints)); if(ipv6_enable) hints.ai_family = PF_INET6; else hints.ai_family = PF_INET; /* ipv4 only support */ hints.ai_socktype = SOCK_DGRAM; /*hints.ai_flags=AI_NUMERICHOST|AI_CANONNAME; */ err = getaddrinfo (address_to_reach, "5060", &hints, &res); if (err != 0) { eXosip_trace (OSIP_ERROR, ("Error in getaddrinfo for %s: %s\n", address_to_reach, gai_strerror (err))); return -1; } if (res == NULL) { eXosip_trace (OSIP_ERROR, ("getaddrinfo reported nothing !")); return -1; } sock = socket (res->ai_family, SOCK_DGRAM, 0); tmp = 1; err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &tmp, sizeof (int)); if (err < 0) { eXosip_trace (OSIP_ERROR, ("Error in setsockopt: %s\n", strerror (errno))); freeaddrinfo (res); close (sock); return -1; } err = connect (sock, res->ai_addr, res->ai_addrlen); if (err < 0) { eXosip_trace (OSIP_ERROR, ("Error in connect: %s\n", strerror (errno))); freeaddrinfo (res); close (sock); return -1; } freeaddrinfo (res); res = NULL; s = sizeof (addr); err = getsockname (sock, (struct sockaddr *) &addr, &s); if (err != 0) { eXosip_trace (OSIP_ERROR, ("Error in getsockname: %s\n", strerror (errno))); close (sock); return -1; } err = getnameinfo ((struct sockaddr *) &addr, s, loc, size, NULL, 0, NI_NUMERICHOST); if (err != 0) { eXosip_trace (OSIP_ERROR, ("getnameinfo error:%s", strerror (errno))); close (sock); return -1; } close (sock); eXosip_trace (OSIP_INFO1, ("Outgoing interface to reach %s is %s.\n", address_to_reach, loc)); return 0;}voideXosip_get_localip_from_via (osip_message_t * mesg, char *locip, int size){ osip_via_t *via = NULL; char *host; via = (osip_via_t *) osip_list_get (mesg->vias, 0); if (via == NULL) { host = "15.128.128.93"; eXosip_trace (OSIP_ERROR, ("Could not get via:%s")); } else host = via->host; eXosip_get_localip_for (host, locip, size);}#endifchar *strdup_printf (const char *fmt, ...){ /* Guess we need no more than 100 bytes. */ int n, size = 100; char *p; va_list ap; if ((p = osip_malloc (size)) == NULL) return NULL; while (1) { /* Try to print in the allocated space. */ va_start (ap, fmt);#ifdef WIN32 n = _vsnprintf (p, size, fmt, ap);#else n = vsnprintf (p, size, fmt, ap);#endif va_end (ap); /* If that worked, return the string. */ if (n > -1 && n < size) return p; /* Else try again with more space. */ if (n > -1) /* glibc 2.1 */ size = n + 1; /* precisely what is needed */ else /* glibc 2.0 */ size *= 2; /* twice the old size */ if ((p = realloc (p, size)) == NULL) return NULL; }}inteXosip_get_addrinfo (struct addrinfo **addrinfo, const char *hostname, int service, int protocol){ struct addrinfo hints; int error; char portbuf[10]; if (hostname == NULL) return -1; if (service != -1) /* -1 for SRV record */ snprintf (portbuf, sizeof (portbuf), "%i", service); memset (&hints, 0, sizeof (hints)); hints.ai_flags = 0; if(ipv6_enable) hints.ai_family = PF_INET6; else hints.ai_family = PF_INET; /* ipv4 only support */ if (protocol == IPPROTO_UDP) hints.ai_socktype = SOCK_DGRAM; else hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = protocol; /* IPPROTO_UDP or IPPROTO_TCP */ if (service == -1) /* -1 for SRV record */ { error = getaddrinfo (hostname, "sip", &hints, addrinfo); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "SRV resolution with udp-sip-%s\n", hostname)); } else { error = getaddrinfo (hostname, portbuf, &hints, addrinfo); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "DNS resolution with %s:%i\n", hostname, service)); } if (error || *addrinfo == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "getaddrinfo failure. %s:%s (%s)\n", hostname, portbuf, gai_strerror (error))); return -1; } return 0;}int_eXosip_srv_lookup(osip_transaction_t * tr, osip_message_t * sip, struct osip_srv_record *record){ int use_srv=1; int port; char *host; osip_via_t *via; via = (osip_via_t *) osip_list_get (&sip->vias, 0); if (via == NULL || via->protocol == NULL) return -1; if (MSG_IS_REQUEST(sip)) { osip_route_t *route; osip_message_get_route (sip, 0, &route); if (route != NULL) { osip_uri_param_t *lr_param = NULL; osip_uri_uparam_get_byname (route->url, "lr", &lr_param); if (lr_param == NULL) route = NULL; } if (route != NULL) { port = 5060; if (route->url->port != NULL) { port = osip_atoi (route->url->port); use_srv=0; } host = route->url->host; } else { port = 5060; if (sip->req_uri->port != NULL) { port = osip_atoi (sip->req_uri->port); use_srv=0; } host = sip->req_uri->host; } } else { osip_generic_param_t *maddr; osip_generic_param_t *received; osip_generic_param_t *rport; osip_via_param_get_byname (via, "maddr", &maddr); osip_via_param_get_byname (via, "received", &received); osip_via_param_get_byname (via, "rport", &rport); if (maddr != NULL) host = maddr->gvalue; else if (received != NULL) host = received->gvalue; else host = via->host; if (via->port == NULL) use_srv=0; if (rport == NULL || rport->gvalue == NULL) { if (via->port != NULL) port = osip_atoi (via->port); else port = 5060; } else port = osip_atoi (rport->gvalue); } if (use_srv==1) { int i; i = _eXosip_get_srv_record(record, host, via->protocol); } return 0;}#if defined(WIN32) && !defined(_WIN32_WCE)int_eXosip_get_srv_record (struct osip_srv_record *record, char *domain, char *protocol){ char zone[1024]; PDNS_RECORD answer, tmp; /* answer buffer from nameserver */ int n; char tr[100]; memset(record, 0, sizeof(struct osip_srv_record)); if (strlen(domain)+strlen(protocol)>1000) return -1; if (strlen(protocol)>=100) return -1; snprintf(tr, 100, protocol); osip_tolower(tr); snprintf(zone, 1024, "_sip._%s.%s", tr, domain); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "About to ask for '%s IN SRV'\n", zone)); if (DnsQuery (zone, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &answer, NULL) != 0) { return -1; } n = 0; for (tmp = answer; tmp != NULL; tmp = tmp->pNext) { struct osip_srv_entry *srventry; DNS_SRV_DATA * data; if (tmp->wType != DNS_TYPE_SRV) continue; srventry = &record->srventry[n]; data=&tmp->Data.SRV; snprintf(srventry->srv, sizeof(srventry->srv), "%s", data->pNameTarget); srventry->priority = data->wPriority; srventry->weight = data->wWeight; if (srventry->weight) srventry->rweight = 1 + rand () % (10000 * srventry->weight); else srventry->rweight = 0; srventry->port = data->wPort; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "SRV record %s IN SRV -> %s:%i/%i/%i/%i\n", zone, srventry->srv, srventry->port, srventry->priority, srventry->weight, srventry->rweight)); n++; } if (n==0) return -1; snprintf(record->name, sizeof(record->name), "%s", domain); return 0;}#elif defined(__linux)/* the biggest packet we'll send and receive */#if PACKETSZ > 1024#define MAXPACKET PACKETSZ#else#define MAXPACKET 1024#endif/* and what we send and receive */ typedef union { HEADER hdr; u_char buf[MAXPACKET]; } querybuf;#ifndef T_SRV#define T_SRV 33#endifint_eXosip_get_srv_record (struct osip_srv_record *record, char *domain, char *protocol){ querybuf answer; /* answer buffer from nameserver */ int n; char zone[1024]; int ancount, qdcount; /* answer count and query count */ HEADER *hp; /* answer buffer header */ char hostbuf[256]; unsigned char *msg, *eom, *cp; /* answer buffer positions */ int dlen, type, aclass, pref, weight, port; long ttl; int answerno; char tr[100]; memset(record, 0, sizeof(struct osip_srv_record)); if (strlen(domain)+strlen(protocol)>1000) return -1; if (strlen(protocol)>=100) return -1; snprintf(tr, 100, protocol); osip_tolower(tr); snprintf(zone, 1024, "_sip._%s.%s", tr, domain); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "About to ask for '%s IN SRV'\n", zone)); n = res_query (zone, C_IN, T_SRV, (unsigned char *) &answer, sizeof (answer)); if (n < (int) sizeof (HEADER)) { return -1; } /* browse message and search for DNS answers part */ hp = (HEADER *) &answer; qdcount = ntohs (hp->qdcount); ancount = ntohs (hp->ancount); msg = (unsigned char *) (&answer); eom = (unsigned char *) (&answer) + n; cp = (unsigned char *) (&answer) + sizeof (HEADER); while (qdcount-- > 0 && cp < eom) { n = dn_expand (msg, eom, cp, (char *) hostbuf, 256); if (n < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Invalid SRV record answer for '%s': bad format\n", zone)); return -1; } cp += n + QFIXEDSZ; } /* browse DNS answers */ answerno = 0; /* loop through the answer buffer and extract SRV records */ while (ancount-- > 0 && cp < eom) { struct osip_srv_entry *srventry; n = dn_expand (msg, eom, cp, (char *) hostbuf, 256); if (n < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Invalid SRV record answer for '%s': bad format\n", zone)); return -1; } cp += n;#if defined(__NetBSD__) || defined(__OpenBSD__) ||\defined(OLD_NAMESER) || defined(__FreeBSD__) type = _get_short (cp); cp += sizeof (u_short);#elif defined(__APPLE_CC__) GETSHORT (type, cp);#else NS_GET16 (type, cp);#endif#if defined(__NetBSD__) || defined(__OpenBSD__) ||\defined(OLD_NAMESER) || defined(__FreeBSD__) aclass = _get_short (cp); cp += sizeof (u_short);#elif defined(__APPLE_CC__) GETSHORT (aclass, cp);#else NS_GET16 (aclass, cp);#endif#if defined(__NetBSD__) || defined(__OpenBSD__) ||\defined(OLD_NAMESER) || defined(__FreeBSD__) ttl = _get_long (cp); cp += sizeof (u_long);#elif defined(__APPLE_CC__) GETLONG (ttl, cp);#else NS_GET32 (ttl, cp);#endif#if defined(__NetBSD__) || defined(__OpenBSD__) ||\defined(OLD_NAMESER) || defined(__FreeBSD__) dlen = _get_short (cp); cp += sizeof (u_short);#elif defined(__APPLE_CC__) GETSHORT (dlen, cp);#else NS_GET16 (dlen, cp);#endif if (type != T_SRV) { cp += dlen; continue; }#if defined(__NetBSD__) || defined(__OpenBSD__) ||\defined(OLD_NAMESER) || defined(__FreeBSD__) pref = _get_short (cp); cp += sizeof (u_short);#elif defined(__APPLE_CC__) GETSHORT (pref, cp);#else NS_GET16 (pref, cp);#endif#if defined(__NetBSD__) || defined(__OpenBSD__) ||\defined(OLD_NAMESER) || defined(__FreeBSD__) weight = _get_short (cp); cp += sizeof (u_short);#elif defined(__APPLE_CC__) GETSHORT (weight, cp);#else NS_GET16 (weight, cp);#endif#if defined(__NetBSD__) || defined(__OpenBSD__) ||\defined(OLD_NAMESER) || defined(__FreeBSD__) port = _get_short (cp); cp += sizeof (u_short);#elif defined(__APPLE_CC__) GETSHORT (port, cp);#else NS_GET16 (port, cp);#endif n = dn_expand (msg, eom, cp, (char *) hostbuf, 256); if (n < 0) break; cp += n; srventry = &record->srventry[answerno]; snprintf(srventry->srv, sizeof(srventry->srv), "%s", hostbuf); srventry->priority = pref; srventry->weight = weight; if (weight) srventry->rweight = 1 + random () % (10000 * srventry->weight); else srventry->rweight = 0; srventry->port = port; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "SRV record %s IN SRV -> %s:%i/%i/%i/%i\n", zone, srventry->srv, srventry->port, srventry->priority, srventry->weight, srventry->rweight)); answerno++; } if (answerno == 0) return -1; snprintf(record->name, sizeof(record->name), "%s", domain); return 0;}#elseint_eXosip_get_srv_record (struct osip_srv_record *record, char *domain, char *protocol){ return -1;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?