Add external session management and support for remote servers

This commit is contained in:
netkas 2025-01-10 14:58:24 -05:00
parent da3fe9c5a7
commit fde3ccfc68
7 changed files with 272 additions and 47 deletions

1
.idea/sqldialects.xml generated
View file

@ -8,6 +8,7 @@
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/sessions.sql" dialect="MariaDB" /> <file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/sessions.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/variables.sql" dialect="MariaDB" /> <file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/variables.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/CaptchaManager.php" dialect="MariaDB" /> <file url="file://$PROJECT_DIR$/src/Socialbox/Managers/CaptchaManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/ExternalSessionManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/OneTimePasswordManager.php" dialect="MariaDB" /> <file url="file://$PROJECT_DIR$/src/Socialbox/Managers/OneTimePasswordManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/PasswordManager.php" dialect="MariaDB" /> <file url="file://$PROJECT_DIR$/src/Socialbox/Managers/PasswordManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/RegisteredPeerManager.php" dialect="MariaDB" /> <file url="file://$PROJECT_DIR$/src/Socialbox/Managers/RegisteredPeerManager.php" dialect="MariaDB" />

View file

@ -1,35 +1,22 @@
create table external_sessions create table external_sessions
( (
uuid varchar(36) default uuid() not null comment 'The UUID of the session for the external connection' domain varchar(256) not null comment 'The unique domain name that this session belongs to'
primary key comment 'The Unique Primary Index for the session UUID', primary key comment 'The Unique Primary index for the external session',
peer_uuid varchar(36) not null comment 'The peer UUID that opened the connection', rpc_endpoint text not null comment 'The RPC endpoint of the external connection',
session_uuid varchar(36) null comment 'The UUID of the parent session responsible for this external session', session_uuid varchar(36) not null comment 'The UUID of the session to the external server',
server varchar(255) null comment 'The domain of the remote server that ths external session is authorized for', transport_encryption_algorithm enum ('xchacha20', 'chacha20', 'aes256gcm') default 'xchacha20' not null comment 'The transport encryption algorithm used',
created timestamp default current_timestamp() not null comment 'The Timestamp for when this record was created', server_keypair_expires int not null comment 'The Timestamp for when the server keypair expires',
last_used timestamp default current_timestamp() not null comment 'The Timestamp for when this session was last used', server_public_signing_key varchar(64) not null comment 'The public signing key of the server resolved from DNS records',
constraint external_sessions_uuid_uindex server_public_encryption_key varchar(64) not null comment 'The public encryption key of the server for this session',
unique (uuid) comment 'The Unique Primary Index for the session UUID', host_public_encryption_key varchar(64) not null comment 'The public encryption key for the host',
constraint external_sessions_registered_peers_uuid_fk host_private_encryption_key varchar(64) not null comment 'The private encryption key for host',
foreign key (peer_uuid) references registered_peers (uuid) private_shared_secret varchar(64) not null comment 'The private shared secret obtained from the DHE procedure',
on update cascade on delete cascade, host_transport_encryption_key varchar(64) not null comment 'The transport encryption key for the host',
constraint external_sessions_sessions_uuid_fk server_transport_encryption_key varchar(64) not null comment 'The transport encryption key for the server',
foreign key (session_uuid) references sessions (uuid) last_accessed timestamp default current_timestamp() not null comment 'The Timestamp for when the record was last accessed',
created timestamp default current_timestamp() not null comment 'The Timestamp for when this record was created',
constraint external_sessions_domain_uindex
unique (domain) comment 'The Unique Primary index for the external session'
) )
comment 'Table for housing external sessions from local to remote servers'; comment 'Table for housing external sessions to external servers';
create index external_sessions_created_index
on external_sessions (created)
comment 'The Index for the created column';
create index external_sessions_last_used_index
on external_sessions (last_used)
comment 'The inex for the last used column';
create index external_sessions_peer_uuid_index
on external_sessions (peer_uuid)
comment 'The Index for the peer UUID';
create index external_sessions_session_uuid_index
on external_sessions (session_uuid)
comment 'The index for the original session uuid';

View file

@ -6,6 +6,7 @@
use Socialbox\Enums\StandardHeaders; use Socialbox\Enums\StandardHeaders;
use Socialbox\Enums\Types\RequestType; use Socialbox\Enums\Types\RequestType;
use Socialbox\Exceptions\CryptographyException; use Socialbox\Exceptions\CryptographyException;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\ResolutionException; use Socialbox\Exceptions\ResolutionException;
use Socialbox\Exceptions\RpcException; use Socialbox\Exceptions\RpcException;
use Socialbox\Objects\ExportedSession; use Socialbox\Objects\ExportedSession;
@ -21,7 +22,7 @@
private const string CLIENT_VERSION = '1.0'; private const string CLIENT_VERSION = '1.0';
private bool $bypassSignatureVerification; private bool $bypassSignatureVerification;
private PeerAddress $peerAddress; private PeerAddress $identifiedAs;
private string $serverPublicSigningKey; private string $serverPublicSigningKey;
private string $serverPublicEncryptionKey; private string $serverPublicEncryptionKey;
private KeyPair $clientSigningKeyPair; private KeyPair $clientSigningKeyPair;
@ -31,18 +32,21 @@
private string $serverTransportEncryptionKey; private string $serverTransportEncryptionKey;
private ServerInformation $serverInformation; private ServerInformation $serverInformation;
private string $rpcEndpoint; private string $rpcEndpoint;
private string $remoteServer;
private string $sessionUuid; private string $sessionUuid;
/** /**
* Constructs a new instance with the specified peer address. * Constructs a new instance with the specified peer address.
* *
* @param string|PeerAddress $peerAddress The peer address to be used for the instance (eg; johndoe@example.com) * @param string|PeerAddress $identifiedAs The peer address to be used for the instance (eg; johndoe@example.com)
* @param string|null $server Optional. The domain of the server to connect to if different from the identified
* @param ExportedSession|null $exportedSession Optional. An exported session to be used to re-connect. * @param ExportedSession|null $exportedSession Optional. An exported session to be used to re-connect.
* @throws CryptographyException If there is an error in the cryptographic operations. * @throws CryptographyException If there is an error in the cryptographic operations.
* @throws RpcException If there is an error in the RPC request or if no response is received.
* @throws ResolutionException If there is an error in the resolution process. * @throws ResolutionException If there is an error in the resolution process.
* @throws RpcException If there is an error in the RPC request or if no response is received.
* @throws DatabaseOperationException
*/ */
public function __construct(string|PeerAddress $peerAddress, ?ExportedSession $exportedSession=null) public function __construct(string|PeerAddress $identifiedAs, ?string $server=null, ?ExportedSession $exportedSession=null)
{ {
$this->bypassSignatureVerification = false; $this->bypassSignatureVerification = false;
@ -56,8 +60,9 @@
throw new RpcException('The server keypair has expired, a new session must be created'); throw new RpcException('The server keypair has expired, a new session must be created');
} }
$this->peerAddress = PeerAddress::fromAddress($exportedSession->getPeerAddress()); $this->identifiedAs = PeerAddress::fromAddress($exportedSession->getPeerAddress());
$this->rpcEndpoint = $exportedSession->getRpcEndpoint(); $this->rpcEndpoint = $exportedSession->getRpcEndpoint();
$this->remoteServer = $exportedSession->getRemoteServer();
$this->sessionUuid = $exportedSession->getSessionUuid(); $this->sessionUuid = $exportedSession->getSessionUuid();
$this->serverPublicSigningKey = $exportedSession->getServerPublicSigningKey(); $this->serverPublicSigningKey = $exportedSession->getServerPublicSigningKey();
$this->serverPublicEncryptionKey = $exportedSession->getServerPublicEncryptionKey(); $this->serverPublicEncryptionKey = $exportedSession->getServerPublicEncryptionKey();
@ -86,16 +91,17 @@
} }
// If the peer address is a string, we need to convert it to a PeerAddress object // If the peer address is a string, we need to convert it to a PeerAddress object
if(is_string($peerAddress)) if(is_string($identifiedAs))
{ {
$peerAddress = PeerAddress::fromAddress($peerAddress); $identifiedAs = PeerAddress::fromAddress($identifiedAs);
} }
// Set the initial properties // Set the initial properties
$this->peerAddress = $peerAddress; $this->identifiedAs = $identifiedAs;
$this->remoteServer = $server ?? $identifiedAs->getDomain();
// Resolve the domain and get the server's Public Key & RPC Endpoint // Resolve the domain and get the server's Public Key & RPC Endpoint
$resolvedServer = ServerResolver::resolveDomain($this->peerAddress->getDomain(), false); $resolvedServer = ServerResolver::resolveDomain($this->remoteServer, false);
// Import the RPC Endpoint & the server's public key. // Import the RPC Endpoint & the server's public key.
$this->serverPublicSigningKey = $resolvedServer->getPublicSigningKey(); $this->serverPublicSigningKey = $resolvedServer->getPublicSigningKey();
@ -117,7 +123,7 @@
// If the username is `host` and the domain is the same as this server's domain, we use our signing keypair // If the username is `host` and the domain is the same as this server's domain, we use our signing keypair
// Essentially this is a special case for the server to contact another server // Essentially this is a special case for the server to contact another server
if($this->peerAddress->isHost()) if($this->identifiedAs->isHost())
{ {
$this->clientSigningKeyPair = new KeyPair(Configuration::getCryptographyConfiguration()->getHostPublicKey(), Configuration::getCryptographyConfiguration()->getHostPrivateKey()); $this->clientSigningKeyPair = new KeyPair(Configuration::getCryptographyConfiguration()->getHostPublicKey(), Configuration::getCryptographyConfiguration()->getHostPrivateKey());
} }
@ -157,14 +163,14 @@
StandardHeaders::REQUEST_TYPE->value . ': ' . RequestType::INITIATE_SESSION->value, StandardHeaders::REQUEST_TYPE->value . ': ' . RequestType::INITIATE_SESSION->value,
StandardHeaders::CLIENT_NAME->value . ': ' . self::CLIENT_NAME, StandardHeaders::CLIENT_NAME->value . ': ' . self::CLIENT_NAME,
StandardHeaders::CLIENT_VERSION->value . ': ' . self::CLIENT_VERSION, StandardHeaders::CLIENT_VERSION->value . ': ' . self::CLIENT_VERSION,
StandardHeaders::IDENTIFY_AS->value . ': ' . $this->peerAddress->getAddress(), StandardHeaders::IDENTIFY_AS->value . ': ' . $this->identifiedAs->getAddress(),
// Always provide our generated encrypted public key // Always provide our generated encrypted public key
StandardHeaders::ENCRYPTION_PUBLIC_KEY->value . ': ' . $this->clientEncryptionKeyPair->getPublicKey() StandardHeaders::ENCRYPTION_PUBLIC_KEY->value . ': ' . $this->clientEncryptionKeyPair->getPublicKey()
]; ];
// If we're not connecting as the host, we need to provide our public key // If we're not connecting as the host, we need to provide our public key
// Otherwise, the server will obtain the public key itself from DNS records rather than trusting the client // Otherwise, the server will obtain the public key itself from DNS records rather than trusting the client
if(!$this->peerAddress->isHost()) if(!$this->identifiedAs->isHost())
{ {
$headers[] = StandardHeaders::SIGNING_PUBLIC_KEY->value . ': ' . $this->clientSigningKeyPair->getPublicKey(); $headers[] = StandardHeaders::SIGNING_PUBLIC_KEY->value . ': ' . $this->clientSigningKeyPair->getPublicKey();
} }
@ -567,8 +573,9 @@
public function exportSession(): ExportedSession public function exportSession(): ExportedSession
{ {
return new ExportedSession([ return new ExportedSession([
'peer_address' => $this->peerAddress->getAddress(), 'peer_address' => $this->identifiedAs->getAddress(),
'rpc_endpoint' => $this->rpcEndpoint, 'rpc_endpoint' => $this->rpcEndpoint,
'remote_server' => $this->remoteServer,
'session_uuid' => $this->sessionUuid, 'session_uuid' => $this->sessionUuid,
'transport_encryption_algorithm' => $this->serverInformation->getTransportEncryptionAlgorithm(), 'transport_encryption_algorithm' => $this->serverInformation->getTransportEncryptionAlgorithm(),
'server_keypair_expires' => $this->serverInformation->getServerKeypairExpires(), 'server_keypair_expires' => $this->serverInformation->getServerKeypairExpires(),

View file

@ -0,0 +1,167 @@
<?php
namespace Socialbox\Managers;
use PDOException;
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Database;
use Socialbox\Enums\ReservedUsernames;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Objects\ExportedSession;
class ExternalSessionManager
{
/**
* Checks if a session exists in the database for the specified domain.
*
* @param string $domain The domain to check for an existing session in the external_sessions table.
* @return bool Returns true if a session exists for the specified domain, otherwise false.
* @throws DatabaseOperationException If the database operation fails.
*/
public static function sessionExists(string $domain): bool
{
try
{
$stmt = Database::getConnection()->prepare("SELECT COUNT(*) FROM external_sessions WHERE domain=:domain LIMIT 1");
$stmt->bindParam(':domain', $domain);
$stmt->execute();
return $stmt->fetchColumn() > 0;
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to check if a session exists in the database', $e);
}
}
/**
* Adds a new external session to the database.
*
* @param ExportedSession $exportedSession The session data to be added, containing all necessary attributes
* such as server keys, client keys, and other metadata.
* @return void
* @throws DatabaseOperationException If the database operation fails.
*/
public static function addSession(ExportedSession $exportedSession): void
{
try
{
$stmt = Database::getConnection()->prepare("INSERT INTO external_sessions (domain, rpc_endpoint, session_uuid, server_keypair_expires, server_public_signing_key, server_public_encryption_key, host_public_encryption_key, host_private_encryption_key, private_shared_secret, host_transport_encryption_key, server_transport_encryption_key) VALUES (:domain, :rpc_endpoint, :session_uuid, :server_keypair_expires, :server_public_signing_key, :server_public_encryption_key, :host_public_encryption_key, :host_private_encryption_key, :private_shared_secret, :host_transport_encryption_key, :server_transport_encryption_key)");
$domain = $exportedSession->getRemoteServer();
$stmt->bindParam(':domain', $domain);
$rpcEndpoint = $exportedSession->getRpcEndpoint();
$stmt->bindParam(':rpc_endpoint', $rpcEndpoint);
$sessionUuid = $exportedSession->getSessionUuid();
$stmt->bindParam(':session_uuid', $sessionUuid);
$serverKeypairExpires = $exportedSession->getServerKeypairExpires();
$stmt->bindParam(':server_keypair_expires', $serverKeypairExpires);
$serverPublicSigningKey = $exportedSession->getServerPublicSigningKey();
$stmt->bindParam(':server_public_signing_key', $serverPublicSigningKey);
$serverPublicEncryptionKey = $exportedSession->getServerPublicEncryptionKey();
$stmt->bindParam(':server_public_encryption_key', $serverPublicEncryptionKey);
$hostPublicEncryptionKey = $exportedSession->getClientPublicEncryptionKey();
$stmt->bindParam(':host_public_encryption_key', $hostPublicEncryptionKey);
$hostPrivateEncryptionKey = $exportedSession->getClientPrivateEncryptionKey();
$stmt->bindParam(':host_private_encryption_key', $hostPrivateEncryptionKey);
$privateSharedSecret = $exportedSession->getPrivateSharedSecret();
$stmt->bindParam(':private_shared_secret', $privateSharedSecret);
$hostTransportEncryptionKey = $exportedSession->getClientTransportEncryptionKey();
$stmt->bindParam(':host_transport_encryption_key', $hostTransportEncryptionKey);
$serverTransportEncryptionKey = $exportedSession->getServerTransportEncryptionKey();
$stmt->bindParam(':server_transport_encryption_key', $serverTransportEncryptionKey);
$stmt->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to add a session to the database', $e);
}
}
/**
* Retrieves a session associated with the specified domain from the database.
*
* @param string $domain The domain for which the session should be retrieved.
* @return ExportedSession|null The retrieved session as an ExportedSession object, or null if no session is found.
* @throws DatabaseOperationException If the operation fails due to a database error.
*/
public static function getSession(string $domain): ?ExportedSession
{
try
{
$stmt = Database::getConnection()->prepare("SELECT * FROM external_sessions WHERE domain=:domain LIMIT 1");
$stmt->bindParam(':domain', $domain);
$stmt->execute();
$result = $stmt->fetch();
if($result === false)
{
return null;
}
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to retrieve the session from the database', $e);
}
return ExportedSession::fromArray([
'peer_address' => sprintf('%s@%s', ReservedUsernames::HOST->value, Configuration::getInstanceConfiguration()->getDomain()),
'rpc_endpoint' => $result['rpc_endpoint'],
'remote_server' => $result['domain'],
'session_uuid' => $result['session_uuid'],
'transport_encryption_algorithm' => $result['transport_encryption_algorithm'],
'server_keypair_expires' => $result['server_keypair_expires'],
'server_public_encryption_key' => $result['server_public_encryption_key'],
'client_public_signing_key' => Configuration::getCryptographyConfiguration()->getHostPublicKey(),
'client_private_signing_key' => Configuration::getCryptographyConfiguration()->getHostPrivateKey(),
'client_public_encryption_key' => $result['host_public_encryption_key'],
'client_private_encryption_key' => $result['host_private_encryption_key'],
'private_shared_secret' => $result['private_shared_secret'],
'client_transport_encryption_key' => $result['host_transport_encryption_key'],
'server_transport_encryption_key' => $result['server_transport_encryption_key']
]);
}
/**
* Removes a session associated with the specified domain from the database.
*
* @param string $domain The domain for which the session should be removed.
* @return void
* @throws DatabaseOperationException If the operation fails due to a database error.
*/
public static function removeSession(string $domain): void
{
try
{
$stmt = Database::getConnection()->prepare("DELETE FROM external_sessions WHERE domain=:domain");
$stmt->bindParam(':domain', $domain);
$stmt->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to remove a session from the database', $e);
}
}
/**
* Updates the last accessed timestamp for a specific external session in the database.
*
* @param string $domain The domain associated with the external session to update.
* @return void
* @throws DatabaseOperationException If the update operation fails.
*/
public static function updateLastAccessed(string $domain): void
{
try
{
$stmt = Database::getConnection()->prepare("UPDATE external_sessions SET last_accessed=CURRENT_TIMESTAMP WHERE domain=:domain");
$stmt->bindParam(':domain', $domain);
$stmt->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to update the last accessed time of a session in the database', $e);
}
}
}

View file

@ -11,6 +11,7 @@
{ {
private string $peerAddress; private string $peerAddress;
private string $rpcEndpoint; private string $rpcEndpoint;
private string $remoteServer;
private string $sessionUUID; private string $sessionUUID;
private string $transportEncryptionAlgorithm; private string $transportEncryptionAlgorithm;
private int $serverKeypairExpires; private int $serverKeypairExpires;
@ -41,6 +42,7 @@
{ {
$this->peerAddress = $data['peer_address']; $this->peerAddress = $data['peer_address'];
$this->rpcEndpoint = $data['rpc_endpoint']; $this->rpcEndpoint = $data['rpc_endpoint'];
$this->remoteServer = $data['remote_server'];
$this->sessionUUID = $data['session_uuid']; $this->sessionUUID = $data['session_uuid'];
$this->transportEncryptionAlgorithm = $data['transport_encryption_algorithm']; $this->transportEncryptionAlgorithm = $data['transport_encryption_algorithm'];
$this->serverKeypairExpires = $data['server_keypair_expires']; $this->serverKeypairExpires = $data['server_keypair_expires'];
@ -75,6 +77,16 @@
return $this->rpcEndpoint; return $this->rpcEndpoint;
} }
/**
* Retrieves the remote server.
*
* @return string The remote server.
*/
public function getRemoteServer(): string
{
return $this->remoteServer;
}
/** /**
* Retrieves the session UUID associated with the current instance. * Retrieves the session UUID associated with the current instance.
* *
@ -203,6 +215,7 @@
return [ return [
'peer_address' => $this->peerAddress, 'peer_address' => $this->peerAddress,
'rpc_endpoint' => $this->rpcEndpoint, 'rpc_endpoint' => $this->rpcEndpoint,
'remote_server' => $this->remoteServer,
'session_uuid' => $this->sessionUUID, 'session_uuid' => $this->sessionUUID,
'transport_encryption_algorithm' => $this->transportEncryptionAlgorithm, 'transport_encryption_algorithm' => $this->transportEncryptionAlgorithm,
'server_keypair_expires' => $this->serverKeypairExpires, 'server_keypair_expires' => $this->serverKeypairExpires,

View file

@ -9,6 +9,7 @@
use Socialbox\Classes\Utilities; use Socialbox\Classes\Utilities;
use Socialbox\Enums\StandardMethods; use Socialbox\Enums\StandardMethods;
use Socialbox\Exceptions\CryptographyException; use Socialbox\Exceptions\CryptographyException;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\ResolutionException; use Socialbox\Exceptions\ResolutionException;
use Socialbox\Exceptions\RpcException; use Socialbox\Exceptions\RpcException;
use Socialbox\Objects\ExportedSession; use Socialbox\Objects\ExportedSession;
@ -22,15 +23,17 @@
/** /**
* Constructs the object from an array of data. * Constructs the object from an array of data.
* *
* @param string|PeerAddress $peerAddress The address of the peer to connect to. * @param string|PeerAddress $identifiedAs The address of the peer to connect to.
* @param string|null $server Optional. The domain of the server to connect to if different from the identified
* @param ExportedSession|null $exportedSession Optional. The exported session to use for communication. * @param ExportedSession|null $exportedSession Optional. The exported session to use for communication.
* @throws CryptographyException If the public key is invalid. * @throws CryptographyException If the public key is invalid.
* @throws DatabaseOperationException If the database operation fails.
* @throws ResolutionException If the domain cannot be resolved. * @throws ResolutionException If the domain cannot be resolved.
* @throws RpcException If the RPC request fails. * @throws RpcException If the RPC request fails.
*/ */
public function __construct(string|PeerAddress $peerAddress, ?ExportedSession $exportedSession=null) public function __construct(string|PeerAddress $identifiedAs, ?string $server=null, ?ExportedSession $exportedSession=null)
{ {
parent::__construct($peerAddress, $exportedSession); parent::__construct($identifiedAs, $server, $exportedSession);
} }
/** /**

View file

@ -8,6 +8,7 @@
use Socialbox\Classes\Cryptography; use Socialbox\Classes\Cryptography;
use Socialbox\Classes\DnsHelper; use Socialbox\Classes\DnsHelper;
use Socialbox\Classes\Logger; use Socialbox\Classes\Logger;
use Socialbox\Classes\RpcClient;
use Socialbox\Classes\ServerResolver; use Socialbox\Classes\ServerResolver;
use Socialbox\Classes\Utilities; use Socialbox\Classes\Utilities;
use Socialbox\Classes\Validator; use Socialbox\Classes\Validator;
@ -20,7 +21,10 @@
use Socialbox\Exceptions\CryptographyException; use Socialbox\Exceptions\CryptographyException;
use Socialbox\Exceptions\DatabaseOperationException; use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\RequestException; use Socialbox\Exceptions\RequestException;
use Socialbox\Exceptions\ResolutionException;
use Socialbox\Exceptions\RpcException;
use Socialbox\Exceptions\StandardException; use Socialbox\Exceptions\StandardException;
use Socialbox\Managers\ExternalSessionManager;
use Socialbox\Managers\RegisteredPeerManager; use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Managers\SessionManager; use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest; use Socialbox\Objects\ClientRequest;
@ -598,6 +602,39 @@
} }
} }
/**
* Retrieves an external session associated with the given domain.
*
* If a session already exists for the specified domain, it retrieves and uses the existing session.
* Otherwise, it establishes a new connection, creates a session, and stores it for later use.
*
* @param string $domain The domain for which the external session is to be retrieved.
* @return RpcClient The RPC client initialized with the external session for the given domain.
* @throws CryptographyException If there was an error in the cryptography
* @throws DatabaseOperationException If there was an error while processing the session against the database
* @throws RpcException If there is an RPC exception while connecting to the remote server
* @throws ResolutionException If the connection to the remote server fails.
*/
public static function getExternalSession(string $domain): RpcClient
{
if(ExternalSessionManager::sessionExists($domain))
{
return new SocialClient(self::getServerAddress(), $domain, ExternalSessionManager::getSession($domain));
}
try
{
$client = new SocialClient(self::getServerAddress(), $domain);
}
catch (Exception $e)
{
throw new ResolutionException(sprintf('Failed to connect to remote server %s: %s', $domain, $e->getMessage()), $e->getCode(), $e);
}
ExternalSessionManager::addSession($client->exportSession());
return $client;
}
/** /**
* Retrieves the server information by assembling data from the configuration settings. * Retrieves the server information by assembling data from the configuration settings.
* *
@ -613,6 +650,16 @@
]); ]);
} }
/**
* Retrieves the server address.
*
* @return PeerAddress The constructed server address containing the host and domain information.
*/
public static function getServerAddress(): PeerAddress
{
return new PeerAddress(ReservedUsernames::HOST->value, Configuration::getInstanceConfiguration()->getDomain());
}
/** /**
* Retrieves the DNS record by generating a TXT record using the RPC endpoint, * Retrieves the DNS record by generating a TXT record using the RPC endpoint,
* host public key, and host key pair expiration from the configuration. * host public key, and host key pair expiration from the configuration.