summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsua2/account.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsua2/account.cpp')
-rw-r--r--pjsip/src/pjsua2/account.cpp799
1 files changed, 799 insertions, 0 deletions
diff --git a/pjsip/src/pjsua2/account.cpp b/pjsip/src/pjsua2/account.cpp
new file mode 100644
index 00000000..247c4a4a
--- /dev/null
+++ b/pjsip/src/pjsua2/account.cpp
@@ -0,0 +1,799 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsua2/account.hpp>
+#include <pjsua2/endpoint.hpp>
+#include <pjsua2/presence.hpp>
+#include <pj/ctype.h>
+#include "util.hpp"
+
+using namespace pj;
+using namespace std;
+
+#define THIS_FILE "account.cpp"
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountRegConfig::readObject(const ContainerNode &node) throw(Error)
+{
+ ContainerNode this_node = node.readContainer("AccountRegConfig");
+
+ NODE_READ_STRING (this_node, registrarUri);
+ NODE_READ_BOOL (this_node, registerOnAdd);
+ NODE_READ_UNSIGNED (this_node, timeoutSec);
+ NODE_READ_UNSIGNED (this_node, retryIntervalSec);
+ NODE_READ_UNSIGNED (this_node, firstRetryIntervalSec);
+ NODE_READ_UNSIGNED (this_node, delayBeforeRefreshSec);
+ NODE_READ_BOOL (this_node, dropCallsOnFail);
+ NODE_READ_UNSIGNED (this_node, unregWaitSec);
+ NODE_READ_UNSIGNED (this_node, proxyUse);
+
+ readSipHeaders(this_node, "headers", headers);
+}
+
+void AccountRegConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+ ContainerNode this_node = node.writeNewContainer("AccountRegConfig");
+
+ NODE_WRITE_STRING (this_node, registrarUri);
+ NODE_WRITE_BOOL (this_node, registerOnAdd);
+ NODE_WRITE_UNSIGNED (this_node, timeoutSec);
+ NODE_WRITE_UNSIGNED (this_node, retryIntervalSec);
+ NODE_WRITE_UNSIGNED (this_node, firstRetryIntervalSec);
+ NODE_WRITE_UNSIGNED (this_node, delayBeforeRefreshSec);
+ NODE_WRITE_BOOL (this_node, dropCallsOnFail);
+ NODE_WRITE_UNSIGNED (this_node, unregWaitSec);
+ NODE_WRITE_UNSIGNED (this_node, proxyUse);
+
+ writeSipHeaders(this_node, "headers", headers);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountSipConfig::readObject(const ContainerNode &node) throw(Error)
+{
+ ContainerNode this_node = node.readContainer("AccountSipConfig");
+
+ NODE_READ_STRINGV (this_node, proxies);
+ NODE_READ_STRING (this_node, contactForced);
+ NODE_READ_STRING (this_node, contactParams);
+ NODE_READ_STRING (this_node, contactUriParams);
+ NODE_READ_BOOL (this_node, authInitialEmpty);
+ NODE_READ_STRING (this_node, authInitialAlgorithm);
+ NODE_READ_INT (this_node, transportId);
+
+ ContainerNode creds_node = this_node.readArray("authCreds");
+ authCreds.resize(0);
+ while (creds_node.hasUnread()) {
+ AuthCredInfo cred;
+ cred.readObject(creds_node);
+ authCreds.push_back(cred);
+ }
+}
+
+void AccountSipConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+ ContainerNode this_node = node.writeNewContainer("AccountSipConfig");
+
+ NODE_WRITE_STRINGV (this_node, proxies);
+ NODE_WRITE_STRING (this_node, contactForced);
+ NODE_WRITE_STRING (this_node, contactParams);
+ NODE_WRITE_STRING (this_node, contactUriParams);
+ NODE_WRITE_BOOL (this_node, authInitialEmpty);
+ NODE_WRITE_STRING (this_node, authInitialAlgorithm);
+ NODE_WRITE_INT (this_node, transportId);
+
+ ContainerNode creds_node = this_node.writeNewArray("authCreds");
+ for (unsigned i=0; i<authCreds.size(); ++i) {
+ authCreds[i].writeObject(creds_node);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountCallConfig::readObject(const ContainerNode &node) throw(Error)
+{
+ ContainerNode this_node = node.readContainer("AccountCallConfig");
+
+ NODE_READ_NUM_T ( this_node, pjsua_call_hold_type, holdType);
+ NODE_READ_NUM_T ( this_node, pjsua_100rel_use, prackUse);
+ NODE_READ_NUM_T ( this_node, pjsua_sip_timer_use, timerUse);
+ NODE_READ_UNSIGNED( this_node, timerMinSESec);
+ NODE_READ_UNSIGNED( this_node, timerSessExpiresSec);
+}
+
+void AccountCallConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+ ContainerNode this_node = node.writeNewContainer("AccountCallConfig");
+
+ NODE_WRITE_NUM_T ( this_node, pjsua_call_hold_type, holdType);
+ NODE_WRITE_NUM_T ( this_node, pjsua_100rel_use, prackUse);
+ NODE_WRITE_NUM_T ( this_node, pjsua_sip_timer_use, timerUse);
+ NODE_WRITE_UNSIGNED( this_node, timerMinSESec);
+ NODE_WRITE_UNSIGNED( this_node, timerSessExpiresSec);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountPresConfig::readObject(const ContainerNode &node) throw(Error)
+{
+ ContainerNode this_node = node.readContainer("AccountPresConfig");
+
+ NODE_READ_BOOL ( this_node, publishEnabled);
+ NODE_READ_BOOL ( this_node, publishQueue);
+ NODE_READ_UNSIGNED( this_node, publishShutdownWaitMsec);
+ NODE_READ_STRING ( this_node, pidfTupleId);
+
+ readSipHeaders(this_node, "headers", headers);
+}
+
+void AccountPresConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+ ContainerNode this_node = node.writeNewContainer("AccountPresConfig");
+
+ NODE_WRITE_BOOL ( this_node, publishEnabled);
+ NODE_WRITE_BOOL ( this_node, publishQueue);
+ NODE_WRITE_UNSIGNED( this_node, publishShutdownWaitMsec);
+ NODE_WRITE_STRING ( this_node, pidfTupleId);
+
+ writeSipHeaders(this_node, "headers", headers);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountMwiConfig::readObject(const ContainerNode &node) throw(Error)
+{
+ ContainerNode this_node = node.readContainer("AccountMwiConfig");
+
+ NODE_READ_BOOL ( this_node, enabled);
+ NODE_READ_UNSIGNED( this_node, expirationSec);
+}
+
+void AccountMwiConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+ ContainerNode this_node = node.writeNewContainer("AccountMwiConfig");
+
+ NODE_WRITE_BOOL ( this_node, enabled);
+ NODE_WRITE_UNSIGNED( this_node, expirationSec);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountNatConfig::readObject(const ContainerNode &node) throw(Error)
+{
+ ContainerNode this_node = node.readContainer("AccountNatConfig");
+
+ NODE_READ_NUM_T ( this_node, pjsua_stun_use, sipStunUse);
+ NODE_READ_NUM_T ( this_node, pjsua_stun_use, mediaStunUse);
+ NODE_READ_BOOL ( this_node, iceEnabled);
+ NODE_READ_INT ( this_node, iceMaxHostCands);
+ NODE_READ_BOOL ( this_node, iceAggressiveNomination);
+ NODE_READ_UNSIGNED( this_node, iceNominatedCheckDelayMsec);
+ NODE_READ_INT ( this_node, iceWaitNominationTimeoutMsec);
+ NODE_READ_BOOL ( this_node, iceNoRtcp);
+ NODE_READ_BOOL ( this_node, iceAlwaysUpdate);
+ NODE_READ_BOOL ( this_node, turnEnabled);
+ NODE_READ_STRING ( this_node, turnServer);
+ NODE_READ_NUM_T ( this_node, pj_turn_tp_type, turnConnType);
+ NODE_READ_STRING ( this_node, turnUserName);
+ NODE_READ_INT ( this_node, turnPasswordType);
+ NODE_READ_STRING ( this_node, turnPassword);
+ NODE_READ_INT ( this_node, contactRewriteUse);
+ NODE_READ_INT ( this_node, contactRewriteMethod);
+ NODE_READ_INT ( this_node, viaRewriteUse);
+ NODE_READ_INT ( this_node, sdpNatRewriteUse);
+ NODE_READ_INT ( this_node, sipOutboundUse);
+ NODE_READ_STRING ( this_node, sipOutboundInstanceId);
+ NODE_READ_STRING ( this_node, sipOutboundRegId);
+ NODE_READ_UNSIGNED( this_node, udpKaIntervalSec);
+ NODE_READ_STRING ( this_node, udpKaData);
+}
+
+void AccountNatConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+ ContainerNode this_node = node.writeNewContainer("AccountNatConfig");
+
+ NODE_WRITE_NUM_T ( this_node, pjsua_stun_use, sipStunUse);
+ NODE_WRITE_NUM_T ( this_node, pjsua_stun_use, mediaStunUse);
+ NODE_WRITE_BOOL ( this_node, iceEnabled);
+ NODE_WRITE_INT ( this_node, iceMaxHostCands);
+ NODE_WRITE_BOOL ( this_node, iceAggressiveNomination);
+ NODE_WRITE_UNSIGNED( this_node, iceNominatedCheckDelayMsec);
+ NODE_WRITE_INT ( this_node, iceWaitNominationTimeoutMsec);
+ NODE_WRITE_BOOL ( this_node, iceNoRtcp);
+ NODE_WRITE_BOOL ( this_node, iceAlwaysUpdate);
+ NODE_WRITE_BOOL ( this_node, turnEnabled);
+ NODE_WRITE_STRING ( this_node, turnServer);
+ NODE_WRITE_NUM_T ( this_node, pj_turn_tp_type, turnConnType);
+ NODE_WRITE_STRING ( this_node, turnUserName);
+ NODE_WRITE_INT ( this_node, turnPasswordType);
+ NODE_WRITE_STRING ( this_node, turnPassword);
+ NODE_WRITE_INT ( this_node, contactRewriteUse);
+ NODE_WRITE_INT ( this_node, contactRewriteMethod);
+ NODE_WRITE_INT ( this_node, viaRewriteUse);
+ NODE_WRITE_INT ( this_node, sdpNatRewriteUse);
+ NODE_WRITE_INT ( this_node, sipOutboundUse);
+ NODE_WRITE_STRING ( this_node, sipOutboundInstanceId);
+ NODE_WRITE_STRING ( this_node, sipOutboundRegId);
+ NODE_WRITE_UNSIGNED( this_node, udpKaIntervalSec);
+ NODE_WRITE_STRING ( this_node, udpKaData);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountMediaConfig::readObject(const ContainerNode &node) throw(Error)
+{
+ ContainerNode this_node = node.readContainer("AccountMediaConfig");
+
+ NODE_READ_BOOL ( this_node, lockCodecEnabled);
+ NODE_READ_BOOL ( this_node, streamKaEnabled);
+ NODE_READ_NUM_T ( this_node, pjmedia_srtp_use, srtpUse);
+ NODE_READ_INT ( this_node, srtpSecureSignaling);
+ NODE_READ_NUM_T ( this_node, pjsua_ipv6_use, ipv6Use);
+ NODE_READ_OBJ ( this_node, transportConfig);
+}
+
+void AccountMediaConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+ ContainerNode this_node = node.writeNewContainer("AccountMediaConfig");
+
+ NODE_WRITE_BOOL ( this_node, lockCodecEnabled);
+ NODE_WRITE_BOOL ( this_node, streamKaEnabled);
+ NODE_WRITE_NUM_T ( this_node, pjmedia_srtp_use, srtpUse);
+ NODE_WRITE_INT ( this_node, srtpSecureSignaling);
+ NODE_WRITE_NUM_T ( this_node, pjsua_ipv6_use, ipv6Use);
+ NODE_WRITE_OBJ ( this_node, transportConfig);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountVideoConfig::readObject(const ContainerNode &node) throw(Error)
+{
+ ContainerNode this_node = node.readContainer("AccountVideoConfig");
+
+ NODE_READ_BOOL ( this_node, autoShowIncoming);
+ NODE_READ_BOOL ( this_node, autoTransmitOutgoing);
+ NODE_READ_UNSIGNED( this_node, windowFlags);
+ NODE_READ_NUM_T ( this_node, pjmedia_vid_dev_index, defaultCaptureDevice);
+ NODE_READ_NUM_T ( this_node, pjmedia_vid_dev_index, defaultRenderDevice);
+ NODE_READ_NUM_T ( this_node, pjmedia_vid_stream_rc_method, rateControlMethod);
+ NODE_READ_UNSIGNED( this_node, rateControlBandwidth);
+}
+
+void AccountVideoConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+ ContainerNode this_node = node.writeNewContainer("AccountVideoConfig");
+
+ NODE_WRITE_BOOL ( this_node, autoShowIncoming);
+ NODE_WRITE_BOOL ( this_node, autoTransmitOutgoing);
+ NODE_WRITE_UNSIGNED( this_node, windowFlags);
+ NODE_WRITE_NUM_T ( this_node, pjmedia_vid_dev_index, defaultCaptureDevice);
+ NODE_WRITE_NUM_T ( this_node, pjmedia_vid_dev_index, defaultRenderDevice);
+ NODE_WRITE_NUM_T ( this_node, pjmedia_vid_stream_rc_method, rateControlMethod);
+ NODE_WRITE_UNSIGNED( this_node, rateControlBandwidth);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+AccountConfig::AccountConfig()
+{
+ pjsua_acc_config acc_cfg;
+ pjsua_acc_config_default(&acc_cfg);
+ pjsua_media_config med_cfg;
+ pjsua_media_config_default(&med_cfg);
+ fromPj(acc_cfg, &med_cfg);
+}
+
+/* Convert to pjsip. */
+void AccountConfig::toPj(pjsua_acc_config &ret) const
+{
+ unsigned i;
+
+ pjsua_acc_config_default(&ret);
+
+ // Global
+ ret.priority = priority;
+ ret.id = str2Pj(idUri);
+
+ // AccountRegConfig
+ ret.reg_uri = str2Pj(regConfig.registrarUri);
+ ret.register_on_acc_add = regConfig.registerOnAdd;
+ ret.reg_timeout = regConfig.timeoutSec;
+ ret.reg_retry_interval = regConfig.retryIntervalSec;
+ ret.reg_first_retry_interval= regConfig.firstRetryIntervalSec;
+ ret.reg_delay_before_refresh= regConfig.delayBeforeRefreshSec;
+ ret.drop_calls_on_reg_fail = regConfig.dropCallsOnFail;
+ ret.unreg_timeout = regConfig.unregWaitSec;
+ ret.reg_use_proxy = regConfig.proxyUse;
+ for (i=0; i<regConfig.headers.size(); ++i) {
+ pj_list_push_back(&ret.reg_hdr_list, &regConfig.headers[i].toPj());
+ }
+
+ // AccountSipConfig
+ ret.cred_count = 0;
+ if (sipConfig.authCreds.size() > PJ_ARRAY_SIZE(ret.cred_info))
+ PJSUA2_RAISE_ERROR(PJ_ETOOMANY);
+ for (i=0; i<sipConfig.authCreds.size(); ++i) {
+ const AuthCredInfo &src = sipConfig.authCreds[i];
+ pjsip_cred_info *dst = &ret.cred_info[i];
+
+ dst->realm = str2Pj(src.realm);
+ dst->scheme = str2Pj(src.scheme);
+ dst->username = str2Pj(src.username);
+ dst->data_type = src.dataType;
+ dst->data = str2Pj(src.data);
+ dst->ext.aka.k = str2Pj(src.akaK);
+ dst->ext.aka.op = str2Pj(src.akaOp);
+ dst->ext.aka.amf= str2Pj(src.akaAmf);
+
+ ret.cred_count++;
+ }
+ ret.proxy_cnt = 0;
+ if (sipConfig.proxies.size() > PJ_ARRAY_SIZE(ret.proxy))
+ PJSUA2_RAISE_ERROR(PJ_ETOOMANY);
+ for (i=0; i<sipConfig.proxies.size(); ++i) {
+ ret.proxy[ret.proxy_cnt++] = str2Pj(sipConfig.proxies[i]);
+ }
+ ret.force_contact = str2Pj(sipConfig.contactForced);
+ ret.contact_params = str2Pj(sipConfig.contactParams);
+ ret.contact_uri_params = str2Pj(sipConfig.contactUriParams);
+ ret.auth_pref.initial_auth = sipConfig.authInitialEmpty;
+ ret.auth_pref.algorithm = str2Pj(sipConfig.authInitialAlgorithm);
+ ret.transport_id = sipConfig.transportId;
+
+ // AccountCallConfig
+ ret.call_hold_type = callConfig.holdType;
+ ret.require_100rel = callConfig.prackUse;
+ ret.use_timer = callConfig.timerUse;
+ ret.timer_setting.min_se = callConfig.timerMinSESec;
+ ret.timer_setting.sess_expires = callConfig.timerSessExpiresSec;
+
+ // AccountPresConfig
+ for (i=0; i<presConfig.headers.size(); ++i) {
+ pj_list_push_back(&ret.sub_hdr_list, &presConfig.headers[i].toPj());
+ }
+ ret.publish_enabled = presConfig.publishEnabled;
+ ret.publish_opt.queue_request= presConfig.publishQueue;
+ ret.unpublish_max_wait_time_msec = presConfig.publishShutdownWaitMsec;
+ ret.pidf_tuple_id = str2Pj(presConfig.pidfTupleId);
+
+ // AccountNatConfig
+ ret.sip_stun_use = natConfig.sipStunUse;
+ ret.media_stun_use = natConfig.mediaStunUse;
+ ret.ice_cfg_use = PJSUA_ICE_CONFIG_USE_CUSTOM;
+ ret.ice_cfg.enable_ice = natConfig.iceEnabled;
+ ret.ice_cfg.ice_max_host_cands = natConfig.iceMaxHostCands;
+ ret.ice_cfg.ice_opt.aggressive = natConfig.iceAggressiveNomination;
+ ret.ice_cfg.ice_opt.nominated_check_delay = natConfig.iceNominatedCheckDelayMsec;
+ ret.ice_cfg.ice_opt.controlled_agent_want_nom_timeout = natConfig.iceWaitNominationTimeoutMsec;
+ ret.ice_cfg.ice_no_rtcp = natConfig.iceNoRtcp;
+ ret.ice_cfg.ice_always_update = natConfig.iceAlwaysUpdate;
+
+ ret.turn_cfg_use = PJSUA_TURN_CONFIG_USE_CUSTOM;
+ ret.turn_cfg.enable_turn = natConfig.turnEnabled;
+ ret.turn_cfg.turn_server = str2Pj(natConfig.turnServer);
+ ret.turn_cfg.turn_conn_type = natConfig.turnConnType;
+ ret.turn_cfg.turn_auth_cred.type = PJ_STUN_AUTH_CRED_STATIC;
+ ret.turn_cfg.turn_auth_cred.data.static_cred.username = str2Pj(natConfig.turnUserName);
+ ret.turn_cfg.turn_auth_cred.data.static_cred.data_type = (pj_stun_passwd_type)natConfig.turnPasswordType;
+ ret.turn_cfg.turn_auth_cred.data.static_cred.data = str2Pj(natConfig.turnPassword);
+ ret.turn_cfg.turn_auth_cred.data.static_cred.realm = pj_str((char*)"");
+ ret.turn_cfg.turn_auth_cred.data.static_cred.nonce = pj_str((char*)"");
+
+ ret.allow_contact_rewrite = natConfig.contactRewriteUse;
+ ret.contact_rewrite_method = natConfig.contactRewriteMethod;
+ ret.allow_via_rewrite = natConfig.viaRewriteUse;
+ ret.allow_sdp_nat_rewrite = natConfig.sdpNatRewriteUse;
+ ret.use_rfc5626 = natConfig.sipOutboundUse;
+ ret.rfc5626_instance_id = str2Pj(natConfig.sipOutboundInstanceId);
+ ret.rfc5626_reg_id = str2Pj(natConfig.sipOutboundRegId);
+ ret.ka_interval = natConfig.udpKaIntervalSec;
+ ret.ka_data = str2Pj(natConfig.udpKaData);
+
+ // AccountMediaConfig
+ ret.rtp_cfg = mediaConfig.transportConfig.toPj();
+ ret.lock_codec = mediaConfig.lockCodecEnabled;
+#if defined(PJMEDIA_STREAM_ENABLE_KA) && (PJMEDIA_STREAM_ENABLE_KA != 0)
+ ret.use_stream_ka = mediaConfig.streamKaEnabled;
+#endif
+ ret.use_srtp = mediaConfig.srtpUse;
+ ret.srtp_secure_signaling = mediaConfig.srtpSecureSignaling;
+ ret.ipv6_media_use = mediaConfig.ipv6Use;
+
+ // AccountVideoConfig
+ ret.vid_in_auto_show = videoConfig.autoShowIncoming;
+ ret.vid_out_auto_transmit = videoConfig.autoTransmitOutgoing;
+ ret.vid_wnd_flags = videoConfig.windowFlags;
+ ret.vid_cap_dev = videoConfig.defaultCaptureDevice;
+ ret.vid_rend_dev = videoConfig.defaultRenderDevice;
+ ret.vid_stream_rc_cfg.method= videoConfig.rateControlMethod;
+ ret.vid_stream_rc_cfg.bandwidth = videoConfig.rateControlBandwidth;
+}
+
+/* Initialize from pjsip. */
+void AccountConfig::fromPj(const pjsua_acc_config &prm,
+ const pjsua_media_config *mcfg)
+{
+ const pjsip_hdr *hdr;
+ unsigned i;
+
+ // Global
+ priority = prm.priority;
+ idUri = pj2Str(prm.id);
+
+ // AccountRegConfig
+ regConfig.registrarUri = pj2Str(prm.reg_uri);
+ regConfig.registerOnAdd = (prm.register_on_acc_add != 0);
+ regConfig.timeoutSec = prm.reg_timeout;
+ regConfig.retryIntervalSec = prm.reg_retry_interval;
+ regConfig.firstRetryIntervalSec = prm.reg_first_retry_interval;
+ regConfig.delayBeforeRefreshSec = prm.reg_delay_before_refresh;
+ regConfig.dropCallsOnFail = PJ2BOOL(prm.drop_calls_on_reg_fail);
+ regConfig.unregWaitSec = prm.unreg_timeout;
+ regConfig.proxyUse = prm.reg_use_proxy;
+ regConfig.headers.clear();
+ hdr = prm.reg_hdr_list.next;
+ while (hdr != &prm.reg_hdr_list) {
+ SipHeader new_hdr;
+ new_hdr.fromPj(hdr);
+
+ regConfig.headers.push_back(new_hdr);
+
+ hdr = hdr->next;
+ }
+
+ // AccountSipConfig
+ sipConfig.authCreds.clear();
+ for (i=0; i<prm.cred_count; ++i) {
+ AuthCredInfo cred;
+ const pjsip_cred_info &src = prm.cred_info[i];
+
+ cred.realm = pj2Str(src.realm);
+ cred.scheme = pj2Str(src.scheme);
+ cred.username = pj2Str(src.username);
+ cred.dataType = src.data_type;
+ cred.data = pj2Str(src.data);
+ cred.akaK = pj2Str(src.ext.aka.k);
+ cred.akaOp = pj2Str(src.ext.aka.op);
+ cred.akaAmf = pj2Str(src.ext.aka.amf);
+
+ sipConfig.authCreds.push_back(cred);
+ }
+ sipConfig.proxies.clear();
+ for (i=0; i<prm.proxy_cnt; ++i) {
+ sipConfig.proxies.push_back(pj2Str(prm.proxy[i]));
+ }
+ sipConfig.contactForced = pj2Str(prm.force_contact);
+ sipConfig.contactParams = pj2Str(prm.contact_params);
+ sipConfig.contactUriParams = pj2Str(prm.contact_uri_params);
+ sipConfig.authInitialEmpty = PJ2BOOL(prm.auth_pref.initial_auth);
+ sipConfig.authInitialAlgorithm = pj2Str(prm.auth_pref.algorithm);
+ sipConfig.transportId = prm.transport_id;
+
+ // AccountCallConfig
+ callConfig.holdType = prm.call_hold_type;
+ callConfig.prackUse = prm.require_100rel;
+ callConfig.timerUse = prm.use_timer;
+ callConfig.timerMinSESec = prm.timer_setting.min_se;
+ callConfig.timerSessExpiresSec = prm.timer_setting.sess_expires;
+
+ // AccountPresConfig
+ presConfig.headers.clear();
+ hdr = prm.sub_hdr_list.next;
+ while (hdr != &prm.sub_hdr_list) {
+ SipHeader new_hdr;
+ new_hdr.fromPj(hdr);
+ presConfig.headers.push_back(new_hdr);
+ hdr = hdr->next;
+ }
+ presConfig.publishEnabled = PJ2BOOL(prm.publish_enabled);
+ presConfig.publishQueue = PJ2BOOL(prm.publish_opt.queue_request);
+ presConfig.publishShutdownWaitMsec = prm.unpublish_max_wait_time_msec;
+ presConfig.pidfTupleId = pj2Str(prm.pidf_tuple_id);
+
+ // AccountMwiConfig
+ mwiConfig.enabled = PJ2BOOL(prm.mwi_enabled);
+ mwiConfig.expirationSec = prm.mwi_expires;
+
+ // AccountNatConfig
+ natConfig.sipStunUse = prm.sip_stun_use;
+ natConfig.mediaStunUse = prm.media_stun_use;
+ if (prm.ice_cfg_use == PJSUA_ICE_CONFIG_USE_CUSTOM) {
+ natConfig.iceEnabled = PJ2BOOL(prm.ice_cfg.enable_ice);
+ natConfig.iceMaxHostCands = prm.ice_cfg.ice_max_host_cands;
+ natConfig.iceAggressiveNomination = PJ2BOOL(prm.ice_cfg.ice_opt.aggressive);
+ natConfig.iceNominatedCheckDelayMsec = prm.ice_cfg.ice_opt.nominated_check_delay;
+ natConfig.iceWaitNominationTimeoutMsec = prm.ice_cfg.ice_opt.controlled_agent_want_nom_timeout;
+ natConfig.iceNoRtcp = PJ2BOOL(prm.ice_cfg.ice_no_rtcp);
+ natConfig.iceAlwaysUpdate = PJ2BOOL(prm.ice_cfg.ice_always_update);
+ } else {
+ pjsua_media_config default_mcfg;
+ if (!mcfg) {
+ pjsua_media_config_default(&default_mcfg);
+ mcfg = &default_mcfg;
+ }
+ natConfig.iceEnabled = PJ2BOOL(mcfg->enable_ice);
+ natConfig.iceMaxHostCands= mcfg->ice_max_host_cands;
+ natConfig.iceAggressiveNomination = PJ2BOOL(mcfg->ice_opt.aggressive);
+ natConfig.iceNominatedCheckDelayMsec = mcfg->ice_opt.nominated_check_delay;
+ natConfig.iceWaitNominationTimeoutMsec = mcfg->ice_opt.controlled_agent_want_nom_timeout;
+ natConfig.iceNoRtcp = PJ2BOOL(mcfg->ice_no_rtcp);
+ natConfig.iceAlwaysUpdate = PJ2BOOL(mcfg->ice_always_update);
+ }
+
+ if (prm.turn_cfg_use == PJSUA_TURN_CONFIG_USE_CUSTOM) {
+ natConfig.turnEnabled = PJ2BOOL(prm.turn_cfg.enable_turn);
+ natConfig.turnServer = pj2Str(prm.turn_cfg.turn_server);
+ natConfig.turnConnType = prm.turn_cfg.turn_conn_type;
+ natConfig.turnUserName = pj2Str(prm.turn_cfg.turn_auth_cred.data.static_cred.username);
+ natConfig.turnPasswordType = prm.turn_cfg.turn_auth_cred.data.static_cred.data_type;
+ natConfig.turnPassword = pj2Str(prm.turn_cfg.turn_auth_cred.data.static_cred.data);
+ } else {
+ pjsua_media_config default_mcfg;
+ if (!mcfg) {
+ pjsua_media_config_default(&default_mcfg);
+ mcfg = &default_mcfg;
+ }
+ natConfig.turnEnabled = PJ2BOOL(mcfg->enable_turn);
+ natConfig.turnServer = pj2Str(mcfg->turn_server);
+ natConfig.turnConnType = mcfg->turn_conn_type;
+ natConfig.turnUserName = pj2Str(mcfg->turn_auth_cred.data.static_cred.username);
+ natConfig.turnPasswordType = mcfg->turn_auth_cred.data.static_cred.data_type;
+ natConfig.turnPassword = pj2Str(mcfg->turn_auth_cred.data.static_cred.data);
+ }
+ natConfig.contactRewriteUse = prm.allow_contact_rewrite;
+ natConfig.contactRewriteMethod = prm.contact_rewrite_method;
+ natConfig.viaRewriteUse = prm.allow_via_rewrite;
+ natConfig.sdpNatRewriteUse = prm.allow_sdp_nat_rewrite;
+ natConfig.sipOutboundUse = prm.use_rfc5626;
+ natConfig.sipOutboundInstanceId = pj2Str(prm.rfc5626_instance_id);
+ natConfig.sipOutboundRegId = pj2Str(prm.rfc5626_reg_id);
+ natConfig.udpKaIntervalSec = prm.ka_interval;
+ natConfig.udpKaData = pj2Str(prm.ka_data);
+
+ // AccountMediaConfig
+ mediaConfig.transportConfig.fromPj(prm.rtp_cfg);
+ mediaConfig.lockCodecEnabled= PJ2BOOL(prm.lock_codec);
+#if defined(PJMEDIA_STREAM_ENABLE_KA) && (PJMEDIA_STREAM_ENABLE_KA != 0)
+ mediaConfig.streamKaEnabled = PJ2BOOL(prm.use_stream_ka);
+#else
+ mediaConfig.streamKaEnabled = false;
+#endif
+ mediaConfig.srtpUse = prm.use_srtp;
+ mediaConfig.srtpSecureSignaling = prm.srtp_secure_signaling;
+ mediaConfig.ipv6Use = prm.ipv6_media_use;
+
+ // AccountVideoConfig
+ videoConfig.autoShowIncoming = PJ2BOOL(prm.vid_in_auto_show);
+ videoConfig.autoTransmitOutgoing = PJ2BOOL(prm.vid_out_auto_transmit);
+ videoConfig.windowFlags = prm.vid_wnd_flags;
+ videoConfig.defaultCaptureDevice = prm.vid_cap_dev;
+ videoConfig.defaultRenderDevice = prm.vid_rend_dev;
+ videoConfig.rateControlMethod = prm.vid_stream_rc_cfg.method;
+ videoConfig.rateControlBandwidth = prm.vid_stream_rc_cfg.bandwidth;
+}
+
+void AccountConfig::readObject(const ContainerNode &node) throw(Error)
+{
+ ContainerNode this_node = node.readContainer("AccountConfig");
+
+ NODE_READ_INT ( this_node, priority);
+ NODE_READ_STRING ( this_node, idUri);
+ NODE_READ_OBJ ( this_node, regConfig);
+ NODE_READ_OBJ ( this_node, sipConfig);
+ NODE_READ_OBJ ( this_node, callConfig);
+ NODE_READ_OBJ ( this_node, presConfig);
+ NODE_READ_OBJ ( this_node, mwiConfig);
+ NODE_READ_OBJ ( this_node, natConfig);
+ NODE_READ_OBJ ( this_node, mediaConfig);
+ NODE_READ_OBJ ( this_node, videoConfig);
+}
+
+void AccountConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+ ContainerNode this_node = node.writeNewContainer("AccountConfig");
+
+ NODE_WRITE_INT ( this_node, priority);
+ NODE_WRITE_STRING ( this_node, idUri);
+ NODE_WRITE_OBJ ( this_node, regConfig);
+ NODE_WRITE_OBJ ( this_node, sipConfig);
+ NODE_WRITE_OBJ ( this_node, callConfig);
+ NODE_WRITE_OBJ ( this_node, presConfig);
+ NODE_WRITE_OBJ ( this_node, mwiConfig);
+ NODE_WRITE_OBJ ( this_node, natConfig);
+ NODE_WRITE_OBJ ( this_node, mediaConfig);
+ NODE_WRITE_OBJ ( this_node, videoConfig);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountInfo::fromPj(const pjsua_acc_info &pai)
+{
+ id = pai.id;
+ isDefault = pai.is_default != 0;
+ uri = pj2Str(pai.acc_uri);
+ regIsConfigured = pai.has_registration != 0;
+ regIsActive = pai.has_registration && pai.expires > 0 &&
+ (pai.status / 100 == 2);
+ regExpiresSec = pai.expires;
+ regStatus = pai.status;
+ regStatusText = pj2Str(pai.status_text);
+ regLastErr = pai.reg_last_err;
+ onlineStatus = pai.online_status != 0;
+ onlineStatusText = pj2Str(pai.online_status_text);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Account::Account()
+: id(PJSUA_INVALID_ID)
+{
+}
+
+Account::~Account()
+{
+ /* If this instance is deleted, also delete the corresponding account in
+ * PJSUA library.
+ */
+ if (isValid() && pjsua_get_state() < PJSUA_STATE_CLOSING) {
+ // Cleanup buddies in the buddy list
+ while(buddyList.size() > 0) {
+ Buddy *b = buddyList[0];
+ delete b; /* this will remove itself from the list */
+ }
+
+ pjsua_acc_set_user_data(id, NULL);
+ pjsua_acc_del(id);
+ }
+}
+
+void Account::create(const AccountConfig &acc_cfg,
+ bool make_default) throw(Error)
+{
+ pjsua_acc_config pj_acc_cfg;
+
+ acc_cfg.toPj(pj_acc_cfg);
+ pj_acc_cfg.user_data = (void*)this;
+ PJSUA2_CHECK_EXPR( pjsua_acc_add(&pj_acc_cfg, make_default, &id) );
+}
+
+void Account::modify(const AccountConfig &acc_cfg) throw(Error)
+{
+ pjsua_acc_config pj_acc_cfg;
+
+ acc_cfg.toPj(pj_acc_cfg);
+ pj_acc_cfg.user_data = (void*)this;
+ PJSUA2_CHECK_EXPR( pjsua_acc_modify(id, &pj_acc_cfg) );
+}
+
+bool Account::isValid() const
+{
+ return pjsua_acc_is_valid(id) != 0;
+}
+
+void Account::setDefault() throw(Error)
+{
+ PJSUA2_CHECK_EXPR( pjsua_acc_set_default(id) );
+}
+
+bool Account::isDefault() const
+{
+ return pjsua_acc_get_default() == id;
+}
+
+int Account::getId() const
+{
+ return id;
+}
+
+Account *Account::lookup(int acc_id)
+{
+ return (Account*)pjsua_acc_get_user_data(acc_id);
+}
+
+AccountInfo Account::getInfo() const throw(Error)
+{
+ pjsua_acc_info pj_ai;
+ AccountInfo ai;
+
+ PJSUA2_CHECK_EXPR( pjsua_acc_get_info(id, &pj_ai) );
+ ai.fromPj(pj_ai);
+ return ai;
+}
+
+void Account::setRegistration(bool renew) throw(Error)
+{
+ PJSUA2_CHECK_EXPR( pjsua_acc_set_registration(id, renew) );
+}
+
+void
+Account::setOnlineStatus(const PresenceStatus &pres_st) throw(Error)
+{
+ pjrpid_element pj_rpid;
+
+ pj_bzero(&pj_rpid, sizeof(pj_rpid));
+ pj_rpid.type = PJRPID_ELEMENT_TYPE_PERSON;
+ pj_rpid.activity = pres_st.activity;
+ pj_rpid.id = str2Pj(pres_st.rpidId);
+ pj_rpid.note = str2Pj(pres_st.note);
+
+ PJSUA2_CHECK_EXPR( pjsua_acc_set_online_status2(
+ id, pres_st.status == PJSUA_BUDDY_STATUS_ONLINE,
+ &pj_rpid) );
+}
+
+void Account::setTransport(TransportId tp_id) throw(Error)
+{
+ PJSUA2_CHECK_EXPR( pjsua_acc_set_transport(id, tp_id) );
+}
+
+void Account::presNotify(const PresNotifyParam &prm) throw(Error)
+{
+ pj_str_t pj_state_str = str2Pj(prm.stateStr);
+ pj_str_t pj_reason = str2Pj(prm.reason);
+ pjsua_msg_data msg_data;
+ prm.txOption.toPj(msg_data);
+
+ PJSUA2_CHECK_EXPR( pjsua_pres_notify(id, (pjsua_srv_pres*)prm.srvPres,
+ prm.state, &pj_state_str,
+ &pj_reason, prm.withBody,
+ &msg_data) );
+}
+
+const BuddyVector& Account::enumBuddies() const throw(Error)
+{
+ return buddyList;
+}
+
+Buddy* Account::findBuddy(string uri, FindBuddyMatch *buddy_match) const
+ throw(Error)
+{
+ if (!buddy_match) {
+ static FindBuddyMatch def_bm;
+ buddy_match = &def_bm;
+ }
+
+ for (unsigned i = 0; i < buddyList.size(); i++) {
+ if (buddy_match->match(uri, *buddyList[i]))
+ return buddyList[i];
+ }
+ PJSUA2_RAISE_ERROR(PJ_ENOTFOUND);
+}
+
+void Account::addBuddy(Buddy *buddy)
+{
+ pj_assert(buddy);
+
+ buddyList.push_back(buddy);
+}
+
+void Account::removeBuddy(Buddy *buddy)
+{
+ pj_assert(buddy);
+
+ BuddyVector::iterator it;
+ for (it = buddyList.begin(); it != buddyList.end(); it++) {
+ if (*it == buddy) {
+ buddyList.erase(it);
+ return;
+ }
+ }
+
+ pj_assert(!"Bug! Buddy to be removed is not in the buddy list!");
+}