static void ui_send_arbitrary_request() { char text[128]; char buf[128]; char *uri; input_result result; pj_str_t tmp; if (pjsua_acc_get_count() == 0) { puts("Sorry, need at least one account configured"); return; } puts("Send arbitrary request to remote host"); /* Input METHOD */ if (!simple_input("Request method:",text,sizeof(text))) return; /* Input destination URI */ uri = NULL; ui_input_url("Destination URI", buf, sizeof(buf), &result); if (result.nb_result != PJSUA_APP_NO_NB) { if (result.nb_result == -1) { puts("Sorry you can't do that!"); return; } else if (result.nb_result == 0) { uri = NULL; if (current_call == PJSUA_INVALID_ID) { puts("No current call"); return; } } else { pjsua_buddy_info binfo; pjsua_buddy_get_info(result.nb_result-1, &binfo); tmp.ptr = buf; pj_strncpy_with_null(&tmp, &binfo.uri, sizeof(buf)); uri = buf; } } else if (result.uri_result) { uri = result.uri_result; } else { return; } if (uri) { tmp = pj_str(uri); send_request(text, &tmp); } else { /* If you send call control request using this method * (such requests includes BYE, CANCEL, etc.), it will * not go well with the call state, so don't do it * unless it's for testing. */ pj_str_t method = pj_str(text); pjsua_call_send_request(current_call, &method, NULL); } }
/* * pjnath_strerror() */ static pj_str_t pjnath_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) if (statcode >= PJNATH_ERRNO_START && statcode < PJNATH_ERRNO_START + PJ_ERRNO_SPACE_SIZE) { /* Find the error in the table. * Use binary search! */ int first = 0; int n = PJ_ARRAY_SIZE(err_str); while (n > 0) { int half = n/2; int mid = first + half; if (err_str[mid].code < statcode) { first = mid+1; n -= (half+1); } else if (err_str[mid].code > statcode) { n = half; } else { first = mid; break; } } if (PJ_ARRAY_SIZE(err_str) && err_str[first].code == statcode) { pj_str_t msg; msg.ptr = (char*)err_str[first].msg; msg.slen = pj_ansi_strlen(err_str[first].msg); errstr.ptr = buf; pj_strncpy_with_null(&errstr, &msg, bufsize); return errstr; } } #endif /* PJ_HAS_ERROR_STRING */ /* Error not found. */ errstr.ptr = buf; errstr.slen = pj_ansi_snprintf(buf, bufsize, "Unknown pjnath error %d", statcode); if (errstr.slen < 0) errstr.slen = 0; else if (errstr.slen > (int)bufsize) errstr.slen = bufsize; return errstr; }
/* * pjmedia_videodev_strerror() */ PJ_DEF(pj_str_t) pjmedia_videodev_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) /* videodev error */ if (statcode >= PJMEDIA_VIDEODEV_ERRNO_START && statcode < PJMEDIA_VIDEODEV_ERRNO_END) { /* Find the error in the table. * Use binary search! */ int first = 0; int n = PJ_ARRAY_SIZE(err_str); while (n > 0) { int half = n/2; int mid = first + half; if (err_str[mid].code < statcode) { first = mid+1; n -= (half+1); } else if (err_str[mid].code > statcode) { n = half; } else { first = mid; break; } } if (PJ_ARRAY_SIZE(err_str) && err_str[first].code == statcode) { pj_str_t msg; msg.ptr = (char*)err_str[first].msg; msg.slen = pj_ansi_strlen(err_str[first].msg); errstr.ptr = buf; pj_strncpy_with_null(&errstr, &msg, bufsize); return errstr; } } #endif /* PJ_HAS_ERROR_STRING */ /* Error not found. */ errstr.ptr = buf; errstr.slen = pj_ansi_snprintf(buf, bufsize, "Unknown pjmedia-videodev error %d", statcode); return errstr; }
bool IpAddr::isValid(const std::string &address, pj_uint16_t family) { pj_str_t pjstring; pj_cstr(&pjstring, address.c_str()); pj_str_t ret_str; pj_uint16_t ret_port; int ret_family; auto status = pj_sockaddr_parse2(pj_AF_UNSPEC(), 0, &pjstring, &ret_str, &ret_port, &ret_family); if (status != PJ_SUCCESS || (family != pj_AF_UNSPEC() && ret_family != family)) return false; char buf[PJ_INET6_ADDRSTRLEN]; pj_str_t addr_with_null = {buf, 0}; pj_strncpy_with_null(&addr_with_null, &ret_str, sizeof(buf)); struct sockaddr sa; return inet_pton(ret_family==pj_AF_INET6()?AF_INET6:AF_INET, buf, &(sa.sa_data)) == 1; }
/* * 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
/* * pjmedia_strerror() */ PJ_DEF(pj_str_t) pjmedia_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 PortAudio. */ #if defined(PJMEDIA_SOUND_IMPLEMENTATION) && \ PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_PORTAUDIO_SOUND if (statcode >= PJMEDIA_PORTAUDIO_ERRNO_START && statcode <= PJMEDIA_PORTAUDIO_ERRNO_END) { //int pa_err = statcode - PJMEDIA_ERRNO_FROM_PORTAUDIO(0); int pa_err = PJMEDIA_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 */ #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) /* LIBSRTP error */ if (statcode >= PJMEDIA_LIBSRTP_ERRNO_START && statcode < PJMEDIA_LIBSRTP_ERRNO_END) { int err = statcode - PJMEDIA_LIBSRTP_ERRNO_START; pj_str_t msg; msg = pj_str((char*)get_libsrtp_errstr(err)); errstr.ptr = buf; pj_strncpy_with_null(&errstr, &msg, bufsize); return errstr; } else #endif /* PJMEDIA error */ if (statcode >= PJMEDIA_ERRNO_START && statcode < PJMEDIA_ERRNO_END) { /* Find the error in the table. * Use binary search! */ int first = 0; int n = PJ_ARRAY_SIZE(err_str); while (n > 0) { int half = n/2; int mid = first + half; if (err_str[mid].code < statcode) { first = mid+1; n -= (half+1); } else if (err_str[mid].code > statcode) { n = half; } else { first = mid; break; } } if (PJ_ARRAY_SIZE(err_str) && err_str[first].code == statcode) { pj_str_t msg; msg.ptr = (char*)err_str[first].msg; msg.slen = pj_ansi_strlen(err_str[first].msg); errstr.ptr = buf; pj_strncpy_with_null(&errstr, &msg, bufsize); return errstr; } } #endif /* PJ_HAS_ERROR_STRING */ /* Error not found. */ errstr.ptr = buf; errstr.slen = pj_ansi_snprintf(buf, bufsize, "Unknown pjmedia error %d", statcode); if (errstr.slen < 1 || errstr.slen >= (pj_ssize_t)bufsize) errstr.slen = bufsize - 1; return errstr; }
/* Resolve IPv4/IPv6 address */ PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename, unsigned *count, pj_addrinfo ai[]) { #if defined(PJ_SOCK_HAS_GETADDRINFO) && PJ_SOCK_HAS_GETADDRINFO!=0 char nodecopy[PJ_MAX_HOSTNAME]; struct addrinfo hint, *res, *orig_res; unsigned i; int rc; PJ_ASSERT_RETURN(nodename && count && *count && ai, PJ_EINVAL); PJ_ASSERT_RETURN(nodename->ptr && nodename->slen, PJ_EINVAL); PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC, PJ_EINVAL); /* Check if nodename is IP address */ pj_bzero(&ai[0], sizeof(ai[0])); if (af == PJ_AF_UNSPEC) { if (pj_inet_pton(PJ_AF_INET, nodename, &ai[0].ai_addr.ipv4.sin_addr) == PJ_SUCCESS) { af = PJ_AF_INET; } else if (pj_inet_pton(PJ_AF_INET6, nodename, &ai[0].ai_addr.ipv6.sin6_addr) == PJ_SUCCESS) { af = PJ_AF_INET6; } if (af != PJ_AF_UNSPEC) { pj_str_t tmp; tmp.ptr = ai[0].ai_canonname; pj_strncpy_with_null(&tmp, nodename, PJ_MAX_HOSTNAME); ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af; *count = 1; return PJ_SUCCESS; } } /* Copy node name to null terminated string. */ if (nodename->slen >= PJ_MAX_HOSTNAME) return PJ_ENAMETOOLONG; pj_memcpy(nodecopy, nodename->ptr, nodename->slen); nodecopy[nodename->slen] = '\0'; /* Call getaddrinfo() */ pj_bzero(&hint, sizeof(hint)); hint.ai_family = af; rc = getaddrinfo(nodecopy, NULL, &hint, &res); if (rc != 0) return PJ_ERESOLVE; orig_res = res; /* Enumerate each item in the result */ for (i=0; i<*count && res; res=res->ai_next) { /* Ignore unwanted address families */ if (af!=PJ_AF_UNSPEC && res->ai_family != af) continue; /* Store canonical name (possibly truncating the name) */ if (res->ai_canonname) { pj_ansi_strncpy(ai[i].ai_canonname, res->ai_canonname, sizeof(ai[i].ai_canonname)); ai[i].ai_canonname[sizeof(ai[i].ai_canonname)-1] = '\0'; } else { pj_ansi_strcpy(ai[i].ai_canonname, nodecopy); } /* Store address */ PJ_ASSERT_ON_FAIL(res->ai_addrlen <= sizeof(pj_sockaddr), continue); pj_memcpy(&ai[i].ai_addr, res->ai_addr, res->ai_addrlen); PJ_SOCKADDR_RESET_LEN(&ai[i].ai_addr); /* Next slot */ ++i; } *count = i; freeaddrinfo(orig_res); /* Done */ return PJ_SUCCESS; #else /* PJ_SOCK_HAS_GETADDRINFO */ PJ_ASSERT_RETURN(count && *count, PJ_EINVAL); /* Check if nodename is IP address */ pj_bzero(&ai[0], sizeof(ai[0])); if (af == PJ_AF_UNSPEC) { if (pj_inet_pton(PJ_AF_INET, nodename, &ai[0].ai_addr.ipv4.sin_addr) == PJ_SUCCESS) { af = PJ_AF_INET; } else if (pj_inet_pton(PJ_AF_INET6, nodename, &ai[0].ai_addr.ipv6.sin6_addr) == PJ_SUCCESS) { af = PJ_AF_INET6; } if (af != PJ_AF_UNSPEC) { pj_str_t tmp; tmp.ptr = ai[0].ai_canonname; pj_strncpy_with_null(&tmp, nodename, PJ_MAX_HOSTNAME); ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af; *count = 1; return PJ_SUCCESS; } } if (af == PJ_AF_INET || af == PJ_AF_UNSPEC) { pj_hostent he; unsigned i, max_count; pj_status_t status; /* VC6 complains that "he" is uninitialized */ #ifdef _MSC_VER pj_bzero(&he, sizeof(he)); #endif status = pj_gethostbyname(nodename, &he); if (status != PJ_SUCCESS) return status; max_count = *count; *count = 0; pj_bzero(ai, max_count * sizeof(pj_addrinfo)); for (i=0; he.h_addr_list[i] && *count<max_count; ++i) { pj_ansi_strncpy(ai[*count].ai_canonname, he.h_name, sizeof(ai[*count].ai_canonname)); ai[*count].ai_canonname[sizeof(ai[*count].ai_canonname)-1] = '\0'; ai[*count].ai_addr.ipv4.sin_family = PJ_AF_INET; pj_memcpy(&ai[*count].ai_addr.ipv4.sin_addr, he.h_addr_list[i], he.h_length); PJ_SOCKADDR_RESET_LEN(&ai[*count].ai_addr); (*count)++; } return PJ_SUCCESS; } else { /* IPv6 is not supported */ *count = 0; return PJ_EIPV6NOTSUP; } #endif /* PJ_SOCK_HAS_GETADDRINFO */ }
/* * pjsip_strerror() */ PJ_DEF(pj_str_t) pjsip_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) if (statcode >= PJSIP_ERRNO_START && statcode < PJSIP_ERRNO_START+800) { /* Status code. */ const pj_str_t *status_text = pjsip_get_status_text(PJSIP_ERRNO_TO_SIP_STATUS(statcode)); errstr.ptr = buf; pj_strncpy_with_null(&errstr, status_text, bufsize); return errstr; } else if (statcode >= PJSIP_ERRNO_START_PJSIP && statcode < PJSIP_ERRNO_START_PJSIP + 1000) { /* Find the error in the table. * Use binary search! */ int first = 0; int n = PJ_ARRAY_SIZE(err_str); while (n > 0) { int half = n/2; int mid = first + half; if (err_str[mid].code < statcode) { first = mid+1; n -= (half+1); } else if (err_str[mid].code > statcode) { n = half; } else { first = mid; break; } } if (PJ_ARRAY_SIZE(err_str) && err_str[first].code == statcode) { pj_str_t msg; msg.ptr = (char*)err_str[first].msg; msg.slen = pj_ansi_strlen(err_str[first].msg); errstr.ptr = buf; pj_strncpy_with_null(&errstr, &msg, bufsize); return errstr; } } #endif /* PJ_HAS_ERROR_STRING */ /* Error not found. */ errstr.ptr = buf; errstr.slen = pj_ansi_snprintf(buf, bufsize, "Unknown pjsip error %d", statcode); return errstr; }
/* Resolve IPv4/IPv6 address */ PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename, unsigned *count, pj_addrinfo ai[]) { #if defined(PJ_SOCK_HAS_GETADDRINFO) && PJ_SOCK_HAS_GETADDRINFO!=0 char nodecopy[PJ_MAX_HOSTNAME]; pj_bool_t has_addr = PJ_FALSE; unsigned i; #if defined(PJ_GETADDRINFO_USE_CFHOST) && PJ_GETADDRINFO_USE_CFHOST!=0 CFStringRef hostname; CFHostRef hostRef; pj_status_t status = PJ_SUCCESS; #else int rc; struct addrinfo hint, *res, *orig_res; #endif PJ_ASSERT_RETURN(nodename && count && *count && ai, PJ_EINVAL); PJ_ASSERT_RETURN(nodename->ptr && nodename->slen, PJ_EINVAL); PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC, PJ_EINVAL); /* Check if nodename is IP address */ pj_bzero(&ai[0], sizeof(ai[0])); if ((af==PJ_AF_INET || af==PJ_AF_UNSPEC) && pj_inet_pton(PJ_AF_INET, nodename, &ai[0].ai_addr.ipv4.sin_addr) == PJ_SUCCESS) { af = PJ_AF_INET; has_addr = PJ_TRUE; } else if ((af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) && pj_inet_pton(PJ_AF_INET6, nodename, &ai[0].ai_addr.ipv6.sin6_addr) == PJ_SUCCESS) { af = PJ_AF_INET6; has_addr = PJ_TRUE; } if (has_addr) { pj_str_t tmp; tmp.ptr = ai[0].ai_canonname; pj_strncpy_with_null(&tmp, nodename, PJ_MAX_HOSTNAME); ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af; *count = 1; return PJ_SUCCESS; } /* Copy node name to null terminated string. */ if (nodename->slen >= PJ_MAX_HOSTNAME) return PJ_ENAMETOOLONG; pj_memcpy(nodecopy, nodename->ptr, nodename->slen); nodecopy[nodename->slen] = '\0'; #if defined(PJ_GETADDRINFO_USE_CFHOST) && PJ_GETADDRINFO_USE_CFHOST!=0 hostname = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, nodecopy, kCFStringEncodingASCII, kCFAllocatorNull); hostRef = CFHostCreateWithName(kCFAllocatorDefault, hostname); if (CFHostStartInfoResolution(hostRef, kCFHostAddresses, nil)) { CFArrayRef addrRef = CFHostGetAddressing(hostRef, nil); i = 0; if (addrRef != nil) { CFIndex idx, naddr; naddr = CFArrayGetCount(addrRef); for (idx = 0; idx < naddr && i < *count; idx++) { struct sockaddr *addr; addr = (struct sockaddr *) CFDataGetBytePtr(CFArrayGetValueAtIndex(addrRef, idx)); /* This should not happen. */ pj_assert(addr); /* Ignore unwanted address families */ if (af!=PJ_AF_UNSPEC && addr->sa_family != af) continue; /* Store canonical name */ pj_ansi_strcpy(ai[i].ai_canonname, nodecopy); /* Store address */ PJ_ASSERT_ON_FAIL(sizeof(*addr) <= sizeof(pj_sockaddr), continue); pj_memcpy(&ai[i].ai_addr, addr, sizeof(*addr)); PJ_SOCKADDR_RESET_LEN(&ai[i].ai_addr); i++; } } *count = i; } else {
static void ui_send_instant_message() { char *uri = NULL; /* i is for call index to send message, if any */ int i = -1; input_result result; char buf[128]; char text[128]; pj_str_t tmp; /* Input destination. */ ui_input_url("Send IM to", buf, sizeof(buf), &result); if (result.nb_result != PJSUA_APP_NO_NB) { if (result.nb_result == -1) { puts("You can't send broadcast IM like that!"); return; } else if (result.nb_result == 0) { i = current_call; } else { pjsua_buddy_info binfo; pjsua_buddy_get_info(result.nb_result-1, &binfo); tmp.ptr = buf; pj_strncpy_with_null(&tmp, &binfo.uri, sizeof(buf)); uri = buf; } } else if (result.uri_result) { uri = result.uri_result; } /* Send typing indication. */ if (i != -1) pjsua_call_send_typing_ind(i, PJ_TRUE, NULL); else { pj_str_t tmp_uri = pj_str(uri); pjsua_im_typing(current_acc, &tmp_uri, PJ_TRUE, NULL); } /* Input the IM . */ if (!simple_input("Message", text, sizeof(text))) { /* * Cancelled. * Send typing notification too, saying we're not typing. */ if (i != -1) pjsua_call_send_typing_ind(i, PJ_FALSE, NULL); else { pj_str_t tmp_uri = pj_str(uri); pjsua_im_typing(current_acc, &tmp_uri, PJ_FALSE, NULL); } return; } tmp = pj_str(text); /* Send the IM */ if (i != -1) pjsua_call_send_im(i, NULL, &tmp, NULL, NULL); else { pj_str_t tmp_uri = pj_str(uri); pjsua_im_send(current_acc, &tmp_uri, NULL, &tmp, NULL, NULL); } }