Skip to content

Commit 3dacc1b

Browse files
committed
Expose socketServer & cleanup Server.php
1 parent f69df72 commit 3dacc1b

File tree

1 file changed

+111
-45
lines changed

1 file changed

+111
-45
lines changed

src/VerifierServer/Server.php

Lines changed: 111 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -84,47 +84,55 @@ public function __construct(
8484
}
8585

8686
/**
87-
* Logs an error message with details about the exception.
88-
*
89-
* @param Exception $e The exception to log.
90-
* @param bool $fatal Optional. Indicates whether the error is fatal. Defaults to false.
91-
* If true, the server will stop after logging the error.
87+
* Initializes the server by creating a stream socket server and setting it to non-blocking mode.
9288
*
93-
* @return string
89+
* @throws Exception If the server fails to be created.
9490
*/
95-
public function logError($e, bool $fatal = false): void
91+
public function init(?LoopInterface $loop = null, bool $stream_socket_server = false): void
9692
{
97-
if ($fatal) $this->close();
98-
$error = 'Error: ' . $e->getMessage() . PHP_EOL .
99-
'Line ' . $e->getLine() . ' in ' . $e->getFile() . PHP_EOL .
100-
$e->getTraceAsString();
101-
if (isset($this->logger)) $this->logger->warning($error);
93+
if ($this->running) return;
94+
$this->initialized = true;
95+
($stream_socket_server)
96+
? $this->initStreamSocketServer()
97+
: $this->initReactHttpServer($loop);
10298
}
10399

104100
/**
105-
* Initializes the server by creating a stream socket server and setting it to non-blocking mode.
101+
* Initializes a stream socket server.
106102
*
107-
* @throws Exception If the server fails to be created.
103+
* This method creates a stream socket server using the specified host address.
104+
* If the server cannot be created, an exception is thrown with the error details.
105+
*
106+
* @throws Exception If the stream socket server fails to initialize.
108107
*/
109-
public function init(?LoopInterface $loop = null, bool $stream_socket_server = false): void
108+
private function initStreamSocketServer(): void
110109
{
111-
if ($this->running) return;
112-
if ($stream_socket_server) {
113-
$this->server = stream_socket_server("{$this->hostAddr}", $errno, $errstr);
114-
if (! is_resource($this->server)) {
115-
throw new Exception("Failed to create server: $errstr ($errno)");
116-
}
117-
} else {
118-
$this->server = new HttpServer(
119-
$this->loop = $loop instanceof LoopInterface
120-
? $loop
121-
: Loop::get(),
122-
fn($request) => $this->handleReact($request)
123-
);
124-
$this->server->on('error', fn(Throwable $e) => $this->logError($e, true));
125-
$this->socket = new SocketServer($this->hostAddr, [], $this->loop);
110+
if (! is_resource($this->server = stream_socket_server("{$this->hostAddr}", $errno, $errstr))) {
111+
throw new Exception("Failed to create server: $errstr ($errno)");
126112
}
127-
$this->initialized = true;
113+
}
114+
115+
/**
116+
* Initializes the ReactPHP HTTP server.
117+
*
118+
* This method sets up an HTTP server using ReactPHP's HttpServer and SocketServer.
119+
* It accepts an optional event loop instance. If no loop is provided, it defaults
120+
* to using the global loop instance. The HTTP server is configured to handle incoming
121+
* requests via the `handleReact` method and logs errors using the `logError` method.
122+
*
123+
* @param LoopInterface|null $loop Optional event loop instance. If null, the global loop is used.
124+
*
125+
* @return void
126+
*/
127+
private function initReactHttpServer(?LoopInterface $loop = null): void
128+
{
129+
$this->server = new HttpServer(
130+
$this->loop = $loop instanceof LoopInterface
131+
? $loop
132+
: Loop::get(),
133+
fn($request) => $this->handleReact($request)
134+
)->on('error', fn(Throwable $e) => $this->logError($e, true));
135+
$this->socket = new SocketServer($this->hostAddr, [], $this->loop);
128136
}
129137

130138
/**
@@ -138,21 +146,48 @@ public function start(bool $start_loop = false): void
138146
$this->init();
139147
}
140148
if (! $this->running) {
141-
if ($this->server instanceof HttpServer) {
142-
$this->server->listen($this->socket);
143-
$this->running = true;
144-
if ($start_loop) $this->loop->run();
145-
} elseif (is_resource($this->server)) {
146-
$this->running = true;
147-
while ($this->running) {
148-
if (stripos(PHP_OS, 'WIN') === false && extension_loaded('pcntl')) {
149-
pcntl_signal_dispatch();
150-
}
151-
if ($client = @stream_socket_accept($this->server, 0)) {
152-
$this->handleResource($client);
153-
}
154-
}
149+
$this->running = true;
150+
($this->server instanceof HttpServer)
151+
? $this->startReact($start_loop)
152+
: $this->startResource();
153+
}
154+
}
155+
156+
/**
157+
* Starts the ReactPHP server by binding it to the specified socket.
158+
*
159+
* @param bool $start_loop Determines whether to start the event loop.
160+
* - If true, the event loop will be started.
161+
* - If false, the event loop will not be started.
162+
*
163+
* @return void
164+
*/
165+
private function startReact(bool $start_loop = false): void
166+
{
167+
$this->server->listen($this->socket);
168+
if ($start_loop) $this->loop->run();
169+
}
170+
171+
/**
172+
* Starts the resource handling loop for the server.
173+
*
174+
* This method continuously listens for incoming client connections
175+
* while the server is running. If the operating system is not Windows
176+
* and the `pcntl` extension is loaded, it dispatches pending signals
177+
* using `pcntl_signal_dispatch`. When a client connection is accepted,
178+
* it delegates the handling of the connection to the `handleResource` method.
179+
*
180+
* @return void
181+
*/
182+
private function startResource(): void
183+
{
184+
while ($this->running) {
185+
if (stripos(PHP_OS, 'WIN') === false && extension_loaded('pcntl')) {
186+
pcntl_signal_dispatch();
155187
}
188+
($client = @stream_socket_accept($this->server, 0))
189+
? $this->handleResource($client)
190+
: $this->logError(new Exception("Failed to accept client connection"), true);
156191
}
157192
}
158193

@@ -214,6 +249,16 @@ public function getServer()
214249
return $this->server ?? null;
215250
}
216251

252+
/**
253+
* Retrieves the socket instance.
254+
*
255+
* @return SocketServer|null Returns the socket instance if set, or null if not set.
256+
*/
257+
public function getSocketServer(): SocketServer|null
258+
{
259+
return $this->socket ?? null;
260+
}
261+
217262
/**
218263
* Retrieves the current state of the server.
219264
*
@@ -353,6 +398,27 @@ private function handleResource($client): null
353398
return null;
354399
}
355400

401+
/**
402+
* Logs an error message with details about the exception.
403+
*
404+
* @param Exception $e The exception to log.
405+
* @param bool $fatal Optional. Indicates whether the error is fatal. Defaults to false.
406+
* If true, the server will stop after logging the error.
407+
*
408+
* @return string
409+
*/
410+
public function logError(Exception $e, bool $fatal = false): void
411+
{
412+
if ($fatal) $this->close();
413+
if (isset($this->logger)) $this->logger->warning(sprintf(
414+
"Error: %s" . PHP_EOL . "Line %d in %s" . PHP_EOL . "%s",
415+
$e->getMessage(),
416+
$e->getLine(),
417+
$e->getFile(),
418+
$e->getTraceAsString()
419+
));
420+
}
421+
356422
/**
357423
* Destructor method that is automatically called when the object is destroyed.
358424
* It ensures that the server is properly stopped by calling the stop() method.

0 commit comments

Comments
 (0)