/*! * \internal * \brief Implements PJSIP_HEADER 'update' by finding the specified header and updating it. * * Retrieve the header_datastore from the session or create one if it doesn't exist. * Create and initialize the list if needed. * Create the pj_strs for name and value. * Create pjsip_msg and hdr_list_entry. * Add the entry to the list. */ static int update_header(void *obj) { struct header_data *data = obj; pjsip_hdr *hdr = NULL; RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(data->channel->session, header_datastore.type), ao2_cleanup); if (!datastore || !datastore->data) { ast_log(AST_LOG_ERROR, "No headers had been previously added to this session.\n"); return -1; } hdr = find_header((struct hdr_list *) datastore->data, data->header_name, data->header_number); if (!hdr) { ast_log(AST_LOG_ERROR, "There was no header named %s.\n", data->header_name); return -1; } pj_strcpy2(&((pjsip_generic_string_hdr *) hdr)->hvalue, data->header_value); return 0; }
static int xpidf_generate_body_content(void *body, void *data) { pjxpidf_pres *pres = body; struct ast_sip_exten_state_data *state_data = data; static pj_str_t STR_ADDR_PARAM = { ";user=ip", 8 }; char *statestring = NULL, *pidfstate = NULL, *pidfnote = NULL; pj_xml_attr *attr; enum ast_sip_pidf_state local_state; pj_str_t uri; char sanitized[PJSIP_MAX_URL_SIZE]; pj_xml_node *atom; pj_xml_node *address; pj_xml_node *status; pj_xml_node *msnsubstatus; ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring, &pidfstate, &pidfnote, &local_state); ast_sip_presence_xml_find_node_attr(state_data->pool, pres, "atom", "id", &atom, &attr); pj_strdup2(state_data->pool, &attr->value, state_data->exten); ast_sip_presence_xml_find_node_attr(state_data->pool, atom, "address", "uri", &address, &attr); ast_sip_sanitize_xml(state_data->remote, sanitized, sizeof(sanitized)); uri.ptr = (char*) pj_pool_alloc(state_data->pool, strlen(sanitized) + STR_ADDR_PARAM.slen); pj_strcpy2( &uri, sanitized); pj_strcat( &uri, &STR_ADDR_PARAM); pj_strdup(state_data->pool, &attr->value, &uri); ast_sip_presence_xml_create_attr(state_data->pool, address, "priority", "0.80000"); ast_sip_presence_xml_find_node_attr(state_data->pool, address, "status", "status", &status, &attr); pj_strdup2(state_data->pool, &attr->value, (local_state == NOTIFY_OPEN) ? "open" : (local_state == NOTIFY_INUSE) ? "inuse" : "closed"); ast_sip_presence_xml_find_node_attr(state_data->pool, address, "msnsubstatus", "substatus", &msnsubstatus, &attr); pj_strdup2(state_data->pool, &attr->value, (local_state == NOTIFY_OPEN) ? "online" : (local_state == NOTIFY_INUSE) ? "onthephone" : "offline"); return 0; }
/* * pjmedia_audiodev_strerror() */ PJ_DEF(pj_str_t) pjmedia_audiodev_strerror(pj_status_t statcode, char *buf, pj_size_t bufsize ) { pj_str_t errstr; #if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0) /* See if the error comes from Core Audio. */ #if PJMEDIA_AUDIO_DEV_HAS_COREAUDIO if (statcode >= PJMEDIA_AUDIODEV_COREAUDIO_ERRNO_START && statcode <= PJMEDIA_AUDIODEV_COREAUDIO_ERRNO_END) { int ca_err = PJMEDIA_AUDIODEV_COREAUDIO_ERRNO_START - statcode; PJ_UNUSED_ARG(ca_err); // TODO: create more helpful error messages errstr.ptr = buf; pj_strcpy2(&errstr, "Core audio error"); return errstr; } else #endif /* See if the error comes from PortAudio. */ #if PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO if (statcode >= PJMEDIA_AUDIODEV_PORTAUDIO_ERRNO_START && statcode <= PJMEDIA_AUDIODEV_PORTAUDIO_ERRNO_END) { //int pa_err = statcode - PJMEDIA_ERRNO_FROM_PORTAUDIO(0); int pa_err = PJMEDIA_AUDIODEV_PORTAUDIO_ERRNO_START - statcode; pj_str_t msg; msg.ptr = (char*)Pa_GetErrorText(pa_err); msg.slen = pj_ansi_strlen(msg.ptr); errstr.ptr = buf; pj_strncpy_with_null(&errstr, &msg, bufsize); return errstr; } else #endif /* PJMEDIA_SOUND_IMPLEMENTATION */ /* See if the error comes from WMME */ #if PJMEDIA_AUDIO_DEV_HAS_WMME if ((statcode >= PJMEDIA_AUDIODEV_WMME_IN_ERROR_START && statcode < PJMEDIA_AUDIODEV_WMME_IN_ERROR_END) || (statcode >= PJMEDIA_AUDIODEV_WMME_OUT_ERROR_START && statcode < PJMEDIA_AUDIODEV_WMME_OUT_ERROR_END)) { MMRESULT native_err, mr; MMRESULT (WINAPI *waveGetErrText)(UINT mmrError, LPTSTR pszText, UINT cchText); PJ_DECL_UNICODE_TEMP_BUF(wbuf, 80) if (statcode >= PJMEDIA_AUDIODEV_WMME_IN_ERROR_START && statcode <= PJMEDIA_AUDIODEV_WMME_IN_ERROR_END) { native_err = statcode - PJMEDIA_AUDIODEV_WMME_IN_ERROR_START; waveGetErrText = &waveInGetErrorText; } else { native_err = statcode - PJMEDIA_AUDIODEV_WMME_OUT_ERROR_START; waveGetErrText = &waveOutGetErrorText; } #if PJ_NATIVE_STRING_IS_UNICODE mr = (*waveGetErrText)(native_err, wbuf, PJ_ARRAY_SIZE(wbuf)); if (mr == MMSYSERR_NOERROR) { int len = wcslen(wbuf); pj_unicode_to_ansi(wbuf, len, buf, bufsize); } #else mr = (*waveGetErrText)(native_err, buf, (UINT)bufsize); #endif if (mr==MMSYSERR_NOERROR) { errstr.ptr = buf; errstr.slen = pj_ansi_strlen(buf); return errstr; } else { pj_ansi_snprintf(buf, bufsize, "MMSYSTEM native error %d", native_err); return pj_str(buf); } } else
/* Generate transport's published address */ static pj_status_t get_published_name(pj_sock_t sock, char hostbuf[], int hostbufsz, pjsip_host_port *bound_name) { pj_sockaddr tmp_addr; int addr_len; pj_status_t status; addr_len = sizeof(tmp_addr); status = pj_sock_getsockname(sock, &tmp_addr, &addr_len); if (status != PJ_SUCCESS) return status; bound_name->host.ptr = hostbuf; if (tmp_addr.addr.sa_family == pj_AF_INET()) { bound_name->port = pj_ntohs(tmp_addr.ipv4.sin_port); /* If bound address specifies "0.0.0.0", get the IP address * of local hostname. */ if (tmp_addr.ipv4.sin_addr.s_addr == PJ_INADDR_ANY) { pj_sockaddr hostip; status = pj_gethostip(pj_AF_INET(), &hostip); if (status != PJ_SUCCESS) return status; pj_strcpy2(&bound_name->host, pj_inet_ntoa(hostip.ipv4.sin_addr)); } else { /* Otherwise use bound address. */ pj_strcpy2(&bound_name->host, pj_inet_ntoa(tmp_addr.ipv4.sin_addr)); status = PJ_SUCCESS; } } else { /* If bound address specifies "INADDR_ANY" (IPv6), get the * IP address of local hostname */ pj_uint32_t loop6[4] = { 0, 0, 0, 0}; bound_name->port = pj_ntohs(tmp_addr.ipv6.sin6_port); if (pj_memcmp(&tmp_addr.ipv6.sin6_addr, loop6, sizeof(loop6))==0) { status = pj_gethostip(tmp_addr.addr.sa_family, &tmp_addr); if (status != PJ_SUCCESS) return status; } status = pj_inet_ntop(tmp_addr.addr.sa_family, pj_sockaddr_get_addr(&tmp_addr), hostbuf, hostbufsz); if (status == PJ_SUCCESS) { bound_name->host.slen = pj_ansi_strlen(hostbuf); } } return status; }
// // Copy the contents of other string. // void strcpy(const char *s) { pj_strcpy2(this, s); }
static void add_dns_entries(pj_dns_resolver *resv) { /* Inject DNS SRV entry */ pj_dns_parsed_packet pkt; pj_dns_parsed_query q; pj_dns_parsed_rr ans[4]; pj_dns_parsed_rr ar[5]; pj_str_t tmp; unsigned i; /* * This is answer to SRV query to "example.com" domain, and * the answer contains full reference to the A records of * the server. The full DNS records is : _sip._udp.example.com 3600 IN SRV 0 0 5060 sip01.example.com. _sip._udp.example.com 3600 IN SRV 0 20 5060 sip02.example.com. _sip._udp.example.com 3600 IN SRV 0 10 5060 sip03.example.com. _sip._udp.example.com 3600 IN SRV 1 0 5060 sip04.example.com. sip01.example.com. 3600 IN A 1.1.1.1 sip02.example.com. 3600 IN A 2.2.2.2 sip03.example.com. 3600 IN A 3.3.3.3 sip04.example.com. 3600 IN A 4.4.4.4 ; Additionally, add A record for "example.com" example.com. 3600 IN A 5.5.5.5 */ pj_bzero(&pkt, sizeof(pkt)); pj_bzero(ans, sizeof(ans)); pj_bzero(ar, sizeof(ar)); pkt.hdr.flags = PJ_DNS_SET_QR(1); pkt.hdr.anscount = PJ_ARRAY_SIZE(ans); pkt.hdr.arcount = 0; pkt.ans = ans; pkt.arr = ar; ans[0].name = pj_str("_sip._udp.example.com"); ans[0].type = PJ_DNS_TYPE_SRV; ans[0].dnsclass = PJ_DNS_CLASS_IN; ans[0].ttl = 3600; ans[0].rdata.srv.prio = 0; ans[0].rdata.srv.weight = 0; ans[0].rdata.srv.port = 5060; ans[0].rdata.srv.target = pj_str("sip01.example.com"); ans[1].name = pj_str("_sip._udp.example.com"); ans[1].type = PJ_DNS_TYPE_SRV; ans[1].dnsclass = PJ_DNS_CLASS_IN; ans[1].ttl = 3600; ans[1].rdata.srv.prio = 0; ans[1].rdata.srv.weight = 20; ans[1].rdata.srv.port = 5060; ans[1].rdata.srv.target = pj_str("sip02.example.com"); ans[2].name = pj_str("_sip._udp.example.com"); ans[2].type = PJ_DNS_TYPE_SRV; ans[2].dnsclass = PJ_DNS_CLASS_IN; ans[2].ttl = 3600; ans[2].rdata.srv.prio = 0; ans[2].rdata.srv.weight = 10; ans[2].rdata.srv.port = 5060; ans[2].rdata.srv.target = pj_str("sip03.example.com"); ans[3].name = pj_str("_sip._udp.example.com"); ans[3].type = PJ_DNS_TYPE_SRV; ans[3].dnsclass = PJ_DNS_CLASS_IN; ans[3].ttl = 3600; ans[3].rdata.srv.prio = 1; ans[3].rdata.srv.weight = 0; ans[3].rdata.srv.port = 5060; ans[3].rdata.srv.target = pj_str("sip04.example.com"); pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE); ar[0].name = pj_str("sip01.example.com"); ar[0].type = PJ_DNS_TYPE_A; ar[0].dnsclass = PJ_DNS_CLASS_IN; ar[0].ttl = 3600; ar[0].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "1.1.1.1")); ar[1].name = pj_str("sip02.example.com"); ar[1].type = PJ_DNS_TYPE_A; ar[1].dnsclass = PJ_DNS_CLASS_IN; ar[1].ttl = 3600; ar[1].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "2.2.2.2")); ar[2].name = pj_str("sip03.example.com"); ar[2].type = PJ_DNS_TYPE_A; ar[2].dnsclass = PJ_DNS_CLASS_IN; ar[2].ttl = 3600; ar[2].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "3.3.3.3")); ar[3].name = pj_str("sip04.example.com"); ar[3].type = PJ_DNS_TYPE_A; ar[3].dnsclass = PJ_DNS_CLASS_IN; ar[3].ttl = 3600; ar[3].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "4.4.4.4")); ar[4].name = pj_str("example.com"); ar[4].type = PJ_DNS_TYPE_A; ar[4].dnsclass = PJ_DNS_CLASS_IN; ar[4].ttl = 3600; ar[4].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "5.5.5.5")); /* * Create individual A records for all hosts in "example.com" domain. */ for (i=0; i<PJ_ARRAY_SIZE(ar); ++i) { pj_bzero(&pkt, sizeof(pkt)); pkt.hdr.flags = PJ_DNS_SET_QR(1); pkt.hdr.qdcount = 1; pkt.q = &q; q.name = ar[i].name; q.type = ar[i].type; q.dnsclass = PJ_DNS_CLASS_IN; pkt.hdr.anscount = 1; pkt.ans = &ar[i]; pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE); } /* * Simulate DNS error response by creating these answers. * Sample of invalid SRV records: _sip._udp.sip01.example.com. */ for (i=0; i<PJ_ARRAY_SIZE(ans); ++i) { pj_dns_parsed_query q; char buf[128]; char *services[] = { "_sip._udp.", "_sip._tcp.", "_sips._tcp."}; unsigned j; for (j=0; j<PJ_ARRAY_SIZE(services); ++j) { q.dnsclass = PJ_DNS_CLASS_IN; q.type = PJ_DNS_TYPE_SRV; q.name.ptr = buf; pj_bzero(buf, sizeof(buf)); pj_strcpy2(&q.name, services[j]); pj_strcat(&q.name, &ans[i].rdata.srv.target); pj_bzero(&pkt, sizeof(pkt)); pkt.hdr.qdcount = 1; pkt.hdr.flags = PJ_DNS_SET_QR(1) | PJ_DNS_SET_RCODE(PJ_DNS_RCODE_NXDOMAIN); pkt.q = &q; pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE); } } /* * ANOTHER DOMAIN. * * This time we let SRV and A get answered in different DNS * query. */ /* The "domain.com" DNS records (note the different the port): _sip._tcp.domain.com 3600 IN SRV 1 0 50060 sip06.domain.com. _sip._tcp.domain.com 3600 IN SRV 2 0 50060 sip07.domain.com. sip06.domain.com. 3600 IN A 6.6.6.6 sip07.domain.com. 3600 IN A 7.7.7.7 */ pj_bzero(&pkt, sizeof(pkt)); pj_bzero(&ans, sizeof(ans)); pkt.hdr.flags = PJ_DNS_SET_QR(1); pkt.hdr.anscount = 2; pkt.ans = ans; /* Add the SRV records, with reverse priority (to test that sorting * works. */ ans[0].name = pj_str("_sip._tcp.domain.com"); ans[0].type = PJ_DNS_TYPE_SRV; ans[0].dnsclass = PJ_DNS_CLASS_IN; ans[0].ttl = 3600; ans[0].rdata.srv.prio = 2; ans[0].rdata.srv.weight = 0; ans[0].rdata.srv.port = 50060; ans[0].rdata.srv.target = pj_str("SIP07.DOMAIN.COM"); ans[1].name = pj_str("_sip._tcp.domain.com"); ans[1].type = PJ_DNS_TYPE_SRV; ans[1].dnsclass = PJ_DNS_CLASS_IN; ans[1].ttl = 3600; ans[1].rdata.srv.prio = 1; ans[1].rdata.srv.weight = 0; ans[1].rdata.srv.port = 50060; ans[1].rdata.srv.target = pj_str("SIP06.DOMAIN.COM"); pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE); /* From herein there is only one answer */ pkt.hdr.anscount = 1; /* Add a single SRV for UDP */ ans[0].name = pj_str("_sip._udp.domain.com"); ans[0].type = PJ_DNS_TYPE_SRV; ans[0].dnsclass = PJ_DNS_CLASS_IN; ans[0].ttl = 3600; ans[0].rdata.srv.prio = 0; ans[0].rdata.srv.weight = 0; ans[0].rdata.srv.port = 50060; ans[0].rdata.srv.target = pj_str("SIP06.DOMAIN.COM"); pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE); /* Add the A record for sip06.domain.com */ ans[0].name = pj_str("sip06.domain.com"); ans[0].type = PJ_DNS_TYPE_A; ans[0].dnsclass = PJ_DNS_CLASS_IN; ans[0].ttl = 3600; ans[0].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "6.6.6.6")); pkt.hdr.qdcount = 1; pkt.q = &q; q.name = ans[0].name; q.type = ans[0].type; q.dnsclass = ans[0].dnsclass; pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE); /* Add the A record for sip07.domain.com */ ans[0].name = pj_str("sip07.domain.com"); ans[0].type = PJ_DNS_TYPE_A; ans[0].dnsclass = PJ_DNS_CLASS_IN; ans[0].ttl = 3600; ans[0].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "7.7.7.7")); pkt.hdr.qdcount = 1; pkt.q = &q; q.name = ans[0].name; q.type = ans[0].type; q.dnsclass = ans[0].dnsclass; pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE); pkt.hdr.qdcount = 0; }