40#pragma GCC diagnostic push
41#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
42#include <yaml-cpp/yaml.h>
43#pragma GCC diagnostic pop
55#include <dhtnet/ip_utils.h>
56#include <dhtnet/upnp/upnp_control.h>
58#include <opendht/crypto.h>
83static constexpr std::string_view
PN_FCM =
"fcm"sv;
84static constexpr std::string_view
PN_APNS =
"apns"sv;
92 std::weak_ptr<SIPAccount>
acc;
102 JAMI_ERR(
"Registration callback parameter is null");
108 JAMI_ERR(
"Account doesn't exist in registration callback");
120 via_addr_.host.ptr = 0;
121 via_addr_.host.slen = 0;
132 JAMI_ERR(
"Exception in SIPAccount destructor");
140 const std::string&
avatar,
153 const std::string& key =
"PHOTO;ENCODING=BASE64;TYPE=" +
fileType;
160 }
catch (
const std::exception&
e) {
167 }
else if (
flag == 1) {
178 if (
file.is_open()) {
186 }
catch (
const std::exception&
e) {
191std::shared_ptr<SIPCall>
193 const std::vector<libjami::MediaMap>&
mediaList,
194 const std::shared_ptr<SipTransport>& transport)
210 std::shared_ptr<SIPCall> call;
216 JAMI_WARN(
"Media list is empty, setting a default list");
224 throw std::runtime_error(
"Failed to create the call");
227 bool ipv6 = dhtnet::IpAddr::isIpv6(
toUrl);
232 std::shared_ptr<SipTransport> t
239 JAMI_DBG(
"New %s IP to IP call to %s",
ipv6 ?
"IPv6" :
"IPv4", to.c_str());
246 JAMI_LOG(
"UserAgent: New registered account call to {}",
toUrl);
254 if (call->createIceMediaTransport(
false)) {
255 call->initIceMediaTransport(
true);
259 call->setPeerNumber(
toUri);
260 call->setPeerUri(
toUri);
277 auto&
sdp = call->getSDP();
290 if (not SIPStartCall(call)) {
291 JAMI_ERROR(
"Unable to send outgoing INVITE request for new call");
292 call->onFailure(PJSIP_SC_INTERNAL_SERVER_ERROR);
305SIPAccount::onTransportStateChanged(pjsip_transport_state state,
const pjsip_transport_state_info* info)
307 pj_status_t currentStatus = transportStatus_;
308 JAMI_DEBUG(
"Transport state changed to {:s} for account {:s}!", SipTransport::stateToStr(state), accountID_);
309 if (!SipTransport::isAlive(state)) {
311 transportStatus_ = info->status;
312 transportError_ = sip_utils::sip_strerror(info->status);
313 JAMI_ERROR(
"Transport disconnected: {:s}", transportError_);
316 transportStatus_ = PJSIP_SC_SERVICE_UNAVAILABLE;
317 transportError_ =
"";
319 setRegistrationState(RegistrationState::ERROR_GENERIC, PJSIP_SC_TSX_TRANSPORT_ERROR);
323 transportStatus_ = info && info->status ? info->status : PJSIP_SC_OK;
324 transportError_ =
"";
328 if (currentStatus != transportStatus_)
333SIPAccount::setTransport(
const std::shared_ptr<SipTransport>& t)
338 JAMI_DEBUG(
"Removing old transport [{}] from account", fmt::ptr(transport_.get()));
342 pjsip_regc_release_transport(regc_);
343 transport_->removeStateListener(
reinterpret_cast<uintptr_t
>(
this));
347 JAMI_DEBUG(
"Set new transport [{}]", fmt::ptr(transport_.get()));
350 transport_->addStateListener(
reinterpret_cast<uintptr_t
>(
this),
351 std::bind(&SIPAccount::onTransportStateChanged,
353 std::placeholders::_1,
354 std::placeholders::_2));
356 if (not initContactAddress()) {
357 JAMI_DEBUG(
"Unable to register: invalid address");
360 updateContactHeader();
365SIPAccount::getTransportSelector()
368 return SIPVoIPLink::getTransportSelector(
nullptr);
369 return SIPVoIPLink::getTransportSelector(transport_->get());
373SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
376 call->addLocalIceAttributes();
378 const std::string& toUri(call->getPeerNumber());
379 pj_str_t pjTo = sip_utils::CONST_PJ_STR(toUri);
382 std::string from(getFromUri());
383 pj_str_t pjFrom = sip_utils::CONST_PJ_STR(from);
385 auto* transport = call->getTransport();
387 JAMI_ERROR(
"Unable to start call without transport");
391 std::string contact = getContactHeader();
392 JAMI_DEBUG(
"Contact header: {:s} / {:s} → {:s}", contact, from, toUri);
394 pj_str_t pjContact = sip_utils::CONST_PJ_STR(contact);
395 auto* local_sdp = isEmptyOffersEnabled() ? nullptr : call->getSDP().getLocalSdpSession();
397 pjsip_dialog* dialog {
nullptr};
398 pjsip_inv_session* inv {
nullptr};
399 if (!CreateClientDialogAndInvite(&pjFrom, &pjContact, &pjTo,
nullptr, local_sdp, &dialog, &inv))
402 inv->mod_data[link_.getModId()] = call.get();
403 call->setInviteSession(inv);
405 updateDialogViaSentBy(dialog);
407 if (hasServiceRoute())
408 pjsip_dlg_set_route_set(dialog, sip_utils::createRouteSet(getServiceRoute(), call->inviteSession_->pool));
411 and pjsip_auth_clt_set_credentials(&dialog->auth_sess,
static_cast<int>(getCredentialCount()), getCredInfo())
413 JAMI_ERROR(
"Unable to initialize credentials for invite session authentication");
417 pjsip_tx_data* tdata;
419 if (pjsip_inv_invite(call->inviteSession_.get(), &tdata) != PJ_SUCCESS) {
420 JAMI_ERROR(
"Unable to initialize invite messager for this call");
424 const pjsip_tpselector tp_sel = link_.getTransportSelector(transport->get());
425 if (pjsip_dlg_set_transport(dialog, &tp_sel) != PJ_SUCCESS) {
426 JAMI_ERROR(
"Unable to associate transport for invite session dialog");
431 sip_utils::addUserAgentHeader(getUserAgentName(), tdata);
433 if (pjsip_inv_send_msg(call->inviteSession_.get(), tdata) != PJ_SUCCESS) {
434 JAMI_ERROR(
"Unable to send invite message for this call");
438 call->setState(Call::CallState::ACTIVE, Call::ConnectionState::PROGRESSING);
444SIPAccount::usePublishedAddressPortInVIA()
446 publishedIpStr_ = getPublishedIpAddress().toString();
447 via_addr_.host.ptr = (
char*) publishedIpStr_.c_str();
448 via_addr_.host.slen =
static_cast<pj_ssize_t
>(publishedIpStr_.size());
449 via_addr_.port = publishedPortUsed_;
453SIPAccount::useUPnPAddressPortInVIA()
455 upnpIpAddr_ = getUPnPIpAddress().toString();
456 via_addr_.host.ptr = (
char*) upnpIpAddr_.c_str();
457 via_addr_.host.slen =
static_cast<pj_ssize_t
>(upnpIpAddr_.size());
458 via_addr_.port = publishedPortUsed_;
463validate(std::string& member,
const std::string& param,
const T& valid)
465 const auto begin = std::begin(valid);
466 const auto end = std::end(valid);
467 if (find(begin, end, param) != end)
470 JAMI_ERROR(
"Invalid parameter \"{:s}\"", param);
473std::map<std::string, std::string>
474SIPAccount::getVolatileAccountDetails()
const
476 auto a = SIPAccountBase::getVolatileAccountDetails();
477 a.emplace(Conf::CONFIG_ACCOUNT_REGISTRATION_STATE_CODE, std::to_string(registrationStateDetailed_.first));
478 a.emplace(Conf::CONFIG_ACCOUNT_REGISTRATION_STATE_DESC, registrationStateDetailed_.second);
482 a.emplace(Conf::CONFIG_PRESENCE_STATUS, presence_->isOnline() ? TRUE_STR : FALSE_STR);
483 a.emplace(Conf::CONFIG_PRESENCE_NOTE, presence_->getNote());
486 if (transport_ and transport_->isSecure() and transport_->isConnected()) {
487 const auto& tlsInfos = transport_->getTlsInfos();
488 const auto* cipher = pj_ssl_cipher_name(tlsInfos.cipher);
489 if (tlsInfos.cipher and not cipher)
490 JAMI_WARN(
"Unknown cipher: %d", tlsInfos.cipher);
493 auto ca = tlsInfos.peerCert->issuer;
496 std::ostringstream name_str;
498 a.emplace(name_str.str(), ca->toString());
508SIPAccount::mapPortUPnP()
510 dhtnet::upnp::Mapping map(dhtnet::upnp::PortType::UDP, config().publishedPort, config().localPort);
511 map.setNotifyCallback([w = weak()](
const dhtnet::upnp::Mapping::sharedPtr_t& mapRes) {
512 if (
auto accPtr = w.lock()) {
513 auto oldPort = static_cast<in_port_t>(accPtr->publishedPortUsed_);
514 bool success = mapRes->getState() == dhtnet::upnp::MappingState::OPEN
515 or mapRes->getState() == dhtnet::upnp::MappingState::IN_PROGRESS;
516 auto newPort = success ? mapRes->getExternalPort() : accPtr->config().publishedPort;
517 if (not success and not accPtr->isRegistered()) {
518 JAMI_WARNING(
"[Account {:s}] Failed to open port {}: registering SIP account anyway",
519 accPtr->getAccountID(),
521 accPtr->doRegister1_();
524 if ((oldPort != newPort) or (accPtr->getRegistrationState() != RegistrationState::REGISTERED)) {
525 if (not accPtr->isRegistered())
526 JAMI_WARNING(
"[Account {:s}] SIP port {} opened: registering SIP account",
527 accPtr->getAccountID(),
530 JAMI_WARNING(
"[Account {:s}] SIP port changed to {}: re-registering SIP account",
531 accPtr->getAccountID(),
533 accPtr->publishedPortUsed_ = newPort;
535 accPtr->connectivityChanged();
538 accPtr->doRegister1_();
542 auto mapRes = upnpCtrl_->reserveMapping(map);
543 if (mapRes and mapRes->getState() == dhtnet::upnp::MappingState::OPEN) {
551SIPAccount::setPushNotificationToken(
const std::string& pushDeviceToken)
553 JAMI_WARNING(
"[SIP Account {}] setPushNotificationToken: {}", getAccountID(), pushDeviceToken);
554 if (SIPAccountBase::setPushNotificationToken(pushDeviceToken)) {
555 if (config().enabled) {
565SIPAccount::setPushNotificationConfig(
const std::map<std::string, std::string>& data)
567 if (SIPAccountBase::setPushNotificationConfig(data)) {
568 if (config().enabled) {
578SIPAccount::pushNotificationReceived(
const std::string& from,
const std::map<std::string, std::string>&)
580 JAMI_WARNING(
"[SIP Account {:s}] pushNotificationReceived: {:s}", getAccountID(), from);
582 if (config().enabled) {
589SIPAccount::doRegister()
591 if (not isUsable()) {
592 JAMI_WARN(
"Account must be enabled and active to register, ignoring");
596 JAMI_DEBUG(
"doRegister {:s}", config_->hostname);
600 JAMI_DBG(
"UPnP: waiting for IGD to register SIP account");
601 setRegistrationState(RegistrationState::TRYING);
602 if (not mapPortUPnP()) {
603 JAMI_DBG(
"UPnP: UPNP request failed, try to register SIP account anyway");
612SIPAccount::doRegister1_()
615 std::lock_guard lock(configurationMutex_);
622 link_.resolveSrvName(hasServiceRoute() ? getServiceRoute() : config().hostname,
623 config().tlsEnable ? PJSIP_TRANSPORT_TLS : PJSIP_TRANSPORT_UDP,
624 [w = weak()](
std::vector<
dhtnet::IpAddr> host_ips) {
625 if (
auto acc = w.lock()) {
626 std::lock_guard lock(acc->configurationMutex_);
627 if (host_ips.empty()) {
628 JAMI_ERR(
"Unable to resolve hostname for registration.");
629 acc->setRegistrationState(RegistrationState::ERROR_GENERIC, PJSIP_SC_NOT_FOUND);
632 acc->hostIp_ = host_ips[0];
639SIPAccount::doRegister2_()
641 if (not isIP2IP() and not hostIp_) {
642 setRegistrationState(RegistrationState::ERROR_GENERIC, PJSIP_SC_NOT_FOUND);
647 dhtnet::IpAddr bindAddress = createBindingAddress();
648 if (not bindAddress) {
649 setRegistrationState(RegistrationState::ERROR_GENERIC, PJSIP_SC_NOT_FOUND);
650 JAMI_ERROR(
"Unable to compute address to bind.");
654 bool ipv6 = bindAddress.isIpv6();
655 transportType_ = config().tlsEnable ? (ipv6 ? PJSIP_TRANSPORT_TLS6 : PJSIP_TRANSPORT_TLS)
656 : (ipv6 ? PJSIP_TRANSPORT_UDP6 : PJSIP_TRANSPORT_UDP);
659 if (config().tlsEnable) {
660 JAMI_DEBUG(
"TLS is enabled for account {}", accountID_);
665 initTlsConfiguration();
668 tlsListener_ = link_.sipTransportBroker->getTlsListener(bindAddress, getTlsSetting());
670 setRegistrationState(RegistrationState::ERROR_GENERIC);
676 tlsListener_.reset();
683 if (!config().tlsEnable) {
684 setTransport(link_.sipTransportBroker->getUdpTransport(bindAddress));
686 setRegistrationState(RegistrationState::REGISTERED);
693 if (isTlsEnabled()) {
694 setTransport(link_.sipTransportBroker->getTlsTransport(tlsListener_,
696 config().tlsServerName.empty()
698 : config().tlsServerName));
700 setTransport(link_.sipTransportBroker->getUdpTransport(bindAddress));
703 throw VoipLinkException(
"Unable to create transport");
706 }
catch (
const VoipLinkException& e) {
708 setRegistrationState(RegistrationState::ERROR_GENERIC);
712 if (presence_ and presence_->isEnabled()) {
713 presence_->subscribeClient(getFromUri(),
true);
714 presence_->sendPresence(
true,
"");
719SIPAccount::doUnregister(
bool )
721 std::unique_lock<std::recursive_mutex> lock(configurationMutex_);
723 tlsListener_.reset();
729 JAMI_ERR(
"doUnregister %s", e.what());
735 resetAutoRegistration();
739SIPAccount::connectivityChanged()
741 if (not isUsable()) {
752SIPAccount::sendRegister()
754 if (not isUsable()) {
755 JAMI_WARNING(
"[Account {}] Must be enabled and active to register, ignoring", accountID_);
760 setRegistrationState(RegistrationState::TRYING);
762 pjsip_regc* regc =
nullptr;
763 if (pjsip_regc_create(link_.getEndpoint(), (
void*)
this, &
registration_cb, ®c) != PJ_SUCCESS)
766 std::string srvUri(getServerUri());
767 pj_str_t pjSrv {(
char*) srvUri.data(), (pj_ssize_t) srvUri.size()};
770 std::string from(getFromUri());
771 pj_str_t pjFrom(sip_utils::CONST_PJ_STR(from));
774 const std::string& received(getReceivedParameter());
776 std::string contact = getContactHeader();
778 JAMI_LOG(
"[Account {}] Using contact header {} in registration", accountID_, contact);
781 if (getUPnPActive() or not getPublishedSameasLocal()
782 or (not received.empty() and received != getPublishedAddress())) {
783 pjsip_host_port* via = getViaAddr();
784 JAMI_LOG(
"Setting VIA sent-by to {:s}:{:d}", sip_utils::as_view(via->host), via->port);
786 if (pjsip_regc_set_via_sent_by(regc, via, transport_->get()) != PJ_SUCCESS)
788 }
else if (isStunEnabled()) {
789 if (pjsip_regc_set_via_sent_by(regc, getViaAddr(), transport_->get()) != PJ_SUCCESS)
794 pj_status_t status = PJ_SUCCESS;
795 pj_str_t pjContact = sip_utils::CONST_PJ_STR(contact);
797 if ((status = pjsip_regc_init(regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, getRegistrationExpire()))
799 JAMI_ERR(
"pjsip_regc_init failed with error %d: %s", status, sip_utils::sip_strerror(status).c_str());
803 if (hasServiceRoute())
804 pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(getServiceRoute(), link_.getPool()));
806 pjsip_regc_set_credentials(regc,
static_cast<int>(getCredentialCount()), getCredInfo());
809 pj_list_init(&hdr_list);
810 auto pjUserAgent = CONST_PJ_STR(getUserAgentName());
811 constexpr pj_str_t STR_USER_AGENT = CONST_PJ_STR(
"User-Agent");
813 pjsip_generic_string_hdr* h = pjsip_generic_string_hdr_create(link_.getPool(), &STR_USER_AGENT, &pjUserAgent);
814 pj_list_push_back(&hdr_list, (pjsip_hdr*) h);
815 pjsip_regc_add_headers(regc, &hdr_list);
817 pjsip_tx_data* tdata;
819 if (pjsip_regc_register(regc, isRegistrationRefreshEnabled(), &tdata) != PJ_SUCCESS)
820 throw VoipLinkException(
"Unable to initialize transaction data for account registration");
822 const pjsip_tpselector tp_sel = getTransportSelector();
823 if (pjsip_regc_set_transport(regc, &tp_sel) != PJ_SUCCESS)
826 if (tp_sel.u.transport)
827 setUpTransmissionData(tdata, tp_sel.u.transport->key.type);
830 if ((status = pjsip_regc_send(regc, tdata)) != PJ_SUCCESS) {
831 JAMI_ERROR(
"pjsip_regc_send failed with error {:d}: {}", status, sip_utils::sip_strerror(status));
835 setRegistrationInfo(regc);
839SIPAccount::setUpTransmissionData(pjsip_tx_data* tdata,
long transportKeyType)
842 auto* ai = &tdata->dest_info;
843 ai->name = pj_strdup3(tdata->pool, config().hostname.c_str());
845 ai->addr.entry[0].type = (pjsip_transport_type_e) transportKeyType;
846 pj_memcpy(&ai->addr.entry[0].addr, hostIp_.pjPtr(),
sizeof(pj_sockaddr));
847 ai->addr.entry[0].addr_len =
static_cast<int>(hostIp_.getLength());
853SIPAccount::onRegister(pjsip_regc_cbparam* param)
855 if (param->regc != getRegistrationInfo())
858 if (param->status != PJ_SUCCESS) {
859 JAMI_ERROR(
"[Account {}] SIP registration error {:d}", accountID_, param->status);
860 destroyRegistrationInfo();
861 setRegistrationState(RegistrationState::ERROR_GENERIC, param->code);
862 }
else if (param->code < 0 || param->code >= 300) {
863 JAMI_ERROR(
"[Account {}] SIP registration failed, status={:d} ({:s})",
866 sip_utils::as_view(param->reason));
867 destroyRegistrationInfo();
868 switch (param->code) {
869 case PJSIP_SC_FORBIDDEN:
870 setRegistrationState(RegistrationState::ERROR_AUTH, param->code);
872 case PJSIP_SC_NOT_FOUND:
873 setRegistrationState(RegistrationState::ERROR_HOST, param->code);
875 case PJSIP_SC_REQUEST_TIMEOUT:
876 setRegistrationState(RegistrationState::ERROR_HOST, param->code);
878 case PJSIP_SC_SERVICE_UNAVAILABLE:
879 setRegistrationState(RegistrationState::ERROR_SERVICE_UNAVAILABLE, param->code);
882 setRegistrationState(RegistrationState::ERROR_GENERIC, param->code);
884 }
else if (PJSIP_IS_STATUS_IN_CLASS(param->code, 200)) {
886 resetAutoRegistration();
888 if (param->expiration < 1) {
889 destroyRegistrationInfo();
891 setRegistrationState(RegistrationState::UNREGISTERED, param->code);
898 if (config().allowIPAutoRewrite and checkNATAddress(param, link_.getPool()))
899 JAMI_WARN(
"New contact: %s", getContactHeader().c_str());
902 if (hasServiceRoute())
903 pjsip_regc_set_route_set(param->regc, sip_utils::createRouteSet(getServiceRoute(), link_.getPool()));
905 setRegistrationState(RegistrationState::REGISTERED, param->code);
913 switch (param->code) {
914 case PJSIP_SC_REQUEST_TIMEOUT:
915 case PJSIP_SC_INTERNAL_SERVER_ERROR:
916 case PJSIP_SC_BAD_GATEWAY:
917 case PJSIP_SC_SERVICE_UNAVAILABLE:
918 case PJSIP_SC_SERVER_TIMEOUT:
919 scheduleReregistration();
924 if (PJSIP_IS_STATUS_IN_CLASS(param->code, 600))
925 scheduleReregistration();
928 if (param->expiration != config().registrationExpire) {
929 JAMI_DBG(
"Registrar returned EXPIRE value [%u s] different from the requested [%u s]",
931 config().registrationExpire);
939SIPAccount::sendUnregister()
942 if (!isRegistered()) {
943 setRegistrationState(RegistrationState::UNREGISTERED);
948 pjsip_regc* regc = getRegistrationInfo();
952 pjsip_tx_data* tdata =
nullptr;
953 if (pjsip_regc_unregister(regc, &tdata) != PJ_SUCCESS)
956 const pjsip_tpselector tp_sel = getTransportSelector();
957 if (pjsip_regc_set_transport(regc, &tp_sel) != PJ_SUCCESS)
960 if (tp_sel.u.transport)
961 setUpTransmissionData(tdata, tp_sel.u.transport->key.type);
964 if ((status = pjsip_regc_send(regc, tdata)) != PJ_SUCCESS) {
965 JAMI_ERR(
"pjsip_regc_send failed with error %d: %s", status, sip_utils::sip_strerror(status).c_str());
971SIPAccount::tlsProtocolFromString(
const std::string& method)
973 if (method ==
"Default")
974 return PJSIP_SSL_DEFAULT_PROTO;
975 if (method ==
"TLSv1.2")
976 return PJ_SSL_SOCK_PROTO_TLS1_2;
977 if (method ==
"TLSv1.1")
978 return PJ_SSL_SOCK_PROTO_TLS1_2 | PJ_SSL_SOCK_PROTO_TLS1_1;
979 if (method ==
"TLSv1")
980 return PJ_SSL_SOCK_PROTO_TLS1_2 | PJ_SSL_SOCK_PROTO_TLS1_1 | PJ_SSL_SOCK_PROTO_TLS1;
981 return PJSIP_SSL_DEFAULT_PROTO;
988SIPAccount::trimCiphers()
992 static const size_t MAX_CIPHERS_STRLEN = 1000;
993 for (
const auto& item : ciphers_) {
994 sum += strlen(pj_ssl_cipher_name(item));
995 if (sum > MAX_CIPHERS_STRLEN)
999 ciphers_.resize(count);
1003SIPAccount::initTlsConfiguration()
1005 pjsip_tls_setting_default(&tlsSetting_);
1006 const auto& conf = config();
1007 tlsSetting_.proto = tlsProtocolFromString(conf.tlsMethod);
1011 unsigned cipherNum = avail_ciphers.size();
1012 if (pj_ssl_cipher_get_availables(&avail_ciphers.front(), &cipherNum) != PJ_SUCCESS)
1013 JAMI_ERR(
"Unable to determine cipher list on this system");
1014 avail_ciphers.resize(cipherNum);
1017 std::string_view stream(conf.tlsCiphers), item;
1019 std::string cipher(item);
1020 auto item_cid = pj_ssl_cipher_id(cipher.c_str());
1021 if (item_cid != PJ_TLS_UNKNOWN_CIPHER) {
1022 JAMI_WARN(
"Valid cipher: %s", cipher.c_str());
1023 ciphers_.push_back(item_cid);
1025 JAMI_ERR(
"Invalid cipher: %s", cipher.c_str());
1028 ciphers_.erase(std::remove_if(ciphers_.begin(),
1030 [&](pj_ssl_cipher c) {
1031 return std::find(avail_ciphers.cbegin(), avail_ciphers.cend(), c)
1032 == avail_ciphers.cend();
1038 tlsSetting_.ca_list_file =
CONST_PJ_STR(conf.tlsCaListFile);
1039 tlsSetting_.cert_file =
CONST_PJ_STR(conf.tlsCaListFile);
1040 tlsSetting_.privkey_file =
CONST_PJ_STR(conf.tlsPrivateKeyFile);
1043 JAMI_DBG(
"Using %zu ciphers", ciphers_.size());
1044 tlsSetting_.ciphers_num = ciphers_.size();
1045 if (tlsSetting_.ciphers_num > 0) {
1046 tlsSetting_.ciphers = &ciphers_.front();
1049 tlsSetting_.verify_server = conf.tlsVerifyServer;
1050 tlsSetting_.verify_client = conf.tlsVerifyClient;
1051 tlsSetting_.require_client_cert = conf.tlsRequireClientCertificate;
1052 pjsip_cfg()->endpt.disable_secure_dlg_check = conf.tlsDisableSecureDlgCheck;
1053 tlsSetting_.timeout.sec = conf.tlsNegotiationTimeout;
1055 tlsSetting_.qos_type = PJ_QOS_TYPE_BEST_EFFORT;
1056 tlsSetting_.qos_ignore_error = PJ_TRUE;
1060SIPAccount::initStunConfiguration()
1062 std::string_view stunServer(config().stunServer);
1063 auto pos = stunServer.find(
':');
1064 if (pos == std::string_view::npos) {
1065 stunServerName_ = sip_utils::CONST_PJ_STR(stunServer);
1066 stunPort_ = PJ_STUN_PORT;
1068 stunServerName_ = sip_utils::CONST_PJ_STR(stunServer.substr(0, pos));
1069 auto serverPort = stunServer.substr(pos + 1);
1070 stunPort_ = to_int<uint16_t>(serverPort);
1075SIPAccount::loadConfig()
1077 SIPAccountBase::loadConfig();
1078 setCredentials(config().credentials);
1079 enablePresence(config().presenceEnabled);
1080 initStunConfiguration();
1081 if (config().tlsEnable) {
1082 initTlsConfiguration();
1083 transportType_ = PJSIP_TRANSPORT_TLS;
1085 transportType_ = PJSIP_TRANSPORT_UDP;
1086 if (registrationState_ == RegistrationState::UNLOADED)
1087 setRegistrationState(RegistrationState::UNREGISTERED);
1091SIPAccount::fullMatch(std::string_view username, std::string_view hostname)
const
1093 return userMatch(username) and hostnameMatch(hostname);
1097SIPAccount::userMatch(std::string_view username)
const
1099 return !username.empty() and username == config().username;
1103SIPAccount::hostnameMatch(std::string_view hostname)
const
1105 if (hostname == config().hostname)
1107 const auto a = dhtnet::ip_utils::getAddrList(hostname);
1108 const auto b = dhtnet::ip_utils::getAddrList(config().hostname);
1109 return dhtnet::ip_utils::haveCommonAddr(a, b);
1113SIPAccount::proxyMatch(std::string_view hostname)
const
1115 if (hostname == config().serviceRoute)
1117 const auto a = dhtnet::ip_utils::getAddrList(hostname);
1118 const auto b = dhtnet::ip_utils::getAddrList(config().hostname);
1119 return dhtnet::ip_utils::haveCommonAddr(a, b);
1123SIPAccount::getLoginName()
1126 struct passwd* user_info = getpwuid(getuid());
1127 return user_info ? user_info->pw_name :
"";
1129 DWORD size = UNLEN + 1;
1130 TCHAR username[UNLEN + 1];
1132 if (GetUserName((TCHAR*) username, &size)) {
1140SIPAccount::getFromUri()
const
1143 std::string transport;
1146 const auto& conf = config();
1147 std::string username(conf.username.empty() ? getLoginName() : conf.username);
1148 std::string hostname(conf.hostname);
1151 if (transportType_ == PJSIP_TRANSPORT_TLS || transportType_ == PJSIP_TRANSPORT_TLS6) {
1153 transport =
";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
1158 if (hostname.empty()) {
1159 hostname = sip_utils::as_view(*pj_gethostname());
1162 if (dhtnet::IpAddr::isIpv6(hostname))
1163 hostname = dhtnet::IpAddr(hostname).toString(
false,
true);
1165 std::string uri =
"<" + scheme + username +
"@" + hostname + transport +
">";
1166 if (not conf.displayName.empty())
1167 return "\"" + conf.displayName +
"\" " + uri;
1172SIPAccount::getToUri(
const std::string& username)
const
1175 std::string transport;
1176 std::string hostname;
1179 if (transportType_ == PJSIP_TRANSPORT_TLS || transportType_ == PJSIP_TRANSPORT_TLS6) {
1181 transport =
";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
1186 if (username.find(
"sip") != std::string::npos)
1190 if (username.find(
'@') == std::string::npos)
1191 hostname = config().hostname;
1193 if (not hostname.empty() and dhtnet::IpAddr::isIpv6(hostname))
1194 hostname = dhtnet::IpAddr(hostname).toString(
false,
true);
1196 const auto* ltSymbol = username.find(
'<') == std::string::npos ?
"<" :
"";
1197 const auto* gtSymbol = username.find(
'>') == std::string::npos ?
">" :
"";
1199 return ltSymbol + scheme + username + (hostname.empty() ?
"" :
"@") + hostname + transport + gtSymbol;
1203SIPAccount::getServerUri()
const
1206 std::string transport;
1209 if (transportType_ == PJSIP_TRANSPORT_TLS || transportType_ == PJSIP_TRANSPORT_TLS6) {
1211 transport =
";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
1217 if (dhtnet::IpAddr::isIpv6(config().hostname))
1218 host = dhtnet::IpAddr(config().hostname).toString(
false,
true);
1220 host = config().hostname;
1222 return "<" + scheme + host + transport +
">";
1226SIPAccount::getContactAddress()
const
1228 std::lock_guard lock(contactMutex_);
1229 return contactAddress_;
1233SIPAccount::getContactHeader()
const
1235 std::lock_guard lock(contactMutex_);
1236 return contactHeader_;
1240SIPAccount::updateContactHeader()
1242 std::lock_guard lock(contactMutex_);
1244 if (not transport_ or not transport_->get()) {
1245 JAMI_ERR(
"Transport not created yet");
1249 if (not contactAddress_) {
1250 JAMI_ERR(
"Invalid contact address: %s", contactAddress_.toString(
true).c_str());
1254 auto contactHdr = printContactHeader(config().username,
1255 config().displayName,
1256 contactAddress_.toString(
false,
true),
1257 contactAddress_.getPort(),
1258 PJSIP_TRANSPORT_IS_SECURE(transport_->get()),
1259 config().deviceKey);
1261 contactHeader_ = std::move(contactHdr);
1265SIPAccount::initContactAddress()
1273 if (not transport_ or not transport_->get()) {
1274 JAMI_ERR(
"Transport not created yet");
1279 pjsip_transport_type_e transportType = transportType_;
1281 if (transportType == PJSIP_TRANSPORT_START_OTHER)
1282 transportType = PJSIP_TRANSPORT_UDP;
1284 std::string address;
1288 link_.findLocalAddressFromTransport(transport_->get(), transportType, config().hostname, address, port);
1290 if (getUPnPActive() and getUPnPIpAddress()) {
1291 address = getUPnPIpAddress().toString();
1292 port = publishedPortUsed_;
1293 useUPnPAddressPortInVIA();
1294 JAMI_DBG(
"Using UPnP address %s and port %d", address.c_str(), port);
1295 }
else if (not config().publishedSameasLocal) {
1296 address = getPublishedIpAddress().toString();
1297 port = config().publishedPort;
1298 JAMI_DBG(
"Using published address %s and port %d", address.c_str(), port);
1299 }
else if (config().stunEnabled) {
1300 auto success = link_.findLocalAddressFromSTUN(transport_->get(), &stunServerName_, stunPort_, address, port);
1302 emitSignal<libjami::ConfigurationSignal::StunStatusFailed>(getAccountID());
1303 setPublishedAddress({address});
1304 publishedPortUsed_ = port;
1305 usePublishedAddressPortInVIA();
1307 if (!receivedParameter_.empty()) {
1308 address = receivedParameter_;
1309 JAMI_DBG(
"Using received address %s", address.c_str());
1314 JAMI_DBG(
"Using received port %d", port);
1318 std::lock_guard lock(contactMutex_);
1319 contactAddress_ = dhtnet::IpAddr(address);
1320 contactAddress_.setPort(port);
1322 return contactAddress_;
1326SIPAccount::printContactHeader(
const std::string& username,
1327 const std::string& displayName,
1328 const std::string& address,
1331 const std::string& deviceKey)
1340 std::string quotedDisplayName = displayName.empty() ?
"" :
"\"" + displayName +
"\" ";
1342 std::ostringstream contact;
1343 const auto* scheme = secure ?
"sips" :
"sip";
1344 const auto* transport = secure ?
";transport=tls" :
"";
1346 contact << quotedDisplayName <<
"<" << scheme <<
":" << username << (username.empty() ?
"" :
"@") << address <<
":"
1347 << port << transport;
1349 if (not deviceKey.empty()) {
1351#if defined(__ANDROID__)
1352 <<
";pn-provider=" <<
PN_FCM
1353#elif defined(__Apple__)
1356 <<
";pn-param=" <<
";pn-prid=" << deviceKey;
1360 return contact.str();
1364SIPAccount::getHostPortFromSTUN(pj_pool_t* pool)
1368 auto success = link_.findLocalAddressFromSTUN(transport_ ? transport_->get() :
nullptr,
1374 emitSignal<libjami::ConfigurationSignal::StunStatusFailed>(getAccountID());
1375 pjsip_host_port result;
1376 pj_strdup2(pool, &result.host, addr.c_str());
1381const std::vector<std::string>&
1382SIPAccount::getSupportedTlsCiphers()
1386 static std::vector<std::string> availCiphers {};
1390 if (availCiphers.empty()) {
1391 unsigned cipherNum = 256;
1393 if (pj_ssl_cipher_get_availables(&avail_ciphers.front(), &cipherNum) != PJ_SUCCESS)
1394 JAMI_ERR(
"Unable to determine cipher list on this system");
1395 avail_ciphers.resize(cipherNum);
1396 availCiphers.reserve(cipherNum);
1397 for (
const auto& item : avail_ciphers) {
1399 availCiphers.push_back(pj_ssl_cipher_name(item));
1402 return availCiphers;
1405const std::vector<std::string>&
1406SIPAccount::getSupportedTlsProtocols()
1413SIPAccount::setCredentials(
const std::vector<SipAccountConfig::Credentials>& creds)
1416 cred_.reserve(creds.size());
1417 bool md5HashingEnabled = Manager::instance().preferences.getMd5Hash();
1419 for (
auto& c : creds) {
1420 cred_.emplace_back(pjsip_cred_info { CONST_PJ_STR(c.realm),
1421 CONST_PJ_STR(
"digest"),
1422 CONST_PJ_STR(c.username),
1424 (md5HashingEnabled ? PJSIP_CRED_DATA_DIGEST : PJSIP_CRED_DATA_PLAIN_PASSWD),
1426 CONST_PJ_STR(md5HashingEnabled ? c.password_h : c.password),
1427 PJSIP_AUTH_ALGORITHM_NOT_SET,
1435 std::string details_str;
1436 const pj_str_t* description = pjsip_get_status_text(details_code);
1438 details_str = sip_utils::as_view(*description);
1439 registrationStateDetailed_ = {details_code, details_str};
1440 SIPAccountBase::setRegistrationState(state, details_code, details_str);
1444SIPAccount::isIP2IP()
const
1446 return config().hostname.empty();
1450SIPAccount::getPresence()
const
1459SIPAccount::enablePresence(
const bool& enabled)
1462 JAMI_ERR(
"Presence not initialized");
1466 JAMI_LOG(
"[Account {}] Presence enabled: {}.", accountID_, enabled ? TRUE_STR : FALSE_STR);
1468 presence_->enable(enabled);
1476SIPAccount::supportPresence(
int function,
bool enabled)
1479 JAMI_ERR(
"Presence not initialized");
1483 if (presence_->isSupported(function) == enabled)
1486 JAMI_LOG(
"[Account {}] Presence support ({}: {}).",
1489 enabled ? TRUE_STR : FALSE_STR);
1490 presence_->support(function, enabled);
1495 enablePresence(
false);
1497 Manager::instance().saveConfig();
1499 emitSignal<libjami::ConfigurationSignal::AccountsChanged>();
1503SIPAccount::matches(std::string_view userName, std::string_view server)
const
1505 if (fullMatch(userName, server)) {
1506 JAMI_LOG(
"Matching account ID in request is a fullmatch {:s}@{:s}", userName, server);
1507 return MatchRank::FULL;
1508 }
else if (hostnameMatch(server)) {
1509 JAMI_LOG(
"Matching account ID in request with hostname {:s}", server);
1510 return MatchRank::PARTIAL;
1511 }
else if (userMatch(userName)) {
1512 JAMI_LOG(
"Matching account ID in request with username {:s}", userName);
1513 return MatchRank::PARTIAL;
1514 }
else if (proxyMatch(server)) {
1515 JAMI_LOG(
"Matching account ID in request with proxy {:s}", server);
1516 return MatchRank::PARTIAL;
1518 return MatchRank::NONE;
1523SIPAccount::destroyRegistrationInfo()
1527 pjsip_regc_destroy(regc_);
1532SIPAccount::resetAutoRegistration()
1534 auto_rereg_.active = PJ_FALSE;
1535 auto_rereg_.attempt_cnt = 0;
1536 if (auto_rereg_.timer.user_data) {
1537 delete ((std::weak_ptr<SIPAccount>*) auto_rereg_.timer.user_data);
1538 auto_rereg_.timer.user_data =
nullptr;
1543SIPAccount::checkNATAddress(pjsip_regc_cbparam* param, pj_pool_t* pool)
1545 JAMI_LOG(
"[Account {}] Checking IP route after the registration", accountID_);
1547 pjsip_transport* tp = param->rdata->tp_info.transport;
1550 pjsip_via_hdr* via = param->rdata->msg_info.via;
1552 if (via->rport_param < 1) {
1554 rport = via->sent_by.port;
1556 pjsip_transport_type_e tp_type;
1557 tp_type = (pjsip_transport_type_e) tp->key.type;
1558 rport = pjsip_transport_get_default_port_for_type(tp_type);
1561 rport = via->rport_param;
1564 const pj_str_t* via_addr = via->recvd_param.slen != 0 ? &via->recvd_param : &via->sent_by.host;
1565 std::string via_addrstr(sip_utils::as_view(*via_addr));
1567 if (dhtnet::IpAddr::isIpv6(via_addrstr))
1568 via_addrstr = dhtnet::IpAddr(via_addrstr).toString(
false,
true);
1570 JAMI_DBG(
"Checking received VIA address: %s", via_addrstr.c_str());
1572 if (via_addr_.host.slen == 0 or via_tp_ != tp) {
1573 if (pj_strcmp(&via_addr_.host, via_addr))
1574 pj_strdup(pool, &via_addr_.host, via_addr);
1577 via_addr_.port = rport;
1579 pjsip_regc_set_via_sent_by(regc_, &via_addr_, via_tp_);
1583 setPublishedAddress(dhtnet::IpAddr(via_addrstr));
1586 dhtnet::IpAddr contact_addr = getContactAddress();
1589 if (contact_addr.getPort() == 0) {
1590 pjsip_transport_type_e tp_type;
1591 tp_type = (pjsip_transport_type_e) tp->key.type;
1592 contact_addr.setPort(pjsip_transport_get_default_port_for_type(tp_type));
1598 bool matched =
false;
1599 dhtnet::IpAddr recv_addr {};
1600 auto status = pj_sockaddr_parse(pj_AF_UNSPEC(), 0, via_addr, recv_addr.pjPtr());
1601 recv_addr.setPort(rport);
1602 if (status == PJ_SUCCESS) {
1604 matched = contact_addr == recv_addr;
1607 auto pjContactAddr = sip_utils::CONST_PJ_STR(contact_addr.toString());
1608 matched = (contact_addr.getPort() == rport and pj_stricmp(&pjContactAddr, via_addr) == 0);
1617 dhtnet::IpAddr srv_ip = {std::string_view(param->rdata->pkt_info.src_name)};
1632 if (not contact_addr.isPrivate() and not srv_ip.isPrivate() and recv_addr.isPrivate()) {
1641 if (contact_addr == recv_addr and recv_addr.isPrivate()) {
1646 JAMI_WARN(
"[account %s] Contact address changed: "
1647 "(%s → %s:%d). Updating registration.",
1649 contact_addr.toString(
true).c_str(),
1657 auto tempContact = printContactHeader(config().username,
1658 config().displayName,
1661 PJSIP_TRANSPORT_IS_SECURE(tp),
1662 config().deviceKey);
1664 if (tempContact.empty()) {
1665 JAMI_ERR(
"Invalid contact header");
1670 std::lock_guard lock(contactMutex_);
1671 contactHeader_ = std::move(tempContact);
1674 if (regc_ !=
nullptr) {
1675 auto contactHdr = getContactHeader();
1676 auto pjContact = sip_utils::CONST_PJ_STR(contactHdr);
1677 pjsip_regc_update_contact(regc_, 1, &pjContact);
1687SIPAccount::autoReregTimerCb()
1693 if (not auto_rereg_.active)
1697 ++auto_rereg_.attempt_cnt;
1700 if (auto_rereg_.attempt_cnt == 1)
1704 }
catch (
const VoipLinkException& e) {
1705 JAMI_ERR(
"Exception during SIP registration: %s", e.what());
1706 scheduleReregistration();
1715SIPAccount::scheduleReregistration()
1721 if (auto_rereg_.timer.id) {
1722 auto_rereg_.timer.id = PJ_FALSE;
1723 pjsip_endpt_cancel_timer(link_.getEndpoint(), &auto_rereg_.timer);
1727 auto_rereg_.active = PJ_TRUE;
1730 auto_rereg_.timer.cb = [](pj_timer_heap_t* , pj_timer_entry* te) {
1731 if (
auto sipAccount =
static_cast<std::weak_ptr<SIPAccount>*
>(te->user_data)->lock())
1732 sipAccount->autoReregTimerCb();
1734 if (not auto_rereg_.timer.user_data)
1735 auto_rereg_.timer.user_data =
new std::weak_ptr<SIPAccount>(weak());
1743 if (delay.sec >= 10) {
1744 delay.msec = delay10ZeroDist_(rand);
1747 delay.msec = delay10PosDist_(rand);
1750 pj_time_val_normalize(&delay);
1752 JAMI_WARNING(
"Scheduling re-registration attempt in {:d} second(s)…", delay.sec);
1753 auto_rereg_.timer.id = PJ_TRUE;
1754 if (pjsip_endpt_schedule_timer(link_.getEndpoint(), &auto_rereg_.timer, &delay) != PJ_SUCCESS)
1755 auto_rereg_.timer.id = PJ_FALSE;
1759SIPAccount::updateDialogViaSentBy(pjsip_dialog* dlg)
1761 if (config().allowIPAutoRewrite && via_addr_.host.slen > 0)
1762 pjsip_dlg_set_via_sent_by(dlg, &via_addr_, via_tp_);
1769static pjsip_accept_hdr* im_create_accept(pj_pool_t *pool)
1772 pjsip_accept_hdr *accept;
1774 accept = pjsip_accept_hdr_create(pool);
1775 accept->values[0] = CONST_PJ_STR(
"text/plain");
1776 accept->values[1] = CONST_PJ_STR(
"application/im-iscomposing+xml");
1784SIPAccount::sendMessage(
const std::string& to,
1786 const std::map<std::string, std::string>& payloads,
1791 if (to.empty() or payloads.empty()) {
1793 messageEngine_.onMessageSent(to,
id,
false);
1797 auto toUri = getToUri(to);
1799 constexpr pjsip_method msg_method = {PJSIP_OTHER_METHOD, CONST_PJ_STR(sip_utils::SIP_METHODS::MESSAGE)};
1800 std::string from(getFromUri());
1801 pj_str_t pjFrom = sip_utils::CONST_PJ_STR(from);
1802 pj_str_t pjTo = sip_utils::CONST_PJ_STR(toUri);
1805 pjsip_tx_data* tdata;
1806 pj_status_t status = pjsip_endpt_create_request(
1807 link_.getEndpoint(), &msg_method, &pjTo, &pjFrom, &pjTo,
nullptr,
nullptr, -1,
nullptr, &tdata);
1808 if (status != PJ_SUCCESS) {
1809 JAMI_ERROR(
"Unable to create request: {:s}", sip_utils::sip_strerror(status));
1810 messageEngine_.onMessageSent(to,
id,
false);
1816 constexpr auto key = CONST_PJ_STR(
"Date");
1818 auto time = std::time(
nullptr);
1819 auto* date = std::ctime(&time);
1821 *std::remove(date, date + strlen(date),
'\n') =
'\0';
1824 hdr =
reinterpret_cast<pjsip_hdr*
>(pjsip_date_hdr_create(tdata->pool, &key, pj_cstr(&date_str, date)));
1825 pjsip_msg_add_hdr(tdata->msg, hdr);
1828 sip_utils::addUserAgentHeader(getUserAgentName(), tdata);
1831 std::unique_ptr<ctx> t {
new ctx(
new pjsip_auth_clt_sess)};
1837 status = pjsip_auth_clt_init(t->auth_sess.get(), link_.getEndpoint(), tdata->pool, 0);
1839 if (status != PJ_SUCCESS) {
1840 JAMI_ERROR(
"Unable to initialize auth session: {:s}", sip_utils::sip_strerror(status));
1841 messageEngine_.onMessageSent(to,
id,
false);
1845 status = pjsip_auth_clt_set_credentials(t->auth_sess.get(),
static_cast<int>(getCredentialCount()), getCredInfo());
1847 if (status != PJ_SUCCESS) {
1848 JAMI_ERROR(
"Unable to set auth session data: {:s}", sip_utils::sip_strerror(status));
1849 messageEngine_.onMessageSent(to,
id,
false);
1853 const pjsip_tpselector tp_sel = getTransportSelector();
1854 status = pjsip_tx_data_set_transport(tdata, &tp_sel);
1856 if (status != PJ_SUCCESS) {
1857 JAMI_ERROR(
"Unable to set transport: {:s}", sip_utils::sip_strerror(status));
1858 messageEngine_.onMessageSent(to,
id,
false);
1862 im::fillPJSIPMessageBody(*tdata, payloads);
1865 status = pjsip_endpt_send_request(link_.getEndpoint(), tdata, -1, t.release(), &onComplete);
1867 if (status != PJ_SUCCESS) {
1868 JAMI_ERROR(
"Unable to send request: {:s}", sip_utils::sip_strerror(status));
1869 messageEngine_.onMessageSent(to,
id,
false);
1875SIPAccount::onComplete(
void* token, pjsip_event* event)
1877 std::unique_ptr<ctx> c {(
ctx*) token};
1880 pj_assert(event->type == PJSIP_EVENT_TSX_STATE);
1881 code =
event->body.tsx_state.tsx->status_code;
1883 auto acc = c->acc.lock();
1888 if (code == PJSIP_SC_UNAUTHORIZED || code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) {
1889 JAMI_INFO(
"Authorization needed for SMS message - Resending");
1890 pjsip_tx_data* new_request;
1893 status = pjsip_auth_clt_reinit_req(c->auth_sess.get(),
1894 event->body.tsx_state.src.rdata,
1895 event->body.tsx_state.tsx->last_tx,
1898 if (status == PJ_SUCCESS) {
1900 pjsip_cseq_hdr* cseq_hdr;
1901 cseq_hdr = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(new_request->msg, PJSIP_H_CSEQ, NULL);
1902 cseq_hdr->cseq += 1;
1907 status = pjsip_endpt_send_request(acc->link_.getEndpoint(), new_request, -1, c.release(), &onComplete);
1909 if (status != PJ_SUCCESS) {
1910 JAMI_ERROR(
"Unable to send request: {:s}", sip_utils::sip_strerror(status));
1911 acc->messageEngine_.onMessageSent(to,
id,
false);
1915 JAMI_ERROR(
"Unable to add Authorization Header into msg");
1916 acc->messageEngine_.onMessageSent(c->to, c->id,
false);
1920 acc->messageEngine_.onMessageSent(c->to,
1922 event && event->body.tsx_state.tsx
1923 && (event->body.tsx_state.tsx->status_code == PJSIP_SC_OK
1924 || event->body.tsx_state.tsx->status_code == PJSIP_SC_ACCEPTED));
1928SIPAccount::getUserUri()
const
1930 return getFromUri();
1934SIPAccount::createBindingAddress()
1936 auto family = hostIp_ ? hostIp_.getFamily() : PJ_AF_INET;
1937 const auto& conf = config();
1939 dhtnet::IpAddr ret = conf.bindAddress.empty()
1940 ? (conf.interface == dhtnet::ip_utils::DEFAULT_INTERFACE || conf.interface.empty()
1941 ? dhtnet::ip_utils::getAnyHostAddr(family)
1942 : dhtnet::ip_utils::getInterfaceAddr(getLocalInterface(), family))
1943 : dhtnet::IpAddr(conf.bindAddress, family);
1945 if (ret.getPort() == 0) {
1946 ret.setPort(conf.tlsEnable ? conf.tlsListenerPort : conf.localPort);
1953SIPAccount::setActiveCodecs(
const std::vector<unsigned>& list)
1955 Account::setActiveCodecs(list);
1957 JAMI_WARNING(
"All audio codecs disabled, enabling all");
1961 JAMI_WARNING(
"All video codecs disabled, enabling all");
1964 config_->activeCodecs = getActiveCodecs(
MEDIA_ALL);
Account specific keys/constants that must be shared in daemon and clients.
const std::string & getAccountID() const
Get the account ID.
std::filesystem::path idPath_
path to account
bool isEmptyOffersEnabled() const
dhtnet::IpAddr getUPnPIpAddress() const
Get the UPnP IP (external router) address.
bool getUPnPActive() const
returns whether or not UPnP is enabled and active ie: if it is able to make port mappings
vCard::utils::VCardData getProfileVcard() const
bool isVideoEnabled() const
std::shared_ptr< SIPCall > newSipCall(const std::shared_ptr< SIPAccountBase > &account, Call::CallType type, const std::vector< libjami::MediaMap > &mediaList)
Create a new call instance.
static LIBJAMI_TEST_EXPORT Manager & instance()
SIPVoIPLink & link_
Voice over IP Link contains a listener thread and calls.
bool getPublishedSameasLocal() const
Get a flag which determine the usage in sip headers of either the local IP address and port (localAdd...
std::string getPublishedAddress() const
Get the public IP address set by the user for this account.
std::vector< MediaAttribute > createDefaultMediaList(bool addVideo, bool hold=false)
virtual dhtnet::IpAddr getPublishedIpAddress(uint16_t family=PF_UNSPEC) const
const std::string & getLocalInterface() const
Get the local interface name on which this account is bound.
void destroyRegistrationInfo()
std::string getToUri(const std::string &username) const override
This method adds the correct scheme, hostname and append the ;transport= parameter at the end of the ...
bool isStunEnabled() const override
SIPAccount(const std::string &accountID, bool presenceEnabled)
Constructor.
bool isIP2IP() const override
Returns true if this is the IP2IP account.
std::shared_ptr< SIPCall > newIncomingCall(const std::string &from, const std::vector< libjami::MediaMap > &mediaList, const std::shared_ptr< SipTransport > &sipTr={}) override
Create incoming SIPCall.
std::shared_ptr< SIPAccount > shared()
pjsip_transport_type_e getTransportType() const
std::string getContactHeader() const
Get the contact header.
void setTransport(const std::shared_ptr< SipTransport > &=nullptr)
std::shared_ptr< Call > newOutgoingCall(std::string_view toUrl, const std::vector< libjami::MediaMap > &mediaList) override
Create outgoing SIPCall.
virtual bool isTlsEnabled() const override
Determine if TLS is enabled for this account.
void updateProfile(const std::string &displayName, const std::string &avatar, const std::string &fileType, int32_t flag) override
updates SIP account profile
bool isSrtpEnabled() const override
std::unique_ptr< SipTransportBroker > sipTransportBroker
Instance that maintain and manage transport (UDP, TLS)
#define JAMI_ERROR(formatstr,...)
#define JAMI_DEBUG(formatstr,...)
#define JAMI_WARNING(formatstr,...)
#define JAMI_LOG(formatstr,...)
std::string encode(std::string_view str)
std::vector< uint8_t > loadFile(const std::filesystem::path &path, const std::filesystem::path &default_dir)
Read the full content of a file at path.
std::string_view getHostFromUri(std::string_view uri)
constexpr const pj_str_t CONST_PJ_STR(T(&a)[N]) noexcept
void removeByKey(VCardData &vCard, std::string_view key)
std::string toString(const VCardData &vCard)
void emitSignal(Args... args)
static constexpr std::string_view PN_FCM
std::vector< pj_ssl_cipher > CipherArray
std::string to_string(double value)
bool getline(std::string_view &str, std::string_view &line, char delim='\n')
Similar to @getline_full but skips empty results.
static void registration_cb(pjsip_regc_cbparam *param)
RegistrationState
Contains all the Registration states for an account can be in.
static constexpr unsigned REGISTRATION_RETRY_INTERVAL
static constexpr std::string_view PN_APNS
static constexpr unsigned REGISTRATION_FIRST_RETRY_INTERVAL
static constexpr std::string_view VALID_TLS_PROTOS[]
static void validate(std::string &member, const std::string ¶m, const T &valid)
static void runOnMainThread(Callback &&cb)
static constexpr const char OFF_CALL[]
static constexpr char TLS_PEER_CA_[]
static constexpr char TLS_CIPHER[]
static constexpr char TLS_PEER_CERT[]
static constexpr char TLS_PEER_CA_NUM[]
void sendRegister(const std::string &accountId, bool enable)
std::map< std::string, std::string > getVolatileAccountDetails(const std::string &accountId)
A SIP Account specify SIP specific functions and object = SIPCall/SIPVoIPLink)
SIPCall are SIP implementation of a normal Call.
A SIP Presence manages buddy subscription in both PBX and IP2IP contexts.
#define PRESENCE_FUNCTION_SUBSCRIBE
#define PRESENCE_FUNCTION_PUBLISH
Specific VoIPLink for SIP (SIP core for incoming and outgoing events).
std::unique_ptr< pjsip_auth_clt_sess, decltype(&pjsip_auth_clt_deinit)> auth_sess
std::weak_ptr< SIPAccount > acc
ctx(pjsip_auth_clt_sess *auth)