enum gui_key gui_msgbox(const char *title, const char *message, enum gui_flag flag) { wchar_t buf_title[64]; wchar_t buf_msg[512]; UINT wflag = 0; int retcode; pj_ansi_to_unicode(title, pj_ansi_strlen(title), buf_title, 64); pj_ansi_to_unicode(message, pj_ansi_strlen(message), buf_msg, 512); switch (flag) { case WITH_OK: wflag = MB_OK; break; case WITH_YESNO: wflag = MB_YESNO; break; case WITH_OKCANCEL: wflag = MB_OKCANCEL; break; } retcode = MessageBox(g_hWndMain, buf_msg, buf_title, wflag); switch (retcode) { case IDOK: return KEY_OK; case IDYES: return KEY_YES; case IDNO: return KEY_NO; default: return KEY_CANCEL; } }
static void on_read_complete(pj_ioqueue_key_t *key, pj_ioqueue_op_key_t *op_key, pj_ssize_t bytes_read) { pj_ssize_t size; char *sendbuf = "Hello world"; pj_status_t status; if (sock_data.unregistered) return; pj_mutex_lock(sock_data.mutex); if (sock_data.unregistered) { pj_mutex_unlock(sock_data.mutex); return; } if (bytes_read < 0) { if (-bytes_read != PJ_STATUS_FROM_OS(PJ_BLOCKING_ERROR_VAL)) app_perror("ioqueue reported recv error", -bytes_read); } else { sock_data.received += bytes_read; } if (test_method == UNREGISTER_IN_CALLBACK) { pj_time_val now; pj_gettimeofday(&now); if (PJ_TIME_VAL_GTE(now, time_to_unregister)) { sock_data.unregistered = 1; pj_ioqueue_unregister(key); pj_mutex_destroy(sock_data.mutex); pj_pool_release(sock_data.pool); sock_data.pool = NULL; return; } } do { size = sock_data.bufsize; status = pj_ioqueue_recv(key, op_key, sock_data.buffer, &size, 0); if (status != PJ_EPENDING && status != PJ_SUCCESS) app_perror("recv() error", status); } while (status == PJ_SUCCESS); pj_mutex_unlock(sock_data.mutex); size = pj_ansi_strlen(sendbuf); status = pj_sock_send(sock_data.csock, sendbuf, &size, 0); if (status != PJ_SUCCESS) app_perror("send() error", status); size = pj_ansi_strlen(sendbuf); status = pj_sock_send(sock_data.csock, sendbuf, &size, 0); if (status != PJ_SUCCESS) app_perror("send() error", status); }
/* generate submenu and register the menu handler, then return next menu id */ static UINT generate_submenu(HMENU parent, UINT id_start, gui_menu *menu) { unsigned i; UINT id = id_start; if (!menu) return id; /* generate submenu */ for (i = 0; i < menu->submenu_cnt; ++i) { if (menu->submenus[i] == NULL) { /* add separator */ AppendMenu(parent, MF_SEPARATOR, 0, 0); } else if (menu->submenus[i]->submenu_cnt != 0) { /* this submenu item has children, generate popup menu */ HMENU hMenu; wchar_t buf[64]; pj_ansi_to_unicode(menu->submenus[i]->title, pj_ansi_strlen(menu->submenus[i]->title), buf, 64); hMenu = CreatePopupMenu(); AppendMenu(parent, MF_STRING|MF_ENABLED|MF_POPUP, (UINT)hMenu, buf); id = generate_submenu(hMenu, id, menu->submenus[i]); } else { /* this submenu item is leaf, register the handler */ wchar_t buf[64]; pj_ansi_to_unicode(menu->submenus[i]->title, pj_ansi_strlen(menu->submenus[i]->title), buf, 64); AppendMenu(parent, MF_STRING, id, buf); if (menu->submenus[i]->handler) { g_menu_handlers[g_menu_handler_cnt].id = id; g_menu_handlers[g_menu_handler_cnt].handler = menu->submenus[i]->handler; ++g_menu_handler_cnt; } ++id; } } return id; }
/** * Callback upon NAT detection completion */ static void nat_detect_cb (const pj_stun_nat_detect_result *res) { if (res->status != PJ_SUCCESS) { char msg[250]; pj_ansi_snprintf (msg, sizeof (msg), "NAT detection failed: %s", res->status_text); SetCallStatus (msg, pj_ansi_strlen (msg)); } else { char msg[250]; pj_ansi_snprintf (msg, sizeof (msg), "NAT type is %s", res->nat_type_name); SetCallStatus (msg, pj_ansi_strlen (msg)); } }
static void ffmpeg_log_cb(void* ptr, int level, const char* fmt, va_list vl) { const char *LOG_SENDER = "ffmpeg"; enum { LOG_LEVEL = 5 }; char buf[100]; int bufsize = sizeof(buf), len; pj_str_t fmt_st; /* Custom callback needs to filter log level by itself */ if (level > av_log_get_level()) return; /* Add original ffmpeg sender to log format */ if (ptr) { AVClass* avc = *(AVClass**)ptr; len = pj_ansi_snprintf(buf, bufsize, "%s: ", avc->item_name(ptr)); bufsize -= len; } /* Copy original log format */ len = pj_ansi_strlen(fmt); if (len > bufsize-1) len = bufsize-1; pj_memcpy(buf+sizeof(buf)-bufsize, fmt, len); bufsize -= len; /* Trim log format */ pj_strset(&fmt_st, buf, sizeof(buf)-bufsize); pj_strrtrim(&fmt_st); buf[fmt_st.slen] = '\0'; pj_log(LOG_SENDER, LOG_LEVEL, buf, vl); }
/* * Register new transport type to PJSIP. */ PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag, const char *tp_name, int def_port, int *p_tp_type) { unsigned i; PJ_ASSERT_RETURN(tp_flag && tp_name && def_port, PJ_EINVAL); PJ_ASSERT_RETURN(pj_ansi_strlen(tp_name) < PJ_ARRAY_SIZE(transport_names[0].name_buf), PJ_ENAMETOOLONG); for (i=1; i<PJ_ARRAY_SIZE(transport_names); ++i) { if (transport_names[i].type == 0) break; } if (i == PJ_ARRAY_SIZE(transport_names)) return PJ_ETOOMANY; transport_names[i].type = (pjsip_transport_type_e)i; transport_names[i].port = (pj_uint16_t)def_port; pj_ansi_strcpy(transport_names[i].name_buf, tp_name); transport_names[i].name = pj_str(transport_names[i].name_buf); transport_names[i].flag = tp_flag; if (p_tp_type) *p_tp_type = i; return PJ_SUCCESS; }
PJ_DEF(unsigned) pjmedia_sdp_attr_remove_all(unsigned *count, pjmedia_sdp_attr *attr_array[], const char *name) { unsigned i, removed = 0; pj_str_t attr_name; PJ_ASSERT_RETURN(count && attr_array && name, PJ_EINVAL); attr_name.ptr = (char*)name; attr_name.slen = pj_ansi_strlen(name); for (i=0; i<*count; ) { if (pj_strcmp(&attr_array[i]->name, &attr_name)==0) { pj_array_erase(attr_array, sizeof(pjmedia_sdp_attr*), *count, i); --(*count); ++removed; } else { ++i; } } return removed; }
/* * 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; }
static void SetCallStatus (const char *state, int len) { wchar_t tmp[128]; if (len==-1) len=pj_ansi_strlen (state); pj_ansi_to_unicode (state, len, tmp, PJ_ARRAY_SIZE (tmp)); SetDlgItemText (hMainWnd, ID_CALL_STATUS, tmp); }
static void sockaddr_to_host_port( pj_pool_t *pool, pjsip_host_port *host_port, const pj_sockaddr_in *addr ) { host_port->host.ptr = (char*) pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN+4); pj_sockaddr_print(addr, host_port->host.ptr, PJ_INET6_ADDRSTRLEN+4, 2); host_port->host.slen = pj_ansi_strlen(host_port->host.ptr); host_port->port = pj_sockaddr_get_port(addr); }
static void SetURI (const char *uri, int len, bool enabled=true) { wchar_t tmp[128]; if (len==-1) len=pj_ansi_strlen (uri); pj_ansi_to_unicode (uri, len, tmp, PJ_ARRAY_SIZE (tmp)); SetDlgItemText (hMainWnd, ID_URI, tmp); EnableWindow (hwndURI, enabled?TRUE:FALSE); }
/* * 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; }
pjmedia_sdp_attr_find2(unsigned count, pjmedia_sdp_attr *const attr_array[], const char *c_name, const pj_str_t *c_fmt) { pj_str_t name; name.ptr = (char*)c_name; name.slen = pj_ansi_strlen(c_name); return pjmedia_sdp_attr_find(count, attr_array, &name, c_fmt); }
/* * Convert text to IPv4/IPv6 address. */ PJ_DEF(pj_status_t) pj_inet_pton(int af, const pj_str_t *src, void *dst) { char tempaddr[PJ_INET6_ADDRSTRLEN]; PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL); PJ_ASSERT_RETURN(src && src->slen && dst, PJ_EINVAL); /* Initialize output with PJ_IN_ADDR_NONE for IPv4 (to be * compatible with pj_inet_aton() */ if (af==PJ_AF_INET) { ((pj_in_addr*)dst)->s_addr = PJ_INADDR_NONE; } /* Caution: * this function might be called with cp->slen >= 46 * (i.e. when called with hostname to check if it's an IP addr). */ if (src->slen >= PJ_INET6_ADDRSTRLEN) { return PJ_ENAMETOOLONG; } pj_memcpy(tempaddr, src->ptr, src->slen); tempaddr[src->slen] = '\0'; wchar_t tempaddr16[PJ_INET6_ADDRSTRLEN]; pj_ansi_to_unicode(tempaddr, pj_ansi_strlen(tempaddr), tempaddr16, sizeof(tempaddr16)); TBuf<PJ_INET6_ADDRSTRLEN> ip_addr((const TText*)tempaddr16); TInetAddr addr; addr.Init(KAfInet6); if (addr.Input(ip_addr) == KErrNone) { if (af==PJ_AF_INET) { /* Success (Symbian IP address is in host byte order) */ pj_uint32_t ip = pj_htonl(addr.Address()); pj_memcpy(dst, &ip, 4); } else if (af==PJ_AF_INET6) { const TIp6Addr & ip6 = addr.Ip6Address(); pj_memcpy(dst, ip6.u.iAddr8, 16); } else { pj_assert(!"Unexpected!"); return PJ_EBUG; } return PJ_SUCCESS; } else { /* Error */ return PJ_EINVAL; } }
/* Send request */ static void send_request(const pjsip_method *method, int cseq, const pj_str_t *branch, pj_bool_t with_offer) { pjsip_tx_data *tdata; pj_str_t dummy_sdp_str = { "v=0\r\n" "o=- 3360842071 3360842071 IN IP4 192.168.0.68\r\n" "s=pjmedia\r\n" "c=IN IP4 192.168.0.68\r\n" "t=0 0\r\n" "m=audio 4000 RTP/AVP 0 101\r\n" "a=rtcp:4001 IN IP4 192.168.0.68\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=sendrecv\r\n" "a=rtpmap:101 telephone-event/8000\r\n" "a=fmtp:101 0-15\r\n", 0 }; pj_status_t status; status = pjsip_dlg_create_request(dlg, method, cseq, &tdata); pj_assert(status == PJ_SUCCESS); if (branch) { pjsip_via_hdr *via; via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); pj_strdup(tdata->pool, &via->branch_param, branch); } if (with_offer) { pjsip_msg_body *body; pj_str_t mime_application = { "application", 11}; pj_str_t mime_sdp = {"sdp", 3}; dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr); body = pjsip_msg_body_create(tdata->pool, &mime_application, &mime_sdp, &dummy_sdp_str); tdata->msg->body = body; } status = pjsip_dlg_send_request(dlg, tdata, -1, NULL); pj_assert(status == PJ_SUCCESS); }
static void ui_echo(char menuin[]) { if (pj_ansi_strnicmp(menuin, "echo", 4)==0) { pj_str_t tmp; tmp.ptr = menuin+5; tmp.slen = pj_ansi_strlen(menuin)-6; if (tmp.slen < 1) { puts("Usage: echo [0|1]"); return; } cmd_echo = *tmp.ptr != '0' || tmp.slen!=1; } }
static pj_bool_t mod_stateful_on_rx_request(pjsip_rx_data *rdata) { const pj_str_t stateful_user = { "1", 1 }; pjsip_uri *uri; pjsip_sip_uri *sip_uri; uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri); /* Only want to receive SIP/SIPS scheme */ if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) return PJ_FALSE; sip_uri = (pjsip_sip_uri*) uri; /* Check for matching user part */ if (pj_strcmp(&sip_uri->user, &stateful_user)!=0) return PJ_FALSE; /* * Yes, this is for us. * Respond statefully with 200/OK. */ switch (rdata->msg_info.msg->line.req.method.id) { case PJSIP_INVITE_METHOD: { pjsip_msg_body *body; if (dummy_sdp_str.slen == 0) dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr); body = pjsip_msg_body_create(rdata->tp_info.pool, &mime_application, &mime_sdp, &dummy_sdp_str); pjsip_endpt_respond(app.sip_endpt, &mod_stateful_server, rdata, 200, NULL, NULL, body, NULL); } break; case PJSIP_ACK_METHOD: return PJ_TRUE; default: pjsip_endpt_respond(app.sip_endpt, &mod_stateful_server, rdata, 200, NULL, NULL, NULL, NULL); break; } app.server.cur_state.stateful_cnt++; return PJ_TRUE; }
/* Util to find child node with the specified substring */ static pj_xml_node *find_node(const pj_xml_node *parent, const char *part_name) { const pj_xml_node *node = parent->node_head.next, *head = (pj_xml_node*) &parent->node_head; pj_ssize_t part_len = pj_ansi_strlen(part_name); while (node != head) { if (substring_match(node, part_name, part_len)) return (pj_xml_node*) node; node = node->next; } return NULL; }
/* Comparison function to find node name substring */ static pj_bool_t substring_match(const pj_xml_node *node, const char *part_name, pj_ssize_t part_len) { pj_str_t end_name; if (part_len < 1) part_len = pj_ansi_strlen(part_name); if (node->name.slen < part_len) return PJ_FALSE; end_name.ptr = node->name.ptr + (node->name.slen - part_len); end_name.slen = part_len; return pj_strnicmp2(&end_name, part_name, part_len)==0; }
/* * Init media stack. */ static pj_status_t init_media() { unsigned i; pj_uint16_t rtp_port; pj_status_t status; /* Initialize media endpoint so that at least error subsystem is properly * initialized. */ status = pjmedia_endpt_create(&app.cp.factory, pjsip_endpt_get_ioqueue(app.sip_endpt), 0, &app.med_endpt); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); /* Must register all codecs to be supported */ pjmedia_codec_register_audio_codecs(app.med_endpt, NULL); /* Init dummy socket addresses */ app.skinfo_cnt = 0; for (i=0, rtp_port=4000; i<PJ_ARRAY_SIZE(app.skinfo); ++i, rtp_port+=2) { pjmedia_sock_info *skinfo; skinfo = &app.skinfo[i]; pj_sockaddr_in_init(&skinfo->rtp_addr_name.ipv4, &app.local_addr, (pj_uint16_t)rtp_port); pj_sockaddr_in_init(&skinfo->rtp_addr_name.ipv4, &app.local_addr, (pj_uint16_t)(rtp_port+1)); app.skinfo_cnt++; } /* Generate dummy SDP */ dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr); status = pjmedia_sdp_parse(app.pool, dummy_sdp_str.ptr, dummy_sdp_str.slen, &app.dummy_sdp); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Error parsing dummy SDP", status); return status; } /* Done */ return PJ_SUCCESS; }
/* API: set capability */ static pj_status_t alsa_stream_set_cap(pjmedia_aud_stream *strm, pjmedia_aud_dev_cap cap, const void *value) { struct alsa_factory *af = ((struct alsa_stream*)strm)->af; if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING && pj_ansi_strlen(af->pb_mixer_name)) { pj_ssize_t min, max; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; snd_mixer_elem_t* elem; unsigned vol = *(unsigned*)value; if (snd_mixer_open(&handle, 0) < 0) return PJMEDIA_EAUD_SYSERR; if (snd_mixer_attach(handle, "default") < 0) return PJMEDIA_EAUD_SYSERR; if (snd_mixer_selem_register(handle, NULL, NULL) < 0) return PJMEDIA_EAUD_SYSERR; if (snd_mixer_load(handle) < 0) return PJMEDIA_EAUD_SYSERR; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, af->pb_mixer_name); elem = snd_mixer_find_selem(handle, sid); if (!elem) return PJMEDIA_EAUD_SYSERR; snd_mixer_selem_get_playback_volume_range(elem, &min, &max); if (snd_mixer_selem_set_playback_volume_all(elem, vol * max / 100) < 0) return PJMEDIA_EAUD_SYSERR; snd_mixer_close(handle); return PJ_SUCCESS; } return PJMEDIA_EAUD_INVCAP; }
static void ui_sleep(char menuin[]) { if (pj_ansi_strnicmp(menuin, "sleep", 5)==0) { pj_str_t tmp; int delay; tmp.ptr = menuin+6; tmp.slen = pj_ansi_strlen(menuin)-7; if (tmp.slen < 1) { puts("Usage: sleep MSEC"); return; } delay = pj_strtoul(&tmp); if (delay < 0) delay = 0; pj_thread_sleep(delay); } }
/* * This function converts the Internet host address cp from the standard * numbers-and-dots notation into binary data and stores it in the structure * that inp points to. */ PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp) { enum { MAXIPLEN = PJ_INET_ADDRSTRLEN }; /* Initialize output with PJ_INADDR_NONE. * Some apps relies on this instead of the return value * (and anyway the return value is quite confusing!) */ inp->s_addr = PJ_INADDR_NONE; /* Caution: * this function might be called with cp->slen >= 16 * (i.e. when called with hostname to check if it's an IP addr). */ PJ_ASSERT_RETURN(cp && cp->slen && inp, 0); if (cp->slen >= 16) { return 0; } char tempaddr8[MAXIPLEN]; pj_memcpy(tempaddr8, cp->ptr, cp->slen); tempaddr8[cp->slen] = '\0'; wchar_t tempaddr16[MAXIPLEN]; pj_ansi_to_unicode(tempaddr8, pj_ansi_strlen(tempaddr8), tempaddr16, sizeof(tempaddr16)); TBuf<MAXIPLEN> ip_addr((const TText*)tempaddr16); TInetAddr addr; addr.Init(KAfInet); if (addr.Input(ip_addr) == KErrNone) { /* Success (Symbian IP address is in host byte order) */ inp->s_addr = pj_htonl(addr.Address()); return 1; } else { /* Error */ return 0; } }
/* * Verify that valid SIP url is given. */ static pj_status_t verify_sip_url(const char *c_url) { pjsip_uri *p; pj_pool_t *pool; char *url; int len = (c_url ? pj_ansi_strlen(c_url) : 0); if (!len) return -1; pool = pj_pool_create(&app.cp.factory, "check%p", 1024, 0, NULL); if (!pool) return PJ_ENOMEM; url = pj_pool_alloc(pool, len+1); pj_ansi_strcpy(url, c_url); url[len] = '\0'; p = pjsip_parse_uri(pool, url, len, 0); if (!p || pj_stricmp2(pjsip_uri_get_scheme(p), "sip") != 0) p = NULL; pj_pool_release(pool); return p ? 0 : -1; }
/* * 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; }
/* 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; }
static int https_client_test(unsigned ms_timeout) { pj_pool_t *pool = NULL; pj_ioqueue_t *ioqueue = NULL; pj_timer_heap_t *timer = NULL; pj_ssl_sock_t *ssock = NULL; pj_ssl_sock_param param; pj_status_t status; struct test_state state = {0}; pj_sockaddr local_addr, rem_addr; pj_str_t tmp_st; pool = pj_pool_create(mem, "https_get", 256, 256, NULL); status = pj_ioqueue_create(pool, 4, &ioqueue); if (status != PJ_SUCCESS) { goto on_return; } status = pj_timer_heap_create(pool, 4, &timer); if (status != PJ_SUCCESS) { goto on_return; } state.pool = pool; state.send_str = HTTP_REQ; state.send_str_len = pj_ansi_strlen(state.send_str); state.is_verbose = PJ_TRUE; pj_ssl_sock_param_default(¶m); param.cb.on_connect_complete = &ssl_on_connect_complete; param.cb.on_data_read = &ssl_on_data_read; param.cb.on_data_sent = &ssl_on_data_sent; param.ioqueue = ioqueue; param.user_data = &state; param.server_name = pj_str((char*)HTTP_SERVER_ADDR); param.timer_heap = timer; param.timeout.sec = 0; param.timeout.msec = ms_timeout; param.proto = PJ_SSL_SOCK_PROTO_SSL23; pj_time_val_normalize(¶m.timeout); status = pj_ssl_sock_create(pool, ¶m, &ssock); if (status != PJ_SUCCESS) { goto on_return; } pj_sockaddr_init(PJ_AF_INET, &local_addr, pj_strset2(&tmp_st, "0.0.0.0"), 0); pj_sockaddr_init(PJ_AF_INET, &rem_addr, pj_strset2(&tmp_st, HTTP_SERVER_ADDR), HTTP_SERVER_PORT); status = pj_ssl_sock_start_connect(ssock, pool, &local_addr, &rem_addr, sizeof(rem_addr)); if (status == PJ_SUCCESS) { ssl_on_connect_complete(ssock, PJ_SUCCESS); } else if (status == PJ_EPENDING) { status = PJ_SUCCESS; } else { goto on_return; } /* Wait until everything has been sent/received */ while (state.err == PJ_SUCCESS && !state.done) { #ifdef PJ_SYMBIAN pj_symbianos_poll(-1, 1000); #else pj_time_val delay = {0, 100}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer, &delay); #endif } if (state.err) { status = state.err; goto on_return; } PJ_LOG(3, ("", "...Done!")); PJ_LOG(3, ("", ".....Sent/recv: %d/%d bytes", state.sent, state.recv)); on_return: if (ssock && !state.err && !state.done) pj_ssl_sock_close(ssock); if (ioqueue) pj_ioqueue_destroy(ioqueue); if (timer) pj_timer_heap_destroy(timer); if (pool) pj_pool_release(pool); return status; }
static int server_thread(void *p) { struct server_t *srv = (struct server_t*)p; char *pkt = (char*)pj_pool_alloc(pool, srv->buf_size); pj_sock_t newsock = PJ_INVALID_SOCKET; while (!thread_quit) { pj_ssize_t pkt_len; int rc; pj_fd_set_t rset; pj_time_val timeout = {0, 500}; while (!thread_quit) { PJ_FD_ZERO(&rset); PJ_FD_SET(srv->sock, &rset); rc = pj_sock_select((int)srv->sock+1, &rset, NULL, NULL, &timeout); if (rc != 1) { continue; } rc = pj_sock_accept(srv->sock, &newsock, NULL, NULL); if (rc == PJ_SUCCESS) { break; } } if (thread_quit) break; while (!thread_quit) { PJ_FD_ZERO(&rset); PJ_FD_SET(newsock, &rset); rc = pj_sock_select((int)newsock+1, &rset, NULL, NULL, &timeout); if (rc != 1) { PJ_LOG(3,("http test", "client timeout")); continue; } pkt_len = srv->buf_size; rc = pj_sock_recv(newsock, pkt, &pkt_len, 0); if (rc == PJ_SUCCESS) { break; } } if (thread_quit) break; /* Simulate network RTT */ pj_thread_sleep(50); if (srv->action == ACTION_IGNORE) { continue; } else if (srv->action == ACTION_REPLY) { pj_size_t send_size = 0; unsigned ctr = 0; pj_ansi_sprintf(pkt, "HTTP/1.0 200 OK\r\n"); if (srv->send_content_length) { pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), "Content-Length: %d\r\n", srv->data_size); } pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), "\r\n"); pkt_len = pj_ansi_strlen(pkt); rc = pj_sock_send(newsock, pkt, &pkt_len, 0); if (rc != PJ_SUCCESS) { pj_sock_close(newsock); continue; } while (send_size < srv->data_size) { pkt_len = srv->data_size - send_size; if (pkt_len > (signed)srv->buf_size) pkt_len = srv->buf_size; send_size += pkt_len; pj_create_random_string(pkt, pkt_len); pj_ansi_sprintf(pkt, "\nPacket: %d", ++ctr); pkt[pj_ansi_strlen(pkt)] = '\n'; rc = pj_sock_send(newsock, pkt, &pkt_len, 0); if (rc != PJ_SUCCESS) break; } pj_sock_close(newsock); } } 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
static int offer_answer_test(pj_pool_t *pool, pjmedia_sdp_neg **p_neg, struct offer_answer *oa) { pjmedia_sdp_session *sdp1; pjmedia_sdp_neg *neg; pj_status_t status; status = pjmedia_sdp_parse(pool, oa->sdp1, pj_ansi_strlen(oa->sdp1), &sdp1); if (status != PJ_SUCCESS) { app_perror(status, " error: unexpected parse status for sdp1"); return -10; } status = pjmedia_sdp_validate(sdp1); if (status != PJ_SUCCESS) { app_perror(status, " error: sdp1 validation failed"); return -15; } neg = *p_neg; if (oa->type == LOCAL_OFFER) { /* * Local creates offer first. */ pjmedia_sdp_session *sdp2, *sdp3; const pjmedia_sdp_session *active; if (neg == NULL) { /* Create negotiator with local offer. */ status = pjmedia_sdp_neg_create_w_local_offer(pool, sdp1, &neg); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_create_w_local_offer"); return -20; } *p_neg = neg; } else { /* Modify local offer */ status = pjmedia_sdp_neg_modify_local_offer(pool, neg, sdp1); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_modify_local_offer"); return -30; } } /* Parse and validate remote answer */ status = pjmedia_sdp_parse(pool, oa->sdp2, pj_ansi_strlen(oa->sdp2), &sdp2); if (status != PJ_SUCCESS) { app_perror(status, " error: parsing sdp2"); return -40; } status = pjmedia_sdp_validate(sdp2); if (status != PJ_SUCCESS) { app_perror(status, " error: sdp2 validation failed"); return -50; } /* Give the answer to negotiator. */ status = pjmedia_sdp_neg_set_remote_answer(pool, neg, sdp2); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_rx_remote_answer"); return -60; } /* Negotiate remote answer with local answer */ status = pjmedia_sdp_neg_negotiate(pool, neg, 0); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_negotiate"); return -70; } /* Get the local active media. */ status = pjmedia_sdp_neg_get_active_local(neg, &active); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_get_local"); return -80; } /* Parse and validate the correct active media. */ status = pjmedia_sdp_parse(pool, oa->sdp3, pj_ansi_strlen(oa->sdp3), &sdp3); if (status != PJ_SUCCESS) { app_perror(status, " error: parsing sdp3"); return -90; } status = pjmedia_sdp_validate(sdp3); if (status != PJ_SUCCESS) { app_perror(status, " error: sdp3 validation failed"); return -100; } /* Compare active with sdp3 */ status = pjmedia_sdp_session_cmp(active, sdp3, 0); if (status != PJ_SUCCESS) { app_perror(status, " error: active local comparison mismatch"); compare_sdp_string("Logical cmp after negotiatin remote answer", "Active local sdp from negotiator", active, "The correct active local sdp", sdp3, status); return -110; } /* Compare the string representation oa both sdps */ status = compare_sdp_string("String cmp after negotiatin remote answer", "Active local sdp from negotiator", active, "The correct active local sdp", sdp3, PJ_SUCCESS); if (status != 0) return -120; } else { /* * Remote creates offer first. */ pjmedia_sdp_session *sdp2 = NULL, *sdp3; const pjmedia_sdp_session *answer; if (oa->sdp2) { /* Parse and validate initial local capability */ status = pjmedia_sdp_parse(pool, oa->sdp2, pj_ansi_strlen(oa->sdp2), &sdp2); if (status != PJ_SUCCESS) { app_perror(status, " error: parsing sdp2"); return -200; } status = pjmedia_sdp_validate(sdp2); if (status != PJ_SUCCESS) { app_perror(status, " error: sdp2 validation failed"); return -210; } } else if (neg) { status = pjmedia_sdp_neg_get_active_local(neg, &sdp2); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_get_active_local"); return -215; } } if (neg == NULL) { /* Create negotiator with remote offer. */ status = pjmedia_sdp_neg_create_w_remote_offer(pool, sdp2, sdp1, &neg); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_create_w_remote_offer"); return -220; } *p_neg = neg; } else { /* Received subsequent offer from remote. */ status = pjmedia_sdp_neg_set_remote_offer(pool, neg, sdp1); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_rx_remote_offer"); return -230; } status = pjmedia_sdp_neg_set_local_answer(pool, neg, sdp2); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_set_local_answer"); return -235; } } /* Negotiate. */ status = pjmedia_sdp_neg_negotiate(pool, neg, 0); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_negotiate"); return -240; } /* Get our answer. */ status = pjmedia_sdp_neg_get_active_local(neg, &answer); if (status != PJ_SUCCESS) { app_perror(status, " error: pjmedia_sdp_neg_get_local"); return -250; } /* Parse the correct answer. */ status = pjmedia_sdp_parse(pool, oa->sdp3, pj_ansi_strlen(oa->sdp3), &sdp3); if (status != PJ_SUCCESS) { app_perror(status, " error: parsing sdp3"); return -260; } /* Validate the correct answer. */ status = pjmedia_sdp_validate(sdp3); if (status != PJ_SUCCESS) { app_perror(status, " error: sdp3 validation failed"); return -270; } /* Compare answer from negotiator and the correct answer */ status = pjmedia_sdp_session_cmp(sdp3, answer, 0); if (status != PJ_SUCCESS) { compare_sdp_string("Logical cmp after negotiating remote offer", "Local answer from negotiator", answer, "The correct local answer", sdp3, status); return -280; } /* Compare the string representation oa both answers */ status = compare_sdp_string("String cmp after negotiating remote offer", "Local answer from negotiator", answer, "The correct local answer", sdp3, PJ_SUCCESS); if (status != 0) return -290; } return 0; }