=> MethodDescriptor ] private $paths_map = []; private function waitForNextEvent() { return $this->requestCall(); } /** * Add a service to this server * * @param Object $service The service to be added */ public function handle($service) { $methodDescriptors = $service->getMethodDescriptors(); $exist_methods = \array_intersect_key($this->paths_map, $methodDescriptors); if (!empty($exist_methods)) { \fwrite(\STDERR, "WARNING: " . 'override already registered methods: ' . \implode(', ', \array_keys($exist_methods)) . \PHP_EOL); } $this->paths_map = \array_merge($this->paths_map, $methodDescriptors); return $this->paths_map; } public function run() { $this->start(); while (\true) { try { // This blocks until the server receives a request $event = $this->waitForNextEvent(); $full_path = $event->method; $context = new ServerContext($event); $server_writer = new ServerCallWriter($event->call, $context); if (!\array_key_exists($full_path, $this->paths_map)) { $context->setStatus(Status::unimplemented()); $server_writer->finish(); continue; } $method_desc = $this->paths_map[$full_path]; $server_reader = new ServerCallReader($event->call, $method_desc->request_type); try { $this->processCall($method_desc, $server_reader, $server_writer, $context); } catch (\Exception $e) { $context->setStatus(Status::status(STATUS_INTERNAL, $e->getMessage())); $server_writer->finish(); } } catch (\Exception $e) { \fwrite(\STDERR, "ERROR: " . $e->getMessage() . \PHP_EOL); exit(1); } } } private function processCall(MethodDescriptor $method_desc, ServerCallReader $server_reader, ServerCallWriter $server_writer, ServerContext $context) { // Dispatch to actual server logic switch ($method_desc->call_type) { case MethodDescriptor::UNARY_CALL: $request = $server_reader->read(); $response = \call_user_func(array($method_desc->service, $method_desc->method_name), $request ?? new $method_desc->request_type(), $context); $server_writer->finish($response); break; case MethodDescriptor::SERVER_STREAMING_CALL: $request = $server_reader->read(); \call_user_func(array($method_desc->service, $method_desc->method_name), $request ?? new $method_desc->request_type(), $server_writer, $context); break; case MethodDescriptor::CLIENT_STREAMING_CALL: $response = \call_user_func(array($method_desc->service, $method_desc->method_name), $server_reader, $context); $server_writer->finish($response); break; case MethodDescriptor::BIDI_STREAMING_CALL: \call_user_func(array($method_desc->service, $method_desc->method_name), $server_reader, $server_writer, $context); break; default: throw new \Exception(); } } }