40#include <dhtnet/diffie-hellman.h>
41#include <dhtnet/tls_session.h>
42#include <dhtnet/multiplexed_socket.h>
43#include <dhtnet/certstore.h>
44#include <dhtnet/connectionmanager.h>
45#include <dhtnet/upnp/mapping.h>
46#include <dhtnet/ip_utils.h>
47#include <dhtnet/fileutils.h>
49#include <opendht/dhtrunner.h>
50#include <opendht/default_types.h>
52#include <pjsip/sip_types.h>
63#include <shared_mutex>
72using h160 = FixedHash<20>;
99 constexpr static const std::pair<uint16_t, uint16_t>
DHT_PORT_RANGE {4000, 8888};
109 std::shared_ptr<JamiAccount const>
shared()
const
113 std::weak_ptr<JamiAccount>
weak()
117 std::weak_ptr<JamiAccount const>
weak()
const
130 return std::move(
conf->credentials);
209 std::string
getToUri(
const std::string& username)
const override;
224 const std::string& messageId,
225 int status)
override;
234 MatchRank matches(std::string_view username, std::string_view hostname)
const override;
247 const std::vector<libjami::MediaMap>&
mediaList)
override;
257 const std::string& from,
258 const std::vector<libjami::MediaMap>&
mediaList,
259 const std::shared_ptr<SipTransport>&
sipTr = {})
override;
262 const std::string& from,
263 const std::shared_ptr<dht::crypto::Certificate>& peerCert,
264 const std::map<std::string, std::string>& payloads)
override;
273 dhtnet::tls::TrustStore::PermissionStatus status);
275 dhtnet::tls::TrustStore::PermissionStatus status,
278 dhtnet::tls::TrustStore::PermissionStatus status);
282 const dht::InfoHash& h,
283 std::function<
void(
const std::shared_ptr<dht::crypto::Certificate>&)>&&
cb = {});
286 std::function<
void(
const std::shared_ptr<dht::crypto::Certificate>&)>&&
cb = {});
299 void addContact(
const std::string& uri,
bool confirmed =
false);
300 void removeContact(
const std::string& uri,
bool banned =
true);
306 std::map<std::string, std::string>
getContactDetails(
const std::string& uri)
const;
307 std::optional<Contact>
getContactInfo(
const std::string& uri)
const;
309 void sendTrustRequest(
const std::string& to,
const std::vector<uint8_t>& payload);
311 const std::string& deviceId,
312 const std::map<std::string, std::string>& payloads,
318 const std::string& deviceId,
319 const std::map<std::string, std::string>& payloads,
323 const std::map<std::string, std::string>&
msg);
329 void getIceOptions(std::function<
void(dhtnet::IceTransportOptions&&)>
cb)
const;
346 const std::string& scheme);
356 std::string_view scheme = {},
357 const std::string& password = {});
359 std::string_view scheme = {},
360 const std::string& password = {});
371 void flush()
override;
377 const std::string& scheme,
378 const std::string& password);
387 std::shared_ptr<dht::DhtRunner>
dht() {
return dht_; }
389 const dht::crypto::Identity&
identity()
const {
return id_; }
392 std::function<
void(
const std::shared_ptr<dht::crypto::PublicKey>&)>&&
op,
393 std::function<
void(
bool)>&& end = {});
403 const std::map<std::string, std::string>& data);
434 std::map<std::string, std::string>
getNearbyPeers()
const override;
445 const std::string&
avatar,
472 const std::string& from,
473 const std::pair<std::string, std::string>& message)
override;
478 const std::string& conversationId =
"");
482 void sendFile(
const std::string& conversationId,
483 const std::filesystem::path& path,
484 const std::string& name,
488 const std::string& path,
489 const std::string& deviceId,
490 const std::string& fileId,
491 const std::string& interactionId,
494 const std::string&
sha3Sum =
"",
496 std::function<
void()> onFinished = {});
499 const std::string& deviceId,
500 const std::string& interactionId,
501 const std::string& fileId,
506 const std::string& deviceId,
514 std::shared_ptr<TransferManager>
dataTransfer(
const std::string&
id =
"");
533 const std::string& deviceId,
542 const std::string& peerUri,
543 const std::string& deviceId);
549 void sendProfile(
const std::string& peerUri,
const std::string& deviceId);
558 const std::shared_ptr<AccountManager>&
accountManager() {
return accountManager_; }
570 const std::string&
pwd,
571 const dht::InfoHash&
id,
603 std::map<Uri::Scheme, std::unique_ptr<ChannelHandlerInterface>>&
channelHandlers()
605 return channelHandlers_;
609 dhtnet::tls::CertificateStore&
certStore()
const {
return *certStore_; }
626 using clock = std::chrono::system_clock;
627 using time_point = clock::time_point;
633 struct PendingMessage;
635 struct DiscoveredPeer;
637 inline std::string getProxyConfigKey()
const
640 return dht::InfoHash::get(
conf.proxyServer +
conf.proxyListUrl).toString();
650 void trackPresence(
const dht::InfoHash& h, BuddyInfo&
buddy);
651 void onPeerConnected(
const std::string& peerId,
bool connected);
655 const dht::ValueType USER_PROFILE_TYPE = {9,
"User profile", std::chrono::hours(24 * 7)};
657 void startOutgoingCall(
const std::shared_ptr<SIPCall>& call,
const std::string&
toUri);
659 void onConnectedOutgoingCall(
const std::shared_ptr<SIPCall>& call,
660 const std::string&
to_id,
668 bool SIPStartCall(SIPCall& call,
const dhtnet::IpAddr&
target);
673 void onTrackedBuddyOffline(
const dht::InfoHash&);
678 void onTrackedBuddyOnline(
const dht::InfoHash&);
683 void registerAsyncOps();
688 void forEachPendingCall(
const DeviceId& deviceId,
689 const std::function<
void(
const std::shared_ptr<SIPCall>&)>&
cb);
691 void loadAccountFromDHT(
const std::string& archive_password,
const std::string& archive_pin);
692 void loadAccount(
const std::string& archive_password_scheme = {},
693 const std::string& archive_password = {},
694 const std::string& archive_pin = {},
695 const std::string& archive_path = {});
697 std::vector<std::string> loadBootstrap()
const;
699 static std::pair<std::string, std::string> saveIdentity(
const dht::crypto::Identity
id,
700 const std::filesystem::path& path,
701 const std::string& name);
703 void replyToIncomingIceMsg(
const std::shared_ptr<SIPCall>&,
704 const std::shared_ptr<IceTransport>&,
705 const std::shared_ptr<IceTransport>&,
706 const dht::IceCandidates&,
707 const std::shared_ptr<dht::crypto::Certificate>& from_cert,
708 const dht::InfoHash& from);
710 void loadCachedUrl(
const std::string& url,
713 std::function<
void(
const dht::http::Response& response)>);
715 std::string getDhtProxyServer(
const std::string&
serverList);
716 void loadCachedProxyServer(std::function<
void(
const std::string&)>
cb);
721 void generateDhParams();
723 void newOutgoingCallHelper(
const std::shared_ptr<SIPCall>& call,
const Uri& uri);
724 std::shared_ptr<SIPCall> newSwarmOutgoingCallHelper(
725 const Uri& uri,
const std::vector<libjami::MediaMap>&
mediaList);
726 std::shared_ptr<SIPCall> createSubCall(
const std::shared_ptr<SIPCall>&
mainCall);
728 std::filesystem::path cachePath_ {};
729 std::filesystem::path dataPath_ {};
750 std::shared_ptr<dht::Logger> logger_;
751 std::shared_ptr<dhtnet::tls::CertificateStore> certStore_;
753 std::shared_ptr<dht::DhtRunner> dht_ {};
754 std::shared_ptr<AccountManager> accountManager_;
755 dht::crypto::Identity id_ {};
757 mutable std::mutex messageMutex_ {};
758 std::map<dht::Value::Id, PendingMessage> sentMessages_;
759 dhtnet::fileutils::IdList treatedMessages_;
762 mutable std::mutex buddyInfoMtx;
763 std::map<dht::InfoHash, BuddyInfo> trackedBuddies_;
765 mutable std::mutex dhtValuesMtx_;
767 std::atomic_int syncCnt_ {0};
776 return (
upnpCtrl_ and dhtUpnpMapping_.isValid()) ? dhtUpnpMapping_.getExternalPort()
781 dhtnet::upnp::Mapping dhtUpnpMapping_ {dhtnet::upnp::PortType::UDP};
786 std::string proxyServerCached_ {};
798 mutable std::shared_mutex connManagerMtx_ {};
799 std::unique_ptr<dhtnet::ConnectionManager> connectionManager_;
801 virtual void updateUpnpController()
override;
803 std::mutex discoveryMapMtx_;
804 std::shared_ptr<dht::PeerDiscovery> peerDiscovery_;
805 std::map<dht::InfoHash, DiscoveredPeer> discoveredPeers_;
806 std::map<std::string, std::string> discoveredPeerMap_;
808 std::set<std::shared_ptr<dht::http::Request>> requests_;
810 mutable std::mutex sipConnsMtx_ {};
813 std::shared_ptr<SipTransport> transport;
816 std::shared_ptr<dhtnet::ChannelSocket> channel;
821 std::map<SipConnectionKey, std::vector<SipConnection>> sipConns_;
823 std::mutex pendingCallsMutex_;
824 std::map<DeviceId, std::vector<std::shared_ptr<SIPCall>>> pendingCalls_;
826 std::mutex onConnectionClosedMtx_ {};
844 void requestSIPConnection(
const std::string& peerId,
848 const std::shared_ptr<SIPCall>&
pc = {});
855 void cacheSIPConnection(std::shared_ptr<dhtnet::ChannelSocket>&& channel,
856 const std::string& peerId,
864 void shutdownSIPConnection(
const std::shared_ptr<dhtnet::ChannelSocket>& channel,
865 const std::string& peerId,
868 void requestMessageConnection(
const std::string& peerId,
873 std::mutex transfersMtx_ {};
874 std::set<std::string> incomingFileTransfers_ {};
887 bool sendSIPMessage(SipConnection&
conn,
888 const std::string& to,
891 const std::map<std::string, std::string>& data,
893 void onMessageSent(
const std::string& to,
uint64_t id,
const std::string& deviceId,
bool success,
bool onlyConnected,
bool retry);
895 std::mutex gitServersMtx_ {};
896 std::map<dht::Value::Id, std::unique_ptr<GitServer>> gitServers_ {};
899 std::shared_ptr<TransferManager> nonSwarmTransferManager_;
901 std::atomic_bool deviceAnnounced_ {
false};
902 std::atomic_bool noSha3sumVerification_ {
false};
904 bool publishPresence_ {
true};
906 std::map<Uri::Scheme, std::unique_ptr<ChannelHandlerInterface>> channelHandlers_ {};
908 std::unique_ptr<ConversationModule> convModule_;
909 std::mutex moduleMtx_;
910 std::unique_ptr<SyncModule> syncModule_;
914 int dhtBoundPort_ {0};
916 void initConnectionManager();
918 enum class PresenceState :
int { DISCONNECTED = 0, AVAILABLE, CONNECTED };
919 std::map<std::string, PresenceState> presenceState_;
920 std::string presenceNote_;
923static inline std::ostream&
const std::string & getAccountID() const
Get the account ID.
std::filesystem::path idPath_
path to account
std::unique_ptr< AccountConfig > config_
void editConfig(std::function< void(AccountConfig &config)> &&edit)
const AccountConfig & config() const
std::shared_ptr< dhtnet::upnp::Controller > upnpCtrl_
Ring Account is build on top of SIPAccountBase and uses DHT to handle call connectivity.
dhtnet::IpAddr getPublishedIpAddress(uint16_t family=PF_UNSPEC) const override
void askForFileChannel(const std::string &conversationId, const std::string &deviceId, const std::string &interactionId, const std::string &fileId, size_t start=0, size_t end=0)
void forceReloadAccount()
Try to reload the account to force the identity to be updated.
std::optional< Contact > getContactInfo(const std::string &uri) const
void sendTrustRequest(const std::string &to, const std::vector< uint8_t > &payload)
bool isConnectedWith(const DeviceId &deviceId) const
Check if a Device is connected.
void addContact(const std::string &uri, bool confirmed=false)
Add contact to the account contact list.
static constexpr int ICE_STREAMS_COUNT
std::shared_ptr< Call > newOutgoingCall(std::string_view toUrl, const std::vector< libjami::MediaMap > &mediaList) override
Create outgoing SIPCall.
bool needToSendProfile(const std::string &peerUri, const std::string &deviceId, const std::string &sha3Sum)
Check (via the cache) if we need to send our profile to a specific device.
std::vector< std::map< std::string, std::string > > getConnectionList(const std::string &conversationId="")
bool provideAccountAuthentication(const std::string &credentialsFromUser, const std::string &scheme)
void sendPresenceNote(const std::string ¬e)
Send a presence note.
const JamiAccountConfig & config() const
std::map< std::string, std::string > getKnownDevices() const
void startAccountDiscovery()
Start Discovery the Jami Account from the Network.
std::vector< std::map< std::string, std::string > > getChannelList(const std::string &connectionId)
bool discardTrustRequest(const std::string &from)
void declineConversationRequest(const std::string &conversationId)
void doRegister() override
Connect to the DHT.
std::string getContactHeader(const std::shared_ptr< SipTransport > &sipTransport)
Get the contact header for.
void unlinkConversations(const std::set< std::string > &removedConv)
Make sure appdata/contacts.yml contains correct information.
bool isSrtpEnabled() const override
static constexpr int ICE_COMP_COUNT_PER_STREAM
void sendProfile(const std::string &peerUri, const std::string &deviceId)
Send profile via cached SIP connection.
std::vector< std::string > getCertificatesByStatus(dhtnet::tls::TrustStore::PermissionStatus status)
void setRegistrationState(RegistrationState state, int detail_code=0, const std::string &detail_str={}) override
Set the registration state of the specified link.
void sendFile(const std::string &conversationId, const std::filesystem::path &path, const std::string &name, const std::string &replyTo)
bool setPushNotificationConfig(const std::map< std::string, std::string > &data) override
void pushNotificationReceived(const std::string &from, const std::map< std::string, std::string > &data)
To be called by clients with relevant data when a push notification is received.
virtual bool getSrtpFallback() const override
std::shared_ptr< dht::DhtRunner > dht()
JamiAccountConfig::Credentials consumeConfigCredentials()
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.
bool changeArchivePassword(const std::string &password_old, const std::string &password_new)
std::shared_ptr< TransferManager > dataTransfer(const std::string &id="")
Retrieve linked transfer manager.
std::map< std::string, std::string > getNearbyPeers() const override
Get current discovered peers account id and display name.
bool exportArchive(const std::string &destinationPath, std::string_view scheme={}, const std::string &password={})
Export the archive to a file.
dhtnet::IceTransportOptions getIceOptions() const override
Create and return ICE options.
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 ...
void askForProfile(const std::string &conversationId, const std::string &deviceId, const std::string &memberUri)
void startAccountPublish()
Start Publish the Jami Account onto the Network.
void shutdownConnections()
This should be called before flushing the account.
static constexpr const std::pair< uint16_t, uint16_t > DHT_PORT_RANGE
bool setMessageDisplayed(const std::string &conversationUri, const std::string &messageId, int status) override
virtual bool isTlsEnabled() const override
Determine if TLS is enabled for this account.
SyncModule * syncModule()
std::vector< std::map< std::string, std::string > > getContacts(bool includeRemoved=false) const
void flush() override
This method is called to request removal of possible account traces on the system,...
std::shared_ptr< JamiAccount > shared()
const std::shared_ptr< AccountManager > & accountManager()
bool isMessageTreated(dht::Value::Id id)
MatchRank matches(std::string_view username, std::string_view hostname) const override
std::string getUserUri() const override
void doUnregister(bool forceShutdownConnections=false) override
Disconnect from the DHT.
bool acceptTrustRequest(const std::string &from, bool includeConversation=true)
bool cancelAddDevice(uint32_t op_token)
void sendProfile(const std::string &convId, const std::string &peerUri, const std::string &deviceId)
Send Profile via cached SIP connection.
std::string getFromUri() const override
ConversationModule * convModule(bool noCreation=false)
Used to get the instance of the ConversationModule class which is responsible for managing conversati...
void sendProfileToPeers()
bool revokeDevice(const std::string &device, std::string_view scheme={}, const std::string &password={})
bool isValidAccountDevice(const dht::crypto::Certificate &cert) const
std::filesystem::path profilePath() const
bool searchUser(const std::string &nameQuery)
const dht::crypto::Identity & identity() const
void sendInstantMessage(const std::string &convId, const std::map< std::string, std::string > &msg)
bool findCertificate(const std::string &id)
bool isPasswordValid(const std::string &password)
std::string getServerUri() const
In the current version, "srv" uri is obtained in the preformated way: hostname:port.
void connectivityChanged() override
Inform the account that the network status has changed.
bool handleMessage(const std::shared_ptr< dht::crypto::Certificate > &cert, const std::string &from, const std::pair< std::string, std::string > &message) override
void transferFile(const std::string &conversationId, const std::string &path, const std::string &deviceId, const std::string &fileId, const std::string &interactionId, size_t start=0, size_t end=0, const std::string &sha3Sum="", uint64_t lastWriteTime=0, std::function< void()> onFinished={})
std::string_view getAccountType() const override
void handleIncomingConversationCall(const std::string &callId, const std::string &destination)
Join incoming call to hosted conference.
std::vector< libjami::Message > getLastMessages(const uint64_t &base_timestamp) override
Get last messages (should be used to retrieve messages when launching the client)
std::map< std::string, bool > getTrackedBuddyPresence() const
Tells for each tracked account id if it has been seen online so far in the last DeviceAnnouncement::T...
bool setValidity(std::string_view scheme, const std::string &pwd, const dht::InfoHash &id, int64_t validity)
Change certificate's validity period.
void updateProfile(const std::string &displayName, const std::string &avatar, const std::string &fileType, int32_t flag) override
Update the profile vcard and send it to peers.
bool setPushNotificationToken(const std::string &pushDeviceToken="") override
bool confirmAddDevice(uint32_t op_token)
void editConfig(std::function< void(JamiAccountConfig &conf)> &&edit)
void removeContact(const std::string &uri, bool banned=true)
bool isMobile() const
The DRT component is composed on some special nodes, that are usually present but not connected.
bool sha3SumVerify() const
int32_t addDevice(const std::string &uriProvided)
Initiates the process of adding a new device to this account.
void sendMessage(const std::string &to, const std::string &deviceId, const std::map< std::string, std::string > &payloads, uint64_t id, bool retryOnTimeout=true, bool onlyConnected=false) override
bool setPushNotificationTopic(const std::string &topic) override
void saveConfig() const override
void setIsComposing(const std::string &conversationUri, bool isWriting) override
std::vector< std::map< std::string, std::string > > getTrustRequests() const
void forEachDevice(const dht::InfoHash &to, std::function< void(const std::shared_ptr< dht::crypto::PublicKey > &)> &&op, std::function< void(bool)> &&end={})
void loadConversation(const std::string &convId)
std::unique_ptr< AccountConfig > buildConfig() const override
bool setCertificateStatus(const std::string &cert_id, dhtnet::tls::TrustStore::PermissionStatus status)
std::weak_ptr< JamiAccount > weak()
void onTextMessage(const std::string &id, const std::string &from, const std::shared_ptr< dht::crypto::Certificate > &peerCert, const std::map< std::string, std::string > &payloads) override
void setActiveCodecs(const std::vector< unsigned > &list) override
Update both the codec order structure and the codec string used for SDP offer and configuration respe...
void clearProfileCache(const std::string &peerUri)
Clear sent profiles (because of a removed contact or new trust request)
static constexpr auto ACCOUNT_TYPE
void loadConfig() override
Load the settings in this account.
uint64_t sendTextMessage(const std::string &to, const std::string &deviceId, const std::map< std::string, std::string > &payloads, uint64_t refreshToken=0, bool onlyConnected=false) override
If supported, send a text message from this account.
std::weak_ptr< JamiAccount const > weak() const
std::shared_ptr< JamiAccount const > shared() const
std::vector< uint8_t > getPasswordKey(const std::string &password)
std::string_view currentDeviceId() const
std::map< std::string, std::string > getContactDetails(const std::string &uri) const
Obtain details about one account contact in serializable form.
virtual std::map< std::string, std::string > getVolatileAccountDetails() const override
Retrieve volatile details such as recent registration errors.
dhtnet::tls::CertificateStore & certStore() const
void trackBuddyPresence(const std::string &buddy_id, bool track)
Adds an account id to the list of accounts to track on the DHT for buddy presence.
h160 Address
An Ethereum address: 20 bytes.
RegistrationState
Contains all the Registration states for an account can be in.
std::pair< std::string, DeviceId > SipConnectionKey
void emitSignal(Args... args)
static constexpr const char MIME_TYPE_IM_COMPOSING[]
static constexpr std::string_view ACCOUNT_TYPE_JAMI
std::chrono::steady_clock clock
static std::ostream & operator<<(std::ostream &os, const Account &acc)
bool lookupName(const std::string &account, const std::string &nameserver, const std::string &name)
bool lookupAddress(const std::string &account, const std::string &nameserver, const std::string &address)
bool registerName(const std::string &account, const std::string &name, const std::string &scheme, const std::string &password)
Simple macro to hide class' copy constructor and assignment operator.
#define NON_COPYABLE(ClassName)
std::string deviceKey
Device push notification token.