39#pragma GCC diagnostic push
40#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
41#include <yaml-cpp/yaml.h>
42#pragma GCC diagnostic pop
61#include <dhtnet/ip_utils.h>
62#include <dhtnet/upnp/upnp_control.h>
64#include <opendht/crypto.h>
94static constexpr std::string_view
PN_FCM =
"fcm"sv;
95static constexpr std::string_view
PN_APNS =
"apns"sv;
102 std::weak_ptr<SIPAccount>
acc;
112 JAMI_ERR(
"Registration callback parameter is null");
118 JAMI_ERR(
"Account doesn't exist in registration callback");
130 via_addr_.host.ptr = 0;
131 via_addr_.host.slen = 0;
142 JAMI_ERR(
"Exception in SIPAccount destructor");
150 const std::string&
avatar,
163 const std::string& key =
"PHOTO;ENCODING=BASE64;TYPE=" +
fileType;
170 }
catch (
const std::exception&
e) {
177 }
else if (
flag == 1) {
188 if (
file.is_open()) {
198 }
catch (
const std::exception&
e) {
203std::shared_ptr<SIPCall>
205 const std::vector<libjami::MediaMap>&
mediaList,
206 const std::shared_ptr<SipTransport>& transport)
224 std::shared_ptr<SIPCall> call;
230 JAMI_WARN(
"Media list is empty, setting a default list");
238 throw std::runtime_error(
"Failed to create the call");
241 bool ipv6 = dhtnet::IpAddr::isIpv6(
toUrl);
246 std::shared_ptr<SipTransport> t
255 JAMI_DBG(
"New %s IP to IP call to %s",
ipv6 ?
"IPv6" :
"IPv4", to.c_str());
262 JAMI_LOG(
"UserAgent: New registered account call to {}",
toUrl);
270 if (call->createIceMediaTransport(
false)) {
271 call->initIceMediaTransport(
true);
275 call->setPeerNumber(
toUri);
276 call->setPeerUri(
toUri);
294 auto&
sdp = call->getSDP();
302 const bool created =
sdp.createOffer(
309 if (not SIPStartCall(call)) {
310 JAMI_ERR(
"Unable to send outgoing INVITE request for new call");
324SIPAccount::onTransportStateChanged(pjsip_transport_state state,
325 const pjsip_transport_state_info* info)
327 pj_status_t currentStatus = transportStatus_;
328 JAMI_DEBUG(
"Transport state changed to {:s} for account {:s}!",
329 SipTransport::stateToStr(state),
331 if (!SipTransport::isAlive(state)) {
333 transportStatus_ = info->status;
334 transportError_ = sip_utils::sip_strerror(info->status);
335 JAMI_ERROR(
"Transport disconnected: {:s}", transportError_);
338 transportStatus_ = PJSIP_SC_SERVICE_UNAVAILABLE;
339 transportError_ =
"";
341 setRegistrationState(RegistrationState::ERROR_GENERIC, PJSIP_SC_TSX_TRANSPORT_ERROR);
345 transportStatus_ = info && info->status ? info->status : PJSIP_SC_OK;
346 transportError_ =
"";
350 if (currentStatus != transportStatus_)
351 emitSignal<libjami::ConfigurationSignal::VolatileDetailsChanged>(accountID_,
356SIPAccount::setTransport(
const std::shared_ptr<SipTransport>& t)
361 JAMI_DEBUG(
"Removing old transport [{}] from account", fmt::ptr(transport_.get()));
365 pjsip_regc_release_transport(regc_);
366 transport_->removeStateListener(
reinterpret_cast<uintptr_t
>(
this));
370 JAMI_DEBUG(
"Set new transport [{}]", fmt::ptr(transport_.get()));
373 transport_->addStateListener(
reinterpret_cast<uintptr_t
>(
this),
374 std::bind(&SIPAccount::onTransportStateChanged,
376 std::placeholders::_1,
377 std::placeholders::_2));
379 if (not initContactAddress()) {
380 JAMI_DEBUG(
"Unable to register: invalid address");
383 updateContactHeader();
388SIPAccount::getTransportSelector()
391 return SIPVoIPLink::getTransportSelector(
nullptr);
392 return SIPVoIPLink::getTransportSelector(transport_->get());
396SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
399 call->addLocalIceAttributes();
401 const std::string& toUri(call->getPeerNumber());
402 pj_str_t pjTo = sip_utils::CONST_PJ_STR(toUri);
405 std::string from(getFromUri());
406 pj_str_t pjFrom = sip_utils::CONST_PJ_STR(from);
408 auto transport = call->getTransport();
410 JAMI_ERROR(
"Unable to start call without transport");
414 std::string contact = getContactHeader();
415 JAMI_DEBUG(
"Contact header: {:s} / {:s} → {:s}", contact, from, toUri);
417 pj_str_t pjContact = sip_utils::CONST_PJ_STR(contact);
418 auto local_sdp = isEmptyOffersEnabled() ? nullptr : call->getSDP().getLocalSdpSession();
420 pjsip_dialog* dialog {
nullptr};
421 pjsip_inv_session* inv {
nullptr};
422 if (!CreateClientDialogAndInvite(&pjFrom, &pjContact, &pjTo,
nullptr, local_sdp, &dialog, &inv))
425 inv->mod_data[link_.getModId()] = call.get();
426 call->setInviteSession(inv);
428 updateDialogViaSentBy(dialog);
430 if (hasServiceRoute())
431 pjsip_dlg_set_route_set(dialog,
432 sip_utils::createRouteSet(getServiceRoute(),
433 call->inviteSession_->pool));
436 and pjsip_auth_clt_set_credentials(&dialog->auth_sess, getCredentialCount(), getCredInfo())
438 JAMI_ERROR(
"Unable to initialize credentials for invite session authentication");
442 pjsip_tx_data* tdata;
444 if (pjsip_inv_invite(call->inviteSession_.get(), &tdata) != PJ_SUCCESS) {
445 JAMI_ERROR(
"Unable to initialize invite messager for this call");
449 const pjsip_tpselector tp_sel = link_.getTransportSelector(transport->get());
450 if (pjsip_dlg_set_transport(dialog, &tp_sel) != PJ_SUCCESS) {
451 JAMI_ERROR(
"Unable to associate transport for invite session dialog");
456 sip_utils::addUserAgentHeader(getUserAgentName(), tdata);
458 if (pjsip_inv_send_msg(call->inviteSession_.get(), tdata) != PJ_SUCCESS) {
459 JAMI_ERROR(
"Unable to send invite message for this call");
463 call->setState(Call::CallState::ACTIVE, Call::ConnectionState::PROGRESSING);
469SIPAccount::usePublishedAddressPortInVIA()
471 publishedIpStr_ = getPublishedIpAddress().toString();
472 via_addr_.host.ptr = (
char*) publishedIpStr_.c_str();
473 via_addr_.host.slen = publishedIpStr_.size();
474 via_addr_.port = publishedPortUsed_;
478SIPAccount::useUPnPAddressPortInVIA()
480 upnpIpAddr_ = getUPnPIpAddress().toString();
481 via_addr_.host.ptr = (
char*) upnpIpAddr_.c_str();
482 via_addr_.host.slen = upnpIpAddr_.size();
483 via_addr_.port = publishedPortUsed_;
488validate(std::string& member,
const std::string& param,
const T& valid)
490 const auto begin = std::begin(valid);
491 const auto end = std::end(valid);
492 if (find(begin, end, param) != end)
495 JAMI_ERROR(
"Invalid parameter \"{:s}\"", param);
498std::map<std::string, std::string>
499SIPAccount::getVolatileAccountDetails()
const
501 auto a = SIPAccountBase::getVolatileAccountDetails();
502 a.emplace(Conf::CONFIG_ACCOUNT_REGISTRATION_STATE_CODE,
503 std::to_string(registrationStateDetailed_.first));
504 a.emplace(Conf::CONFIG_ACCOUNT_REGISTRATION_STATE_DESC, registrationStateDetailed_.second);
508 a.emplace(Conf::CONFIG_PRESENCE_STATUS, presence_->isOnline() ? TRUE_STR : FALSE_STR);
509 a.emplace(Conf::CONFIG_PRESENCE_NOTE, presence_->getNote());
512 if (transport_ and transport_->isSecure() and transport_->isConnected()) {
513 const auto& tlsInfos = transport_->getTlsInfos();
514 auto cipher = pj_ssl_cipher_name(tlsInfos.cipher);
515 if (tlsInfos.cipher and not cipher)
516 JAMI_WARN(
"Unknown cipher: %d", tlsInfos.cipher);
519 auto ca = tlsInfos.peerCert->issuer;
522 std::ostringstream name_str;
524 a.emplace(name_str.str(), ca->toString());
534SIPAccount::mapPortUPnP()
536 dhtnet::upnp::Mapping map(dhtnet::upnp::PortType::UDP,
537 config().publishedPort,
539 map.setNotifyCallback([w = weak()](dhtnet::upnp::Mapping::sharedPtr_t mapRes) {
540 if (
auto accPtr = w.lock()) {
541 auto oldPort = static_cast<in_port_t>(accPtr->publishedPortUsed_);
542 bool success = mapRes->getState() == dhtnet::upnp::MappingState::OPEN
543 or mapRes->getState() == dhtnet::upnp::MappingState::IN_PROGRESS;
544 auto newPort = success ? mapRes->getExternalPort() : accPtr->config().publishedPort;
545 if (not success and not accPtr->isRegistered()) {
547 "[Account {:s}] Failed to open port {}: registering SIP account anyway",
548 accPtr->getAccountID(),
550 accPtr->doRegister1_();
553 if ((oldPort != newPort)
554 or (accPtr->getRegistrationState() != RegistrationState::REGISTERED)) {
555 if (not accPtr->isRegistered())
556 JAMI_WARNING(
"[Account {:s}] SIP port {} opened: registering SIP account",
557 accPtr->getAccountID(),
561 "[Account {:s}] SIP port changed to {}: re-registering SIP account",
562 accPtr->getAccountID(),
564 accPtr->publishedPortUsed_ = newPort;
566 accPtr->connectivityChanged();
569 accPtr->doRegister1_();
573 auto mapRes = upnpCtrl_->reserveMapping(map);
574 if (mapRes and mapRes->getState() == dhtnet::upnp::MappingState::OPEN) {
582SIPAccount::setPushNotificationToken(
const std::string& pushDeviceToken)
584 JAMI_WARNING(
"[SIP Account {}] setPushNotificationToken: {}", getAccountID(), pushDeviceToken);
585 if (SIPAccountBase::setPushNotificationToken(pushDeviceToken)) {
586 if (config().enabled) {
596SIPAccount::setPushNotificationConfig(
const std::map<std::string, std::string>& data)
598 if (SIPAccountBase::setPushNotificationConfig(data)) {
599 if (config().enabled) {
609SIPAccount::pushNotificationReceived(
const std::string& from,
610 const std::map<std::string, std::string>&)
612 JAMI_WARNING(
"[SIP Account {:s}] pushNotificationReceived: {:s}", getAccountID(), from);
614 if (config().enabled) {
621SIPAccount::doRegister()
623 if (not isUsable()) {
624 JAMI_WARN(
"Account must be enabled and active to register, ignoring");
628 JAMI_DEBUG(
"doRegister {:s}", config_->hostname);
632 JAMI_DBG(
"UPnP: waiting for IGD to register SIP account");
633 setRegistrationState(RegistrationState::TRYING);
634 if (not mapPortUPnP()) {
635 JAMI_DBG(
"UPnP: UPNP request failed, try to register SIP account anyway");
644SIPAccount::doRegister1_()
647 std::lock_guard lock(configurationMutex_);
654 link_.resolveSrvName(hasServiceRoute() ? getServiceRoute() : config().hostname,
655 config().tlsEnable ? PJSIP_TRANSPORT_TLS : PJSIP_TRANSPORT_UDP,
656 [w = weak()](
std::vector<
dhtnet::IpAddr> host_ips) {
657 if (
auto acc = w.lock()) {
658 std::lock_guard lock(
659 acc->configurationMutex_);
660 if (host_ips.empty()) {
661 JAMI_ERR(
"Unable to resolve hostname for registration.");
662 acc->setRegistrationState(RegistrationState::ERROR_GENERIC,
666 acc->hostIp_ = host_ips[0];
673SIPAccount::doRegister2_()
675 if (not isIP2IP() and not hostIp_) {
676 setRegistrationState(RegistrationState::ERROR_GENERIC, PJSIP_SC_NOT_FOUND);
681 dhtnet::IpAddr bindAddress = createBindingAddress();
682 if (not bindAddress) {
683 setRegistrationState(RegistrationState::ERROR_GENERIC, PJSIP_SC_NOT_FOUND);
684 JAMI_ERROR(
"Unable to compute address to bind.");
688 bool ipv6 = bindAddress.isIpv6();
689 transportType_ = config().tlsEnable ? (ipv6 ? PJSIP_TRANSPORT_TLS6 : PJSIP_TRANSPORT_TLS)
690 : (ipv6 ? PJSIP_TRANSPORT_UDP6 : PJSIP_TRANSPORT_UDP);
693 if (config().tlsEnable) {
694 JAMI_DEBUG(
"TLS is enabled for account {}", accountID_);
699 initTlsConfiguration();
702 tlsListener_ = link_.sipTransportBroker->getTlsListener(bindAddress, getTlsSetting());
704 setRegistrationState(RegistrationState::ERROR_GENERIC);
710 tlsListener_.reset();
717 if (!config().tlsEnable) {
718 setTransport(link_.sipTransportBroker->getUdpTransport(bindAddress));
720 setRegistrationState(RegistrationState::REGISTERED);
727 if (isTlsEnabled()) {
728 setTransport(link_.sipTransportBroker->getTlsTransport(tlsListener_,
730 config().tlsServerName.empty()
732 : config().tlsServerName));
734 setTransport(link_.sipTransportBroker->getUdpTransport(bindAddress));
737 throw VoipLinkException(
"Unable to create transport");
740 }
catch (
const VoipLinkException& e) {
742 setRegistrationState(RegistrationState::ERROR_GENERIC);
746 if (presence_ and presence_->isEnabled()) {
747 presence_->subscribeClient(getFromUri(),
true);
748 presence_->sendPresence(
true,
"");
753SIPAccount::doUnregister(
bool )
755 std::unique_lock<std::recursive_mutex> lock(configurationMutex_);
757 tlsListener_.reset();
763 JAMI_ERR(
"doUnregister %s", e.what());
769 resetAutoRegistration();
773SIPAccount::connectivityChanged()
775 if (not isUsable()) {
786SIPAccount::sendRegister()
788 if (not isUsable()) {
789 JAMI_WARNING(
"[Account {}] Must be enabled and active to register, ignoring", accountID_);
794 setRegistrationState(RegistrationState::TRYING);
796 pjsip_regc* regc =
nullptr;
797 if (pjsip_regc_create(link_.getEndpoint(), (
void*)
this, &
registration_cb, ®c) != PJ_SUCCESS)
800 std::string srvUri(getServerUri());
801 pj_str_t pjSrv {(
char*) srvUri.data(), (pj_ssize_t) srvUri.size()};
804 std::string from(getFromUri());
805 pj_str_t pjFrom(sip_utils::CONST_PJ_STR(from));
808 const std::string& received(getReceivedParameter());
810 std::string contact = getContactHeader();
812 JAMI_LOG(
"[Account {}] Using contact header {} in registration", accountID_, contact);
815 if (getUPnPActive() or not getPublishedSameasLocal()
816 or (not received.empty() and received != getPublishedAddress())) {
817 pjsip_host_port* via = getViaAddr();
818 JAMI_LOG(
"Setting VIA sent-by to {:s}:{:d}",
819 sip_utils::as_view(via->host),
822 if (pjsip_regc_set_via_sent_by(regc, via, transport_->get()) != PJ_SUCCESS)
824 }
else if (isStunEnabled()) {
825 if (pjsip_regc_set_via_sent_by(regc, getViaAddr(), transport_->get()) != PJ_SUCCESS)
830 pj_status_t status = PJ_SUCCESS;
831 pj_str_t pjContact = sip_utils::CONST_PJ_STR(contact);
834 = pjsip_regc_init(regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, getRegistrationExpire()))
836 JAMI_ERR(
"pjsip_regc_init failed with error %d: %s",
838 sip_utils::sip_strerror(status).c_str());
842 if (hasServiceRoute())
843 pjsip_regc_set_route_set(regc,
844 sip_utils::createRouteSet(getServiceRoute(), link_.getPool()));
846 pjsip_regc_set_credentials(regc, getCredentialCount(), getCredInfo());
849 pj_list_init(&hdr_list);
850 auto pjUserAgent = CONST_PJ_STR(getUserAgentName());
851 constexpr pj_str_t STR_USER_AGENT = CONST_PJ_STR(
"User-Agent");
853 pjsip_generic_string_hdr* h = pjsip_generic_string_hdr_create(link_.getPool(),
856 pj_list_push_back(&hdr_list, (pjsip_hdr*) h);
857 pjsip_regc_add_headers(regc, &hdr_list);
859 pjsip_tx_data* tdata;
861 if (pjsip_regc_register(regc, isRegistrationRefreshEnabled(), &tdata) != PJ_SUCCESS)
862 throw VoipLinkException(
"Unable to initialize transaction data for account registration");
864 const pjsip_tpselector tp_sel = getTransportSelector();
865 if (pjsip_regc_set_transport(regc, &tp_sel) != PJ_SUCCESS)
868 if (tp_sel.u.transport)
869 setUpTransmissionData(tdata, tp_sel.u.transport->key.type);
872 if ((status = pjsip_regc_send(regc, tdata)) != PJ_SUCCESS) {
873 JAMI_ERROR(
"pjsip_regc_send failed with error {:d}: {}",
875 sip_utils::sip_strerror(status));
879 setRegistrationInfo(regc);
883SIPAccount::setUpTransmissionData(pjsip_tx_data* tdata,
long transportKeyType)
886 auto ai = &tdata->dest_info;
887 ai->name = pj_strdup3(tdata->pool, config().hostname.c_str());
889 ai->addr.entry[0].type = (pjsip_transport_type_e) transportKeyType;
890 pj_memcpy(&ai->addr.entry[0].addr, hostIp_.pjPtr(),
sizeof(pj_sockaddr));
891 ai->addr.entry[0].addr_len = hostIp_.getLength();
897SIPAccount::onRegister(pjsip_regc_cbparam* param)
899 if (param->regc != getRegistrationInfo())
902 if (param->status != PJ_SUCCESS) {
903 JAMI_ERROR(
"[Account {}] SIP registration error {:d}",
904 accountID_, param->status);
905 destroyRegistrationInfo();
906 setRegistrationState(RegistrationState::ERROR_GENERIC, param->code);
907 }
else if (param->code < 0 || param->code >= 300) {
908 JAMI_ERROR(
"[Account {}] SIP registration failed, status={:d} ({:s})",
909 accountID_, param->code,
910 sip_utils::as_view(param->reason));
911 destroyRegistrationInfo();
912 switch (param->code) {
913 case PJSIP_SC_FORBIDDEN:
914 setRegistrationState(RegistrationState::ERROR_AUTH, param->code);
916 case PJSIP_SC_NOT_FOUND:
917 setRegistrationState(RegistrationState::ERROR_HOST, param->code);
919 case PJSIP_SC_REQUEST_TIMEOUT:
920 setRegistrationState(RegistrationState::ERROR_HOST, param->code);
922 case PJSIP_SC_SERVICE_UNAVAILABLE:
923 setRegistrationState(RegistrationState::ERROR_SERVICE_UNAVAILABLE, param->code);
926 setRegistrationState(RegistrationState::ERROR_GENERIC, param->code);
928 }
else if (PJSIP_IS_STATUS_IN_CLASS(param->code, 200)) {
930 resetAutoRegistration();
932 if (param->expiration < 1) {
933 destroyRegistrationInfo();
935 setRegistrationState(RegistrationState::UNREGISTERED, param->code);
942 if (config().allowIPAutoRewrite and checkNATAddress(param, link_.getPool()))
943 JAMI_WARN(
"New contact: %s", getContactHeader().c_str());
946 if (hasServiceRoute())
947 pjsip_regc_set_route_set(param->regc,
948 sip_utils::createRouteSet(getServiceRoute(),
951 setRegistrationState(RegistrationState::REGISTERED, param->code);
959 switch (param->code) {
960 case PJSIP_SC_REQUEST_TIMEOUT:
961 case PJSIP_SC_INTERNAL_SERVER_ERROR:
962 case PJSIP_SC_BAD_GATEWAY:
963 case PJSIP_SC_SERVICE_UNAVAILABLE:
964 case PJSIP_SC_SERVER_TIMEOUT:
965 scheduleReregistration();
970 if (PJSIP_IS_STATUS_IN_CLASS(param->code, 600))
971 scheduleReregistration();
974 if (param->expiration != config().registrationExpire) {
975 JAMI_DBG(
"Registrar returned EXPIRE value [%u s] different from the requested [%u s]",
977 config().registrationExpire);
985SIPAccount::sendUnregister()
988 if (!isRegistered()) {
989 setRegistrationState(RegistrationState::UNREGISTERED);
994 pjsip_regc* regc = getRegistrationInfo();
998 pjsip_tx_data* tdata =
nullptr;
999 if (pjsip_regc_unregister(regc, &tdata) != PJ_SUCCESS)
1002 const pjsip_tpselector tp_sel = getTransportSelector();
1003 if (pjsip_regc_set_transport(regc, &tp_sel) != PJ_SUCCESS)
1006 if (tp_sel.u.transport)
1007 setUpTransmissionData(tdata, tp_sel.u.transport->key.type);
1010 if ((status = pjsip_regc_send(regc, tdata)) != PJ_SUCCESS) {
1011 JAMI_ERR(
"pjsip_regc_send failed with error %d: %s",
1013 sip_utils::sip_strerror(status).c_str());
1019SIPAccount::tlsProtocolFromString(
const std::string& method)
1021 if (method ==
"Default")
1022 return PJSIP_SSL_DEFAULT_PROTO;
1023 if (method ==
"TLSv1.2")
1024 return PJ_SSL_SOCK_PROTO_TLS1_2;
1025 if (method ==
"TLSv1.1")
1026 return PJ_SSL_SOCK_PROTO_TLS1_2 | PJ_SSL_SOCK_PROTO_TLS1_1;
1027 if (method ==
"TLSv1")
1028 return PJ_SSL_SOCK_PROTO_TLS1_2 | PJ_SSL_SOCK_PROTO_TLS1_1 | PJ_SSL_SOCK_PROTO_TLS1;
1029 return PJSIP_SSL_DEFAULT_PROTO;
1036SIPAccount::trimCiphers()
1040 static const size_t MAX_CIPHERS_STRLEN = 1000;
1041 for (
const auto& item : ciphers_) {
1042 sum += strlen(pj_ssl_cipher_name(item));
1043 if (sum > MAX_CIPHERS_STRLEN)
1047 ciphers_.resize(count);
1051SIPAccount::initTlsConfiguration()
1053 pjsip_tls_setting_default(&tlsSetting_);
1054 const auto& conf = config();
1055 tlsSetting_.proto = tlsProtocolFromString(conf.tlsMethod);
1059 unsigned cipherNum = avail_ciphers.size();
1060 if (pj_ssl_cipher_get_availables(&avail_ciphers.front(), &cipherNum) != PJ_SUCCESS)
1061 JAMI_ERR(
"Unable to determine cipher list on this system");
1062 avail_ciphers.resize(cipherNum);
1065 std::string_view stream(conf.tlsCiphers), item;
1067 std::string cipher(item);
1068 auto item_cid = pj_ssl_cipher_id(cipher.c_str());
1069 if (item_cid != PJ_TLS_UNKNOWN_CIPHER) {
1070 JAMI_WARN(
"Valid cipher: %s", cipher.c_str());
1071 ciphers_.push_back(item_cid);
1073 JAMI_ERR(
"Invalid cipher: %s", cipher.c_str());
1076 ciphers_.erase(std::remove_if(ciphers_.begin(),
1078 [&](pj_ssl_cipher c) {
1079 return std::find(avail_ciphers.cbegin(),
1080 avail_ciphers.cend(),
1082 == avail_ciphers.cend();
1088 tlsSetting_.ca_list_file =
CONST_PJ_STR(conf.tlsCaListFile);
1089 tlsSetting_.cert_file =
CONST_PJ_STR(conf.tlsCaListFile);
1090 tlsSetting_.privkey_file =
CONST_PJ_STR(conf.tlsPrivateKeyFile);
1093 JAMI_DBG(
"Using %zu ciphers", ciphers_.size());
1094 tlsSetting_.ciphers_num = ciphers_.size();
1095 if (tlsSetting_.ciphers_num > 0) {
1096 tlsSetting_.ciphers = &ciphers_.front();
1099 tlsSetting_.verify_server = conf.tlsVerifyServer;
1100 tlsSetting_.verify_client = conf.tlsVerifyClient;
1101 tlsSetting_.require_client_cert = conf.tlsRequireClientCertificate;
1102 pjsip_cfg()->endpt.disable_secure_dlg_check = conf.tlsDisableSecureDlgCheck;
1103 tlsSetting_.timeout.sec = conf.tlsNegotiationTimeout;
1105 tlsSetting_.qos_type = PJ_QOS_TYPE_BEST_EFFORT;
1106 tlsSetting_.qos_ignore_error = PJ_TRUE;
1110SIPAccount::initStunConfiguration()
1112 std::string_view stunServer(config().stunServer);
1113 auto pos = stunServer.find(
':');
1114 if (pos == std::string_view::npos) {
1115 stunServerName_ = sip_utils::CONST_PJ_STR(stunServer);
1116 stunPort_ = PJ_STUN_PORT;
1118 stunServerName_ = sip_utils::CONST_PJ_STR(stunServer.substr(0, pos));
1119 auto serverPort = stunServer.substr(pos + 1);
1120 stunPort_ = to_int<uint16_t>(serverPort);
1125SIPAccount::loadConfig()
1127 SIPAccountBase::loadConfig();
1128 setCredentials(config().credentials);
1129 enablePresence(config().presenceEnabled);
1130 initStunConfiguration();
1131 if (config().tlsEnable) {
1132 initTlsConfiguration();
1133 transportType_ = PJSIP_TRANSPORT_TLS;
1135 transportType_ = PJSIP_TRANSPORT_UDP;
1136 if (registrationState_ == RegistrationState::UNLOADED)
1137 setRegistrationState(RegistrationState::UNREGISTERED);
1141SIPAccount::fullMatch(std::string_view username, std::string_view hostname)
const
1143 return userMatch(username) and hostnameMatch(hostname);
1147SIPAccount::userMatch(std::string_view username)
const
1149 return !username.empty() and username == config().username;
1153SIPAccount::hostnameMatch(std::string_view hostname)
const
1155 if (hostname == config().hostname)
1157 const auto a = dhtnet::ip_utils::getAddrList(hostname);
1158 const auto b = dhtnet::ip_utils::getAddrList(config().hostname);
1159 return dhtnet::ip_utils::haveCommonAddr(a, b);
1163SIPAccount::proxyMatch(std::string_view hostname)
const
1165 if (hostname == config().serviceRoute)
1167 const auto a = dhtnet::ip_utils::getAddrList(hostname);
1168 const auto b = dhtnet::ip_utils::getAddrList(config().hostname);
1169 return dhtnet::ip_utils::haveCommonAddr(a, b);
1173SIPAccount::getLoginName()
1176 struct passwd* user_info = getpwuid(getuid());
1177 return user_info ? user_info->pw_name :
"";
1179 DWORD
size = UNLEN + 1;
1180 TCHAR username[UNLEN + 1];
1182 if (GetUserName((TCHAR*) username, &size)) {
1190SIPAccount::getFromUri()
const
1193 std::string transport;
1196 const auto& conf = config();
1197 std::string username(conf.username.empty() ? getLoginName() : conf.username);
1198 std::string hostname(conf.hostname);
1201 if (transportType_ == PJSIP_TRANSPORT_TLS || transportType_ == PJSIP_TRANSPORT_TLS6) {
1203 transport =
";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
1208 if (hostname.empty()) {
1209 hostname = sip_utils::as_view(*pj_gethostname());
1212 if (dhtnet::IpAddr::isIpv6(hostname))
1213 hostname = dhtnet::IpAddr(hostname).toString(
false,
true);
1215 std::string uri =
"<" + scheme + username +
"@" + hostname + transport +
">";
1216 if (not conf.displayName.empty())
1217 return "\"" + conf.displayName +
"\" " + uri;
1222SIPAccount::getToUri(
const std::string& username)
const
1225 std::string transport;
1226 std::string hostname;
1229 if (transportType_ == PJSIP_TRANSPORT_TLS || transportType_ == PJSIP_TRANSPORT_TLS6) {
1231 transport =
";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
1236 if (username.find(
"sip") != std::string::npos)
1240 if (username.find(
'@') == std::string::npos)
1241 hostname = config().hostname;
1243 if (not hostname.empty() and dhtnet::IpAddr::isIpv6(hostname))
1244 hostname = dhtnet::IpAddr(hostname).toString(
false,
true);
1246 auto ltSymbol = username.find(
'<') == std::string::npos ?
"<" :
"";
1247 auto gtSymbol = username.find(
'>') == std::string::npos ?
">" :
"";
1249 return ltSymbol + scheme + username + (hostname.empty() ?
"" :
"@") + hostname + transport
1254SIPAccount::getServerUri()
const
1257 std::string transport;
1260 if (transportType_ == PJSIP_TRANSPORT_TLS || transportType_ == PJSIP_TRANSPORT_TLS6) {
1262 transport =
";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
1268 if (dhtnet::IpAddr::isIpv6(config().hostname))
1269 host = dhtnet::IpAddr(config().hostname).toString(
false,
true);
1271 host = config().hostname;
1273 return "<" + scheme + host + transport +
">";
1277SIPAccount::getContactAddress()
const
1279 std::lock_guard lock(contactMutex_);
1280 return contactAddress_;
1284SIPAccount::getContactHeader()
const
1286 std::lock_guard lock(contactMutex_);
1287 return contactHeader_;
1291SIPAccount::updateContactHeader()
1293 std::lock_guard lock(contactMutex_);
1295 if (not transport_ or not transport_->get()) {
1296 JAMI_ERR(
"Transport not created yet");
1300 if (not contactAddress_) {
1301 JAMI_ERR(
"Invalid contact address: %s", contactAddress_.toString(
true).c_str());
1305 auto contactHdr = printContactHeader(config().username,
1306 config().displayName,
1307 contactAddress_.toString(
false,
true),
1308 contactAddress_.getPort(),
1309 PJSIP_TRANSPORT_IS_SECURE(transport_->get()),
1310 config().deviceKey);
1312 contactHeader_ = std::move(contactHdr);
1316SIPAccount::initContactAddress()
1324 if (not transport_ or not transport_->get()) {
1325 JAMI_ERR(
"Transport not created yet");
1330 pjsip_transport_type_e transportType = transportType_;
1332 if (transportType == PJSIP_TRANSPORT_START_OTHER)
1333 transportType = PJSIP_TRANSPORT_UDP;
1335 std::string address;
1339 link_.findLocalAddressFromTransport(transport_->get(),
1345 if (getUPnPActive() and getUPnPIpAddress()) {
1346 address = getUPnPIpAddress().toString();
1347 port = publishedPortUsed_;
1348 useUPnPAddressPortInVIA();
1349 JAMI_DBG(
"Using UPnP address %s and port %d", address.c_str(), port);
1350 }
else if (not config().publishedSameasLocal) {
1351 address = getPublishedIpAddress().toString();
1352 port = config().publishedPort;
1353 JAMI_DBG(
"Using published address %s and port %d", address.c_str(), port);
1354 }
else if (config().stunEnabled) {
1355 auto success = link_.findLocalAddressFromSTUN(transport_->get(),
1361 emitSignal<libjami::ConfigurationSignal::StunStatusFailed>(getAccountID());
1362 setPublishedAddress({address});
1363 publishedPortUsed_ = port;
1364 usePublishedAddressPortInVIA();
1366 if (!receivedParameter_.empty()) {
1367 address = receivedParameter_;
1368 JAMI_DBG(
"Using received address %s", address.c_str());
1373 JAMI_DBG(
"Using received port %d", port);
1377 std::lock_guard lock(contactMutex_);
1378 contactAddress_ = dhtnet::IpAddr(address);
1379 contactAddress_.setPort(port);
1381 return contactAddress_;
1385SIPAccount::printContactHeader(
const std::string& username,
1386 const std::string& displayName,
1387 const std::string& address,
1390 const std::string& deviceKey)
1399 std::string quotedDisplayName = displayName.empty() ?
"" :
"\"" + displayName +
"\" ";
1401 std::ostringstream contact;
1402 auto scheme = secure ?
"sips" :
"sip";
1403 auto transport = secure ?
";transport=tls" :
"";
1405 contact << quotedDisplayName <<
"<" << scheme <<
":" << username
1406 << (username.empty() ?
"" :
"@") << address <<
":" << port << transport;
1408 if (not deviceKey.empty()) {
1410#if defined(__ANDROID__)
1411 <<
";pn-provider=" <<
PN_FCM
1412#elif defined(__Apple__)
1416 <<
";pn-prid=" << deviceKey;
1420 return contact.str();
1424SIPAccount::getHostPortFromSTUN(pj_pool_t* pool)
1428 auto success = link_.findLocalAddressFromSTUN(transport_ ? transport_->get() :
nullptr,
1434 emitSignal<libjami::ConfigurationSignal::StunStatusFailed>(getAccountID());
1435 pjsip_host_port result;
1436 pj_strdup2(pool, &result.host, addr.c_str());
1441const std::vector<std::string>&
1442SIPAccount::getSupportedTlsCiphers()
1446 static std::vector<std::string> availCiphers {};
1450 if (availCiphers.empty()) {
1451 unsigned cipherNum = 256;
1453 if (pj_ssl_cipher_get_availables(&avail_ciphers.front(), &cipherNum) != PJ_SUCCESS)
1454 JAMI_ERR(
"Unable to determine cipher list on this system");
1455 avail_ciphers.resize(cipherNum);
1456 availCiphers.reserve(cipherNum);
1457 for (
const auto& item : avail_ciphers) {
1459 availCiphers.push_back(pj_ssl_cipher_name(item));
1462 return availCiphers;
1465const std::vector<std::string>&
1466SIPAccount::getSupportedTlsProtocols()
1474SIPAccount::setCredentials(
const std::vector<SipAccountConfig::Credentials>& creds)
1477 cred_.reserve(creds.size());
1478 bool md5HashingEnabled = Manager::instance().preferences.getMd5Hash();
1480 for (
auto& c : creds) {
1482 pjsip_cred_info { CONST_PJ_STR(c.realm),
1483 CONST_PJ_STR(
"digest"),
1484 CONST_PJ_STR(c.username),
1486 (md5HashingEnabled ? PJSIP_CRED_DATA_DIGEST
1487 : PJSIP_CRED_DATA_PLAIN_PASSWD),
1489 CONST_PJ_STR(md5HashingEnabled ? c.password_h : c.password),
1497 const std::string& )
1499 std::string details_str;
1500 const pj_str_t* description = pjsip_get_status_text(details_code);
1502 details_str = sip_utils::as_view(*description);
1503 registrationStateDetailed_ = {details_code, details_str};
1504 SIPAccountBase::setRegistrationState(state, details_code, details_str);
1508SIPAccount::isIP2IP()
const
1510 return config().hostname.empty();
1514SIPAccount::getPresence()
const
1523SIPAccount::enablePresence(
const bool& enabled)
1526 JAMI_ERR(
"Presence not initialized");
1530 JAMI_LOG(
"[Account {}] Presence enabled: {}.", accountID_, enabled ? TRUE_STR : FALSE_STR);
1532 presence_->enable(enabled);
1540SIPAccount::supportPresence(
int function,
bool enabled)
1543 JAMI_ERR(
"Presence not initialized");
1547 if (presence_->isSupported(function) == enabled)
1550 JAMI_LOG(
"[Account {}] Presence support ({}: {}).",
1553 enabled ? TRUE_STR : FALSE_STR);
1554 presence_->support(function, enabled);
1559 enablePresence(
false);
1561 Manager::instance().saveConfig();
1563 emitSignal<libjami::ConfigurationSignal::AccountsChanged>();
1567SIPAccount::matches(std::string_view userName, std::string_view server)
const
1569 if (fullMatch(userName, server)) {
1570 JAMI_LOG(
"Matching account ID in request is a fullmatch {:s}@{:s}",
1573 return MatchRank::FULL;
1574 }
else if (hostnameMatch(server)) {
1575 JAMI_LOG(
"Matching account ID in request with hostname {:s}", server);
1576 return MatchRank::PARTIAL;
1577 }
else if (userMatch(userName)) {
1578 JAMI_LOG(
"Matching account ID in request with username {:s}", userName);
1579 return MatchRank::PARTIAL;
1580 }
else if (proxyMatch(server)) {
1581 JAMI_LOG(
"Matching account ID in request with proxy {:s}", server);
1582 return MatchRank::PARTIAL;
1584 return MatchRank::NONE;
1589SIPAccount::destroyRegistrationInfo()
1593 pjsip_regc_destroy(regc_);
1598SIPAccount::resetAutoRegistration()
1600 auto_rereg_.active = PJ_FALSE;
1601 auto_rereg_.attempt_cnt = 0;
1602 if (auto_rereg_.timer.user_data) {
1603 delete ((std::weak_ptr<SIPAccount>*) auto_rereg_.timer.user_data);
1604 auto_rereg_.timer.user_data =
nullptr;
1609SIPAccount::checkNATAddress(pjsip_regc_cbparam* param, pj_pool_t* pool)
1611 JAMI_LOG(
"[Account {}] Checking IP route after the registration", accountID_);
1613 pjsip_transport* tp = param->rdata->tp_info.transport;
1616 pjsip_via_hdr* via = param->rdata->msg_info.via;
1618 if (via->rport_param < 1) {
1620 rport = via->sent_by.port;
1622 pjsip_transport_type_e tp_type;
1623 tp_type = (pjsip_transport_type_e) tp->key.type;
1624 rport = pjsip_transport_get_default_port_for_type(tp_type);
1627 rport = via->rport_param;
1630 const pj_str_t* via_addr = via->recvd_param.slen != 0 ? &via->recvd_param : &via->sent_by.host;
1631 std::string via_addrstr(sip_utils::as_view(*via_addr));
1633 if (dhtnet::IpAddr::isIpv6(via_addrstr))
1634 via_addrstr = dhtnet::IpAddr(via_addrstr).toString(
false,
true);
1636 JAMI_DBG(
"Checking received VIA address: %s", via_addrstr.c_str());
1638 if (via_addr_.host.slen == 0 or via_tp_ != tp) {
1639 if (pj_strcmp(&via_addr_.host, via_addr))
1640 pj_strdup(pool, &via_addr_.host, via_addr);
1643 via_addr_.port = rport;
1645 pjsip_regc_set_via_sent_by(regc_, &via_addr_, via_tp_);
1649 setPublishedAddress(dhtnet::IpAddr(via_addrstr));
1652 dhtnet::IpAddr contact_addr = getContactAddress();
1655 if (contact_addr.getPort() == 0) {
1656 pjsip_transport_type_e tp_type;
1657 tp_type = (pjsip_transport_type_e) tp->key.type;
1658 contact_addr.setPort(pjsip_transport_get_default_port_for_type(tp_type));
1664 bool matched =
false;
1665 dhtnet::IpAddr recv_addr {};
1666 auto status = pj_sockaddr_parse(pj_AF_UNSPEC(), 0, via_addr, recv_addr.pjPtr());
1667 recv_addr.setPort(rport);
1668 if (status == PJ_SUCCESS) {
1670 matched = contact_addr == recv_addr;
1673 auto pjContactAddr = sip_utils::CONST_PJ_STR(contact_addr.toString());
1674 matched = (contact_addr.getPort() == rport and pj_stricmp(&pjContactAddr, via_addr) == 0);
1683 dhtnet::IpAddr srv_ip = {std::string_view(param->rdata->pkt_info.src_name)};
1698 if (not contact_addr.isPrivate() and not srv_ip.isPrivate() and recv_addr.isPrivate()) {
1707 if (contact_addr == recv_addr and recv_addr.isPrivate()) {
1712 JAMI_WARN(
"[account %s] Contact address changed: "
1713 "(%s → %s:%d). Updating registration.",
1715 contact_addr.toString(
true).c_str(),
1723 auto tempContact = printContactHeader(config().username,
1724 config().displayName,
1727 PJSIP_TRANSPORT_IS_SECURE(tp),
1728 config().deviceKey);
1730 if (tempContact.empty()) {
1731 JAMI_ERR(
"Invalid contact header");
1736 std::lock_guard lock(contactMutex_);
1737 contactHeader_ = std::move(tempContact);
1740 if (regc_ !=
nullptr) {
1741 auto contactHdr = getContactHeader();
1742 auto pjContact = sip_utils::CONST_PJ_STR(contactHdr);
1743 pjsip_regc_update_contact(regc_, 1, &pjContact);
1753SIPAccount::autoReregTimerCb()
1759 if (not auto_rereg_.active)
1763 ++auto_rereg_.attempt_cnt;
1766 if (auto_rereg_.attempt_cnt == 1)
1770 }
catch (
const VoipLinkException& e) {
1771 JAMI_ERR(
"Exception during SIP registration: %s", e.what());
1772 scheduleReregistration();
1781SIPAccount::scheduleReregistration()
1787 if (auto_rereg_.timer.id) {
1788 auto_rereg_.timer.id = PJ_FALSE;
1789 pjsip_endpt_cancel_timer(link_.getEndpoint(), &auto_rereg_.timer);
1793 auto_rereg_.active = PJ_TRUE;
1796 auto_rereg_.timer.cb = [](pj_timer_heap_t* , pj_timer_entry* te) {
1797 if (
auto sipAccount =
static_cast<std::weak_ptr<SIPAccount>*
>(te->user_data)->lock())
1798 sipAccount->autoReregTimerCb();
1800 if (not auto_rereg_.timer.user_data)
1801 auto_rereg_.timer.user_data =
new std::weak_ptr<SIPAccount>(weak());
1810 if (delay.sec >= 10) {
1811 delay.msec = delay10ZeroDist_(rand);
1814 delay.msec = delay10PosDist_(rand);
1817 pj_time_val_normalize(&delay);
1819 JAMI_WARNING(
"Scheduling re-registration attempt in {:d} second(s)…", delay.sec);
1820 auto_rereg_.timer.id = PJ_TRUE;
1821 if (pjsip_endpt_schedule_timer(link_.getEndpoint(), &auto_rereg_.timer, &delay) != PJ_SUCCESS)
1822 auto_rereg_.timer.id = PJ_FALSE;
1826SIPAccount::updateDialogViaSentBy(pjsip_dialog* dlg)
1828 if (config().allowIPAutoRewrite && via_addr_.host.slen > 0)
1829 pjsip_dlg_set_via_sent_by(dlg, &via_addr_, via_tp_);
1836static pjsip_accept_hdr* im_create_accept(pj_pool_t *pool)
1839 pjsip_accept_hdr *accept;
1841 accept = pjsip_accept_hdr_create(pool);
1842 accept->values[0] = CONST_PJ_STR(
"text/plain");
1843 accept->values[1] = CONST_PJ_STR(
"application/im-iscomposing+xml");
1851SIPAccount::sendMessage(
const std::string& to,
1853 const std::map<std::string, std::string>& payloads,
1858 if (to.empty() or payloads.empty()) {
1860 messageEngine_.onMessageSent(to,
id,
false);
1864 auto toUri = getToUri(to);
1866 constexpr pjsip_method msg_method = {PJSIP_OTHER_METHOD,
1867 CONST_PJ_STR(sip_utils::SIP_METHODS::MESSAGE)};
1868 std::string from(getFromUri());
1869 pj_str_t pjFrom = sip_utils::CONST_PJ_STR(from);
1870 pj_str_t pjTo = sip_utils::CONST_PJ_STR(toUri);
1873 pjsip_tx_data* tdata;
1874 pj_status_t status = pjsip_endpt_create_request(link_.getEndpoint(),
1884 if (status != PJ_SUCCESS) {
1885 JAMI_ERROR(
"Unable to create request: {:s}", sip_utils::sip_strerror(status));
1886 messageEngine_.onMessageSent(to,
id,
false);
1892 constexpr auto key = CONST_PJ_STR(
"Date");
1894 auto time = std::time(
nullptr);
1895 auto date = std::ctime(&time);
1897 *std::remove(date, date + strlen(date),
'\n') =
'\0';
1900 hdr =
reinterpret_cast<pjsip_hdr*
>(
1901 pjsip_date_hdr_create(tdata->pool, &key, pj_cstr(&date_str, date)));
1902 pjsip_msg_add_hdr(tdata->msg, hdr);
1905 sip_utils::addUserAgentHeader(getUserAgentName(), tdata);
1908 std::unique_ptr<ctx> t {
new ctx(
new pjsip_auth_clt_sess)};
1914 status = pjsip_auth_clt_init(t->auth_sess.get(), link_.getEndpoint(), tdata->pool, 0);
1916 if (status != PJ_SUCCESS) {
1917 JAMI_ERROR(
"Unable to initialize auth session: {:s}", sip_utils::sip_strerror(status));
1918 messageEngine_.onMessageSent(to,
id,
false);
1922 status = pjsip_auth_clt_set_credentials(t->auth_sess.get(), getCredentialCount(), getCredInfo());
1924 if (status != PJ_SUCCESS) {
1925 JAMI_ERROR(
"Unable to set auth session data: {:s}", sip_utils::sip_strerror(status));
1926 messageEngine_.onMessageSent(to,
id,
false);
1930 const pjsip_tpselector tp_sel = getTransportSelector();
1931 status = pjsip_tx_data_set_transport(tdata, &tp_sel);
1933 if (status != PJ_SUCCESS) {
1934 JAMI_ERROR(
"Unable to set transport: {:s}", sip_utils::sip_strerror(status));
1935 messageEngine_.onMessageSent(to,
id,
false);
1939 im::fillPJSIPMessageBody(*tdata, payloads);
1942 status = pjsip_endpt_send_request(link_.getEndpoint(), tdata, -1, t.release(), &onComplete);
1944 if (status != PJ_SUCCESS) {
1945 JAMI_ERROR(
"Unable to send request: {:s}", sip_utils::sip_strerror(status));
1946 messageEngine_.onMessageSent(to,
id,
false);
1952SIPAccount::onComplete(
void* token, pjsip_event* event)
1954 std::unique_ptr<ctx> c {(
ctx*) token};
1957 pj_assert(event->type == PJSIP_EVENT_TSX_STATE);
1958 code =
event->body.tsx_state.tsx->status_code;
1960 auto acc = c->acc.lock();
1965 if (code == PJSIP_SC_UNAUTHORIZED || code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) {
1966 JAMI_INFO(
"Authorization needed for SMS message - Resending");
1967 pjsip_tx_data* new_request;
1970 status = pjsip_auth_clt_reinit_req(c->auth_sess.get(),
1971 event->body.tsx_state.src.rdata,
1972 event->body.tsx_state.tsx->last_tx,
1975 if (status == PJ_SUCCESS) {
1977 pjsip_cseq_hdr* cseq_hdr;
1978 cseq_hdr = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(new_request->msg, PJSIP_H_CSEQ, NULL);
1979 cseq_hdr->cseq += 1;
1984 status = pjsip_endpt_send_request(acc->link_.getEndpoint(),
1990 if (status != PJ_SUCCESS) {
1991 JAMI_ERROR(
"Unable to send request: {:s}", sip_utils::sip_strerror(status));
1992 acc->messageEngine_.onMessageSent(to,
id,
false);
1996 JAMI_ERROR(
"Unable to add Authorization Header into msg");
1997 acc->messageEngine_.onMessageSent(c->to, c->id,
false);
2001 acc->messageEngine_.onMessageSent(c->to,
2003 event && event->body.tsx_state.tsx
2004 && (event->body.tsx_state.tsx->status_code == PJSIP_SC_OK
2005 || event->body.tsx_state.tsx->status_code
2006 == PJSIP_SC_ACCEPTED));
2010SIPAccount::getUserUri()
const
2012 return getFromUri();
2016SIPAccount::createBindingAddress()
2018 auto family = hostIp_ ? hostIp_.getFamily() : PJ_AF_INET;
2019 const auto& conf = config();
2021 dhtnet::IpAddr ret = conf.bindAddress.empty() ? (
2022 conf.interface == dhtnet::ip_utils::DEFAULT_INTERFACE
2023 || conf.interface.empty()
2024 ? dhtnet::ip_utils::getAnyHostAddr(family)
2025 : dhtnet::ip_utils::getInterfaceAddr(getLocalInterface(), family))
2026 : dhtnet::IpAddr(conf.bindAddress, family);
2028 if (ret.getPort() == 0) {
2029 ret.setPort(conf.tlsEnable ? conf.tlsListenerPort : conf.localPort);
2036SIPAccount::setActiveCodecs(
const std::vector<unsigned>& list)
2038 Account::setActiveCodecs(list);
2040 JAMI_WARNING(
"All audio codecs disabled, enabling all");
2044 JAMI_WARNING(
"All video codecs disabled, enabling all");
2047 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
std::map< std::string, std::string > getProfileVcard() 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
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::vector< MediaAttribute > createDefaultMediaList(bool addVideo, bool onHold=false)
std::string getPublishedAddress() const
Get the public IP address set by the user for this account.
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 dat)
int64_t size(const std::filesystem::path &path)
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
RegistrationState
Contains all the Registration states for an account can be in.
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)
static constexpr unsigned REGISTRATION_RETRY_INTERVAL
static constexpr std::string_view PN_APNS
static constexpr unsigned REGISTRATION_FIRST_RETRY_INTERVAL
void hangupCalls(Call::SubcallSet &&callptr_list, int errcode)
Hangup many calls with same error code.
static constexpr std::string_view VALID_TLS_PROTOS[]
static void validate(std::string &member, const std::string ¶m, const T &valid)
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)
std::map< std::string, std::string > initVcard()
std::string toString(const std::map< std::string, std::string > &vCard)
void removeByKey(std::map< std::string, std::string > &vCard, std::string_view key)
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)