Alexandre Lision | 0e14301 | 2014-01-22 11:02:46 -0500 | [diff] [blame^] | 1 | /* $Id: account.cpp 4704 2014-01-16 05:30:46Z ming $ */ |
| 2 | /* |
| 3 | * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com) |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation; either version 2 of the License, or |
| 8 | * (at your option) any later version. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 18 | */ |
| 19 | #include <pjsua2/account.hpp> |
| 20 | #include <pjsua2/endpoint.hpp> |
| 21 | #include <pjsua2/presence.hpp> |
| 22 | #include <pj/ctype.h> |
| 23 | #include "util.hpp" |
| 24 | |
| 25 | using namespace pj; |
| 26 | using namespace std; |
| 27 | |
| 28 | #define THIS_FILE "account.cpp" |
| 29 | |
| 30 | /////////////////////////////////////////////////////////////////////////////// |
| 31 | |
| 32 | void AccountRegConfig::readObject(const ContainerNode &node) throw(Error) |
| 33 | { |
| 34 | ContainerNode this_node = node.readContainer("AccountRegConfig"); |
| 35 | |
| 36 | NODE_READ_STRING (this_node, registrarUri); |
| 37 | NODE_READ_BOOL (this_node, registerOnAdd); |
| 38 | NODE_READ_UNSIGNED (this_node, timeoutSec); |
| 39 | NODE_READ_UNSIGNED (this_node, retryIntervalSec); |
| 40 | NODE_READ_UNSIGNED (this_node, firstRetryIntervalSec); |
| 41 | NODE_READ_UNSIGNED (this_node, delayBeforeRefreshSec); |
| 42 | NODE_READ_BOOL (this_node, dropCallsOnFail); |
| 43 | NODE_READ_UNSIGNED (this_node, unregWaitSec); |
| 44 | NODE_READ_UNSIGNED (this_node, proxyUse); |
| 45 | |
| 46 | readSipHeaders(this_node, "headers", headers); |
| 47 | } |
| 48 | |
| 49 | void AccountRegConfig::writeObject(ContainerNode &node) const throw(Error) |
| 50 | { |
| 51 | ContainerNode this_node = node.writeNewContainer("AccountRegConfig"); |
| 52 | |
| 53 | NODE_WRITE_STRING (this_node, registrarUri); |
| 54 | NODE_WRITE_BOOL (this_node, registerOnAdd); |
| 55 | NODE_WRITE_UNSIGNED (this_node, timeoutSec); |
| 56 | NODE_WRITE_UNSIGNED (this_node, retryIntervalSec); |
| 57 | NODE_WRITE_UNSIGNED (this_node, firstRetryIntervalSec); |
| 58 | NODE_WRITE_UNSIGNED (this_node, delayBeforeRefreshSec); |
| 59 | NODE_WRITE_BOOL (this_node, dropCallsOnFail); |
| 60 | NODE_WRITE_UNSIGNED (this_node, unregWaitSec); |
| 61 | NODE_WRITE_UNSIGNED (this_node, proxyUse); |
| 62 | |
| 63 | writeSipHeaders(this_node, "headers", headers); |
| 64 | } |
| 65 | |
| 66 | /////////////////////////////////////////////////////////////////////////////// |
| 67 | |
| 68 | void AccountSipConfig::readObject(const ContainerNode &node) throw(Error) |
| 69 | { |
| 70 | ContainerNode this_node = node.readContainer("AccountSipConfig"); |
| 71 | |
| 72 | NODE_READ_STRINGV (this_node, proxies); |
| 73 | NODE_READ_STRING (this_node, contactForced); |
| 74 | NODE_READ_STRING (this_node, contactParams); |
| 75 | NODE_READ_STRING (this_node, contactUriParams); |
| 76 | NODE_READ_BOOL (this_node, authInitialEmpty); |
| 77 | NODE_READ_STRING (this_node, authInitialAlgorithm); |
| 78 | NODE_READ_INT (this_node, transportId); |
| 79 | |
| 80 | ContainerNode creds_node = this_node.readArray("authCreds"); |
| 81 | authCreds.resize(0); |
| 82 | while (creds_node.hasUnread()) { |
| 83 | AuthCredInfo cred; |
| 84 | cred.readObject(creds_node); |
| 85 | authCreds.push_back(cred); |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | void AccountSipConfig::writeObject(ContainerNode &node) const throw(Error) |
| 90 | { |
| 91 | ContainerNode this_node = node.writeNewContainer("AccountSipConfig"); |
| 92 | |
| 93 | NODE_WRITE_STRINGV (this_node, proxies); |
| 94 | NODE_WRITE_STRING (this_node, contactForced); |
| 95 | NODE_WRITE_STRING (this_node, contactParams); |
| 96 | NODE_WRITE_STRING (this_node, contactUriParams); |
| 97 | NODE_WRITE_BOOL (this_node, authInitialEmpty); |
| 98 | NODE_WRITE_STRING (this_node, authInitialAlgorithm); |
| 99 | NODE_WRITE_INT (this_node, transportId); |
| 100 | |
| 101 | ContainerNode creds_node = this_node.writeNewArray("authCreds"); |
| 102 | for (unsigned i=0; i<authCreds.size(); ++i) { |
| 103 | authCreds[i].writeObject(creds_node); |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | /////////////////////////////////////////////////////////////////////////////// |
| 108 | |
| 109 | void AccountCallConfig::readObject(const ContainerNode &node) throw(Error) |
| 110 | { |
| 111 | ContainerNode this_node = node.readContainer("AccountCallConfig"); |
| 112 | |
| 113 | NODE_READ_NUM_T ( this_node, pjsua_call_hold_type, holdType); |
| 114 | NODE_READ_NUM_T ( this_node, pjsua_100rel_use, prackUse); |
| 115 | NODE_READ_NUM_T ( this_node, pjsua_sip_timer_use, timerUse); |
| 116 | NODE_READ_UNSIGNED( this_node, timerMinSESec); |
| 117 | NODE_READ_UNSIGNED( this_node, timerSessExpiresSec); |
| 118 | } |
| 119 | |
| 120 | void AccountCallConfig::writeObject(ContainerNode &node) const throw(Error) |
| 121 | { |
| 122 | ContainerNode this_node = node.writeNewContainer("AccountCallConfig"); |
| 123 | |
| 124 | NODE_WRITE_NUM_T ( this_node, pjsua_call_hold_type, holdType); |
| 125 | NODE_WRITE_NUM_T ( this_node, pjsua_100rel_use, prackUse); |
| 126 | NODE_WRITE_NUM_T ( this_node, pjsua_sip_timer_use, timerUse); |
| 127 | NODE_WRITE_UNSIGNED( this_node, timerMinSESec); |
| 128 | NODE_WRITE_UNSIGNED( this_node, timerSessExpiresSec); |
| 129 | } |
| 130 | |
| 131 | /////////////////////////////////////////////////////////////////////////////// |
| 132 | |
| 133 | void AccountPresConfig::readObject(const ContainerNode &node) throw(Error) |
| 134 | { |
| 135 | ContainerNode this_node = node.readContainer("AccountPresConfig"); |
| 136 | |
| 137 | NODE_READ_BOOL ( this_node, publishEnabled); |
| 138 | NODE_READ_BOOL ( this_node, publishQueue); |
| 139 | NODE_READ_UNSIGNED( this_node, publishShutdownWaitMsec); |
| 140 | NODE_READ_STRING ( this_node, pidfTupleId); |
| 141 | |
| 142 | readSipHeaders(this_node, "headers", headers); |
| 143 | } |
| 144 | |
| 145 | void AccountPresConfig::writeObject(ContainerNode &node) const throw(Error) |
| 146 | { |
| 147 | ContainerNode this_node = node.writeNewContainer("AccountPresConfig"); |
| 148 | |
| 149 | NODE_WRITE_BOOL ( this_node, publishEnabled); |
| 150 | NODE_WRITE_BOOL ( this_node, publishQueue); |
| 151 | NODE_WRITE_UNSIGNED( this_node, publishShutdownWaitMsec); |
| 152 | NODE_WRITE_STRING ( this_node, pidfTupleId); |
| 153 | |
| 154 | writeSipHeaders(this_node, "headers", headers); |
| 155 | } |
| 156 | |
| 157 | /////////////////////////////////////////////////////////////////////////////// |
| 158 | |
| 159 | void AccountMwiConfig::readObject(const ContainerNode &node) throw(Error) |
| 160 | { |
| 161 | ContainerNode this_node = node.readContainer("AccountMwiConfig"); |
| 162 | |
| 163 | NODE_READ_BOOL ( this_node, enabled); |
| 164 | NODE_READ_UNSIGNED( this_node, expirationSec); |
| 165 | } |
| 166 | |
| 167 | void AccountMwiConfig::writeObject(ContainerNode &node) const throw(Error) |
| 168 | { |
| 169 | ContainerNode this_node = node.writeNewContainer("AccountMwiConfig"); |
| 170 | |
| 171 | NODE_WRITE_BOOL ( this_node, enabled); |
| 172 | NODE_WRITE_UNSIGNED( this_node, expirationSec); |
| 173 | } |
| 174 | |
| 175 | /////////////////////////////////////////////////////////////////////////////// |
| 176 | |
| 177 | void AccountNatConfig::readObject(const ContainerNode &node) throw(Error) |
| 178 | { |
| 179 | ContainerNode this_node = node.readContainer("AccountNatConfig"); |
| 180 | |
| 181 | NODE_READ_NUM_T ( this_node, pjsua_stun_use, sipStunUse); |
| 182 | NODE_READ_NUM_T ( this_node, pjsua_stun_use, mediaStunUse); |
| 183 | NODE_READ_BOOL ( this_node, iceEnabled); |
| 184 | NODE_READ_INT ( this_node, iceMaxHostCands); |
| 185 | NODE_READ_BOOL ( this_node, iceAggressiveNomination); |
| 186 | NODE_READ_UNSIGNED( this_node, iceNominatedCheckDelayMsec); |
| 187 | NODE_READ_INT ( this_node, iceWaitNominationTimeoutMsec); |
| 188 | NODE_READ_BOOL ( this_node, iceNoRtcp); |
| 189 | NODE_READ_BOOL ( this_node, iceAlwaysUpdate); |
| 190 | NODE_READ_BOOL ( this_node, turnEnabled); |
| 191 | NODE_READ_STRING ( this_node, turnServer); |
| 192 | NODE_READ_NUM_T ( this_node, pj_turn_tp_type, turnConnType); |
| 193 | NODE_READ_STRING ( this_node, turnUserName); |
| 194 | NODE_READ_INT ( this_node, turnPasswordType); |
| 195 | NODE_READ_STRING ( this_node, turnPassword); |
| 196 | NODE_READ_INT ( this_node, contactRewriteUse); |
| 197 | NODE_READ_INT ( this_node, contactRewriteMethod); |
| 198 | NODE_READ_INT ( this_node, viaRewriteUse); |
| 199 | NODE_READ_INT ( this_node, sdpNatRewriteUse); |
| 200 | NODE_READ_INT ( this_node, sipOutboundUse); |
| 201 | NODE_READ_STRING ( this_node, sipOutboundInstanceId); |
| 202 | NODE_READ_STRING ( this_node, sipOutboundRegId); |
| 203 | NODE_READ_UNSIGNED( this_node, udpKaIntervalSec); |
| 204 | NODE_READ_STRING ( this_node, udpKaData); |
| 205 | } |
| 206 | |
| 207 | void AccountNatConfig::writeObject(ContainerNode &node) const throw(Error) |
| 208 | { |
| 209 | ContainerNode this_node = node.writeNewContainer("AccountNatConfig"); |
| 210 | |
| 211 | NODE_WRITE_NUM_T ( this_node, pjsua_stun_use, sipStunUse); |
| 212 | NODE_WRITE_NUM_T ( this_node, pjsua_stun_use, mediaStunUse); |
| 213 | NODE_WRITE_BOOL ( this_node, iceEnabled); |
| 214 | NODE_WRITE_INT ( this_node, iceMaxHostCands); |
| 215 | NODE_WRITE_BOOL ( this_node, iceAggressiveNomination); |
| 216 | NODE_WRITE_UNSIGNED( this_node, iceNominatedCheckDelayMsec); |
| 217 | NODE_WRITE_INT ( this_node, iceWaitNominationTimeoutMsec); |
| 218 | NODE_WRITE_BOOL ( this_node, iceNoRtcp); |
| 219 | NODE_WRITE_BOOL ( this_node, iceAlwaysUpdate); |
| 220 | NODE_WRITE_BOOL ( this_node, turnEnabled); |
| 221 | NODE_WRITE_STRING ( this_node, turnServer); |
| 222 | NODE_WRITE_NUM_T ( this_node, pj_turn_tp_type, turnConnType); |
| 223 | NODE_WRITE_STRING ( this_node, turnUserName); |
| 224 | NODE_WRITE_INT ( this_node, turnPasswordType); |
| 225 | NODE_WRITE_STRING ( this_node, turnPassword); |
| 226 | NODE_WRITE_INT ( this_node, contactRewriteUse); |
| 227 | NODE_WRITE_INT ( this_node, contactRewriteMethod); |
| 228 | NODE_WRITE_INT ( this_node, viaRewriteUse); |
| 229 | NODE_WRITE_INT ( this_node, sdpNatRewriteUse); |
| 230 | NODE_WRITE_INT ( this_node, sipOutboundUse); |
| 231 | NODE_WRITE_STRING ( this_node, sipOutboundInstanceId); |
| 232 | NODE_WRITE_STRING ( this_node, sipOutboundRegId); |
| 233 | NODE_WRITE_UNSIGNED( this_node, udpKaIntervalSec); |
| 234 | NODE_WRITE_STRING ( this_node, udpKaData); |
| 235 | } |
| 236 | |
| 237 | /////////////////////////////////////////////////////////////////////////////// |
| 238 | |
| 239 | void AccountMediaConfig::readObject(const ContainerNode &node) throw(Error) |
| 240 | { |
| 241 | ContainerNode this_node = node.readContainer("AccountMediaConfig"); |
| 242 | |
| 243 | NODE_READ_BOOL ( this_node, lockCodecEnabled); |
| 244 | NODE_READ_BOOL ( this_node, streamKaEnabled); |
| 245 | NODE_READ_NUM_T ( this_node, pjmedia_srtp_use, srtpUse); |
| 246 | NODE_READ_INT ( this_node, srtpSecureSignaling); |
| 247 | NODE_READ_NUM_T ( this_node, pjsua_ipv6_use, ipv6Use); |
| 248 | NODE_READ_OBJ ( this_node, transportConfig); |
| 249 | } |
| 250 | |
| 251 | void AccountMediaConfig::writeObject(ContainerNode &node) const throw(Error) |
| 252 | { |
| 253 | ContainerNode this_node = node.writeNewContainer("AccountMediaConfig"); |
| 254 | |
| 255 | NODE_WRITE_BOOL ( this_node, lockCodecEnabled); |
| 256 | NODE_WRITE_BOOL ( this_node, streamKaEnabled); |
| 257 | NODE_WRITE_NUM_T ( this_node, pjmedia_srtp_use, srtpUse); |
| 258 | NODE_WRITE_INT ( this_node, srtpSecureSignaling); |
| 259 | NODE_WRITE_NUM_T ( this_node, pjsua_ipv6_use, ipv6Use); |
| 260 | NODE_WRITE_OBJ ( this_node, transportConfig); |
| 261 | } |
| 262 | |
| 263 | /////////////////////////////////////////////////////////////////////////////// |
| 264 | |
| 265 | void AccountVideoConfig::readObject(const ContainerNode &node) throw(Error) |
| 266 | { |
| 267 | ContainerNode this_node = node.readContainer("AccountVideoConfig"); |
| 268 | |
| 269 | NODE_READ_BOOL ( this_node, autoShowIncoming); |
| 270 | NODE_READ_BOOL ( this_node, autoTransmitOutgoing); |
| 271 | NODE_READ_UNSIGNED( this_node, windowFlags); |
| 272 | NODE_READ_NUM_T ( this_node, pjmedia_vid_dev_index, defaultCaptureDevice); |
| 273 | NODE_READ_NUM_T ( this_node, pjmedia_vid_dev_index, defaultRenderDevice); |
| 274 | NODE_READ_NUM_T ( this_node, pjmedia_vid_stream_rc_method, rateControlMethod); |
| 275 | NODE_READ_UNSIGNED( this_node, rateControlBandwidth); |
| 276 | } |
| 277 | |
| 278 | void AccountVideoConfig::writeObject(ContainerNode &node) const throw(Error) |
| 279 | { |
| 280 | ContainerNode this_node = node.writeNewContainer("AccountVideoConfig"); |
| 281 | |
| 282 | NODE_WRITE_BOOL ( this_node, autoShowIncoming); |
| 283 | NODE_WRITE_BOOL ( this_node, autoTransmitOutgoing); |
| 284 | NODE_WRITE_UNSIGNED( this_node, windowFlags); |
| 285 | NODE_WRITE_NUM_T ( this_node, pjmedia_vid_dev_index, defaultCaptureDevice); |
| 286 | NODE_WRITE_NUM_T ( this_node, pjmedia_vid_dev_index, defaultRenderDevice); |
| 287 | NODE_WRITE_NUM_T ( this_node, pjmedia_vid_stream_rc_method, rateControlMethod); |
| 288 | NODE_WRITE_UNSIGNED( this_node, rateControlBandwidth); |
| 289 | } |
| 290 | |
| 291 | /////////////////////////////////////////////////////////////////////////////// |
| 292 | |
| 293 | AccountConfig::AccountConfig() |
| 294 | { |
| 295 | pjsua_acc_config acc_cfg; |
| 296 | pjsua_acc_config_default(&acc_cfg); |
| 297 | pjsua_media_config med_cfg; |
| 298 | pjsua_media_config_default(&med_cfg); |
| 299 | fromPj(acc_cfg, &med_cfg); |
| 300 | } |
| 301 | |
| 302 | /* Convert to pjsip. */ |
| 303 | void AccountConfig::toPj(pjsua_acc_config &ret) const |
| 304 | { |
| 305 | unsigned i; |
| 306 | |
| 307 | pjsua_acc_config_default(&ret); |
| 308 | |
| 309 | // Global |
| 310 | ret.priority = priority; |
| 311 | ret.id = str2Pj(idUri); |
| 312 | |
| 313 | // AccountRegConfig |
| 314 | ret.reg_uri = str2Pj(regConfig.registrarUri); |
| 315 | ret.register_on_acc_add = regConfig.registerOnAdd; |
| 316 | ret.reg_timeout = regConfig.timeoutSec; |
| 317 | ret.reg_retry_interval = regConfig.retryIntervalSec; |
| 318 | ret.reg_first_retry_interval= regConfig.firstRetryIntervalSec; |
| 319 | ret.reg_delay_before_refresh= regConfig.delayBeforeRefreshSec; |
| 320 | ret.drop_calls_on_reg_fail = regConfig.dropCallsOnFail; |
| 321 | ret.unreg_timeout = regConfig.unregWaitSec; |
| 322 | ret.reg_use_proxy = regConfig.proxyUse; |
| 323 | for (i=0; i<regConfig.headers.size(); ++i) { |
| 324 | pj_list_push_back(&ret.reg_hdr_list, ®Config.headers[i].toPj()); |
| 325 | } |
| 326 | |
| 327 | // AccountSipConfig |
| 328 | ret.cred_count = 0; |
| 329 | if (sipConfig.authCreds.size() > PJ_ARRAY_SIZE(ret.cred_info)) |
| 330 | PJSUA2_RAISE_ERROR(PJ_ETOOMANY); |
| 331 | for (i=0; i<sipConfig.authCreds.size(); ++i) { |
| 332 | const AuthCredInfo &src = sipConfig.authCreds[i]; |
| 333 | pjsip_cred_info *dst = &ret.cred_info[i]; |
| 334 | |
| 335 | dst->realm = str2Pj(src.realm); |
| 336 | dst->scheme = str2Pj(src.scheme); |
| 337 | dst->username = str2Pj(src.username); |
| 338 | dst->data_type = src.dataType; |
| 339 | dst->data = str2Pj(src.data); |
| 340 | dst->ext.aka.k = str2Pj(src.akaK); |
| 341 | dst->ext.aka.op = str2Pj(src.akaOp); |
| 342 | dst->ext.aka.amf= str2Pj(src.akaAmf); |
| 343 | |
| 344 | ret.cred_count++; |
| 345 | } |
| 346 | ret.proxy_cnt = 0; |
| 347 | if (sipConfig.proxies.size() > PJ_ARRAY_SIZE(ret.proxy)) |
| 348 | PJSUA2_RAISE_ERROR(PJ_ETOOMANY); |
| 349 | for (i=0; i<sipConfig.proxies.size(); ++i) { |
| 350 | ret.proxy[ret.proxy_cnt++] = str2Pj(sipConfig.proxies[i]); |
| 351 | } |
| 352 | ret.force_contact = str2Pj(sipConfig.contactForced); |
| 353 | ret.contact_params = str2Pj(sipConfig.contactParams); |
| 354 | ret.contact_uri_params = str2Pj(sipConfig.contactUriParams); |
| 355 | ret.auth_pref.initial_auth = sipConfig.authInitialEmpty; |
| 356 | ret.auth_pref.algorithm = str2Pj(sipConfig.authInitialAlgorithm); |
| 357 | ret.transport_id = sipConfig.transportId; |
| 358 | |
| 359 | // AccountCallConfig |
| 360 | ret.call_hold_type = callConfig.holdType; |
| 361 | ret.require_100rel = callConfig.prackUse; |
| 362 | ret.use_timer = callConfig.timerUse; |
| 363 | ret.timer_setting.min_se = callConfig.timerMinSESec; |
| 364 | ret.timer_setting.sess_expires = callConfig.timerSessExpiresSec; |
| 365 | |
| 366 | // AccountPresConfig |
| 367 | for (i=0; i<presConfig.headers.size(); ++i) { |
| 368 | pj_list_push_back(&ret.sub_hdr_list, &presConfig.headers[i].toPj()); |
| 369 | } |
| 370 | ret.publish_enabled = presConfig.publishEnabled; |
| 371 | ret.publish_opt.queue_request= presConfig.publishQueue; |
| 372 | ret.unpublish_max_wait_time_msec = presConfig.publishShutdownWaitMsec; |
| 373 | ret.pidf_tuple_id = str2Pj(presConfig.pidfTupleId); |
| 374 | |
| 375 | // AccountNatConfig |
| 376 | ret.sip_stun_use = natConfig.sipStunUse; |
| 377 | ret.media_stun_use = natConfig.mediaStunUse; |
| 378 | ret.ice_cfg_use = PJSUA_ICE_CONFIG_USE_CUSTOM; |
| 379 | ret.ice_cfg.enable_ice = natConfig.iceEnabled; |
| 380 | ret.ice_cfg.ice_max_host_cands = natConfig.iceMaxHostCands; |
| 381 | ret.ice_cfg.ice_opt.aggressive = natConfig.iceAggressiveNomination; |
| 382 | ret.ice_cfg.ice_opt.nominated_check_delay = natConfig.iceNominatedCheckDelayMsec; |
| 383 | ret.ice_cfg.ice_opt.controlled_agent_want_nom_timeout = natConfig.iceWaitNominationTimeoutMsec; |
| 384 | ret.ice_cfg.ice_no_rtcp = natConfig.iceNoRtcp; |
| 385 | ret.ice_cfg.ice_always_update = natConfig.iceAlwaysUpdate; |
| 386 | |
| 387 | ret.turn_cfg_use = PJSUA_TURN_CONFIG_USE_CUSTOM; |
| 388 | ret.turn_cfg.enable_turn = natConfig.turnEnabled; |
| 389 | ret.turn_cfg.turn_server = str2Pj(natConfig.turnServer); |
| 390 | ret.turn_cfg.turn_conn_type = natConfig.turnConnType; |
| 391 | ret.turn_cfg.turn_auth_cred.type = PJ_STUN_AUTH_CRED_STATIC; |
| 392 | ret.turn_cfg.turn_auth_cred.data.static_cred.username = str2Pj(natConfig.turnUserName); |
| 393 | ret.turn_cfg.turn_auth_cred.data.static_cred.data_type = (pj_stun_passwd_type)natConfig.turnPasswordType; |
| 394 | ret.turn_cfg.turn_auth_cred.data.static_cred.data = str2Pj(natConfig.turnPassword); |
| 395 | ret.turn_cfg.turn_auth_cred.data.static_cred.realm = pj_str((char*)""); |
| 396 | ret.turn_cfg.turn_auth_cred.data.static_cred.nonce = pj_str((char*)""); |
| 397 | |
| 398 | ret.allow_contact_rewrite = natConfig.contactRewriteUse; |
| 399 | ret.contact_rewrite_method = natConfig.contactRewriteMethod; |
| 400 | ret.allow_via_rewrite = natConfig.viaRewriteUse; |
| 401 | ret.allow_sdp_nat_rewrite = natConfig.sdpNatRewriteUse; |
| 402 | ret.use_rfc5626 = natConfig.sipOutboundUse; |
| 403 | ret.rfc5626_instance_id = str2Pj(natConfig.sipOutboundInstanceId); |
| 404 | ret.rfc5626_reg_id = str2Pj(natConfig.sipOutboundRegId); |
| 405 | ret.ka_interval = natConfig.udpKaIntervalSec; |
| 406 | ret.ka_data = str2Pj(natConfig.udpKaData); |
| 407 | |
| 408 | // AccountMediaConfig |
| 409 | ret.rtp_cfg = mediaConfig.transportConfig.toPj(); |
| 410 | ret.lock_codec = mediaConfig.lockCodecEnabled; |
| 411 | #if defined(PJMEDIA_STREAM_ENABLE_KA) && (PJMEDIA_STREAM_ENABLE_KA != 0) |
| 412 | ret.use_stream_ka = mediaConfig.streamKaEnabled; |
| 413 | #endif |
| 414 | ret.use_srtp = mediaConfig.srtpUse; |
| 415 | ret.srtp_secure_signaling = mediaConfig.srtpSecureSignaling; |
| 416 | ret.ipv6_media_use = mediaConfig.ipv6Use; |
| 417 | |
| 418 | // AccountVideoConfig |
| 419 | ret.vid_in_auto_show = videoConfig.autoShowIncoming; |
| 420 | ret.vid_out_auto_transmit = videoConfig.autoTransmitOutgoing; |
| 421 | ret.vid_wnd_flags = videoConfig.windowFlags; |
| 422 | ret.vid_cap_dev = videoConfig.defaultCaptureDevice; |
| 423 | ret.vid_rend_dev = videoConfig.defaultRenderDevice; |
| 424 | ret.vid_stream_rc_cfg.method= videoConfig.rateControlMethod; |
| 425 | ret.vid_stream_rc_cfg.bandwidth = videoConfig.rateControlBandwidth; |
| 426 | } |
| 427 | |
| 428 | /* Initialize from pjsip. */ |
| 429 | void AccountConfig::fromPj(const pjsua_acc_config &prm, |
| 430 | const pjsua_media_config *mcfg) |
| 431 | { |
| 432 | const pjsip_hdr *hdr; |
| 433 | unsigned i; |
| 434 | |
| 435 | // Global |
| 436 | priority = prm.priority; |
| 437 | idUri = pj2Str(prm.id); |
| 438 | |
| 439 | // AccountRegConfig |
| 440 | regConfig.registrarUri = pj2Str(prm.reg_uri); |
| 441 | regConfig.registerOnAdd = (prm.register_on_acc_add != 0); |
| 442 | regConfig.timeoutSec = prm.reg_timeout; |
| 443 | regConfig.retryIntervalSec = prm.reg_retry_interval; |
| 444 | regConfig.firstRetryIntervalSec = prm.reg_first_retry_interval; |
| 445 | regConfig.delayBeforeRefreshSec = prm.reg_delay_before_refresh; |
| 446 | regConfig.dropCallsOnFail = PJ2BOOL(prm.drop_calls_on_reg_fail); |
| 447 | regConfig.unregWaitSec = prm.unreg_timeout; |
| 448 | regConfig.proxyUse = prm.reg_use_proxy; |
| 449 | regConfig.headers.clear(); |
| 450 | hdr = prm.reg_hdr_list.next; |
| 451 | while (hdr != &prm.reg_hdr_list) { |
| 452 | SipHeader new_hdr; |
| 453 | new_hdr.fromPj(hdr); |
| 454 | |
| 455 | regConfig.headers.push_back(new_hdr); |
| 456 | |
| 457 | hdr = hdr->next; |
| 458 | } |
| 459 | |
| 460 | // AccountSipConfig |
| 461 | sipConfig.authCreds.clear(); |
| 462 | for (i=0; i<prm.cred_count; ++i) { |
| 463 | AuthCredInfo cred; |
| 464 | const pjsip_cred_info &src = prm.cred_info[i]; |
| 465 | |
| 466 | cred.realm = pj2Str(src.realm); |
| 467 | cred.scheme = pj2Str(src.scheme); |
| 468 | cred.username = pj2Str(src.username); |
| 469 | cred.dataType = src.data_type; |
| 470 | cred.data = pj2Str(src.data); |
| 471 | cred.akaK = pj2Str(src.ext.aka.k); |
| 472 | cred.akaOp = pj2Str(src.ext.aka.op); |
| 473 | cred.akaAmf = pj2Str(src.ext.aka.amf); |
| 474 | |
| 475 | sipConfig.authCreds.push_back(cred); |
| 476 | } |
| 477 | sipConfig.proxies.clear(); |
| 478 | for (i=0; i<prm.proxy_cnt; ++i) { |
| 479 | sipConfig.proxies.push_back(pj2Str(prm.proxy[i])); |
| 480 | } |
| 481 | sipConfig.contactForced = pj2Str(prm.force_contact); |
| 482 | sipConfig.contactParams = pj2Str(prm.contact_params); |
| 483 | sipConfig.contactUriParams = pj2Str(prm.contact_uri_params); |
| 484 | sipConfig.authInitialEmpty = PJ2BOOL(prm.auth_pref.initial_auth); |
| 485 | sipConfig.authInitialAlgorithm = pj2Str(prm.auth_pref.algorithm); |
| 486 | sipConfig.transportId = prm.transport_id; |
| 487 | |
| 488 | // AccountCallConfig |
| 489 | callConfig.holdType = prm.call_hold_type; |
| 490 | callConfig.prackUse = prm.require_100rel; |
| 491 | callConfig.timerUse = prm.use_timer; |
| 492 | callConfig.timerMinSESec = prm.timer_setting.min_se; |
| 493 | callConfig.timerSessExpiresSec = prm.timer_setting.sess_expires; |
| 494 | |
| 495 | // AccountPresConfig |
| 496 | presConfig.headers.clear(); |
| 497 | hdr = prm.sub_hdr_list.next; |
| 498 | while (hdr != &prm.sub_hdr_list) { |
| 499 | SipHeader new_hdr; |
| 500 | new_hdr.fromPj(hdr); |
| 501 | presConfig.headers.push_back(new_hdr); |
| 502 | hdr = hdr->next; |
| 503 | } |
| 504 | presConfig.publishEnabled = PJ2BOOL(prm.publish_enabled); |
| 505 | presConfig.publishQueue = PJ2BOOL(prm.publish_opt.queue_request); |
| 506 | presConfig.publishShutdownWaitMsec = prm.unpublish_max_wait_time_msec; |
| 507 | presConfig.pidfTupleId = pj2Str(prm.pidf_tuple_id); |
| 508 | |
| 509 | // AccountMwiConfig |
| 510 | mwiConfig.enabled = PJ2BOOL(prm.mwi_enabled); |
| 511 | mwiConfig.expirationSec = prm.mwi_expires; |
| 512 | |
| 513 | // AccountNatConfig |
| 514 | natConfig.sipStunUse = prm.sip_stun_use; |
| 515 | natConfig.mediaStunUse = prm.media_stun_use; |
| 516 | if (prm.ice_cfg_use == PJSUA_ICE_CONFIG_USE_CUSTOM) { |
| 517 | natConfig.iceEnabled = PJ2BOOL(prm.ice_cfg.enable_ice); |
| 518 | natConfig.iceMaxHostCands = prm.ice_cfg.ice_max_host_cands; |
| 519 | natConfig.iceAggressiveNomination = PJ2BOOL(prm.ice_cfg.ice_opt.aggressive); |
| 520 | natConfig.iceNominatedCheckDelayMsec = prm.ice_cfg.ice_opt.nominated_check_delay; |
| 521 | natConfig.iceWaitNominationTimeoutMsec = prm.ice_cfg.ice_opt.controlled_agent_want_nom_timeout; |
| 522 | natConfig.iceNoRtcp = PJ2BOOL(prm.ice_cfg.ice_no_rtcp); |
| 523 | natConfig.iceAlwaysUpdate = PJ2BOOL(prm.ice_cfg.ice_always_update); |
| 524 | } else { |
| 525 | pjsua_media_config default_mcfg; |
| 526 | if (!mcfg) { |
| 527 | pjsua_media_config_default(&default_mcfg); |
| 528 | mcfg = &default_mcfg; |
| 529 | } |
| 530 | natConfig.iceEnabled = PJ2BOOL(mcfg->enable_ice); |
| 531 | natConfig.iceMaxHostCands= mcfg->ice_max_host_cands; |
| 532 | natConfig.iceAggressiveNomination = PJ2BOOL(mcfg->ice_opt.aggressive); |
| 533 | natConfig.iceNominatedCheckDelayMsec = mcfg->ice_opt.nominated_check_delay; |
| 534 | natConfig.iceWaitNominationTimeoutMsec = mcfg->ice_opt.controlled_agent_want_nom_timeout; |
| 535 | natConfig.iceNoRtcp = PJ2BOOL(mcfg->ice_no_rtcp); |
| 536 | natConfig.iceAlwaysUpdate = PJ2BOOL(mcfg->ice_always_update); |
| 537 | } |
| 538 | |
| 539 | if (prm.turn_cfg_use == PJSUA_TURN_CONFIG_USE_CUSTOM) { |
| 540 | natConfig.turnEnabled = PJ2BOOL(prm.turn_cfg.enable_turn); |
| 541 | natConfig.turnServer = pj2Str(prm.turn_cfg.turn_server); |
| 542 | natConfig.turnConnType = prm.turn_cfg.turn_conn_type; |
| 543 | natConfig.turnUserName = pj2Str(prm.turn_cfg.turn_auth_cred.data.static_cred.username); |
| 544 | natConfig.turnPasswordType = prm.turn_cfg.turn_auth_cred.data.static_cred.data_type; |
| 545 | natConfig.turnPassword = pj2Str(prm.turn_cfg.turn_auth_cred.data.static_cred.data); |
| 546 | } else { |
| 547 | pjsua_media_config default_mcfg; |
| 548 | if (!mcfg) { |
| 549 | pjsua_media_config_default(&default_mcfg); |
| 550 | mcfg = &default_mcfg; |
| 551 | } |
| 552 | natConfig.turnEnabled = PJ2BOOL(mcfg->enable_turn); |
| 553 | natConfig.turnServer = pj2Str(mcfg->turn_server); |
| 554 | natConfig.turnConnType = mcfg->turn_conn_type; |
| 555 | natConfig.turnUserName = pj2Str(mcfg->turn_auth_cred.data.static_cred.username); |
| 556 | natConfig.turnPasswordType = mcfg->turn_auth_cred.data.static_cred.data_type; |
| 557 | natConfig.turnPassword = pj2Str(mcfg->turn_auth_cred.data.static_cred.data); |
| 558 | } |
| 559 | natConfig.contactRewriteUse = prm.allow_contact_rewrite; |
| 560 | natConfig.contactRewriteMethod = prm.contact_rewrite_method; |
| 561 | natConfig.viaRewriteUse = prm.allow_via_rewrite; |
| 562 | natConfig.sdpNatRewriteUse = prm.allow_sdp_nat_rewrite; |
| 563 | natConfig.sipOutboundUse = prm.use_rfc5626; |
| 564 | natConfig.sipOutboundInstanceId = pj2Str(prm.rfc5626_instance_id); |
| 565 | natConfig.sipOutboundRegId = pj2Str(prm.rfc5626_reg_id); |
| 566 | natConfig.udpKaIntervalSec = prm.ka_interval; |
| 567 | natConfig.udpKaData = pj2Str(prm.ka_data); |
| 568 | |
| 569 | // AccountMediaConfig |
| 570 | mediaConfig.transportConfig.fromPj(prm.rtp_cfg); |
| 571 | mediaConfig.lockCodecEnabled= PJ2BOOL(prm.lock_codec); |
| 572 | #if defined(PJMEDIA_STREAM_ENABLE_KA) && (PJMEDIA_STREAM_ENABLE_KA != 0) |
| 573 | mediaConfig.streamKaEnabled = PJ2BOOL(prm.use_stream_ka); |
| 574 | #else |
| 575 | mediaConfig.streamKaEnabled = false; |
| 576 | #endif |
| 577 | mediaConfig.srtpUse = prm.use_srtp; |
| 578 | mediaConfig.srtpSecureSignaling = prm.srtp_secure_signaling; |
| 579 | mediaConfig.ipv6Use = prm.ipv6_media_use; |
| 580 | |
| 581 | // AccountVideoConfig |
| 582 | videoConfig.autoShowIncoming = PJ2BOOL(prm.vid_in_auto_show); |
| 583 | videoConfig.autoTransmitOutgoing = PJ2BOOL(prm.vid_out_auto_transmit); |
| 584 | videoConfig.windowFlags = prm.vid_wnd_flags; |
| 585 | videoConfig.defaultCaptureDevice = prm.vid_cap_dev; |
| 586 | videoConfig.defaultRenderDevice = prm.vid_rend_dev; |
| 587 | videoConfig.rateControlMethod = prm.vid_stream_rc_cfg.method; |
| 588 | videoConfig.rateControlBandwidth = prm.vid_stream_rc_cfg.bandwidth; |
| 589 | } |
| 590 | |
| 591 | void AccountConfig::readObject(const ContainerNode &node) throw(Error) |
| 592 | { |
| 593 | ContainerNode this_node = node.readContainer("AccountConfig"); |
| 594 | |
| 595 | NODE_READ_INT ( this_node, priority); |
| 596 | NODE_READ_STRING ( this_node, idUri); |
| 597 | NODE_READ_OBJ ( this_node, regConfig); |
| 598 | NODE_READ_OBJ ( this_node, sipConfig); |
| 599 | NODE_READ_OBJ ( this_node, callConfig); |
| 600 | NODE_READ_OBJ ( this_node, presConfig); |
| 601 | NODE_READ_OBJ ( this_node, mwiConfig); |
| 602 | NODE_READ_OBJ ( this_node, natConfig); |
| 603 | NODE_READ_OBJ ( this_node, mediaConfig); |
| 604 | NODE_READ_OBJ ( this_node, videoConfig); |
| 605 | } |
| 606 | |
| 607 | void AccountConfig::writeObject(ContainerNode &node) const throw(Error) |
| 608 | { |
| 609 | ContainerNode this_node = node.writeNewContainer("AccountConfig"); |
| 610 | |
| 611 | NODE_WRITE_INT ( this_node, priority); |
| 612 | NODE_WRITE_STRING ( this_node, idUri); |
| 613 | NODE_WRITE_OBJ ( this_node, regConfig); |
| 614 | NODE_WRITE_OBJ ( this_node, sipConfig); |
| 615 | NODE_WRITE_OBJ ( this_node, callConfig); |
| 616 | NODE_WRITE_OBJ ( this_node, presConfig); |
| 617 | NODE_WRITE_OBJ ( this_node, mwiConfig); |
| 618 | NODE_WRITE_OBJ ( this_node, natConfig); |
| 619 | NODE_WRITE_OBJ ( this_node, mediaConfig); |
| 620 | NODE_WRITE_OBJ ( this_node, videoConfig); |
| 621 | } |
| 622 | |
| 623 | |
| 624 | /////////////////////////////////////////////////////////////////////////////// |
| 625 | |
| 626 | void AccountInfo::fromPj(const pjsua_acc_info &pai) |
| 627 | { |
| 628 | id = pai.id; |
| 629 | isDefault = pai.is_default != 0; |
| 630 | uri = pj2Str(pai.acc_uri); |
| 631 | regIsConfigured = pai.has_registration != 0; |
| 632 | regIsActive = pai.has_registration && pai.expires > 0 && |
| 633 | (pai.status / 100 == 2); |
| 634 | regExpiresSec = pai.expires; |
| 635 | regStatus = pai.status; |
| 636 | regStatusText = pj2Str(pai.status_text); |
| 637 | regLastErr = pai.reg_last_err; |
| 638 | onlineStatus = pai.online_status != 0; |
| 639 | onlineStatusText = pj2Str(pai.online_status_text); |
| 640 | } |
| 641 | |
| 642 | /////////////////////////////////////////////////////////////////////////////// |
| 643 | |
| 644 | Account::Account() |
| 645 | : id(PJSUA_INVALID_ID) |
| 646 | { |
| 647 | } |
| 648 | |
| 649 | Account::~Account() |
| 650 | { |
| 651 | /* If this instance is deleted, also delete the corresponding account in |
| 652 | * PJSUA library. |
| 653 | */ |
| 654 | if (isValid() && pjsua_get_state() < PJSUA_STATE_CLOSING) { |
| 655 | // Cleanup buddies in the buddy list |
| 656 | while(buddyList.size() > 0) { |
| 657 | Buddy *b = buddyList[0]; |
| 658 | delete b; /* this will remove itself from the list */ |
| 659 | } |
| 660 | |
| 661 | pjsua_acc_set_user_data(id, NULL); |
| 662 | pjsua_acc_del(id); |
| 663 | } |
| 664 | } |
| 665 | |
| 666 | void Account::create(const AccountConfig &acc_cfg, |
| 667 | bool make_default) throw(Error) |
| 668 | { |
| 669 | pjsua_acc_config pj_acc_cfg; |
| 670 | |
| 671 | acc_cfg.toPj(pj_acc_cfg); |
| 672 | pj_acc_cfg.user_data = (void*)this; |
| 673 | PJSUA2_CHECK_EXPR( pjsua_acc_add(&pj_acc_cfg, make_default, &id) ); |
| 674 | } |
| 675 | |
| 676 | void Account::modify(const AccountConfig &acc_cfg) throw(Error) |
| 677 | { |
| 678 | pjsua_acc_config pj_acc_cfg; |
| 679 | |
| 680 | acc_cfg.toPj(pj_acc_cfg); |
| 681 | pj_acc_cfg.user_data = (void*)this; |
| 682 | PJSUA2_CHECK_EXPR( pjsua_acc_modify(id, &pj_acc_cfg) ); |
| 683 | } |
| 684 | |
| 685 | bool Account::isValid() const |
| 686 | { |
| 687 | return pjsua_acc_is_valid(id) != 0; |
| 688 | } |
| 689 | |
| 690 | void Account::setDefault() throw(Error) |
| 691 | { |
| 692 | PJSUA2_CHECK_EXPR( pjsua_acc_set_default(id) ); |
| 693 | } |
| 694 | |
| 695 | bool Account::isDefault() const |
| 696 | { |
| 697 | return pjsua_acc_get_default() == id; |
| 698 | } |
| 699 | |
| 700 | int Account::getId() const |
| 701 | { |
| 702 | return id; |
| 703 | } |
| 704 | |
| 705 | Account *Account::lookup(int acc_id) |
| 706 | { |
| 707 | return (Account*)pjsua_acc_get_user_data(acc_id); |
| 708 | } |
| 709 | |
| 710 | AccountInfo Account::getInfo() const throw(Error) |
| 711 | { |
| 712 | pjsua_acc_info pj_ai; |
| 713 | AccountInfo ai; |
| 714 | |
| 715 | PJSUA2_CHECK_EXPR( pjsua_acc_get_info(id, &pj_ai) ); |
| 716 | ai.fromPj(pj_ai); |
| 717 | return ai; |
| 718 | } |
| 719 | |
| 720 | void Account::setRegistration(bool renew) throw(Error) |
| 721 | { |
| 722 | PJSUA2_CHECK_EXPR( pjsua_acc_set_registration(id, renew) ); |
| 723 | } |
| 724 | |
| 725 | void |
| 726 | Account::setOnlineStatus(const PresenceStatus &pres_st) throw(Error) |
| 727 | { |
| 728 | pjrpid_element pj_rpid; |
| 729 | |
| 730 | pj_bzero(&pj_rpid, sizeof(pj_rpid)); |
| 731 | pj_rpid.type = PJRPID_ELEMENT_TYPE_PERSON; |
| 732 | pj_rpid.activity = pres_st.activity; |
| 733 | pj_rpid.id = str2Pj(pres_st.rpidId); |
| 734 | pj_rpid.note = str2Pj(pres_st.note); |
| 735 | |
| 736 | PJSUA2_CHECK_EXPR( pjsua_acc_set_online_status2( |
| 737 | id, pres_st.status == PJSUA_BUDDY_STATUS_ONLINE, |
| 738 | &pj_rpid) ); |
| 739 | } |
| 740 | |
| 741 | void Account::setTransport(TransportId tp_id) throw(Error) |
| 742 | { |
| 743 | PJSUA2_CHECK_EXPR( pjsua_acc_set_transport(id, tp_id) ); |
| 744 | } |
| 745 | |
| 746 | void Account::presNotify(const PresNotifyParam &prm) throw(Error) |
| 747 | { |
| 748 | pj_str_t pj_state_str = str2Pj(prm.stateStr); |
| 749 | pj_str_t pj_reason = str2Pj(prm.reason); |
| 750 | pjsua_msg_data msg_data; |
| 751 | prm.txOption.toPj(msg_data); |
| 752 | |
| 753 | PJSUA2_CHECK_EXPR( pjsua_pres_notify(id, (pjsua_srv_pres*)prm.srvPres, |
| 754 | prm.state, &pj_state_str, |
| 755 | &pj_reason, prm.withBody, |
| 756 | &msg_data) ); |
| 757 | } |
| 758 | |
| 759 | const BuddyVector& Account::enumBuddies() const throw(Error) |
| 760 | { |
| 761 | return buddyList; |
| 762 | } |
| 763 | |
| 764 | Buddy* Account::findBuddy(string uri, FindBuddyMatch *buddy_match) const |
| 765 | throw(Error) |
| 766 | { |
| 767 | if (!buddy_match) { |
| 768 | static FindBuddyMatch def_bm; |
| 769 | buddy_match = &def_bm; |
| 770 | } |
| 771 | |
| 772 | for (unsigned i = 0; i < buddyList.size(); i++) { |
| 773 | if (buddy_match->match(uri, *buddyList[i])) |
| 774 | return buddyList[i]; |
| 775 | } |
| 776 | PJSUA2_RAISE_ERROR(PJ_ENOTFOUND); |
| 777 | } |
| 778 | |
| 779 | void Account::addBuddy(Buddy *buddy) |
| 780 | { |
| 781 | pj_assert(buddy); |
| 782 | |
| 783 | buddyList.push_back(buddy); |
| 784 | } |
| 785 | |
| 786 | void Account::removeBuddy(Buddy *buddy) |
| 787 | { |
| 788 | pj_assert(buddy); |
| 789 | |
| 790 | BuddyVector::iterator it; |
| 791 | for (it = buddyList.begin(); it != buddyList.end(); it++) { |
| 792 | if (*it == buddy) { |
| 793 | buddyList.erase(it); |
| 794 | return; |
| 795 | } |
| 796 | } |
| 797 | |
| 798 | pj_assert(!"Bug! Buddy to be removed is not in the buddy list!"); |
| 799 | } |