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, transport_encryption_algorithm, 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, :transport_encryption_algorithm, :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); $transportEncryptionAlgorithm = $exportedSession->getTransportEncryptionAlgorithm(); $stmt->bindParam(':transport_encryption_algorithm', $transportEncryptionAlgorithm); $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_signing_key' => $result['server_public_signing_key'], '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); } } }