1<?php 2/** 3 * This file is part of the FreeDSx LDAP package. 4 * 5 * (c) Chad Sikorra <Chad.Sikorra@gmail.com> 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11namespace FreeDSx\Ldap\Server\ServerRunner; 12 13use FreeDSx\Ldap\Exception\RuntimeException; 14use FreeDSx\Ldap\Protocol\Queue\ServerQueue; 15use FreeDSx\Ldap\Protocol\ServerProtocolHandler; 16use FreeDSx\Ldap\Server\RequestHandler\RequestHandlerInterface; 17use FreeDSx\Socket\SocketServer; 18 19/** 20 * Uses PNCTL to fork incoming requests and send them to the server protocol handler. 21 * 22 * @author Chad Sikorra <Chad.Sikorra@gmail.com> 23 */ 24class PcntlServerRunner implements ServerRunnerInterface 25{ 26 /** 27 * @var SocketServer 28 */ 29 protected $server; 30 31 /** 32 * @var array 33 */ 34 protected $options; 35 36 /** 37 * @param array $options 38 */ 39 public function __construct(array $options = []) 40 { 41 if (!extension_loaded('pcntl')) { 42 throw new RuntimeException('The PCNTL extension is needed to fork incoming requests, which is only available on Linux.'); 43 } 44 $this->options = $options; 45 } 46 47 /** 48 * {@inheritdoc} 49 */ 50 public function run(SocketServer $server): void 51 { 52 $this->server = $server; 53 54 while ($socket = $this->server->accept()) { 55 $pid = pcntl_fork(); 56 if ($pid == -1) { 57 throw new RuntimeException('Unable to fork process.'); 58 } elseif ($pid === 0) { 59 $serverProtocolHandler = new ServerProtocolHandler( 60 new ServerQueue($socket), 61 $this->constructRequestHandler(), 62 $this->options 63 ); 64 $serverProtocolHandler->handle(); 65 $this->server->removeClient($socket); 66 exit; 67 } 68 } 69 } 70 71 /** 72 * Try to instantiate the user supplied request handler. 73 */ 74 protected function constructRequestHandler(): RequestHandlerInterface 75 { 76 try { 77 return new $this->options['request_handler'](); 78 } catch (\Throwable $e) { 79 throw new RuntimeException(sprintf( 80 'Unable to instantiate the request handler: "%s"', 81 $e->getMessage() 82 ), $e->getCode(), $e); 83 } 84 } 85} 86