📄 pjsua_core.c
字号:
} else if (type == PJSIP_TRANSPORT_TCP) { /* * Create TCP transport. */ pjsua_transport_config config; pjsip_host_port a_name; pjsip_tpfactory *tcp; pj_sockaddr_in local_addr; /* Supply default config if it's not specified */ if (cfg == NULL) { pjsua_transport_config_default(&config); cfg = &config; } /* Init local address */ pj_sockaddr_in_init(&local_addr, 0, 0); if (cfg->port) local_addr.sin_port = pj_htons((pj_uint16_t)cfg->port); if (cfg->bound_addr.slen) { status = pj_sockaddr_in_set_str_addr(&local_addr,&cfg->bound_addr); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to resolve transport bound address", status); goto on_return; } } /* Init published name */ pj_bzero(&a_name, sizeof(pjsip_host_port)); if (cfg->public_addr.slen) a_name.host = cfg->public_addr; /* Create the TCP transport */ status = pjsip_tcp_transport_start2(pjsua_var.endpt, &local_addr, &a_name, 1, &tcp); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Error creating SIP TCP listener", status); goto on_return; } /* Save the transport */ pjsua_var.tpdata[id].type = type; pjsua_var.tpdata[id].local_name = tcp->addr_name; pjsua_var.tpdata[id].data.factory = tcp;#endif /* PJ_HAS_TCP */#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0 } else if (type == PJSIP_TRANSPORT_TLS) { /* * Create TLS transport. */ /* * Create TCP transport. */ pjsua_transport_config config; pjsip_host_port a_name; pjsip_tpfactory *tls; pj_sockaddr_in local_addr; /* Supply default config if it's not specified */ if (cfg == NULL) { pjsua_transport_config_default(&config); config.port = 5061; cfg = &config; } /* Init local address */ pj_sockaddr_in_init(&local_addr, 0, 0); if (cfg->port) local_addr.sin_port = pj_htons((pj_uint16_t)cfg->port); if (cfg->bound_addr.slen) { status = pj_sockaddr_in_set_str_addr(&local_addr,&cfg->bound_addr); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to resolve transport bound address", status); goto on_return; } } /* Init published name */ pj_bzero(&a_name, sizeof(pjsip_host_port)); if (cfg->public_addr.slen) a_name.host = cfg->public_addr; status = pjsip_tls_transport_start(pjsua_var.endpt, &cfg->tls_setting, &local_addr, &a_name, 1, &tls); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Error creating SIP TLS listener", status); goto on_return; } /* Save the transport */ pjsua_var.tpdata[id].type = type; pjsua_var.tpdata[id].local_name = tls->addr_name; pjsua_var.tpdata[id].data.factory = tls;#endif } else { status = PJSIP_EUNSUPTRANSPORT; pjsua_perror(THIS_FILE, "Error creating transport", status); goto on_return; } /* Return the ID */ if (p_id) *p_id = id; status = PJ_SUCCESS;on_return: PJSUA_UNLOCK(); return status;}/* * Register transport that has been created by application. */PJ_DEF(pj_status_t) pjsua_transport_register( pjsip_transport *tp, pjsua_transport_id *p_id){ unsigned id; PJSUA_LOCK(); /* Find empty transport slot */ for (id=0; id < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++id) { if (pjsua_var.tpdata[id].data.ptr == NULL) break; } if (id == PJ_ARRAY_SIZE(pjsua_var.tpdata)) { pjsua_perror(THIS_FILE, "Error creating transport", PJ_ETOOMANY); PJSUA_UNLOCK(); return PJ_ETOOMANY; } /* Save the transport */ pjsua_var.tpdata[id].type = tp->key.type; pjsua_var.tpdata[id].local_name = tp->local_name; pjsua_var.tpdata[id].data.tp = tp; /* Return the ID */ if (p_id) *p_id = id; PJSUA_UNLOCK(); return PJ_SUCCESS;}/* * Enumerate all transports currently created in the system. */PJ_DEF(pj_status_t) pjsua_enum_transports( pjsua_transport_id id[], unsigned *p_count ){ unsigned i, count; PJSUA_LOCK(); for (i=0, count=0; i<PJ_ARRAY_SIZE(pjsua_var.tpdata) && count<*p_count; ++i) { if (!pjsua_var.tpdata[i].data.ptr) continue; id[count++] = i; } *p_count = count; PJSUA_UNLOCK(); return PJ_SUCCESS;}/* * Get information about transports. */PJ_DEF(pj_status_t) pjsua_transport_get_info( pjsua_transport_id id, pjsua_transport_info *info){ pjsua_transport_data *t = &pjsua_var.tpdata[id]; pj_status_t status; pj_bzero(info, sizeof(*info)); /* Make sure id is in range. */ PJ_ASSERT_RETURN(id>=0 && id<PJ_ARRAY_SIZE(pjsua_var.tpdata), PJ_EINVAL); /* Make sure that transport exists */ PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL); PJSUA_LOCK(); if (pjsua_var.tpdata[id].type == PJSIP_TRANSPORT_UDP) { pjsip_transport *tp = t->data.tp; if (tp == NULL) { PJSUA_UNLOCK(); return PJ_EINVALIDOP; } info->id = id; info->type = tp->key.type; info->type_name = pj_str(tp->type_name); info->info = pj_str(tp->info); info->flag = tp->flag; info->addr_len = tp->addr_len; info->local_addr = tp->local_addr; info->local_name = tp->local_name; info->usage_count = pj_atomic_get(tp->ref_cnt); status = PJ_SUCCESS; } else if (pjsua_var.tpdata[id].type == PJSIP_TRANSPORT_TCP) { pjsip_tpfactory *factory = t->data.factory; if (factory == NULL) { PJSUA_UNLOCK(); return PJ_EINVALIDOP; } info->id = id; info->type = t->type; info->type_name = pj_str("TCP"); info->info = pj_str("TCP transport"); info->flag = factory->flag; info->addr_len = sizeof(factory->local_addr); info->local_addr = factory->local_addr; info->local_name = factory->addr_name; info->usage_count = 0; status = PJ_SUCCESS; } else { pj_assert(!"Unsupported transport"); status = PJ_EINVALIDOP; } PJSUA_UNLOCK(); return status;}/* * Disable a transport or re-enable it. */PJ_DEF(pj_status_t) pjsua_transport_set_enable( pjsua_transport_id id, pj_bool_t enabled){ /* Make sure id is in range. */ PJ_ASSERT_RETURN(id>=0 && id<PJ_ARRAY_SIZE(pjsua_var.tpdata), PJ_EINVAL); /* Make sure that transport exists */ PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL); /* To be done!! */ PJ_TODO(pjsua_transport_set_enable); PJ_UNUSED_ARG(enabled); return PJ_EINVALIDOP;}/* * Close the transport. */PJ_DEF(pj_status_t) pjsua_transport_close( pjsua_transport_id id, pj_bool_t force ){ pj_status_t status; /* Make sure id is in range. */ PJ_ASSERT_RETURN(id>=0 && id<PJ_ARRAY_SIZE(pjsua_var.tpdata), PJ_EINVAL); /* Make sure that transport exists */ PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL); /* Note: destroy() may not work if there are objects still referencing * the transport. */ if (force) { switch (pjsua_var.tpdata[id].type) { case PJSIP_TRANSPORT_UDP: status = pjsip_transport_shutdown(pjsua_var.tpdata[id].data.tp); if (status != PJ_SUCCESS) return status; status = pjsip_transport_destroy(pjsua_var.tpdata[id].data.tp); if (status != PJ_SUCCESS) return status; break; case PJSIP_TRANSPORT_TLS: case PJSIP_TRANSPORT_TCP: /* This will close the TCP listener, but existing TCP/TLS * connections (if any) will still linger */ status = (*pjsua_var.tpdata[id].data.factory->destroy) (pjsua_var.tpdata[id].data.factory); if (status != PJ_SUCCESS) return status; break; default: return PJ_EINVAL; } } else { /* If force is not specified, transports will be closed at their * convenient time. However this will leak PJSUA-API transport * descriptors as PJSUA-API wouldn't know when exactly the * transport is closed thus it can't cleanup PJSUA transport * descriptor. */ switch (pjsua_var.tpdata[id].type) { case PJSIP_TRANSPORT_UDP: return pjsip_transport_shutdown(pjsua_var.tpdata[id].data.tp); case PJSIP_TRANSPORT_TLS: case PJSIP_TRANSPORT_TCP: return (*pjsua_var.tpdata[id].data.factory->destroy) (pjsua_var.tpdata[id].data.factory); default: return PJ_EINVAL; } } /* Cleanup pjsua data when force is applied */ if (force) { pjsua_var.tpdata[id].type = PJSIP_TRANSPORT_UNSPECIFIED; pjsua_var.tpdata[id].data.ptr = NULL; } return PJ_SUCCESS;}/* * Add additional headers etc in msg_data specified by application * when sending requests. */void pjsua_process_msg_data(pjsip_tx_data *tdata, const pjsua_msg_data *msg_data){ pj_bool_t allow_body; const pjsip_hdr *hdr; /* Always add User-Agent */ if (pjsua_var.ua_cfg.user_agent.slen && tdata->msg->type == PJSIP_REQUEST_MSG) { const pj_str_t STR_USER_AGENT = { "User-Agent", 10 }; pjsip_hdr *h; h = (pjsip_hdr*)pjsip_generic_string_hdr_create(tdata->pool, &STR_USER_AGENT, &pjsua_var.ua_cfg.user_agent); pjsip_msg_add_hdr(tdata->msg, h); } if (!msg_data) return; hdr = msg_data->hdr_list.next; while (hdr && hdr != &msg_data->hdr_list) { pjsip_hdr *new_hdr; new_hdr = pjsip_hdr_clone(tdata->pool, hdr); pjsip_msg_add_hdr(tdata->msg, new_hdr); hdr = hdr->next; } allow_body = (tdata->msg->body == NULL); if (allow_body && msg_data->content_type.slen && msg_data->msg_body.slen) { pjsip_media_type ctype; pjsip_msg_body *body; pjsua_parse_media_type(tdata->pool, &msg_data->content_type, &ctype); body = pjsip_msg_body_create(tdata->pool, &ctype.type, &ctype.subtype, &msg_data->msg_body); tdata->msg->body = body; }}/* * Add route_set to outgoing requests */void pjsua_set_msg_route_set( pjsip_tx_data *tdata, const pjsip_route_hdr *route_set ){ const pjsip_route_hdr *r; r = route_set->next; while (r != route_set) { pjsip_route_hdr *new_r; new_r = pjsip_hdr_clone(tdata->pool, r); pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)new_r); r = r->next; }}/* * Simple version of MIME type parsing (it doesn't support parameters) */void pjsua_parse_media_type( pj_pool_t *pool, const pj_str_t *mime, pjsip_media_type *media_type){ pj_str_t tmp; char *pos; pj_bzero(media_type, sizeof(*media_type)); pj_strdup_with_null(pool, &tmp, mime); pos = pj_strchr(&tmp, '/'); if (pos) { media_type->type.ptr = tmp.ptr; media_type->type.slen = (pos-tmp.ptr); media_type->subtype.ptr = pos+1; media_type->subtype.slen = tmp.ptr+tmp.slen-pos-1; } else { media_type->type = tmp; }}/* * Internal function to init transport selector from transport id. */void pjsua_init_tpselector(pjsua_transport_id tp_id, pjsip_tpselector *sel){ pjsua_transport_data *tpdata; unsigned flag; pj_bzero(sel, sizeof(*sel)); if (tp_id == PJSUA_INVALID_ID) return; pj_assert(tp_id >= 0 && tp_id < PJ_ARRAY_SIZE(pjsua_var.tpdata)); tpdata = &pjsua_var.tpdata[tp_id]; flag = pjsip_transport_get_flag_from_type(tpdata->type); if (flag & PJSIP_TRANSPORT_DATAGRAM) { sel->type = PJSIP_TPSELECTOR_TRANSPORT; sel->u.transport = tpdata->data.tp; } else { sel->type = PJSIP_TPSELECTOR_LISTENER; sel->u.listener = tpdata->data.factory; }}/* * Verify that valid SIP url is given. */PJ_DEF(pj_status_t) pjsua_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(&pjsua_var.cp.factory, "check%p", 1024, 0, NULL); if (!pool) return -1; url = pj_pool_alloc(pool, len+1); pj_ansi_strcpy(url, c_url); 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -