isExternal()) { return self::handleExternal($request, $rpcRequest); } return self::handleInternal($request, $rpcRequest); } catch (DatabaseOperationException $e) { throw new StandardRpcException('An error occurred while checking the request type', StandardError::INTERNAL_SERVER_ERROR, $e); } } /** * @param ClientRequest $request * @param RpcRequest $rpcRequest * @return SerializableInterface|null * @throws StandardRpcException */ private static function handleInternal(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface { if(!$rpcRequest->containsParameter('channel_uuid')) { throw new MissingRpcArgumentException('channel_uuid'); } elseif(!Validator::validateUuid($rpcRequest->getParameter('channel_uuid'))) { throw new InvalidRpcArgumentException('channel_uuid', 'The given channel uuid is not a valid UUID V4'); } if(!$rpcRequest->containsParameter('public_encryption_key')) { throw new MissingRpcArgumentException('public_encryption_key'); } elseif(!Cryptography::validatePublicEncryptionKey('public_encryption_key')) { throw new InvalidRpcArgumentException('public_encryption_key', 'The given public encryption key is invalid'); } try { $receivingPeer = $request->getPeer(); $encryptionChannel = EncryptionChannelManager::getChannel($rpcRequest->getParameter('channel_uuid')); } catch(DatabaseOperationException $e) { throw new StandardRpcException('There was an error while trying to obtain the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); } if($encryptionChannel === null) { return $rpcRequest->produceError(StandardError::NOT_FOUND, 'The requested encryption channel was not found'); } elseif($encryptionChannel->getReceivingPeerAddress()->getAddress() !== $receivingPeer->getAddress()) { return $rpcRequest->produceError(StandardError::UNAUTHORIZED, 'The requested encryption channel is not accessible'); } elseif($encryptionChannel->getStatus() !== EncryptionChannelStatus::AWAITING_RECEIVER) { return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The encryption channel is not awaiting the receiver'); } if($encryptionChannel->getCallingPeerAddress()->isExternal()) { try { $rpcClient = Socialbox::getExternalSession($encryptionChannel->getCallingPeerAddress()->getDomain()); $rpcClient->encryptionAcceptChannel( channelUuid: $rpcRequest->getParameter('channel_uuid'), publicEncryptionKey: $rpcRequest->getParameter('public_encryption_key'), identifiedAs: $receivingPeer->getAddress() ); } catch(Exception $e) { try { EncryptionChannelManager::declineChannel($rpcRequest->getParameter('channel_uuid'), true); } catch(DatabaseOperationException $e) { Logger::getLogger()->error('Error declining channel as server', $e); } if($e instanceof RpcException) { throw StandardRpcException::fromRpcException($e); } throw new StandardRpcException('There was an error while trying to notify the external server of the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); } } try { EncryptionChannelManager::acceptChannel( channelUuid: $rpcRequest->getParameter('channel_uuid'), publicEncryptionKey: $rpcRequest->getParameter('public_encryption_key') ); } catch (DatabaseOperationException $e) { throw new StandardRpcException('There was an error while trying to accept the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); } return $rpcRequest->produceResponse(true); } /** * @param ClientRequest $request * @param RpcRequest $rpcRequest * @return SerializableInterface|null * @throws StandardRpcException */ private static function handleExternal(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface { if($request->getIdentifyAs() === null) { return $rpcRequest->produceError(StandardError::BAD_REQUEST, 'Missing required header IdentifyAs'); } if(!$rpcRequest->containsParameter('channel_uuid')) { throw new MissingRpcArgumentException('channel_uuid'); } elseif(!Validator::validateUuid($rpcRequest->getParameter('channel_uuid'))) { throw new InvalidRpcArgumentException('channel_uuid', 'The given channel uuid is not a valid UUID V4'); } if(!$rpcRequest->containsParameter('public_encryption_key')) { throw new MissingRpcArgumentException('public_encryption_key'); } elseif(!Cryptography::validatePublicEncryptionKey('public_encryption_key')) { throw new InvalidRpcArgumentException('public_encryption_key', 'The given public encryption key is invalid'); } try { $receivingPeer = Socialbox::resolvePeer($request->getIdentifyAs()); $encryptionChannel = EncryptionChannelManager::getChannel($rpcRequest->getParameter('channel_uuid')); } catch(DatabaseOperationException $e) { throw new StandardRpcException('There was an error while trying to obtain the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); } if($encryptionChannel === null) { return $rpcRequest->produceError(StandardError::NOT_FOUND, 'The requested encryption channel was not found'); } elseif($encryptionChannel->getReceivingPeerAddress() !== $receivingPeer->getAddress()) { return $rpcRequest->produceError(StandardError::UNAUTHORIZED, 'The requested encryption channel is not accessible'); } elseif($encryptionChannel->getStatus() !== EncryptionChannelStatus::AWAITING_RECEIVER) { return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The encryption channel is not awaiting the receiver'); } try { EncryptionChannelManager::acceptChannel( channelUuid: $rpcRequest->getParameter('channel_uuid'), publicEncryptionKey: $rpcRequest->getParameter('public_encryption_key') ); } catch (DatabaseOperationException $e) { throw new StandardRpcException('There was an error while trying to accept the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); } return $rpcRequest->produceResponse(true); } }