diff --git a/src/Socialbox/Classes/StandardMethods/ResolvePeer.php b/src/Socialbox/Classes/StandardMethods/ResolvePeer.php new file mode 100644 index 0000000..73ce94f --- /dev/null +++ b/src/Socialbox/Classes/StandardMethods/ResolvePeer.php @@ -0,0 +1,86 @@ +containsParameter('peer')) + { + return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'peer' parameter"); + } + + // Parse the peer address + try + { + $peerAddress = PeerAddress::fromAddress($rpcRequest->getParameter('peer')); + } + catch(InvalidArgumentException $e) + { + throw new StandardException('Peer Address Error: ' . $e->getMessage(), StandardError::RPC_INVALID_ARGUMENTS, $e); + } + + // If the requested peer resides in the server, resolve the peer internally. + if($peerAddress->getDomain() === Configuration::getInstanceConfiguration()->getDomain()) + { + try + { + $registeredPeer = RegisteredPeerManager::getPeerByAddress($peerAddress); + } + catch (DatabaseOperationException $e) + { + throw new StandardException('There was an unexpected error while trying to resolve the peer internally', StandardError::INTERNAL_SERVER_ERROR, $e); + } + + // Return not found if the returned record is null or if the registered peer isn't enabled + if($registeredPeer === null || !$registeredPeer->isEnabled()) + { + return $rpcRequest->produceError(StandardError::PEER_NOT_FOUND, sprintf('Peer %s not found', $peerAddress->getAddress())); + } + + // Return standard peer representation + return $rpcRequest->produceResponse($registeredPeer->toStandardPeer()); + } + + // Otherwise, resolve the peer from the remote server + try + { + $client = Socialbox::getExternalSession($peerAddress->getDomain()); + } + catch(Exception $e) + { + throw new StandardException(sprintf('There was an error while trying to connect to %s: %s', $peerAddress->getDomain(), $e->getMessage()), StandardError::RESOLUTION_FAILED, $e); + } + + // Return the result/error of the resolution + try + { + return $rpcRequest->produceResponse($client->resolvePeer($peerAddress)); + } + catch(RpcException $e) + { + throw new StandardException($e->getMessage(), StandardError::tryFrom($e->getCode()) ?? StandardError::UNKNOWN, $e); + } + } + } \ No newline at end of file diff --git a/src/Socialbox/Enums/StandardMethods.php b/src/Socialbox/Enums/StandardMethods.php index 8cf92c8..f9ee7f5 100644 --- a/src/Socialbox/Enums/StandardMethods.php +++ b/src/Socialbox/Enums/StandardMethods.php @@ -12,6 +12,7 @@ use Socialbox\Classes\StandardMethods\GetSessionState; use Socialbox\Classes\StandardMethods\GetTermsOfService; use Socialbox\Classes\StandardMethods\Ping; + use Socialbox\Classes\StandardMethods\ResolvePeer; use Socialbox\Classes\StandardMethods\SettingsAddSigningKey; use Socialbox\Classes\StandardMethods\SettingsDeleteBirthday; use Socialbox\Classes\StandardMethods\SettingsDeleteDisplayName; @@ -94,6 +95,8 @@ case SETTINGS_ADD_SIGNING_KEY = 'settingsAddSigningKey'; case SETTINGS_GET_SIGNING_KEYS = 'settingsGetSigningKeys'; + case RESOLVE_PEER = 'resolvePeer'; + /** * Executes the appropriate operation based on the current context and requests provided. * @@ -140,6 +143,8 @@ self::SETTINGS_ADD_SIGNING_KEY => SettingsAddSigningKey::execute($request, $rpcRequest), self::SETTINGS_GET_SIGNING_KEYS => SettingsGetSigningKeys::execute($request, $rpcRequest), + self::RESOLVE_PEER => ResolvePeer::execute($request, $rpcRequest), + default => $rpcRequest->produceError(StandardError::METHOD_NOT_ALLOWED, sprintf("The method %s is not supported by the server", $rpcRequest->getMethod())) }; } @@ -227,7 +232,9 @@ **/ private static function getExternalMethods(ClientRequest $clientRequest): array { - return []; + return [ + self::RESOLVE_PEER + ]; } /** @@ -249,7 +256,8 @@ self::SETTINGS_SET_OTP, self::SETTINGS_SET_EMAIL, self::SETTINGS_SET_PHONE, - self::SETTINGS_SET_BIRTHDAY + self::SETTINGS_SET_BIRTHDAY, + self::RESOLVE_PEER ]; // Prevent the user from deleting their display name if it is required diff --git a/src/Socialbox/Managers/RegisteredPeerManager.php b/src/Socialbox/Managers/RegisteredPeerManager.php index 1838226..9310846 100644 --- a/src/Socialbox/Managers/RegisteredPeerManager.php +++ b/src/Socialbox/Managers/RegisteredPeerManager.php @@ -165,6 +165,13 @@ $username = $address->getUsername(); $statement->bindParam(1, $username); $server = $address->getDomain(); + + // Convert to 'host' if the domain is the same as the server's host + if($server === Configuration::getInstanceConfiguration()->getDomain()) + { + $server = 'host'; + } + $statement->bindParam(2, $server); $statement->execute(); diff --git a/src/Socialbox/Objects/Database/RegisteredPeerRecord.php b/src/Socialbox/Objects/Database/RegisteredPeerRecord.php index f2c04f4..f36cd32 100644 --- a/src/Socialbox/Objects/Database/RegisteredPeerRecord.php +++ b/src/Socialbox/Objects/Database/RegisteredPeerRecord.php @@ -261,7 +261,7 @@ * * @return Peer The Peer representation of the current instance. */ - public function toPeer(): Peer + public function toStandardPeer(): Peer { return Peer::fromArray($this->toArray()); } diff --git a/src/Socialbox/SocialClient.php b/src/Socialbox/SocialClient.php index 7407e95..57870ec 100644 --- a/src/Socialbox/SocialClient.php +++ b/src/Socialbox/SocialClient.php @@ -15,6 +15,7 @@ use Socialbox\Objects\ExportedSession; use Socialbox\Objects\PeerAddress; use Socialbox\Objects\RpcRequest; + use Socialbox\Objects\Standard\Peer; use Socialbox\Objects\Standard\ServerDocument; use Socialbox\Objects\Standard\SessionState; @@ -611,4 +612,25 @@ new RpcRequest(StandardMethods::SETTINGS_DELETE_BIRTHDAY->value, Utilities::randomCrc32()) )->getResponse()->getResult(); } + + /** + * Resolves a peer by its address or a PeerAddress instance through a remote procedure call. + * + * @param string|PeerAddress $peerAddress The peer address as a string or an instance of PeerAddress. + * @return Peer The resolved peer object. + * @throws RpcException Thrown if the RPC request fails. + */ + public function resolvePeer(string|PeerAddress $peerAddress): Peer + { + if($peerAddress instanceof PeerAddress) + { + $peerAddress = $peerAddress->getAddress(); + } + + return Peer::fromArray($this->sendRequest( + new RpcRequest(StandardMethods::RESOLVE_PEER->value, Utilities::randomCrc32(), [ + 'peer_address' => $peerAddress + ]) + )->getResponse()->getResult()); + } } \ No newline at end of file diff --git a/src/Socialbox/Socialbox.php b/src/Socialbox/Socialbox.php index 995506c..6c59135 100644 --- a/src/Socialbox/Socialbox.php +++ b/src/Socialbox/Socialbox.php @@ -609,13 +609,13 @@ * 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. + * @return SocialClient 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. + * @throws RpcException If there is an RPC exception while connecting to the remote server */ - public static function getExternalSession(string $domain): RpcClient + public static function getExternalSession(string $domain): SocialClient { if(ExternalSessionManager::sessionExists($domain)) {