diff options
Diffstat (limited to 'pjsip/src/pjsua/pjsua_core.c')
-rw-r--r-- | pjsip/src/pjsua/pjsua_core.c | 322 |
1 files changed, 200 insertions, 122 deletions
diff --git a/pjsip/src/pjsua/pjsua_core.c b/pjsip/src/pjsua/pjsua_core.c index f5c35468..974c6d53 100644 --- a/pjsip/src/pjsua/pjsua_core.c +++ b/pjsip/src/pjsua/pjsua_core.c @@ -45,6 +45,8 @@ struct pjsua pjsua; */ void pjsua_default(void) { + unsigned i; + /* Normally need another thread for console application, because main * thread will be blocked in fgets(). @@ -53,44 +55,38 @@ void pjsua_default(void) /* Default transport settings: */ - pjsua.sip_port = 5060; /* Default logging settings: */ - pjsua.log_level = 5; pjsua.app_log_level = 4; pjsua.log_decor = PJ_LOG_HAS_SENDER | PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE; - /* Default: do not use STUN: */ + /* Default: do not use STUN: */ pjsua.stun_port1 = pjsua.stun_port2 = 0; - /* Default URIs: */ - - pjsua.local_uri = pj_str(PJSUA_LOCAL_URI); - - /* Default registration timeout: */ - - pjsua.reg_timeout = 55; - - /* Default maximum conference ports: */ - - pjsua.max_ports = 8; - - /* Init route set list: */ - - pj_list_init(&pjsua.route_set); + /* Init accounts: */ + pjsua.acc_cnt = 1; + for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) { + pjsua.acc[i].index = i; + pjsua.acc[i].local_uri = pj_str(PJSUA_LOCAL_URI); + pjsua.acc[i].reg_timeout = 55; + pj_list_init(&pjsua.acc[i].route_set); + pj_list_init(&pjsua.acc[i].pres_srv_list); + } - /* Init invite session list: */ + /* Init call array: */ + for (i=0; i<PJ_ARRAY_SIZE(pjsua.calls); ++i) + pjsua.calls[i].index = i; - pj_list_init(&pjsua.inv_list); + /* Default max nb of calls. */ + pjsua.max_calls = 4; /* Init server presence subscription list: */ - pj_list_init(&pjsua.pres_srv_list); } @@ -110,8 +106,7 @@ static pj_bool_t mod_pjsua_on_rx_request(pjsip_rx_data *rdata) if (rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD) { - return pjsua_inv_on_incoming(rdata); - + return pjsua_call_on_incoming(rdata); } return PJ_FALSE; @@ -145,7 +140,7 @@ static pj_status_t init_sockets(pj_bool_t sip, enum { RTP_START_PORT = 4000, RTP_RANDOM_START = 2, - RTP_RETRY = 20 + RTP_RETRY = 100 }; enum { SIP_SOCK, @@ -240,37 +235,49 @@ static pj_status_t init_sockets(pj_bool_t sip, for (i=0; i<3; ++i) pj_memcpy(&mapped_addr[i], &addr, sizeof(addr)); - if (sip) - mapped_addr[SIP_SOCK].sin_port = pj_htons((pj_uint16_t)pjsua.sip_port); - mapped_addr[RTP_SOCK].sin_port = pj_htons((pj_uint16_t)rtp_port); - mapped_addr[RTCP_SOCK].sin_port = pj_htons((pj_uint16_t)(rtp_port+1)); + if (sip) { + mapped_addr[SIP_SOCK].sin_port = + pj_htons((pj_uint16_t)pjsua.sip_port); + } + mapped_addr[RTP_SOCK].sin_port=pj_htons((pj_uint16_t)rtp_port); + mapped_addr[RTCP_SOCK].sin_port=pj_htons((pj_uint16_t)(rtp_port+1)); break; + } else { - status = pj_stun_get_mapped_addr( &pjsua.cp.factory, 3, sock, - &pjsua.stun_srv1, pjsua.stun_port1, - &pjsua.stun_srv2, pjsua.stun_port2, - mapped_addr); + status=pj_stun_get_mapped_addr(&pjsua.cp.factory, 3, sock, + &pjsua.stun_srv1, pjsua.stun_port1, + &pjsua.stun_srv2, pjsua.stun_port2, + mapped_addr); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "STUN error", status); goto on_error; } - if (pj_ntohs(mapped_addr[2].sin_port) == pj_ntohs(mapped_addr[1].sin_port)+1) + if (pj_ntohs(mapped_addr[2].sin_port) == + pj_ntohs(mapped_addr[1].sin_port)+1) + { break; + } - pj_sock_close(sock[RTP_SOCK]); sock[RTP_SOCK] = PJ_INVALID_SOCKET; - pj_sock_close(sock[RTCP_SOCK]); sock[RTCP_SOCK] = PJ_INVALID_SOCKET; + pj_sock_close(sock[RTP_SOCK]); + sock[RTP_SOCK] = PJ_INVALID_SOCKET; + + pj_sock_close(sock[RTCP_SOCK]); + sock[RTCP_SOCK] = PJ_INVALID_SOCKET; } } if (sock[RTP_SOCK] == PJ_INVALID_SOCKET) { - PJ_LOG(1,(THIS_FILE, "Unable to find appropriate RTP/RTCP ports combination")); + PJ_LOG(1,(THIS_FILE, + "Unable to find appropriate RTP/RTCP ports combination")); goto on_error; } if (sip) { pjsua.sip_sock = sock[SIP_SOCK]; - pj_memcpy(&pjsua.sip_sock_name, &mapped_addr[SIP_SOCK], sizeof(pj_sockaddr_in)); + pj_memcpy(&pjsua.sip_sock_name, + &mapped_addr[SIP_SOCK], + sizeof(pj_sockaddr_in)); } else { pj_sock_close(sock[0]); } @@ -391,30 +398,13 @@ static pj_status_t init_stack(void) /* Initialize invite session module: */ - { - - /* Initialize invite session callback. */ - pjsip_inv_callback inv_cb; - - pj_memset(&inv_cb, 0, sizeof(inv_cb)); - inv_cb.on_state_changed = &pjsua_inv_on_state_changed; - inv_cb.on_new_session = &pjsua_inv_on_new_session; - inv_cb.on_media_update = &pjsua_inv_on_media_update; - inv_cb.on_rx_offer = &pjsua_inv_on_rx_offer; - inv_cb.on_tsx_state_changed = &pjsua_inv_on_tsx_state_changed; - - - /* Initialize invite session module: */ - status = pjsip_inv_usage_init(pjsua.endpt, &pjsua.mod, &inv_cb); - if (status != PJ_SUCCESS) { - pjsua_perror(THIS_FILE, "Invite usage initialization error", - status); - goto on_error; - } - + status = pjsua_call_init(); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Invite usage initialization error", + status); + goto on_error; } - /* Done */ return PJ_SUCCESS; @@ -520,7 +510,8 @@ pj_status_t pjsua_init(void) /* Init conference bridge. */ - status = pjmedia_conf_create(pjsua.pool, pjsua.max_ports, + status = pjmedia_conf_create(pjsua.pool, + pjsua.max_calls+PJSUA_CONF_MORE_PORTS, 8000, 160, 16, &pjsua.mconf); if (status != PJ_SUCCESS) { pj_caching_pool_destroy(&pjsua.cp); @@ -547,6 +538,67 @@ pj_status_t pjsua_init(void) } +/* + * Find account for incoming request. + */ +int pjsua_find_account_for_incoming(pjsip_rx_data *rdata) +{ + pjsip_uri *uri; + pjsip_sip_uri *sip_uri; + int acc_index; + + uri = rdata->msg_info.to->uri; + + /* Just return account #0 if To URI is not SIP: */ + if (!PJSIP_URI_SCHEME_IS_SIP(uri) && + !PJSIP_URI_SCHEME_IS_SIPS(uri)) + { + return 0; + } + + + sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri); + + /* Find account which has matching username and domain. */ + for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) { + + pjsua_acc *acc = &pjsua.acc[acc_index]; + + if (pj_stricmp(&acc->user_part, &sip_uri->user)==0 && + pj_stricmp(&acc->host_part, &sip_uri->host)==0) + { + /* Match ! */ + return acc_index; + } + } + + /* No matching, try match domain part only. */ + for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) { + + pjsua_acc *acc = &pjsua.acc[acc_index]; + + if (pj_stricmp(&acc->host_part, &sip_uri->host)==0) { + /* Match ! */ + return acc_index; + } + } + + /* Still no match, just return account #0 */ + return 0; +} + + +/* + * Find account for outgoing request. + */ +int pjsua_find_account_for_outgoing(const pj_str_t *url) +{ + PJ_UNUSED_ARG(url); + + /* Just use account #0 */ + return 0; +} + /* * Start pjsua stack. @@ -588,11 +640,18 @@ pj_status_t pjsua_start(void) /* Init sockets (STUN etc): */ - for (i=0; i<PJ_ARRAY_SIZE(pjsua.med_sock_info); ++i) { - status = init_sockets(i==0, &pjsua.med_sock_info[i]); + for (i=0; i<(int)pjsua.max_calls; ++i) { + status = init_sockets(i==0, &pjsua.calls[i].skinfo); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "init_sockets() has returned error", status); + --i; + if (i >= 0) + pj_sock_close(pjsua.sip_sock); + while (i >= 0) { + pj_sock_close(pjsua.calls[i].skinfo.rtp_sock); + pj_sock_close(pjsua.calls[i].skinfo.rtcp_sock); + } return status; } } @@ -623,34 +682,26 @@ pj_status_t pjsua_start(void) } /* Initialize Contact URI, if one is not specified: */ - - if (pjsua.contact_uri.slen == 0 && pjsua.local_uri.slen) { + for (i=0; i<pjsua.acc_cnt; ++i) { pjsip_uri *uri; pjsip_sip_uri *sip_uri; - char contact[128]; - int len; - /* The local Contact is the username@ip-addr, where - * - username is taken from the local URI, - * - ip-addr in UDP transport's address name (which may have been - * resolved from STUN. - */ - /* Need to parse local_uri to get the elements: */ - uri = pjsip_parse_uri(pjsua.pool, pjsua.local_uri.ptr, - pjsua.local_uri.slen, 0); + uri = pjsip_parse_uri(pjsua.pool, pjsua.acc[i].local_uri.ptr, + pjsua.acc[i].local_uri.slen, 0); if (uri == NULL) { pjsua_perror(THIS_FILE, "Invalid local URI", PJSIP_EINVALIDURI); return PJSIP_EINVALIDURI; } - /* Local URI MUST be a SIP or SIPS: */ - if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) { + if (!PJSIP_URI_SCHEME_IS_SIP(uri) && + !PJSIP_URI_SCHEME_IS_SIPS(uri)) + { pjsua_perror(THIS_FILE, "Invalid local URI", PJSIP_EINVALIDSCHEME); return PJSIP_EINVALIDSCHEME; @@ -661,39 +712,54 @@ pj_status_t pjsua_start(void) sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri); - - /* Build temporary contact string. */ - - if (sip_uri->user.slen) { - - /* With the user part. */ - len = pj_snprintf(contact, sizeof(contact), - "<sip:%.*s@%.*s:%d>", - (int)sip_uri->user.slen, - sip_uri->user.ptr, - (int)udp_transport->local_name.host.slen, - udp_transport->local_name.host.ptr, - udp_transport->local_name.port); - } else { - - /* Without user part */ + pjsua.acc[i].user_part = sip_uri->user; + pjsua.acc[i].host_part = sip_uri->host; - len = pj_snprintf(contact, sizeof(contact), - "<sip:%.*s:%d>", - (int)udp_transport->local_name.host.slen, - udp_transport->local_name.host.ptr, - udp_transport->local_name.port); - } + if (pjsua.acc[i].contact_uri.slen == 0 && + pjsua.acc[i].local_uri.slen) + { + char contact[128]; + int len; + + /* The local Contact is the username@ip-addr, where + * - username is taken from the local URI, + * - ip-addr in UDP transport's address name (which may have been + * resolved from STUN. + */ + + /* Build temporary contact string. */ + + if (sip_uri->user.slen) { + + /* With the user part. */ + len = pj_snprintf(contact, sizeof(contact), + "<sip:%.*s@%.*s:%d>", + (int)sip_uri->user.slen, + sip_uri->user.ptr, + (int)udp_transport->local_name.host.slen, + udp_transport->local_name.host.ptr, + udp_transport->local_name.port); + } else { + + /* Without user part */ + + len = pj_snprintf(contact, sizeof(contact), + "<sip:%.*s:%d>", + (int)udp_transport->local_name.host.slen, + udp_transport->local_name.host.ptr, + udp_transport->local_name.port); + } - if (len < 1 || len >= sizeof(contact)) { - pjsua_perror(THIS_FILE, "Invalid Contact", PJSIP_EURITOOLONG); - return PJSIP_EURITOOLONG; - } + if (len < 1 || len >= sizeof(contact)) { + pjsua_perror(THIS_FILE, "Invalid Contact", PJSIP_EURITOOLONG); + return PJSIP_EURITOOLONG; + } - /* Duplicate Contact uri. */ + /* Duplicate Contact uri. */ - pj_strdup2(pjsua.pool, &pjsua.contact_uri, contact); + pj_strdup2(pjsua.pool, &pjsua.acc[i].contact_uri, contact); + } } /* If outbound_proxy is specified, put it in the route_set: */ @@ -714,7 +780,9 @@ pj_status_t pjsua_start(void) return PJSIP_EINVALIDURI; } - pj_list_push_back(&pjsua.route_set, route); + for (i=0; i<pjsua.acc_cnt; ++i) { + pj_list_push_front(&pjsua.acc[i].route_set, route); + } } @@ -736,14 +804,22 @@ pj_status_t pjsua_start(void) /* Start registration: */ /* Create client registration session: */ + for (i=0; i<pjsua.acc_cnt; ++i) { + status = pjsua_regc_init(i); + if (status != PJ_SUCCESS) + return status; - status = pjsua_regc_init(); - if (status != PJ_SUCCESS) - return status; + /* Perform registration, if required. */ + if (pjsua.acc[i].regc) { + pjsua_regc_update(i, 1); + } + } - /* Perform registration, if required. */ - if (pjsua.regc) { - pjsua_regc_update(1); + + /* Find account for outgoing preence subscription */ + for (i=0; i<pjsua.buddy_cnt; ++i) { + pjsua.buddies[i].acc_index = + pjsua_find_account_for_outgoing(&pjsua.buddies[i].uri); } @@ -777,6 +853,19 @@ pj_status_t pjsua_destroy(void) /* Signal threads to quit: */ pjsua.quit_flag = 1; + /* Terminate all calls. */ + pjsua_inv_shutdown(); + + /* Terminate all presence subscriptions. */ + pjsua_pres_shutdown(); + + /* Unregister, if required: */ + for (i=0; i<pjsua.acc_cnt; ++i) { + if (pjsua.acc[i].regc) { + pjsua_regc_update(i, 0); + } + } + /* Wait worker threads to quit: */ for (i=0; i<pjsua.thread_cnt; ++i) { @@ -788,17 +877,6 @@ pj_status_t pjsua_destroy(void) } - /* Terminate all calls. */ - pjsua_inv_shutdown(); - - /* Terminate all presence subscriptions. */ - pjsua_pres_shutdown(); - - /* Unregister, if required: */ - if (pjsua.regc) { - pjsua_regc_update(0); - } - /* Wait for some time to allow unregistration to complete: */ PJ_LOG(4,(THIS_FILE, "Shutting down...")); busy_sleep(1000); |