Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"keywords": ["module", "xp"],
"require" : {
"xp-framework/core": "^12.0 | ^11.0 | ^10.0",
"xp-framework/networking": "^10.1",
"xp-framework/networking": "^11.0",
"xp-forge/uri": "^3.1",
"xp-forge/websockets": "^4.1",
"php": ">=7.4.0"
Expand Down
3 changes: 2 additions & 1 deletion src/main/php/web/Application.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ public final function routing() {
* Initializes this application, being run once when the server starts.
* Empty in this default implementation, overwrite in subclasses.
*
* @param peer.server.ServerImplementation $impl
* @return void
*/
public function initialize() {
public function initialize($impl) {
// Empty
}

Expand Down
8 changes: 3 additions & 5 deletions src/main/php/xp/web/Servers.class.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php namespace xp\web;

use lang\{Enum, IllegalArgumentException};
use peer\server\{AsyncServer, PreforkingServer};
use peer\server\{AsynchronousServer, ForkedServer};
use xp\web\srv\{Standalone, Develop};

/** @test web.unittest.server.ServersTest */
Expand All @@ -12,15 +12,13 @@ static function __static() {
self::$ASYNC= new class(0, 'ASYNC') extends Servers {
static function __static() { }
public function newInstance($address, $arguments= []) {
return new Standalone($address, new AsyncServer());
return new Standalone($address, new AsynchronousServer());
}
};
self::$PREFORK= new class(1, 'PREFORK') extends Servers {
static function __static() { }
public function newInstance($address, $arguments= []) {
return new Standalone($address, new PreforkingServer(
null,
null,
return new Standalone($address, new ForkedServer(
self::argument($arguments, 'children') ?? $arguments[0] ?? 10
));
}
Expand Down
27 changes: 5 additions & 22 deletions src/main/php/xp/web/srv/Develop.class.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php namespace xp\web\srv;

use lang\ClassLoader;
use peer\server\AsyncServer;
use peer\{Socket, ServerSocket, SocketTimeoutException};
use peer\server\AsynchronousServer;
use peer\{ServerSocket, SocketTimeoutException};
use util\cmd\Console;
use web\{Application, Environment, Logging};
use xp\web\Source;
Expand Down Expand Up @@ -33,9 +33,10 @@ public function __construct($address, $workers= 1) {
* @param string[] $logging
*/
public function serve($source, $profile, $webroot, $docroot, $config, $args, $logging) {
$impl= new AsynchronousServer();
$environment= new Environment($profile, $webroot, $docroot, $config, $args, $logging);
$application= (new Source($source, $environment))->application($args);
$application->initialize();
$application->initialize($impl);

// PHP doesn't start with a nonexistant document root
if (!$docroot->exists()) {
Expand Down Expand Up @@ -72,31 +73,13 @@ public function serve($source, $profile, $webroot, $docroot, $config, $args, $lo
);

// Start the multiplex protocol in the foreground and forward requests
$impl= new AsyncServer();
$impl->listen(new ServerSocket($this->host, $this->port), Protocol::multiplex()
->serving('http', new ForwardRequests($backends))
->serving('websocket', new WebSocketProtocol(new ForwardMessages($backends)))
);

// Inside `xp -supervise`, connect to signalling socket. Unfortunately, there
// is no way to signal "no timeout", so set a pretty high timeout of one year,
// then catch and handle it by continuing to check for reads.
if ($port= getenv('XP_SIGNAL')) {
$signal= new Socket('127.0.0.1', $port);
$signal->setTimeout(31536000);
$signal->connect();
$impl->select($signal, function() use($impl) {
try {
next: yield 'read' => null;
} catch (SocketTimeoutException $e) {
goto next;
}
$impl->shutdown();
});
}

$this->connect(getenv('XP_SIGNAL'), $impl);
try {
$impl->init();
$impl->service();
} finally {
Console::write('[');
Expand Down
26 changes: 26 additions & 0 deletions src/main/php/xp/web/srv/Server.class.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php namespace xp\web\srv;

use peer\Socket;

abstract class Server {
protected $host, $port;

Expand All @@ -19,6 +21,30 @@ public function __construct($address) {
}
}

/**
* Inside `xp -supervise`, connect to signalling socket. Unfortunately, there
* is no way to signal "no timeout", so set a pretty high timeout of one year,
* then catch and handle it by continuing to check for reads.
*
* @param int $signal
* @param peer.server.ServerImplementation $impl
*/
protected function connect(int $signal, $impl) {
if (0 === $signal) return;

$s= new Socket('127.0.0.1', $signal);
$s->setTimeout(31536000);
$s->connect();
$impl->select($s, function() use($impl) {
try {
next: yield 'read' => null;
} catch (SocketTimeoutException $e) {
goto next;
}
$impl->shutdown();
});
}

/** @return string */
public function host() { return $this->host; }

Expand Down
10 changes: 8 additions & 2 deletions src/main/php/xp/web/srv/Standalone.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ public function __construct($address, $impl) {
public function serve($source, $profile, $webroot, $docroot, $config, $args, $logging) {
$environment= new Environment($profile, $webroot, $docroot, $config, $args, $logging);
$application= (new Source($source, $environment))->application($args);
$application->initialize();
$application->initialize($this->impl);
$application->routing();

$socket= new ServerSocket($this->host, $this->port);
$this->impl->listen($socket, Protocol::multiplex()
->serving('http', new HttpProtocol($application, $environment->logging()))
->serving('websocket', new WebSocketProtocol(null, $environment->logging()))
);
// DEBUG $this->impl->setTrace(\util\log\Logging::all()->toConsole());

Console::writeLine("\e[33m@", nameof($this), '(HTTP @ ', $socket->toString(), ")\e[0m");
Console::writeLine("\e[1mServing {$profile}:", $application, $config, "\e[0m > ", $environment->logging()->target());
Expand All @@ -56,6 +57,11 @@ public function serve($source, $profile, $webroot, $docroot, $config, $args, $lo
getmypid()
);

$this->impl->service();
$this->connect(getenv('XP_SIGNAL'), $this->impl);
try {
$this->impl->service();
} finally {
Console::writeLine('[.]');
}
}
}
Loading