From cbbf03babf1f512dc7fec1e98d2d78359f3b72d5 Mon Sep 17 00:00:00 2001 From: Anton Kozhemyakin <51966037+rubyqorn@users.noreply.github.com> Date: Thu, 22 Oct 2020 18:22:20 +0300 Subject: [PATCH 01/41] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e4364df..9edee05 100755 --- a/README.md +++ b/README.md @@ -1 +1 @@ -web-socket +#socket From 3a17bae0a6ef7b4986614fe0acaca549a2145788 Mon Sep 17 00:00:00 2001 From: Anton Kozhemyakin <51966037+rubyqorn@users.noreply.github.com> Date: Wed, 4 Nov 2020 20:09:25 +0300 Subject: [PATCH 02/41] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9edee05..60eb96c 100755 --- a/README.md +++ b/README.md @@ -1 +1 @@ -#socket +# Layer for client and server socket connections From 82f17f5b5896ec5f140dd32dc9bea93af381f54d Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sat, 21 Nov 2020 20:38:38 +0300 Subject: [PATCH 03/41] Global refactored architecture of classes --- src/AbstractSocket.php | 28 +++++ src/ActionFactory.php | 65 +++++++++++ src/Actionable.php | 12 ++ src/Client.php | 71 ----------- src/ClientSocket.php | 26 +++++ src/ISocketImplementer.php | 22 ---- src/Server.php | 71 ----------- src/ServerSocket.php | 36 ++++++ src/ServiceContainer.php | 68 ----------- src/ServicesHelper.php | 8 -- src/Socket.php | 168 --------------------------- src/SocketAcceptor.php | 23 ++++ src/SocketBinder.php | 33 ++++++ src/SocketCloser.php | 23 ++++ src/SocketConnector.php | 34 ++++++ src/SocketCreator.php | 28 +++++ src/SocketEndpoint.php | 95 --------------- src/SocketListener.php | 35 ++++++ src/SocketReader.php | 30 +++++ src/SocketWriter.php | 35 ++++++ tests/unit/SocketCredentialsTest.php | 24 ---- tests/unit/SocketTest.php | 19 --- 22 files changed, 408 insertions(+), 546 deletions(-) create mode 100644 src/AbstractSocket.php create mode 100644 src/ActionFactory.php create mode 100644 src/Actionable.php delete mode 100644 src/Client.php create mode 100644 src/ClientSocket.php delete mode 100644 src/ISocketImplementer.php delete mode 100644 src/Server.php create mode 100644 src/ServerSocket.php delete mode 100755 src/Socket.php create mode 100644 src/SocketAcceptor.php create mode 100644 src/SocketBinder.php create mode 100644 src/SocketCloser.php create mode 100644 src/SocketConnector.php create mode 100644 src/SocketCreator.php delete mode 100755 src/SocketEndpoint.php create mode 100644 src/SocketListener.php create mode 100644 src/SocketReader.php create mode 100644 src/SocketWriter.php delete mode 100755 tests/unit/SocketCredentialsTest.php delete mode 100755 tests/unit/SocketTest.php diff --git a/src/AbstractSocket.php b/src/AbstractSocket.php new file mode 100644 index 0000000..25eb410 --- /dev/null +++ b/src/AbstractSocket.php @@ -0,0 +1,28 @@ +credentials = $credentials; + } + + abstract public function create(); + + abstract public function read(); + + abstract public function write(); + + abstract public function close(); + + public function __destruct() + { + $this->close(); + } +} diff --git a/src/ActionFactory.php b/src/ActionFactory.php new file mode 100644 index 0000000..01e1a67 --- /dev/null +++ b/src/ActionFactory.php @@ -0,0 +1,65 @@ +credentials = $credentials; + } + + private function getHost() + { + return $this->credentials->getCredential('host'); + } + + private function getPort() + { + return $this->credentials->getCredential('port'); + } + + public function getCreator() + { + return new SocketCreator($this->getHost(), $this->getPort()); + } + + public function getAcceptor() + { + return new SocketAcceptor(); + } + + public function getConnector() + { + return new SocketConnector($this->getHost(), $this->getPort()); + } + + public function getListener() + { + return new SocketListener(); + } + + public function getBinder() + { + return new SocketBinder($this->getHost(), $this->getPort()); + } + + public function getReader() + { + return new SocketReader(); + } + + public function getWriter() + { + return new SocketWriter(); + } + + public function getCloser() + { + return new SocketCloser(); + } +} diff --git a/src/Actionable.php b/src/Actionable.php new file mode 100644 index 0000000..d3a64a0 --- /dev/null +++ b/src/Actionable.php @@ -0,0 +1,12 @@ +createdSocket = $this->connectToSocket(); - - if (!$this->createdSocket) { - return new SocketError('Can\'t accepted connected socket'); - } - - return $this->createdSocket; - } - - /** - * Read message from accepted server socket - * @return \Qonsillium\SocketError|\Qonsillium\SocketMessage - */ - public function read() - { - $socketResponse = new SocketMessage( - $this->readFromSocket($this->createdSocket) - ); - - if (!$socketResponse->getSocketResponse()) { - return new SocketError('Can\'t read message from client socket'); - } - - return $socketResponse; - } - - /** - * Write message to server accepted socket - * @param string $message - * @return int|\Qonsillium\SocketError - */ - public function write(string $message) - { - $writtenMessage = $this->writeToSocket($this->createdSocket, $message); - - if (!$writtenMessage) { - return new SocketError('Can\'t write to accepted client socket'); - } - - return $writtenMessage; - } - - /** - * Call Client destructor method when socket - * connection was broken - * @return void - */ - public function __destruct() - { - return $this->closeSocketConnection($this->createdSocket); - } -} diff --git a/src/ClientSocket.php b/src/ClientSocket.php new file mode 100644 index 0000000..bd11653 --- /dev/null +++ b/src/ClientSocket.php @@ -0,0 +1,26 @@ +createdSocket = $this->acceptConnectionOnSocket(); - - if (!$this->createdSocket) { - return new SocketError('Can\'t accepted connected socket'); - } - - return $this->createdSocket; - } - - /** - * Read message from accepted client socket - * @return \Qonsillium\SocketError|\Qonsillium\SocketMessage - */ - public function read() - { - $socketResponse = new SocketMessage( - $this->readFromSocket($this->createdSocket) - ); - - if (!$socketResponse->getSocketResponse()) { - return new SocketError('Can\'t read message from client socket'); - } - - return $socketResponse; - } - - /** - * Write message to client accepted socket - * @param string $message - * @return int|\Qonsillium\SocketError - */ - public function write(string $message) - { - $writtenMessage = $this->writeToSocket($this->createdSocket, $message); - - if (!$writtenMessage) { - return new SocketError('Can\'t write to accepted client socket'); - } - - return $writtenMessage; - } - - /** - * Call Server destructor method when socket - * connection was broken - * @return void - */ - public function __destruct() - { - return $this->closeSocketConnection($this->createdSocket); - } -} diff --git a/src/ServerSocket.php b/src/ServerSocket.php new file mode 100644 index 0000000..0b04a07 --- /dev/null +++ b/src/ServerSocket.php @@ -0,0 +1,36 @@ +helper->validateService($serviceName); } - /** - * Validate availablility of Server socket layer - * and return instance of this class - * @return \Qonsillium\Server - */ - public function serverSocketHandler(): Server - { - $service = $this->validateServiceExistence('server_socket'); - - if (!$service) { - return false; - } - - return new $service(); - } - - /** - * Validate availablility of Client socket layer - * and return instance of this class - * @return \Qonsillium\Client - */ - public function clientSocketHandler(): Client - { - $service = $this->validateServiceExistence('client_socket'); - - if (!$service) { - return false; - } - - return new $service(); - } - - /** - * Validate availablility of Socket layer - * and return instance of this class - * @return \Qonsillium\Socket - */ - public function socketLayerHandler(): Socket - { - $service = $this->validateServiceExistence('socket_layer'); - - if (!$service) { - return false; - } - - return new $service(); - } - - /** - * Validate availablility of SocketEndpoint layer - * and return instance of this class - * @return \Qonsillium\SocketEndpoint - */ - public function socketsManagerHandler(): SocketEndpoint - { - $service = $this->validateServiceExistence('socket_endpoint'); - - if (!$service) { - return false; - } - - return new $service(); - } - /** * Validate availablility of SocketCredentials layer * and return instance of this class diff --git a/src/ServicesHelper.php b/src/ServicesHelper.php index 40d0536..3619ee4 100644 --- a/src/ServicesHelper.php +++ b/src/ServicesHelper.php @@ -2,10 +2,6 @@ namespace Qonsillium; -use Qonsillium\Client; -use Qonsillium\Server; -use Qonsillium\Socket; -use Qonsillium\SocketEndpoint; use Qonsillium\Credential\SocketCredentials; use Qonsillium\Exceptions\ServiceNotFound; @@ -17,10 +13,6 @@ class ServicesHelper * @var array */ protected array $container = [ - 'client_socket' => Client::class, - 'server_socket' => Server::class, - 'socket_layer' => Socket::class, - 'socket_endpoint' => SocketEndpoint::class, 'socket_credentials' => SocketCredentials::class ]; diff --git a/src/Socket.php b/src/Socket.php deleted file mode 100755 index 4026462..0000000 --- a/src/Socket.php +++ /dev/null @@ -1,168 +0,0 @@ -host = $host; - $this->port = $port; - $this->socket = $this->create(); - } - - /** - * Creates and returns a socket resource, also - * referred to as an endpoint of communication - * @return resource - */ - public function create() - { - return socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - } - - /** - * Binds a name to a socket - * @return bool - */ - public function bind() - { - return socket_bind($this->socket, $this->host, $this->port); - } - - /** - * Listens for a connection on a socket - * @return bool - */ - public function listen() - { - return socket_listen($this->socket, 1); - } - - /** - * Accept a connection on a socket - * @return resource - */ - public function accept() - { - return socket_accept($this->socket); - } - - /** - * Bind, listen and return accepted socket - * connection - * @return resource - */ - public function acceptSocketConnection() - { - if (!$this->bind()) { - return false; - } - - if (!$this->listen()) { - return false; - } - - $acceptedSocket = $this->accept(); - - if (!$acceptedSocket) { - return false; - } - - return $acceptedSocket; - } - - /** - * Return resource of type Socket - * which was created right now. Can get - * access by connect method - * @return resource - */ - public function getConnectedSocket() - { - return $this->socket; - } - - /** - * Initiates a connection on a socket - * @return \Qonsillium\Socket - */ - public function connect() - { - socket_connect( - $this->socket, $this->host, $this->port - ); - - return $this->socket; - } - - /** - * Write to a socket specified messages - * @param string $message - * @return int - */ - public function write($socket, string $message) - { - return socket_write( - $socket, $message, strlen($message) - ); - } - - /** - * Reads a maximum of length bytes from a socket - * @param resource $socket - * @return string - */ - public function read($socket) - { - while(socket_recv($socket, $buffer, 2048, 0)) { - $this->content .= $buffer; - } - - return $this->content; - } - - /** - * Close specified socket connection - * @param resource $socket - * @return void - */ - public function close($socket) - { - return socket_close($socket); - } -} diff --git a/src/SocketAcceptor.php b/src/SocketAcceptor.php new file mode 100644 index 0000000..0610dfa --- /dev/null +++ b/src/SocketAcceptor.php @@ -0,0 +1,23 @@ +acceptedSocket = $socket; + } + + public function getAcceptedSocket() + { + return $this->acceptedSocket; + } + + public function make() + { + + } +} diff --git a/src/SocketBinder.php b/src/SocketBinder.php new file mode 100644 index 0000000..4ecb73d --- /dev/null +++ b/src/SocketBinder.php @@ -0,0 +1,33 @@ +host = $host; + $this->port = $port; + } + + public function setSocket($socket) + { + $this->socket = $socket; + } + + public function getSocket() + { + return $this->socket; + } + + public function make() + { + + } +} diff --git a/src/SocketCloser.php b/src/SocketCloser.php new file mode 100644 index 0000000..c014294 --- /dev/null +++ b/src/SocketCloser.php @@ -0,0 +1,23 @@ +socket = $socket; + } + + public function getSocket() + { + return $this->socket; + } + + public function make() + { + + } +} diff --git a/src/SocketConnector.php b/src/SocketConnector.php new file mode 100644 index 0000000..1f33bac --- /dev/null +++ b/src/SocketConnector.php @@ -0,0 +1,34 @@ +host = $host; + $this->port = $port; + } + + public function setCreatedSocket($socket) + { + $this->socket = $socket; + } + + public function getConnectedSocket() + { + return $this->socket; + } + + public function make() + { + + } + +} diff --git a/src/SocketCreator.php b/src/SocketCreator.php new file mode 100644 index 0000000..033236f --- /dev/null +++ b/src/SocketCreator.php @@ -0,0 +1,28 @@ +host = $host; + $this->port = $port; + } + + public function make() + { + + } + + public function getCreatedSocket() + { + return $this->createdSocket; + } +} diff --git a/src/SocketEndpoint.php b/src/SocketEndpoint.php deleted file mode 100755 index 7e00777..0000000 --- a/src/SocketEndpoint.php +++ /dev/null @@ -1,95 +0,0 @@ -credential = $credential; - } - - /** - * Return instance of SocketCredentials - * @return SocketCredentials - */ - public function getCredentials() - { - return $this->credential; - } - - /** - * Socket factory method which manipulate - * PHP socket API - * @return \Qonsillium\Socket - */ - protected function getSocket() - { - return new Socket( - $this->getCredentials()->getCredential('host'), - $this->getCredentials()->getCredential('port') - ); - } - - /** - * Bind, listen and accept connection on socket. - * Usually use when wanted to create server socket - * @return resource|bool - */ - protected function acceptConnectionOnSocket() - { - return $this->getSocket()->acceptSocketConnection(); - } - - /** - * Connect to created to socket. Usually use - * when wanted to create client socket - * @return resource|bool - */ - protected function connectToSocket() - { - return $this->getSocket()->connect(); - } - - /** - * Write content from current listening socket - * @param resource $socket - * @param string $message - * @return int - */ - protected function writeToSocket($socket, string $message) - { - return $this->getSocket()->write($socket, $message); - } - - /** - * Read content from current listening socket - * @param resource $socket - * @return string - */ - protected function readFromSocket($socket) - { - return $this->getSocket()->read($socket); - } - - /** - * Close socket connection which was created - * acceptSocketConnection() or connectToSocket() - * @param resource $socket - * @return void - */ - protected function closeSocketConnection($socket) - { - return $this->getSocket()->close($socket); - } -} diff --git a/src/SocketListener.php b/src/SocketListener.php new file mode 100644 index 0000000..84206da --- /dev/null +++ b/src/SocketListener.php @@ -0,0 +1,35 @@ +socket = $socket; + } + + public function getListenedSocket() + { + return $this->socket; + } + + public function setBacklog(int $backlog) + { + $this->backlog = $backlog; + } + + public function getBacklog() + { + return $this->backlog; + } + + public function make() + { + + } +} diff --git a/src/SocketReader.php b/src/SocketReader.php new file mode 100644 index 0000000..6ddb486 --- /dev/null +++ b/src/SocketReader.php @@ -0,0 +1,30 @@ +socket = $socket; + } + + public function getSocket() + { + return $this->socket; + } + + public function getMessage() + { + return $this->message; + } + + public function make() + { + + } +} diff --git a/src/SocketWriter.php b/src/SocketWriter.php new file mode 100644 index 0000000..005a0a6 --- /dev/null +++ b/src/SocketWriter.php @@ -0,0 +1,35 @@ +socket = $socket; + } + + public function getSocket() + { + return $this->socket; + } + + public function setMessage(string $message) + { + $this->message = $message; + } + + public function getMessage() + { + return $this->message; + } + + public function make() + { + + } +} diff --git a/tests/unit/SocketCredentialsTest.php b/tests/unit/SocketCredentialsTest.php deleted file mode 100755 index ec2c63d..0000000 --- a/tests/unit/SocketCredentialsTest.php +++ /dev/null @@ -1,24 +0,0 @@ -assertInstanceOf( - \WebSocket\Credential\ICredential::class, - $credential - ); - - $credential->setCredential('host', 'localhost'); - - $this->assertSame( - $credential->getCredential('host'), - 'localhost' - ); - } -} \ No newline at end of file diff --git a/tests/unit/SocketTest.php b/tests/unit/SocketTest.php deleted file mode 100755 index 65a3b85..0000000 --- a/tests/unit/SocketTest.php +++ /dev/null @@ -1,19 +0,0 @@ -setCredentials(new SocketCredentials()); - - $this->assertInstanceOf( - \WebSocket\Credential\SocketCredentials::class, - $socket->getCredentials() - ); - } -} From c7ea235f14c0b80f93ec2ae125723cf9f004fe17 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sat, 21 Nov 2020 20:56:02 +0300 Subject: [PATCH 04/41] Updated composer.json file and removed phpunit.xml --- composer.json | 10 ++++++++-- phpunit.xml | 7 ------- 2 files changed, 8 insertions(+), 9 deletions(-) delete mode 100755 phpunit.xml diff --git a/composer.json b/composer.json index fd49e93..4a5ad8e 100755 --- a/composer.json +++ b/composer.json @@ -1,12 +1,14 @@ { "name": "rubyqorn/socket", "description": "Socket layer over PHP socket api", + "keywords": ["socket", "stream", "datagram", "client", "server", "ipv6", "tcp", "udp", "icmp", "unix", "udg"], + "homepage": "https://github.com/rubyqorn/socket.git", "type": "library", "license": "MIT", "authors": [ { "name": "Anton Hideger", - "email": "rubyqorn@example.com" + "email": "antonhideger1337@gmail.com" } ], "autoload": { @@ -14,7 +16,11 @@ "Qonsillium\\": "src/" } }, - "require": { + "require-dev": { "phpunit/phpunit": "^9.3" + }, + "require": { + "php": ">=5.3", + "ext-sockets": "*" } } diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100755 index 3801934..0000000 --- a/phpunit.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - ./tests/unit/* - ./tests/unit/SocketTest.php - ./tests/unit/SocketCredentialsTest.php - - \ No newline at end of file From e0cd7dde1d01a2a26e93ec084527dedd756ac3ff Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sun, 22 Nov 2020 21:15:36 +0300 Subject: [PATCH 05/41] Implemented socket actions --- src/AbstractSocketAction.php | 13 ++++++ src/Actionable.php | 12 ----- src/ClientSocket.php | 5 +++ src/SocketAcceptor.php | 4 +- src/SocketBinder.php | 4 +- src/SocketCloser.php | 4 +- src/SocketConnector.php | 5 +-- src/SocketCreator.php | 15 ++----- src/SocketFacade.php | 86 ++++++++++++++++++++++++++++++++++++ src/SocketListener.php | 4 +- src/SocketReader.php | 8 +++- src/SocketWriter.php | 8 +++- 12 files changed, 129 insertions(+), 39 deletions(-) create mode 100644 src/AbstractSocketAction.php delete mode 100644 src/Actionable.php create mode 100644 src/SocketFacade.php diff --git a/src/AbstractSocketAction.php b/src/AbstractSocketAction.php new file mode 100644 index 0000000..a845980 --- /dev/null +++ b/src/AbstractSocketAction.php @@ -0,0 +1,13 @@ +make(); + } + + abstract public function make(); +} diff --git a/src/Actionable.php b/src/Actionable.php deleted file mode 100644 index d3a64a0..0000000 --- a/src/Actionable.php +++ /dev/null @@ -1,12 +0,0 @@ -getAcceptedSocket()); } } diff --git a/src/SocketBinder.php b/src/SocketBinder.php index 4ecb73d..825b474 100644 --- a/src/SocketBinder.php +++ b/src/SocketBinder.php @@ -2,7 +2,7 @@ namespace Qonsillium; -class SocketBinder implements Actionable +class SocketBinder extends AbstractSocketAction { private $socket; @@ -28,6 +28,6 @@ public function getSocket() public function make() { - + return socket_bind($this->getSocket(), $this->host, $this->port); } } diff --git a/src/SocketCloser.php b/src/SocketCloser.php index c014294..8341ee5 100644 --- a/src/SocketCloser.php +++ b/src/SocketCloser.php @@ -2,7 +2,7 @@ namespace Qonsillium; -class SocketCloser implements Actionable +class SocketCloser extends AbstractSocketAction { private $socket; @@ -18,6 +18,6 @@ public function getSocket() public function make() { - + return socket_close($this->getSocket()); } } diff --git a/src/SocketConnector.php b/src/SocketConnector.php index 1f33bac..5224d17 100644 --- a/src/SocketConnector.php +++ b/src/SocketConnector.php @@ -2,7 +2,7 @@ namespace Qonsillium; -class SocketConnector implements Actionable +class SocketConnector extends AbstractSocketAction { private $socket; @@ -28,7 +28,6 @@ public function getConnectedSocket() public function make() { - + return socket_connect($this->getConnectedSocket(), $this->host, $this->port); } - } diff --git a/src/SocketCreator.php b/src/SocketCreator.php index 033236f..be331e3 100644 --- a/src/SocketCreator.php +++ b/src/SocketCreator.php @@ -2,23 +2,14 @@ namespace Qonsillium; -class SocketCreator implements Actionable +class SocketCreator extends AbstractSocketAction { - protected string $host; - - protected int $port; - private $createdSocket; - public function __construct(string $host, int $port) - { - $this->host = $host; - $this->port = $port; - } - public function make() { - + $this->createdSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + return $this; } public function getCreatedSocket() diff --git a/src/SocketFacade.php b/src/SocketFacade.php new file mode 100644 index 0000000..eec00dc --- /dev/null +++ b/src/SocketFacade.php @@ -0,0 +1,86 @@ +factory = $factory; + } + + protected function createSocket() + { + $socket = $this->factory->getCreator()->make(); + $this->createdSocket = $socket->getCreatedSocket(); + return $this->createdSocket; + } + + protected function bindSocket($socket) + { + $binder = $this->factory->getBinder(); + $binder->setSocket($socket); + + return $binder->make(); + } + + protected function listenSocket($socket) + { + $listener = $this->factory->getListener(); + $listener->setCreatedSocket($socket); + $listener->setBacklog(1); + + return $listener->make(); + } + + protected function acceptSocket($socket) + { + $acceptor = $this->factory->getAcceptor(); + $acceptor->setAcceptSocket($socket); + return $acceptor->make(); + } + + protected function connectSocket($socket) + { + $connector = $this->factory->getConnector(); + $connector->setCreatedSocket($socket); + return $connector->make(); + } + + protected function readSocket($socket) + { + $reader = $this->factory->getReader(); + $reader->setSocket($socket); + return $reader->make()->getMessage(); + } + + protected function writeSocket($socket, string $message) + { + $writer = $this->factory->getWriter(); + $writer->setSocket($socket); + $writer->setMessage($message); + return $writer->make(); + } + + public function sendFromServer($message) + { + $this->createSocket(); + $this->bindSocket($this->createdSocket); + $this->listenSocket($this->createdSocket); + $accept = $this->acceptSocket($this->createdSocket); + echo $this->readSocket($accept) . "\n\n\n"; + $this->writeSocket($this->createdSocket, $message); + } + + public function sendFromClient($message) + { + $this->createSocket(); + $this->connectSocket($this->createdSocket); + echo $this->readSocket($this->createdSocket); + $this->writeSocket($this->createdSocket, $message); + } +} diff --git a/src/SocketListener.php b/src/SocketListener.php index 84206da..186965b 100644 --- a/src/SocketListener.php +++ b/src/SocketListener.php @@ -2,7 +2,7 @@ namespace Qonsillium; -class SocketListener implements Actionable +class SocketListener extends AbstractSocketAction { private $socket; @@ -30,6 +30,6 @@ public function getBacklog() public function make() { - + return socket_listen($this->getListenedSocket(), $this->getBacklog()); } } diff --git a/src/SocketReader.php b/src/SocketReader.php index 6ddb486..bb6b37f 100644 --- a/src/SocketReader.php +++ b/src/SocketReader.php @@ -2,7 +2,7 @@ namespace Qonsillium; -class SocketReader implements Actionable +class SocketReader extends AbstractSocketAction { private $socket; @@ -25,6 +25,10 @@ public function getMessage() public function make() { - + while(socket_recv($this->getSocket(), $buffer, 2048, 0)) { + $this->message .= $buffer; + } + + return $this; } } diff --git a/src/SocketWriter.php b/src/SocketWriter.php index 005a0a6..f5b1e1d 100644 --- a/src/SocketWriter.php +++ b/src/SocketWriter.php @@ -2,7 +2,7 @@ namespace Qonsillium; -class SocketWriter implements Actionable +class SocketWriter extends AbstractSocketAction { private $socket; @@ -30,6 +30,10 @@ public function getMessage() public function make() { - + return socket_write( + $this->getSocket(), + $this->getMessage(), + strlen($this->getMessage()) + ); } } From 6cf94a940dbbe3687a3e8c0cc64b90601392aac4 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Mon, 23 Nov 2020 16:37:03 +0300 Subject: [PATCH 06/41] Created socket exception handlers and implemented client and server socket by facade --- src/AbstractSocket.php | 12 +-- src/ClientSocket.php | 23 ++--- src/Exceptions/FailedAcceptSocket.php | 13 +++ src/Exceptions/FailedBindSocket.php | 13 +++ src/Exceptions/FailedCloseSocket.php | 13 +++ src/Exceptions/FailedConnectSocket.php | 13 +++ src/Exceptions/FailedCreateSocket.php | 13 +++ src/Exceptions/FailedListenSocket.php | 13 +++ src/Exceptions/FailedReadSocket.php | 13 +++ src/Exceptions/FailedWriteSocket.php | 13 +++ src/ServerSocket.php | 28 ++---- src/SocketFacade.php | 129 ++++++++++++++++++++++--- 12 files changed, 236 insertions(+), 60 deletions(-) create mode 100644 src/Exceptions/FailedAcceptSocket.php create mode 100644 src/Exceptions/FailedBindSocket.php create mode 100644 src/Exceptions/FailedCloseSocket.php create mode 100644 src/Exceptions/FailedConnectSocket.php create mode 100644 src/Exceptions/FailedCreateSocket.php create mode 100644 src/Exceptions/FailedListenSocket.php create mode 100644 src/Exceptions/FailedReadSocket.php create mode 100644 src/Exceptions/FailedWriteSocket.php diff --git a/src/AbstractSocket.php b/src/AbstractSocket.php index 25eb410..a750779 100644 --- a/src/AbstractSocket.php +++ b/src/AbstractSocket.php @@ -6,18 +6,14 @@ abstract class AbstractSocket { - protected ?SocketCredentials $credentials = null; + protected ?SocketFacade $facade = null; - public function __construct(SocketCredentials $credentials) + public function __construct(SocketFacade $facade) { - $this->credentials = $credentials; + $this->facade = $facade; } - abstract public function create(); - - abstract public function read(); - - abstract public function write(); + abstract public function send(string $message); abstract public function close(); diff --git a/src/ClientSocket.php b/src/ClientSocket.php index 838bb91..8e77e4f 100644 --- a/src/ClientSocket.php +++ b/src/ClientSocket.php @@ -4,28 +4,19 @@ class ClientSocket extends AbstractSocket { - public function create() + public function send(string $message) { - - } + $sendedMessage = $this->facade->sendFromClient($message); - public function connect() - { - - } + if (!$sendedMessage) { + return false; + } - public function read() - { - - } - - public function write() - { - + return $sendedMessage->getMessage(); } public function close() { - + return $this->facade->closeSocket(); } } diff --git a/src/Exceptions/FailedAcceptSocket.php b/src/Exceptions/FailedAcceptSocket.php new file mode 100644 index 0000000..b598c97 --- /dev/null +++ b/src/Exceptions/FailedAcceptSocket.php @@ -0,0 +1,13 @@ +facade->sendFromServer($message); - } + if (!$sendedMessage) { + return false; + } - public function listen() - { - - } - - public function read() - { - - } - - public function write() - { - + return $sendedMessage->getMessage(); } public function close() { - + return $this->facade->closeSocket(); } } diff --git a/src/SocketFacade.php b/src/SocketFacade.php index eec00dc..2c6a4eb 100644 --- a/src/SocketFacade.php +++ b/src/SocketFacade.php @@ -2,6 +2,17 @@ namespace Qonsillium; +use Qonsillium\Exceptions\ { + FailedAcceptSocket, + FailedConnectSocket, + FailedListenSocket, + FailedCreateSocket, + FailedWriteSocket, + FailedCloseSocket, + FailedBindSocket, + FailedReadSocket +}; + class SocketFacade { private ?ActionFactory $factory = null; @@ -16,6 +27,11 @@ public function __construct(ActionFactory $factory) protected function createSocket() { $socket = $this->factory->getCreator()->make(); + + if(!$socket) { + return false; + } + $this->createdSocket = $socket->getCreatedSocket(); return $this->createdSocket; } @@ -24,8 +40,13 @@ protected function bindSocket($socket) { $binder = $this->factory->getBinder(); $binder->setSocket($socket); + $bindAction = $binder->make(); + + if (!$bindAction) { + return false; + } - return $binder->make(); + return $bindAction; } protected function listenSocket($socket) @@ -33,29 +54,52 @@ protected function listenSocket($socket) $listener = $this->factory->getListener(); $listener->setCreatedSocket($socket); $listener->setBacklog(1); + $listenAction = $listener->make(); - return $listener->make(); + if (!$listenAction) { + return false; + } + + return $listenAction; } protected function acceptSocket($socket) { $acceptor = $this->factory->getAcceptor(); $acceptor->setAcceptSocket($socket); - return $acceptor->make(); + $acceptAction = $acceptor->make(); + + if (!$acceptAction) { + return false; + } + + return $acceptAction; } protected function connectSocket($socket) { $connector = $this->factory->getConnector(); $connector->setCreatedSocket($socket); - return $connector->make(); + $connectionAction = $connector->make(); + + if (!$connectionAction) { + return false; + } + + return $connectionAction; } protected function readSocket($socket) { $reader = $this->factory->getReader(); $reader->setSocket($socket); - return $reader->make()->getMessage(); + $readAction = $reader->make(); + + if (!$readAction) { + return false; + } + + return $readAction; } protected function writeSocket($socket, string $message) @@ -63,24 +107,79 @@ protected function writeSocket($socket, string $message) $writer = $this->factory->getWriter(); $writer->setSocket($socket); $writer->setMessage($message); - return $writer->make(); + $writeAction = $writer->make(); + + if (!$writeAction) { + return false; + } + + return $writeAction; + } + + public function closeSocket() + { + if (!$this->createdSocket) { + throw new FailedCloseSocket('Failed close, because doesn\'t exists'); + } + + $closer = $this->factory->getCloser(); + $closer->setSocket($this->createdSocket); + return $closer->make(); } public function sendFromServer($message) { - $this->createSocket(); - $this->bindSocket($this->createdSocket); - $this->listenSocket($this->createdSocket); + if (!$this->createSocket()) { + throw new FailedCreateSocket('Failed to create socket'); + } + + if (!$this->bindSocket($this->createdSocket)) { + throw new FailedBindSocket('Failed to bind socket'); + } + + if (!$this->listenSocket($this->createdSocket)) { + throw new FailedListenSocket('Failed to listen socket'); + } + $accept = $this->acceptSocket($this->createdSocket); - echo $this->readSocket($accept) . "\n\n\n"; - $this->writeSocket($this->createdSocket, $message); + + if (!$accept) { + throw new FailedAcceptSocket('Failed accept socket'); + } + + if (!$this->writeSocket($accept, $message)) { + throw new FailedWriteSocket('Failed to write socket'); + } + + $readedSocket = $this->readSocket($accept); + + if (!$readedSocket) { + throw new FailedAcceptSocket('Failed to write socket'); + } + + return $readedSocket; } public function sendFromClient($message) { - $this->createSocket(); - $this->connectSocket($this->createdSocket); - echo $this->readSocket($this->createdSocket); - $this->writeSocket($this->createdSocket, $message); + if (!$this->createSocket()) { + throw new FailedCreateSocket('Failed to create socket'); + } + + if (!$this->connectSocket($this->createdSocket)) { + throw new FailedConnectSocket('Failed to connect socket'); + } + + if (!$this->writeSocket($this->createdSocket, $message)) { + throw new FailedWriteSocket('Failed to write socket'); + } + + $readedSocket = $this->readSocket($this->createdSocket); + + if (!$readedSocket) { + throw new FailedReadSocket('Failed to read socket'); + } + + return $readedSocket; } } From 1e9649ce935a08dd481bec7f632cc4cecf52675d Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Mon, 23 Nov 2020 17:24:46 +0300 Subject: [PATCH 07/41] Commented socket handler methods --- src/AbstractSocket.php | 26 ++++++++++- src/AbstractSocketAction.php | 9 ++++ src/ActionFactory.php | 59 +++++++++++++++++++++---- src/ClientSocket.php | 11 +++++ src/ServerSocket.php | 11 +++++ src/SocketAcceptor.php | 15 +++++++ src/SocketBinder.php | 33 ++++++++++++++ src/SocketCloser.php | 15 +++++++ src/SocketConnector.php | 33 ++++++++++++++ src/SocketCreator.php | 14 ++++++ src/SocketFacade.php | 83 ++++++++++++++++++++++++++++++++++-- src/SocketListener.php | 26 +++++++++++ src/SocketReader.php | 22 ++++++++++ src/SocketWriter.php | 28 ++++++++++++ 14 files changed, 372 insertions(+), 13 deletions(-) diff --git a/src/AbstractSocket.php b/src/AbstractSocket.php index a750779..06d30a0 100644 --- a/src/AbstractSocket.php +++ b/src/AbstractSocket.php @@ -2,21 +2,43 @@ namespace Qonsillium; -use Qonsillium\Credential\SocketCredentials; - abstract class AbstractSocket { + /** + * @var \Qonsillium\SocketFacade|null + */ protected ?SocketFacade $facade = null; + /** + * Initiate AbstractSocket constructor method + * and set SocketFacade property + * @param \Qonsillium\SocketFacade $facade + * @return void + */ public function __construct(SocketFacade $facade) { $this->facade = $facade; } + /** + * Send message on client or server socket + * @param string $message + * @return string|bool + */ abstract public function send(string $message); + /** + * Close created socket connection + * @throws \Qonsillium\Exceptions\FailedCloseSocket + * @return void + */ abstract public function close(); + /** + * Destruct AbstractSocket class and + * close socket connection + * @return void + */ public function __destruct() { $this->close(); diff --git a/src/AbstractSocketAction.php b/src/AbstractSocketAction.php index a845980..f02380e 100644 --- a/src/AbstractSocketAction.php +++ b/src/AbstractSocketAction.php @@ -4,10 +4,19 @@ abstract class AbstractSocketAction { + /** + * Make socket action when need + * to make class like function + * @return mixed + */ public function __invoke() { return $this->make(); } + /** + * Make socket action + * @return mixed + */ abstract public function make(); } diff --git a/src/ActionFactory.php b/src/ActionFactory.php index 01e1a67..360ce0d 100644 --- a/src/ActionFactory.php +++ b/src/ActionFactory.php @@ -6,59 +6,102 @@ class ActionFactory { + /** + * @var \Qonsillium\Credential\SocketCredentials|null; + */ private ?SocketCredentials $credentials = null; + /** + * Initiate ActionFactory constructor method and + * set SocketCredetials property + * @param \Qonsillium\Credential\SocketCredentials $credentials + * @return void + */ public function __construct(SocketCredentials $credentials) { $this->credentials = $credentials; } + /** + * Return setted host name from + * credentials handler + * @return string + */ private function getHost() { return $this->credentials->getCredential('host'); } + /** + * Return setted socket port from + * credentials handler + * @return string + */ private function getPort() { return $this->credentials->getCredential('port'); } - public function getCreator() + /** + * @return \Qonsillium\SocketCreator + */ + public function getCreator(): SocketCreator { return new SocketCreator($this->getHost(), $this->getPort()); } - public function getAcceptor() + /** + * @return \Qonsillium\SocketAcceptor + */ + public function getAcceptor(): SocketAcceptor { return new SocketAcceptor(); } - public function getConnector() + /** + * @return \Qonsillium\SocketConnector + */ + public function getConnector(): SocketConnector { return new SocketConnector($this->getHost(), $this->getPort()); } - public function getListener() + /** + * @return \Qonsillium\SocketListener + */ + public function getListener(): SocketListener { return new SocketListener(); } - public function getBinder() + /** + * @return \Qonsillium\SocketBinder + */ + public function getBinder(): SocketBinder { return new SocketBinder($this->getHost(), $this->getPort()); } - public function getReader() + /** + * @return \Qonsillium\SocketReader + */ + public function getReader(): SocketReader { return new SocketReader(); } - public function getWriter() + /** + * @return \Qonsillium\SocketWriter + */ + public function getWriter(): SocketWriter { return new SocketWriter(); } - public function getCloser() + /** + * @return \Qonsillium\SocketCloser + */ + public function getCloser(): SocketCloser { return new SocketCloser(); } diff --git a/src/ClientSocket.php b/src/ClientSocket.php index 8e77e4f..63b08ce 100644 --- a/src/ClientSocket.php +++ b/src/ClientSocket.php @@ -4,6 +4,12 @@ class ClientSocket extends AbstractSocket { + /** + * Send specific message on server socket + * and get response from it + * @param string $message + * @return bool|string + */ public function send(string $message) { $sendedMessage = $this->facade->sendFromClient($message); @@ -15,6 +21,11 @@ public function send(string $message) return $sendedMessage->getMessage(); } + /** + * Close socket created socket connection + * @throws \Qonsillium\Exceptions\FailedCloseSocket + * @return void + */ public function close() { return $this->facade->closeSocket(); diff --git a/src/ServerSocket.php b/src/ServerSocket.php index a3f4359..5b68657 100644 --- a/src/ServerSocket.php +++ b/src/ServerSocket.php @@ -4,6 +4,12 @@ class ServerSocket extends AbstractSocket { + /** + * Send specific message on client socket + * and get response from it + * @param string $message + * @return bool|string + */ public function send(string $message) { $sendedMessage = $this->facade->sendFromServer($message); @@ -15,6 +21,11 @@ public function send(string $message) return $sendedMessage->getMessage(); } + /** + * Close socket created socket connection + * @throws \Qonsillium\Exceptions\FailedCloseSocket + * @return void + */ public function close() { return $this->facade->closeSocket(); diff --git a/src/SocketAcceptor.php b/src/SocketAcceptor.php index 91ed4b7..67fc9ea 100644 --- a/src/SocketAcceptor.php +++ b/src/SocketAcceptor.php @@ -4,18 +4,33 @@ class SocketAcceptor extends AbstractSocketAction { + /** + * Accepted socket connection + * @var resource + */ private $acceptedSocket; + /** + * @param resource $socket + * @return void + */ public function setAcceptSocket($socket) { $this->acceptedSocket = $socket; } + /** + * @return resource + */ public function getAcceptedSocket() { return $this->acceptedSocket; } + /** + * Accept socket connection + * @return resource + */ public function make() { return socket_accept($this->getAcceptedSocket()); diff --git a/src/SocketBinder.php b/src/SocketBinder.php index 825b474..dea7eb7 100644 --- a/src/SocketBinder.php +++ b/src/SocketBinder.php @@ -4,28 +4,61 @@ class SocketBinder extends AbstractSocketAction { + /** + * Created socket connection + * @var resource + */ private $socket; + /** + * Host name which will be + * binded + * @var string + */ private string $host; + /** + * Socket port which will be + * binded + * @var int + */ private int $port; + /** + * Initiate SocketBinder onstructo method and + * set socket host and port values + * @param string $host + * @param int $port + * @return void + */ public function __construct(string $host, int $port) { $this->host = $host; $this->port = $port; } + /** + * @param resource $socket + * @return void + */ public function setSocket($socket) { $this->socket = $socket; } + /** + * @return resource + */ public function getSocket() { return $this->socket; } + /** + * Bind host and port values with + * creatd socket + * @return bool + */ public function make() { return socket_bind($this->getSocket(), $this->host, $this->port); diff --git a/src/SocketCloser.php b/src/SocketCloser.php index 8341ee5..698def9 100644 --- a/src/SocketCloser.php +++ b/src/SocketCloser.php @@ -4,18 +4,33 @@ class SocketCloser extends AbstractSocketAction { + /** + * Accepted or created socket + * @var resource + */ private $socket; + /** + * @param resource $socket + * @return void + */ public function setSocket($socket) { $this->socket = $socket; } + /** + * @return resource + */ public function getSocket() { return $this->socket; } + /** + * Close created or accepted socket connection + * @return void + */ public function make() { return socket_close($this->getSocket()); diff --git a/src/SocketConnector.php b/src/SocketConnector.php index 5224d17..ec00881 100644 --- a/src/SocketConnector.php +++ b/src/SocketConnector.php @@ -4,28 +4,61 @@ class SocketConnector extends AbstractSocketAction { + /** + * Created socket connection + * @var resource + */ private $socket; + /** + * Host name where will + * be connected + * @var string + */ private string $host; + /** + * Socket port where + * will be connected + * @var int + */ private int $port; + /** + * Initiate SocketConnector constructor method and + * set socket host and port values + * @param string $host + * @param int $port + * @return void + */ public function __construct(string $host, int $port) { $this->host = $host; $this->port = $port; } + /** + * @param resource $socket + * @return void + */ public function setCreatedSocket($socket) { $this->socket = $socket; } + /** + * @return resource + */ public function getConnectedSocket() { return $this->socket; } + /** + * Connect to created socket and specific host with + * port + * @return bool + */ public function make() { return socket_connect($this->getConnectedSocket(), $this->host, $this->port); diff --git a/src/SocketCreator.php b/src/SocketCreator.php index be331e3..83ec22f 100644 --- a/src/SocketCreator.php +++ b/src/SocketCreator.php @@ -4,14 +4,28 @@ class SocketCreator extends AbstractSocketAction { + /** + * Socket which was created by + * socket_create + * @var resource + */ private $createdSocket; + /** + * Create socket. Lately have to refactor + * hard coded socket_create parameters + * @return \Qonsillium\SocketCreator + */ public function make() { + // TODO: Resolve hard coded parameters $this->createdSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); return $this; } + /** + * @return resource + */ public function getCreatedSocket() { return $this->createdSocket; diff --git a/src/SocketFacade.php b/src/SocketFacade.php index 2c6a4eb..e5b57ca 100644 --- a/src/SocketFacade.php +++ b/src/SocketFacade.php @@ -15,15 +15,33 @@ class SocketFacade { + /** + * @var \Qonsillium\ActionFactory|null + */ private ?ActionFactory $factory = null; + /** + * Created socket by socket_create + * @var resource + */ private $createdSocket; + /** + * Initiate SocketFacade constructor method and + * set socket actions factory + * @param \Qonsillium\ActionFactory $factory + * @return void + */ public function __construct(ActionFactory $factory) { $this->factory = $factory; } + /** + * Create socket. While can create only + * TCP socket + * @return bool|resource + */ protected function createSocket() { $socket = $this->factory->getCreator()->make(); @@ -36,6 +54,11 @@ protected function createSocket() return $this->createdSocket; } + /** + * Bind socket host and port + * @param resource $socket + * @return bool + */ protected function bindSocket($socket) { $binder = $this->factory->getBinder(); @@ -49,6 +72,11 @@ protected function bindSocket($socket) return $bindAction; } + /** + * Listen socket connections + * @param resource $socket + * @return bool + */ protected function listenSocket($socket) { $listener = $this->factory->getListener(); @@ -63,6 +91,11 @@ protected function listenSocket($socket) return $listenAction; } + /** + * Accept socket connections + * @param resource $socket + * @return bool + */ protected function acceptSocket($socket) { $acceptor = $this->factory->getAcceptor(); @@ -76,6 +109,11 @@ protected function acceptSocket($socket) return $acceptAction; } + /** + * Connect to created socket + * @param resource $socket + * @return bool + */ protected function connectSocket($socket) { $connector = $this->factory->getConnector(); @@ -89,6 +127,11 @@ protected function connectSocket($socket) return $connectionAction; } + /** + * Read messages from client or server sockets + * @param resource $socket + * @return bool|\Qonsillium\SocketReader + */ protected function readSocket($socket) { $reader = $this->factory->getReader(); @@ -102,6 +145,12 @@ protected function readSocket($socket) return $readAction; } + /** + * Write messages on client or server sockets + * @param resource $socket + * @param string $message + * @return bool|int + */ protected function writeSocket($socket, string $message) { $writer = $this->factory->getWriter(); @@ -116,6 +165,11 @@ protected function writeSocket($socket, string $message) return $writeAction; } + /** + * Close accepted or created socket connections + * @throws \Qonsillium\Exceptions\FailedCloseSocket + * @return void + */ public function closeSocket() { if (!$this->createdSocket) { @@ -127,7 +181,20 @@ public function closeSocket() return $closer->make(); } - public function sendFromServer($message) + /** + * This method can be used only with ServerSocket. + * Here we create, bind, listen, accept, read and + * write socket + * @param string $message + * @throws \Qonsillium\Exceptions\FailedCreateSocket + * @throws \Qonsillium\Exceptions\FailedBindSocket + * @throws \Qonsillium\Exceptions\FailedListenSocket + * @throws \Qonsillium\Exceptions\FailedAcceptSocket + * @throws \Qonsillium\Exceptions\FailedWriteSocket + * @throws \Qonsillium\Exceptions\FailedReadSocket + * @return \Qonsillium\SocketReader + */ + public function sendFromServer(string $message) { if (!$this->createSocket()) { throw new FailedCreateSocket('Failed to create socket'); @@ -154,13 +221,23 @@ public function sendFromServer($message) $readedSocket = $this->readSocket($accept); if (!$readedSocket) { - throw new FailedAcceptSocket('Failed to write socket'); + throw new FailedReadSocket('Failed to write socket'); } return $readedSocket; } - public function sendFromClient($message) + /** + * This method can be used only with ClientSocket. + * Here we create, read and write socket + * @param string $message + * @throws \Qonsillium\Exceptions\FailedCreateSocket + * @throws \Qonsillium\Exceptions\FailedConnectSocket + * @throws \Qonsillium\Exceptions\FailedWriteSocket + * @throws \Qonsillium\Exceptions\FailedReadSocket + * @return \Qonsillium\SocketReader + */ + public function sendFromClient(string $message) { if (!$this->createSocket()) { throw new FailedCreateSocket('Failed to create socket'); diff --git a/src/SocketListener.php b/src/SocketListener.php index 186965b..9d3be3c 100644 --- a/src/SocketListener.php +++ b/src/SocketListener.php @@ -4,30 +4,56 @@ class SocketListener extends AbstractSocketAction { + /** + * Created socket + * @var resource + */ private $socket; + /** + * Maximum incoming connections + * @var int + */ private int $backlog; + /** + * @param resource $socket + * @return void + */ public function setCreatedSocket($socket) { $this->socket = $socket; } + /** + * @return resource + */ public function getListenedSocket() { return $this->socket; } + /** + * @param int $backlog + * @return void + */ public function setBacklog(int $backlog) { $this->backlog = $backlog; } + /** + * @return int + */ public function getBacklog() { return $this->backlog; } + /** + * Listen socket connections + * @return book + */ public function make() { return socket_listen($this->getListenedSocket(), $this->getBacklog()); diff --git a/src/SocketReader.php b/src/SocketReader.php index bb6b37f..71eb461 100644 --- a/src/SocketReader.php +++ b/src/SocketReader.php @@ -4,25 +4,47 @@ class SocketReader extends AbstractSocketAction { + /** + * Created or accepted socket + * @var resource + */ private $socket; + /** + * Readed message from socket + * @var string + */ private string $message = ''; + /** + * @param resource $socket + * @return void + */ public function setSocket($socket) { $this->socket = $socket; } + /** + * @return resource + */ public function getSocket() { return $this->socket; } + /** + * @return string + */ public function getMessage() { return $this->message; } + /** + * Read messages from createdd or accepted sockets + * @return \Qonsillium\SocketReader + */ public function make() { while(socket_recv($this->getSocket(), $buffer, 2048, 0)) { diff --git a/src/SocketWriter.php b/src/SocketWriter.php index f5b1e1d..d56e0ba 100644 --- a/src/SocketWriter.php +++ b/src/SocketWriter.php @@ -4,30 +4,58 @@ class SocketWriter extends AbstractSocketAction { + /** + * Created or accepted socket + * @var resource + */ private $socket; + /** + * Message which will be sent + * on server or client socket + * @var string + */ private string $message; + /** + * @param resource $socket + * @return void + */ public function setSocket($socket) { $this->socket = $socket; } + /** + * @return resource + */ public function getSocket() { return $this->socket; } + /** + * @param string $message + * @return void + */ public function setMessage(string $message) { $this->message = $message; } + /** + * @return string + */ public function getMessage() { return $this->message; } + /** + * Send specific message on created + * or accepted socket + * @return int|bool + */ public function make() { return socket_write( From 819990fed8dc10a2bd9bc357d20f0f6a9fff501e Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Mon, 23 Nov 2020 17:28:47 +0300 Subject: [PATCH 08/41] Renamed package name in composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4a5ad8e..ad6b2c6 100755 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "rubyqorn/socket", + "name": "qonsillium/socket", "description": "Socket layer over PHP socket api", "keywords": ["socket", "stream", "datagram", "client", "server", "ipv6", "tcp", "udp", "icmp", "unix", "udg"], "homepage": "https://github.com/rubyqorn/socket.git", From 3bd3a213717f9308226d0b7799e47ac3b56d930b Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Mon, 23 Nov 2020 21:32:19 +0300 Subject: [PATCH 09/41] Created yaml(yml) and json config file parsers --- src/Parsers/ConfigParser.php | 32 ++++++++++++++++ src/Parsers/ConfigParsersFactory.php | 57 ++++++++++++++++++++++++++++ src/Parsers/JSONConfigParser.php | 28 ++++++++++++++ src/Parsers/NullConfigFile.php | 11 ++++++ src/Parsers/YAMLConfigParser.php | 25 ++++++++++++ 5 files changed, 153 insertions(+) create mode 100644 src/Parsers/ConfigParser.php create mode 100644 src/Parsers/ConfigParsersFactory.php create mode 100644 src/Parsers/JSONConfigParser.php create mode 100644 src/Parsers/NullConfigFile.php create mode 100644 src/Parsers/YAMLConfigParser.php diff --git a/src/Parsers/ConfigParser.php b/src/Parsers/ConfigParser.php new file mode 100644 index 0000000..3c50a14 --- /dev/null +++ b/src/Parsers/ConfigParser.php @@ -0,0 +1,32 @@ +file = $file; + } + + /** + * Parse configuraton files using PHP + * yaml and json extensions + * @return array + */ + abstract public function parse(): array; +} diff --git a/src/Parsers/ConfigParsersFactory.php b/src/Parsers/ConfigParsersFactory.php new file mode 100644 index 0000000..e7c84bd --- /dev/null +++ b/src/Parsers/ConfigParsersFactory.php @@ -0,0 +1,57 @@ +configFile = $configFile; + $this->configFileExtension = pathinfo($this->configFile)['extension']; + $this->nullObj = new NullConfigFile($this->configFile); + } + + /** + * Factory method which return config file + * handler by its extension. Can be ONLY + * yaml(yml) or json + * @return \Qonsillium\Parsers\ConfigParser + */ + public function getParser(): ConfigParser + { + if ($this->configFileExtension === 'yaml' || $this->configFileExtension === 'yml') { + return new YAMLConfigParser($this->configFile); + } elseif ($this->configFileExtension === 'json') { + return new JSONConfigParser($this->configFile); + } else { + return $this->nullObj; + } + } +} diff --git a/src/Parsers/JSONConfigParser.php b/src/Parsers/JSONConfigParser.php new file mode 100644 index 0000000..4f73dfe --- /dev/null +++ b/src/Parsers/JSONConfigParser.php @@ -0,0 +1,28 @@ +file), true); + } +} diff --git a/src/Parsers/NullConfigFile.php b/src/Parsers/NullConfigFile.php new file mode 100644 index 0000000..4531fc1 --- /dev/null +++ b/src/Parsers/NullConfigFile.php @@ -0,0 +1,11 @@ +file); + } +} From b091ea064c862e41c2dab77b8c68da0dd05d78eb Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Mon, 23 Nov 2020 22:02:08 +0300 Subject: [PATCH 10/41] Implemeted bootstap class which return configured client and server sockets --- src/Bootstrapper.php | 130 ++++++++++++++++++++++ src/Credential/SocketCredentials.php | 13 --- src/Exceptions/ConfigFileDoesntExists.php | 13 +++ src/QonsilliumSocket.php | 48 ++++++++ src/ServiceContainer.php | 57 ++-------- src/ServiceProvider.php | 32 ++++++ src/ServicesHelper.php | 73 ------------ 7 files changed, 235 insertions(+), 131 deletions(-) create mode 100644 src/Bootstrapper.php create mode 100644 src/Exceptions/ConfigFileDoesntExists.php create mode 100644 src/QonsilliumSocket.php create mode 100644 src/ServiceProvider.php delete mode 100644 src/ServicesHelper.php diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php new file mode 100644 index 0000000..e6c97a2 --- /dev/null +++ b/src/Bootstrapper.php @@ -0,0 +1,130 @@ +configFile = $configFile; + $this->services = new ServiceProvider(); + $this->settings = $this->parseConfigFile(); + $this->credentials = $this->setCredentials(); + } + + /** + * Parse json or yaml(yml) file using using + * factory + * @return array + */ + protected function parseConfigFile(): array + { + return $this->getConfigParserFactory()->getParser()->parse(); + } + + /** + * Set socket domain, type, protocol, host and port + * in SocketCredentials instance + * @return \Qonsillium\Credential\SocketCredentials + */ + protected function setCredentials() + { + $credentials = $this->getCredentialsHandler(); + $credentials->setCredential('domain', $this->settings['settings']['domain']); + $credentials->setCredential('type', $this->settings['settings']['type']); + $credentials->setCredential('protocol', $this->settings['settings']['protocol']); + $credentials->setCredential('host', $this->settings['settings']['host']); + $credentials->setCredential('port', $this->settings['settings']['port']); + return $credentials; + } + + /** + * Returns ConfigParserFactory factory class + * @return \Qonsillium\Parsers\ConfigParsersFactory + */ + public function getConfigParserFactory(): ConfigParsersFactory + { + $configParserFactory = $this->services->getFromList('config_parser_factory'); + return new $configParserFactory($this->configFile); + } + + /** + * Returns SocketCredentials class + * @return \Qonsillium\Credential\SocketCredentials + */ + public function getCredentialsHandler(): SocketCredentials + { + $socketCredentials = $this->services->getFromList('socket_credentials'); + return new $socketCredentials; + } + + /** + * Returns ActionFactory factory class + * @return \Qonsillium\ActionFactory + */ + public function getSocketActionFactory(): ActionFactory + { + $actionFactory = $this->services->getFromList('socket_actions_factory'); + return new $actionFactory($this->credentials); + } + + /** + * Returns SocketFacade class + * @return \Qonsillium\SocketFacade + */ + public function getSocketFacade(): SocketFacade + { + $socketFacade = $this->services->getFromList('socket_facade'); + return new $socketFacade($this->getSocketActionFactory()); + } + + /** + * Return ClientSocket class + * @return \Qonsillium\ClientSocket + */ + public function getClientSocket(): ClientSocket + { + $clientSocket = $this->services->getFromList('client_socket'); + return new $clientSocket($this->getSocketFacade()); + } + + /** + * Return ServerSocket class + * @return \Qonsillium\ServerSocket + */ + public function getServerSocket(): ServerSocket + { + $serverSocket = $this->services->getFromList('server_socket'); + return new $serverSocket($this->getSocketFacade()); + } +} diff --git a/src/Credential/SocketCredentials.php b/src/Credential/SocketCredentials.php index ad489a8..78306eb 100755 --- a/src/Credential/SocketCredentials.php +++ b/src/Credential/SocketCredentials.php @@ -4,19 +4,6 @@ class SocketCredentials implements ICredential { - /** - * Host name where will - * be connected - * @var string - */ - private string $host; - - /** - * Port for host - * @var string - */ - private string $port; - /** * Set credentials for socket connection * @param string $name diff --git a/src/Exceptions/ConfigFileDoesntExists.php b/src/Exceptions/ConfigFileDoesntExists.php new file mode 100644 index 0000000..fb90560 --- /dev/null +++ b/src/Exceptions/ConfigFileDoesntExists.php @@ -0,0 +1,13 @@ +bootstrapper = new Bootstrapper($configFile); + } + + /** + * Return ClientSocket handler + * @return \Qonsillium\ClientSocket + */ + public function getClientSocket(): ClientSocket + { + return $this->bootstrapper->getClientSocket(); + } + + /** + * Return ServerSocket handler + * @return \Qonsillium\ServerSocket + */ + public function getServerSocket(): ServerSocket + { + return $this->bootstrapper->getServerSocket(); + } +} diff --git a/src/ServiceContainer.php b/src/ServiceContainer.php index 7804b74..d833cd9 100644 --- a/src/ServiceContainer.php +++ b/src/ServiceContainer.php @@ -3,53 +3,20 @@ namespace Qonsillium; use Qonsillium\Credential\SocketCredentials; +use Qonsillium\Parsers\ConfigParsersFactory; -class ServiceContainer +abstract class ServiceContainer { /** - * @var \Qonsillium\ServicesHelper + * Socket services container + * @var array */ - private ?ServicesHelper $helper; - - /** - * Initialize ServiceContainer constructor - * method - * @return void - */ - public function __construct() - { - $this->helper = new ServicesHelper(); - } - - /** - * Validate service name existence in container - * @param string $serviceName - * @return string - * @throws \Qonsillium\Exceptions\ServiceNotFound - */ - private function validateServiceExistence(string $serviceName) - { - return $this->helper->validateService($serviceName); - } - - /** - * Validate availablility of SocketCredentials layer - * and return instance of this class - * @return \Qonsillium\SocketCredentials - */ - public function socketCredentialsHandler(): SocketCredentials - { - $service = $this->validateServiceExistence('socket_credential'); - - if (!$service) { - return false; - } - - return new $service(); - } - - public function bootstrap() - { - // - } + protected array $container = [ + 'socket_credentials' => SocketCredentials::class, + 'client_socket' => ClientSocket::class, + 'server_socket' => ServerSocket::class, + 'config_parser_factory' => ConfigParsersFactory::class, + 'socket_actions_factory' => ActionFactory::class, + 'socket_facade' => SocketFacade::class, + ]; } diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php new file mode 100644 index 0000000..8ea1415 --- /dev/null +++ b/src/ServiceProvider.php @@ -0,0 +1,32 @@ +container[$descriptiveName] = $className; + } + + /** + * Return service from services list by unique + * key + * @param string $serviceName + * @return mixed + */ + public function getFromList(string $serviceName) + { + return $this->container[$serviceName]; + } +} diff --git a/src/ServicesHelper.php b/src/ServicesHelper.php deleted file mode 100644 index 3619ee4..0000000 --- a/src/ServicesHelper.php +++ /dev/null @@ -1,73 +0,0 @@ - SocketCredentials::class - ]; - - /** - * Register new service in service container. Must set - * new service using little descriptive name, but if - * you SET service name which already exists this will - * delete previous service, and class name which respond for - * this service - * @param string $descriptiveName - * @param string $className - * @return void - */ - public function addToList(string $descriptiveName, string $className) - { - $this->container[$descriptiveName] = $className; - } - - /** - * Return service from services list by unique - * key - * @param string $serviceName - * @return mixed - */ - public function getFromList(string $serviceName) - { - return $this->container[$serviceName]; - } - - /** - * Validate service existence and return namespace - * of this service in string representation or throws - * exception - * @param string $serviceName - * @return string - * @throws \Qonsillium\Exceptions\ServiceNotFound - */ - public function validateService(string $serviceName) - { - $service = "\\{$this->getFromList($serviceName)}"; - - if (!class_exists($service)) { - throw new ServiceNotFound("Service with {$serviceName} was not found"); - } - - return $service; - } - - /** - * Remove service from services list by unique key - * @param string $serviceName - * @return void - */ - public function removeFromList(string $serviceName) - { - unset($this->container[$serviceName]); - } -} From 70d82fc2a8aca514c94b219695008a242307a0b7 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 24 Nov 2020 22:08:29 +0300 Subject: [PATCH 11/41] Resolved hard coded socket creator parameters (domain, type, protocol) --- src/ActionFactory.php | 29 ++++++++++++++++++++++++++++- src/SocketCreator.php | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/ActionFactory.php b/src/ActionFactory.php index 360ce0d..eb9b48f 100644 --- a/src/ActionFactory.php +++ b/src/ActionFactory.php @@ -22,6 +22,33 @@ public function __construct(SocketCredentials $credentials) $this->credentials = $credentials; } + /** + * Returns socket domain setting from config file + * @return string + */ + private function getDomain() + { + return $this->credentials->getCredential('domain'); + } + + /** + * Returns socket type setting from config file + * @return string + */ + private function getType() + { + return $this->credentials->getCredential('type'); + } + + /** + * Returns socket protocol setting from config file + * @return string + */ + private function getProtocol() + { + return $this->credentials->getCredential('protocol'); + } + /** * Return setted host name from * credentials handler @@ -47,7 +74,7 @@ private function getPort() */ public function getCreator(): SocketCreator { - return new SocketCreator($this->getHost(), $this->getPort()); + return new SocketCreator($this->getDomain(), $this->getType(), $this->getProtocol()); } /** diff --git a/src/SocketCreator.php b/src/SocketCreator.php index 83ec22f..9e64e1a 100644 --- a/src/SocketCreator.php +++ b/src/SocketCreator.php @@ -11,6 +11,43 @@ class SocketCreator extends AbstractSocketAction */ private $createdSocket; + /** + * Protocol family to be used + * by the socket + * @var int + */ + private int $domain; + + /** + * Type of communication to be + * used by the socket + * @var int + */ + private int $type; + + /** + * The specific protocol within the + * specified domain to be used when + * communicating on the returned socket + * @var int + */ + private int $protocol; + + /** + * Initiate SocketCreator constructor method and + * set domain, type and socket protocol values + * @param int $domain + * @param int $type + * @param int $protocol + * @return void + */ + public function __construct(int $domain, int $type, int $protocol) + { + $this->domain = $domain; + $this->type = $type; + $this->protocol = $protocol; + } + /** * Create socket. Lately have to refactor * hard coded socket_create parameters @@ -18,8 +55,7 @@ class SocketCreator extends AbstractSocketAction */ public function make() { - // TODO: Resolve hard coded parameters - $this->createdSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + $this->createdSocket = socket_create($this->domain, $this->type, $this->protocol); return $this; } From dfd7ed05f131b0e5750f87d85114d142980bf3a1 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Wed, 25 Nov 2020 14:37:33 +0300 Subject: [PATCH 12/41] Created socket constants locator for socket creator --- src/SocketConstantsLocator.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/SocketConstantsLocator.php diff --git a/src/SocketConstantsLocator.php b/src/SocketConstantsLocator.php new file mode 100644 index 0000000..b253575 --- /dev/null +++ b/src/SocketConstantsLocator.php @@ -0,0 +1,25 @@ + [ + 'AF_INET' => 2, + 'AF_INET6' => 10, + 'AF_UNIX' => 1 + ], + 'type' => [ + 'SOCK_STREAM' => 1, + 'SOCK_DGRAM' => 2, + 'SOCK_SEQPACKET' => 5, + 'SOCK_RAW' => 3, + 'SOCK_RDM' => 4 + ], + 'protocol' => [ + 'SOL_TCP' => 6, + 'SOL_UDP' => 17 + ] + ]; +} From ee1042d3b8529d5302f2758f1c7916ef2174fc1b Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Wed, 25 Nov 2020 18:14:01 +0300 Subject: [PATCH 13/41] Fixed setting socket const values by SocketConstantsLocator --- src/Bootstrapper.php | 61 ++++++++++++++++++-- src/Exceptions/ConfigSettingDoesntExists.php | 13 +++++ src/ServiceContainer.php | 1 + 3 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 src/Exceptions/ConfigSettingDoesntExists.php diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php index e6c97a2..920784b 100644 --- a/src/Bootstrapper.php +++ b/src/Bootstrapper.php @@ -4,6 +4,7 @@ use Qonsillium\Parsers\ConfigParsersFactory; use Qonsillium\Credential\SocketCredentials; +use Qonsillium\Exceptions\ConfigSettingDoesntExists; class Bootstrapper { @@ -55,19 +56,71 @@ protected function parseConfigFile(): array /** * Set socket domain, type, protocol, host and port * in SocketCredentials instance + * @throws \Qonsillium\Exceptions\ConfigSettingDoesntExists * @return \Qonsillium\Credential\SocketCredentials */ - protected function setCredentials() + public function setCredentials() { $credentials = $this->getCredentialsHandler(); - $credentials->setCredential('domain', $this->settings['settings']['domain']); - $credentials->setCredential('type', $this->settings['settings']['type']); - $credentials->setCredential('protocol', $this->settings['settings']['protocol']); + $domain = $this->getConstValue('domain', $this->settings['settings']['domain']); + + if (!$domain) { + throw new ConfigSettingDoesntExists('Domain setting doesn\'t exists'); + } + + $credentials->setCredential('domain', $domain); + $type = $this->getConstValue('type', $this->settings['settings']['type']); + + if (!$type) { + throw new ConfigSettingDoesntExists('Type setting doesn\'t exists'); + } + + $credentials->setCredential('type', $type); + $protocol = $this->getConstValue('protocol', $this->settings['settings']['protocol']); + + if (!$protocol) { + throw new ConfigSettingDoesntExists('Protocol setting doesn\'t exists'); + } + + $credentials->setCredential('protocol', $protocol); $credentials->setCredential('host', $this->settings['settings']['host']); $credentials->setCredential('port', $this->settings['settings']['port']); return $credentials; } + /** + * Get setting value from from config file and match + * with constants locator constant and finally return + * integer value about this const + * @param string $setting + * @param string $const + * @return int|bool + */ + protected function getConstValue(string $setting, string $const) + { + if (!isset($this->getSocketConstLocator()::MODIFIERS[$setting][$const])) { + return false; + } + + return $this->getSocketConstLocator()::MODIFIERS[$setting][$const]; + } + + /** + * Returns SocketConstLocator which contain + * all socket settings constants. Usually + * used when need to get socket const integer + * value. + * + * Example: + * $this->getSocketConstLocator()::MODIFIERS + * + * @return string + */ + protected function getSocketConstLocator() + { + return $this->services->getFromList('socket_constants'); + } + /** * Returns ConfigParserFactory factory class * @return \Qonsillium\Parsers\ConfigParsersFactory diff --git a/src/Exceptions/ConfigSettingDoesntExists.php b/src/Exceptions/ConfigSettingDoesntExists.php new file mode 100644 index 0000000..0fd1cad --- /dev/null +++ b/src/Exceptions/ConfigSettingDoesntExists.php @@ -0,0 +1,13 @@ + ConfigParsersFactory::class, 'socket_actions_factory' => ActionFactory::class, 'socket_facade' => SocketFacade::class, + 'socket_constants' => SocketConstantsLocator::class ]; } From 2c50212c60101adbd95f5724df56d4a6d6460542 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Wed, 25 Nov 2020 19:33:14 +0300 Subject: [PATCH 14/41] Created not completely implemented client and server socket run methods --- src/QonsilliumSocket.php | 40 ++++++++++++++++++++++++++++++++++++++-- src/SocketError.php | 31 ------------------------------- src/SocketMessage.php | 31 ------------------------------- 3 files changed, 38 insertions(+), 64 deletions(-) delete mode 100644 src/SocketError.php delete mode 100755 src/SocketMessage.php diff --git a/src/QonsilliumSocket.php b/src/QonsilliumSocket.php index dbd450a..31d83be 100644 --- a/src/QonsilliumSocket.php +++ b/src/QonsilliumSocket.php @@ -32,7 +32,7 @@ public function __construct(string $configFile) * Return ClientSocket handler * @return \Qonsillium\ClientSocket */ - public function getClientSocket(): ClientSocket + protected function getClientSocket(): ClientSocket { return $this->bootstrapper->getClientSocket(); } @@ -41,8 +41,44 @@ public function getClientSocket(): ClientSocket * Return ServerSocket handler * @return \Qonsillium\ServerSocket */ - public function getServerSocket(): ServerSocket + protected function getServerSocket(): ServerSocket { return $this->bootstrapper->getServerSocket(); } + + /** + * Run client socket and handle user + * setted callback function. + * @param callback $handler + * + * Example: + * $socket = QonsilliumSocket('config.yml'); + * $socket->runClient(function(ClientSocket $client) { + * $client->send('Hello from client'); + * }) + * + * @return void + */ + public function runClient($handler) + { + call_user_func($handler($this->getClientSocket())); + } + + /** + * Run server socket and handle user + * setted callback function. + * @param callback $handler + * + * Example: + * $socket = QonsilliumSocket('config.yml'); + * $socket->runClient(function(ServerSocket $server) { + * $server->send('Hello from server'); + * }) + * + * @return void + */ + public function runServer($handler) + { + call_user_func($handler($this->getServerSocket())); + } } diff --git a/src/SocketError.php b/src/SocketError.php deleted file mode 100644 index 1ed0e61..0000000 --- a/src/SocketError.php +++ /dev/null @@ -1,31 +0,0 @@ -errorMessage = $error; - } - - /** - * Return setted socket error - * @return string - */ - public function getSocketError() - { - return $this->errorMessage; - } -} diff --git a/src/SocketMessage.php b/src/SocketMessage.php deleted file mode 100755 index 9af76f7..0000000 --- a/src/SocketMessage.php +++ /dev/null @@ -1,31 +0,0 @@ -message = $message; - } - - /** - * Get current readed socket response - * @return string - */ - public function getSocketResponse() - { - return $this->message; - } -} From d96bfc4759608347d83e00c2756092bd16d33eea Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Fri, 27 Nov 2020 16:40:31 +0300 Subject: [PATCH 15/41] Refactored getting and validating socket const from SocketConstantLocator --- src/Bootstrapper.php | 30 +++++++++++------------------- src/SocketConstantsLocator.php | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php index 920784b..f26b1a1 100644 --- a/src/Bootstrapper.php +++ b/src/Bootstrapper.php @@ -62,27 +62,16 @@ protected function parseConfigFile(): array public function setCredentials() { $credentials = $this->getCredentialsHandler(); - $domain = $this->getConstValue('domain', $this->settings['settings']['domain']); - - if (!$domain) { - throw new ConfigSettingDoesntExists('Domain setting doesn\'t exists'); - } + $domain = $this->getConstValue('domain', $this->settings['settings']['domain']); $credentials->setCredential('domain', $domain); + $type = $this->getConstValue('type', $this->settings['settings']['type']); - - if (!$type) { - throw new ConfigSettingDoesntExists('Type setting doesn\'t exists'); - } - $credentials->setCredential('type', $type); + $protocol = $this->getConstValue('protocol', $this->settings['settings']['protocol']); - - if (!$protocol) { - throw new ConfigSettingDoesntExists('Protocol setting doesn\'t exists'); - } - $credentials->setCredential('protocol', $protocol); + $credentials->setCredential('host', $this->settings['settings']['host']); $credentials->setCredential('port', $this->settings['settings']['port']); return $credentials; @@ -94,15 +83,18 @@ public function setCredentials() * integer value about this const * @param string $setting * @param string $const - * @return int|bool + * @throws \Qonsillium\Exceptions\ConfigSettingDoesntExists + * @return int */ protected function getConstValue(string $setting, string $const) { - if (!isset($this->getSocketConstLocator()::MODIFIERS[$setting][$const])) { - return false; + if (!$this->getSocketConstLocator()::hasConst($setting, $const)) { + throw new ConfigSettingDoesntExists( + "Setting with type: {$setting} and const name: {$const} doesn't exists" + ); } - return $this->getSocketConstLocator()::MODIFIERS[$setting][$const]; + return $this->getSocketConstLocator()::getConstValue($setting, $const); } /** diff --git a/src/SocketConstantsLocator.php b/src/SocketConstantsLocator.php index b253575..7059f5f 100644 --- a/src/SocketConstantsLocator.php +++ b/src/SocketConstantsLocator.php @@ -22,4 +22,30 @@ class SocketConstantsLocator 'SOL_UDP' => 17 ] ]; + + /** + * Get integer value of socket constant + * @param string $type + * @param string $const + * @return int + */ + public static function getConstValue(string $type, string $const) + { + return self::MODIFIERS[$type][$const]; + } + + /** + * Validate socket constant existence in list + * @param string $type + * @param string $const + * @return bool + */ + public static function hasConst(string $type, string $const): bool + { + if (!isset(self::MODIFIERS[$type], self::MODIFIERS[$type][$const])) { + return false; + } + + return true; + } } From 7afaef4ebd8b66cbd2a8973d8ce36f88e1763d69 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Fri, 27 Nov 2020 16:46:32 +0300 Subject: [PATCH 16/41] Removed socket make method executing and use __invoke method in SocketFacade --- src/SocketFacade.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/SocketFacade.php b/src/SocketFacade.php index e5b57ca..d9854c0 100644 --- a/src/SocketFacade.php +++ b/src/SocketFacade.php @@ -44,7 +44,7 @@ public function __construct(ActionFactory $factory) */ protected function createSocket() { - $socket = $this->factory->getCreator()->make(); + $socket = $this->factory->getCreator()(); if(!$socket) { return false; @@ -63,7 +63,7 @@ protected function bindSocket($socket) { $binder = $this->factory->getBinder(); $binder->setSocket($socket); - $bindAction = $binder->make(); + $bindAction = $binder(); if (!$bindAction) { return false; @@ -82,7 +82,7 @@ protected function listenSocket($socket) $listener = $this->factory->getListener(); $listener->setCreatedSocket($socket); $listener->setBacklog(1); - $listenAction = $listener->make(); + $listenAction = $listener(); if (!$listenAction) { return false; @@ -100,7 +100,7 @@ protected function acceptSocket($socket) { $acceptor = $this->factory->getAcceptor(); $acceptor->setAcceptSocket($socket); - $acceptAction = $acceptor->make(); + $acceptAction = $acceptor(); if (!$acceptAction) { return false; @@ -118,7 +118,7 @@ protected function connectSocket($socket) { $connector = $this->factory->getConnector(); $connector->setCreatedSocket($socket); - $connectionAction = $connector->make(); + $connectionAction = $connector(); if (!$connectionAction) { return false; @@ -136,7 +136,7 @@ protected function readSocket($socket) { $reader = $this->factory->getReader(); $reader->setSocket($socket); - $readAction = $reader->make(); + $readAction = $reader(); if (!$readAction) { return false; @@ -156,7 +156,7 @@ protected function writeSocket($socket, string $message) $writer = $this->factory->getWriter(); $writer->setSocket($socket); $writer->setMessage($message); - $writeAction = $writer->make(); + $writeAction = $writer(); if (!$writeAction) { return false; @@ -178,7 +178,7 @@ public function closeSocket() $closer = $this->factory->getCloser(); $closer->setSocket($this->createdSocket); - return $closer->make(); + return $closer(); } /** From 15020b4b49dba8112e7ba061074ee87b44929def Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sat, 28 Nov 2020 15:53:11 +0300 Subject: [PATCH 17/41] Setted PHP 8.0 requires in composer.json file --- .gitignore | 0 README.md | 0 composer.json | 2 +- src/Credential/ICredential.php | 0 src/Credential/SocketCredentials.php | 0 5 files changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 .gitignore mode change 100755 => 100644 README.md mode change 100755 => 100644 composer.json mode change 100755 => 100644 src/Credential/ICredential.php mode change 100755 => 100644 src/Credential/SocketCredentials.php diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/composer.json b/composer.json old mode 100755 new mode 100644 index ad6b2c6..2d65aa5 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "phpunit/phpunit": "^9.3" }, "require": { - "php": ">=5.3", + "php": "^8.0", "ext-sockets": "*" } } diff --git a/src/Credential/ICredential.php b/src/Credential/ICredential.php old mode 100755 new mode 100644 diff --git a/src/Credential/SocketCredentials.php b/src/Credential/SocketCredentials.php old mode 100755 new mode 100644 From 004ce9d1f2f610fdc050ee19e38478df071b9874 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sat, 28 Nov 2020 16:17:45 +0300 Subject: [PATCH 18/41] Setted \Socket type in actions --- src/SocketAcceptor.php | 10 ++++++---- src/SocketBinder.php | 12 +++++++----- src/SocketCloser.php | 8 +++++--- src/SocketConnector.php | 10 ++++++---- src/SocketCreator.php | 8 +++++--- src/SocketListener.php | 10 ++++++---- src/SocketReader.php | 12 +++++++----- src/SocketWriter.php | 6 ++++-- 8 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/SocketAcceptor.php b/src/SocketAcceptor.php index 67fc9ea..8ea5b72 100644 --- a/src/SocketAcceptor.php +++ b/src/SocketAcceptor.php @@ -2,25 +2,27 @@ namespace Qonsillium; +use \Socket; + class SocketAcceptor extends AbstractSocketAction { /** * Accepted socket connection - * @var resource + * @var \Socket */ private $acceptedSocket; /** - * @param resource $socket + * @param \Socket $socket * @return void */ - public function setAcceptSocket($socket) + public function setAcceptSocket(Socket $socket) { $this->acceptedSocket = $socket; } /** - * @return resource + * @return \Socket */ public function getAcceptedSocket() { diff --git a/src/SocketBinder.php b/src/SocketBinder.php index dea7eb7..7bb7977 100644 --- a/src/SocketBinder.php +++ b/src/SocketBinder.php @@ -2,11 +2,13 @@ namespace Qonsillium; +use \Socket; + class SocketBinder extends AbstractSocketAction { /** * Created socket connection - * @var resource + * @var \Socket */ private $socket; @@ -38,18 +40,18 @@ public function __construct(string $host, int $port) } /** - * @param resource $socket + * @param \Socket $socket * @return void */ - public function setSocket($socket) + public function setSocket(Socket $socket) { $this->socket = $socket; } /** - * @return resource + * @return \Socket */ - public function getSocket() + public function getSocket(): Socket { return $this->socket; } diff --git a/src/SocketCloser.php b/src/SocketCloser.php index 698def9..6ba7c46 100644 --- a/src/SocketCloser.php +++ b/src/SocketCloser.php @@ -2,11 +2,13 @@ namespace Qonsillium; +use \Socket; + class SocketCloser extends AbstractSocketAction { /** * Accepted or created socket - * @var resource + * @var \Socket */ private $socket; @@ -14,7 +16,7 @@ class SocketCloser extends AbstractSocketAction * @param resource $socket * @return void */ - public function setSocket($socket) + public function setSocket(Socket $socket) { $this->socket = $socket; } @@ -22,7 +24,7 @@ public function setSocket($socket) /** * @return resource */ - public function getSocket() + public function getSocket(): Socket { return $this->socket; } diff --git a/src/SocketConnector.php b/src/SocketConnector.php index ec00881..08d4ac1 100644 --- a/src/SocketConnector.php +++ b/src/SocketConnector.php @@ -2,6 +2,8 @@ namespace Qonsillium; +use \Socket; + class SocketConnector extends AbstractSocketAction { /** @@ -38,18 +40,18 @@ public function __construct(string $host, int $port) } /** - * @param resource $socket + * @param \Socket $socket * @return void */ - public function setCreatedSocket($socket) + public function setCreatedSocket(Socket $socket) { $this->socket = $socket; } /** - * @return resource + * @return \Socket */ - public function getConnectedSocket() + public function getConnectedSocket(): Socket { return $this->socket; } diff --git a/src/SocketCreator.php b/src/SocketCreator.php index 9e64e1a..f4fb5eb 100644 --- a/src/SocketCreator.php +++ b/src/SocketCreator.php @@ -2,12 +2,14 @@ namespace Qonsillium; +use \Socket; + class SocketCreator extends AbstractSocketAction { /** * Socket which was created by * socket_create - * @var resource + * @var \Socket */ private $createdSocket; @@ -60,9 +62,9 @@ public function make() } /** - * @return resource + * @return \Socket */ - public function getCreatedSocket() + public function getCreatedSocket(): Socket { return $this->createdSocket; } diff --git a/src/SocketListener.php b/src/SocketListener.php index 9d3be3c..e2c7d5e 100644 --- a/src/SocketListener.php +++ b/src/SocketListener.php @@ -2,6 +2,8 @@ namespace Qonsillium; +use \Socket; + class SocketListener extends AbstractSocketAction { /** @@ -17,18 +19,18 @@ class SocketListener extends AbstractSocketAction private int $backlog; /** - * @param resource $socket + * @param \Socket $socket * @return void */ - public function setCreatedSocket($socket) + public function setCreatedSocket(Socket $socket) { $this->socket = $socket; } /** - * @return resource + * @return \Socket */ - public function getListenedSocket() + public function getListenedSocket(): Socket { return $this->socket; } diff --git a/src/SocketReader.php b/src/SocketReader.php index 71eb461..48aa5df 100644 --- a/src/SocketReader.php +++ b/src/SocketReader.php @@ -2,11 +2,13 @@ namespace Qonsillium; +use \Socket; + class SocketReader extends AbstractSocketAction { /** * Created or accepted socket - * @var resource + * @var \Socket */ private $socket; @@ -17,18 +19,18 @@ class SocketReader extends AbstractSocketAction private string $message = ''; /** - * @param resource $socket + * @param \Socket $socket * @return void */ - public function setSocket($socket) + public function setSocket(Socket $socket) { $this->socket = $socket; } /** - * @return resource + * @return \Socket */ - public function getSocket() + public function getSocket(): Socket { return $this->socket; } diff --git a/src/SocketWriter.php b/src/SocketWriter.php index d56e0ba..4b21380 100644 --- a/src/SocketWriter.php +++ b/src/SocketWriter.php @@ -2,6 +2,8 @@ namespace Qonsillium; +use \Socket; + class SocketWriter extends AbstractSocketAction { /** @@ -21,7 +23,7 @@ class SocketWriter extends AbstractSocketAction * @param resource $socket * @return void */ - public function setSocket($socket) + public function setSocket(Socket $socket) { $this->socket = $socket; } @@ -29,7 +31,7 @@ public function setSocket($socket) /** * @return resource */ - public function getSocket() + public function getSocket(): Socket { return $this->socket; } From 8104545b7172d4062a4d8419fe1a0721e4ac648d Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sun, 29 Nov 2020 19:58:13 +0300 Subject: [PATCH 19/41] Added property existence validation in credential handler --- src/Credential/SocketCredentials.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Credential/SocketCredentials.php b/src/Credential/SocketCredentials.php index 78306eb..7332993 100644 --- a/src/Credential/SocketCredentials.php +++ b/src/Credential/SocketCredentials.php @@ -24,4 +24,18 @@ public function getCredential(string $name) { return $this->$name; } + + /** + * Validate existence of credential + * @param string $name + * @return bool + */ + public function validateExistence(string $name) + { + if (!property_exists($this, $name)) { + return false; + } + + return true; + } } From 82bfb0d3fab907210d77eb0f440c48c515a34eb6 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sun, 29 Nov 2020 20:23:36 +0300 Subject: [PATCH 20/41] Created TCP and Unix socket handlers and factory which return theme --- src/Types/NullSocketType.php | 15 ++++++++ src/Types/SocketType.php | 53 +++++++++++++++++++++++++++ src/Types/SocketTypeFactory.php | 42 ++++++++++++++++++++++ src/Types/TCPSocketType.php | 15 ++++++++ src/Types/TypeConfiguration.php | 64 +++++++++++++++++++++++++++++++++ src/Types/UnixSocketType.php | 15 ++++++++ 6 files changed, 204 insertions(+) create mode 100644 src/Types/NullSocketType.php create mode 100644 src/Types/SocketType.php create mode 100644 src/Types/SocketTypeFactory.php create mode 100644 src/Types/TCPSocketType.php create mode 100644 src/Types/TypeConfiguration.php create mode 100644 src/Types/UnixSocketType.php diff --git a/src/Types/NullSocketType.php b/src/Types/NullSocketType.php new file mode 100644 index 0000000..9f585a4 --- /dev/null +++ b/src/Types/NullSocketType.php @@ -0,0 +1,15 @@ +configuration = $configuration; + } + + /** + * Validate existence of socket setting + * @param string $setting + * @return bool + */ + public function validate(string $setting) + { + if (!$this->configuration->validateSettingsExistence($setting)) { + return false; + } + + return true; + } + + /** + * Return setting which was setted in + * configuration file and validate existence + * @return bool|string + */ + public function get(string $setting) + { + if (!$this->validate($setting)) { + return false; + } + + return $this->configuration->getConfigurationSetting($setting); + } + + /** + * Configure TCP or Unix socket + * @return void + */ + abstract public function configure(); +} diff --git a/src/Types/SocketTypeFactory.php b/src/Types/SocketTypeFactory.php new file mode 100644 index 0000000..85ae4f2 --- /dev/null +++ b/src/Types/SocketTypeFactory.php @@ -0,0 +1,42 @@ +configuration = $configuration; + $this->nullObj = new NullSocketType($this->configuration); + } + + /** + * Factory method which return socket by + * type + * @param string $type + * @return \Qonsillium\Types\SocketType + */ + public function getSocket(string $type): SocketType + { + if ($type === 'tcp') { + return new TCPSocketType($this->configuration); + } elseif ($type === 'unix') { + return new UnixSocketType($this->configuration); + } else { + return $this->nullObj; + } + } +} diff --git a/src/Types/TCPSocketType.php b/src/Types/TCPSocketType.php new file mode 100644 index 0000000..0349e02 --- /dev/null +++ b/src/Types/TCPSocketType.php @@ -0,0 +1,15 @@ +configuration->configure(); + } +} diff --git a/src/Types/TypeConfiguration.php b/src/Types/TypeConfiguration.php new file mode 100644 index 0000000..ca0c891 --- /dev/null +++ b/src/Types/TypeConfiguration.php @@ -0,0 +1,64 @@ +settings = $settings; + } + + /** + * Configure TCP or Unix settings + * @return void + */ + public function configure() + { + foreach($this->settings as $key => $value) { + $this->configured[$key] = $value; + } + } + + /** + * Validate settings existence in list + * @param string $setting + * @return bool + */ + public function validateSettingsExistence(string $setting) + { + if (!isset($this->configured[$setting])) { + return false; + } + + return true; + } + + /** + * Return configured setting by passsed name + * @return string + */ + public function getConfigurationSetting(string $setting) + { + return $this->configured[$setting]; + } +} diff --git a/src/Types/UnixSocketType.php b/src/Types/UnixSocketType.php new file mode 100644 index 0000000..eb6f99a --- /dev/null +++ b/src/Types/UnixSocketType.php @@ -0,0 +1,15 @@ +configuration->configure(); + } +} From 8e8efc30af9fba86e51b0a33aa669ce0a8f4801a Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sun, 29 Nov 2020 20:43:54 +0300 Subject: [PATCH 21/41] Refactored setting socket credentials --- src/ActionFactory.php | 20 +++++-- src/Bootstrapper.php | 103 +++++++++++++++++++++++++++++---- src/ServiceContainer.php | 6 +- src/SocketBinder.php | 8 +-- src/SocketCloser.php | 4 +- src/SocketConstantsLocator.php | 9 ++- src/SocketFacade.php | 15 ++--- 7 files changed, 134 insertions(+), 31 deletions(-) diff --git a/src/ActionFactory.php b/src/ActionFactory.php index eb9b48f..84bb770 100644 --- a/src/ActionFactory.php +++ b/src/ActionFactory.php @@ -50,12 +50,16 @@ private function getProtocol() } /** - * Return setted host name from + * Return setted host or socket file name from * credentials handler * @return string */ - private function getHost() + private function getAddress() { + if ($this->credentials->validateExistence('socket_file')) { + return $this->credentials->getCredential('socket_file'); + } + return $this->credentials->getCredential('host'); } @@ -66,7 +70,11 @@ private function getHost() */ private function getPort() { - return $this->credentials->getCredential('port'); + if ($this->credentials->validateExistence('port')) { + return $this->credentials->getCredential('port'); + } + + return 0; } /** @@ -90,7 +98,7 @@ public function getAcceptor(): SocketAcceptor */ public function getConnector(): SocketConnector { - return new SocketConnector($this->getHost(), $this->getPort()); + return new SocketConnector($this->getAddress(), $this->getPort()); } /** @@ -105,8 +113,8 @@ public function getListener(): SocketListener * @return \Qonsillium\SocketBinder */ public function getBinder(): SocketBinder - { - return new SocketBinder($this->getHost(), $this->getPort()); + { + return new SocketBinder($this->getAddress(), $this->getPort()); } /** diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php index f26b1a1..eb6d3ca 100644 --- a/src/Bootstrapper.php +++ b/src/Bootstrapper.php @@ -5,6 +5,8 @@ use Qonsillium\Parsers\ConfigParsersFactory; use Qonsillium\Credential\SocketCredentials; use Qonsillium\Exceptions\ConfigSettingDoesntExists; +use Qonsillium\Types\TypeConfiguration; +use Qonsillium\Types\SocketTypeFactory; class Bootstrapper { @@ -22,6 +24,8 @@ class Bootstrapper */ protected array $settings; + protected ?TypeConfiguration $configuration; + /** * @var \Qonsillium\Credential\SocketCredentials */ @@ -40,6 +44,7 @@ public function __construct(string $configFile) $this->configFile = $configFile; $this->services = new ServiceProvider(); $this->settings = $this->parseConfigFile(); + $this->configuration = $this->configureSettingsFromFile(); $this->credentials = $this->setCredentials(); } @@ -54,26 +59,72 @@ protected function parseConfigFile(): array } /** - * Set socket domain, type, protocol, host and port - * in SocketCredentials instance + * Set socket domain, type, protocol, host and port, + * backlog, read length and backlog, unix socket file + * and return a SocketCredentials instance. * @throws \Qonsillium\Exceptions\ConfigSettingDoesntExists * @return \Qonsillium\Credential\SocketCredentials */ public function setCredentials() { $credentials = $this->getCredentialsHandler(); + $socketTypeFactory = $this->getSocketTypeFactory(); + $socketType = $socketTypeFactory->getSocket($this->settings['settings']['socket_type']); + - $domain = $this->getConstValue('domain', $this->settings['settings']['domain']); - $credentials->setCredential('domain', $domain); + $credentials->setCredential( + 'domain', + $this->getConstValue('domain', $socketType->get('domain')) + ); + + $credentials->setCredential( + 'type', + $this->getConstValue('type', $socketType->get('type')) + ); - $type = $this->getConstValue('type', $this->settings['settings']['type']); - $credentials->setCredential('type', $type); + $credentials->setCredential( + 'protocol', + $this->getConstValue('protocol', $socketType->get('protocol')) + ); + + $credentials->setCredential( + 'backlog', + $socketType->get('backlog') + ); + + $credentials->setCredential( + 'read_length', + $socketType->get('read_length') + ); + + $credentials->setCredential( + 'read_flag', + $this->getConstValue('read_flags', $socketType->get('read_flag')) + ); + + // We have two types of sockets it's TCP or Unix, so also + // we have two handlers which contain this settings + // TCP handler contains host and port and Unix handler + // socket file + if ($socketType->validate('socket_file')) { + $credentials->setCredential( + 'socket_file', + $socketType->get('socket_file') + ); + + return $credentials; + } - $protocol = $this->getConstValue('protocol', $this->settings['settings']['protocol']); - $credentials->setCredential('protocol', $protocol); + $credentials->setCredential( + 'host', + $socketType->get('host') + ); - $credentials->setCredential('host', $this->settings['settings']['host']); - $credentials->setCredential('port', $this->settings['settings']['port']); + $credentials->setCredential( + 'port', + $socketType->get('port') + ); + return $credentials; } @@ -97,6 +148,18 @@ protected function getConstValue(string $setting, string $const) return $this->getSocketConstLocator()::getConstValue($setting, $const); } + /** + * Configure settings from config file by + * TypeConfiguration and return this instance + * @return \Qonsillium\Types\TypeConfiguration + */ + protected function configureSettingsFromFile(): TypeConfiguration + { + $configuration = $this->getSocketConfigurator(); + $configuration->configure(); + return $configuration; + } + /** * Returns SocketConstLocator which contain * all socket settings constants. Usually @@ -113,6 +176,26 @@ protected function getSocketConstLocator() return $this->services->getFromList('socket_constants'); } + /** + * Returns TypeConfiguration instance + * @return \Qonsillium\Types\TypeConfiguration + */ + public function getSocketConfigurator(): TypeConfiguration + { + $configuration = $this->services->getFromList('socket_configuration'); + return new $configuration($this->settings['settings']); + } + + /** + * Returns SocketTypeFactory instance + * @return \Qonsillium\Types\SocketTypeFactory + */ + public function getSocketTypeFactory(): SocketTypeFactory + { + $factory = $this->services->getFromList('socket_type_factory'); + return new $factory($this->configuration); + } + /** * Returns ConfigParserFactory factory class * @return \Qonsillium\Parsers\ConfigParsersFactory diff --git a/src/ServiceContainer.php b/src/ServiceContainer.php index ec3203c..280e157 100644 --- a/src/ServiceContainer.php +++ b/src/ServiceContainer.php @@ -4,6 +4,8 @@ use Qonsillium\Credential\SocketCredentials; use Qonsillium\Parsers\ConfigParsersFactory; +use Qonsillium\Types\TypeConfiguration; +use Qonsillium\Types\SocketTypeFactory; abstract class ServiceContainer { @@ -18,6 +20,8 @@ abstract class ServiceContainer 'config_parser_factory' => ConfigParsersFactory::class, 'socket_actions_factory' => ActionFactory::class, 'socket_facade' => SocketFacade::class, - 'socket_constants' => SocketConstantsLocator::class + 'socket_constants' => SocketConstantsLocator::class, + 'socket_configuration' => TypeConfiguration::class, + 'socket_type_factory' => SocketTypeFactory::class ]; } diff --git a/src/SocketBinder.php b/src/SocketBinder.php index 7bb7977..ee1ec24 100644 --- a/src/SocketBinder.php +++ b/src/SocketBinder.php @@ -17,7 +17,7 @@ class SocketBinder extends AbstractSocketAction * binded * @var string */ - private string $host; + private string $address; /** * Socket port which will be @@ -33,9 +33,9 @@ class SocketBinder extends AbstractSocketAction * @param int $port * @return void */ - public function __construct(string $host, int $port) + public function __construct(string $address, int $port = 0) { - $this->host = $host; + $this->address = $address; $this->port = $port; } @@ -63,6 +63,6 @@ public function getSocket(): Socket */ public function make() { - return socket_bind($this->getSocket(), $this->host, $this->port); + return socket_bind($this->getSocket(), $this->address, $this->port); } } diff --git a/src/SocketCloser.php b/src/SocketCloser.php index 6ba7c46..3ec1a34 100644 --- a/src/SocketCloser.php +++ b/src/SocketCloser.php @@ -13,7 +13,7 @@ class SocketCloser extends AbstractSocketAction private $socket; /** - * @param resource $socket + * @param \Socket $socket * @return void */ public function setSocket(Socket $socket) @@ -22,7 +22,7 @@ public function setSocket(Socket $socket) } /** - * @return resource + * @return \Socket */ public function getSocket(): Socket { diff --git a/src/SocketConstantsLocator.php b/src/SocketConstantsLocator.php index 7059f5f..fbed7c8 100644 --- a/src/SocketConstantsLocator.php +++ b/src/SocketConstantsLocator.php @@ -19,7 +19,14 @@ class SocketConstantsLocator ], 'protocol' => [ 'SOL_TCP' => 6, - 'SOL_UDP' => 17 + 'SOL_UDP' => 17, + '0' => 0 + ], + 'read_flags' => [ + 'MSG_OOB' => 1, + 'MSG_PEEK' => 2, + 'MSG_WAITALL' => 256, + 'MSG_DONTWAIT' => 64 ] ]; diff --git a/src/SocketFacade.php b/src/SocketFacade.php index d9854c0..672ea75 100644 --- a/src/SocketFacade.php +++ b/src/SocketFacade.php @@ -12,6 +12,7 @@ FailedBindSocket, FailedReadSocket }; +use \Socket; class SocketFacade { @@ -22,7 +23,7 @@ class SocketFacade /** * Created socket by socket_create - * @var resource + * @var \Socket */ private $createdSocket; @@ -56,7 +57,7 @@ protected function createSocket() /** * Bind socket host and port - * @param resource $socket + * @param \Socket $socket * @return bool */ protected function bindSocket($socket) @@ -74,7 +75,7 @@ protected function bindSocket($socket) /** * Listen socket connections - * @param resource $socket + * @param \Socket $socket * @return bool */ protected function listenSocket($socket) @@ -93,7 +94,7 @@ protected function listenSocket($socket) /** * Accept socket connections - * @param resource $socket + * @param \Socket $socket * @return bool */ protected function acceptSocket($socket) @@ -111,7 +112,7 @@ protected function acceptSocket($socket) /** * Connect to created socket - * @param resource $socket + * @param \Socket $socket * @return bool */ protected function connectSocket($socket) @@ -129,7 +130,7 @@ protected function connectSocket($socket) /** * Read messages from client or server sockets - * @param resource $socket + * @param \Socket $socket * @return bool|\Qonsillium\SocketReader */ protected function readSocket($socket) @@ -147,7 +148,7 @@ protected function readSocket($socket) /** * Write messages on client or server sockets - * @param resource $socket + * @param \Socket $socket * @param string $message * @return bool|int */ From 350c5228e20bf2f1f3d77951a09e512e16a00cb3 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sun, 29 Nov 2020 21:49:41 +0300 Subject: [PATCH 22/41] Written README file --- README.md | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e4364df..30ab2ad 100644 --- a/README.md +++ b/README.md @@ -1 +1,131 @@ -web-socket +# Socket + +## This is a layer for client and server socket connections. + +### PHP extension which have to be installed before to work: +* [Yaml](https://www.php.net/manual/en/book.yaml.php) +* [Sockets](https://www.php.net/manual/en/book.sockets.php) + +### Four actions you have to make: +* Configure your configuration file. +* Create client.php or server.php file +* Call methods +* Run from CLI or extends + +### Examples of TCP and UNIX sockets: + +#### 1) Create configuration file. File can be **ONLY** with yaml(yml) or json extensions + +##### * TCP socket configuration using YAML +``` +settings: + socket_type: tcp + domain: AF_INET + type: SOCK_STREAM + protocol: SOL_TCP + backlog: 1 + host: '127.0.0.1' + port: '8001' + backlog: 1 + read_length: 2048 + read_flag: MSG_WAITALL +``` + +##### * UNIX socket configuration using YAML +``` +settings: + socket_type: unix + domain: AF_UNIX + type: SOCK_STREAM + protocol: 0 + backlog: 1 + socket_file: socket.sock + backlog: 1 + read_length: 2048 + read_flag: MSG_WAITALL +``` + +#### 2) Create client and server file handlers. + +##### server.php +``` +runServer(function(ServerSocket $socket) { + echo $socket->send('Hello from server!'); +}); +``` + +##### client.php +``` +runClient(function(ClinetSocket $socket) { + echo $socket->send('Hello from client!'); +}); +``` + +#### 3) Run from CLI +``` + john@doe:/workdir/$ php server.php + john@doe:/workdir/$ php client.php +``` + +## List of available configuration vars: +#### 1) sock_type - Type of socket which will be created. +* tcp +* unix + +#### 2) domain - Specifies the protocol family +* AF_INET +* AF_INET6 +* AF_UNIX + +#### 3) type - Selects the type of communication +* SOCK_STREAM +* SOCK_DGRAM +* SOCK_SEQPACKET +* SOCK_RAW +* SOCK_RDM + +#### 3) protocol - Sets the specific protocol within the specified domain to be used when communicating on the returned socket +* SOL_TCP +* SOL_UDP +* 0 (when use unix) + +#### 4) backlog - A maximum of backlog incoming connections will be queued for processing +* Number of incoming backlogs (1 or 2 etc.) + +#### 5) host - Host name which where will be accepted or created connection. Can be used when if socket is of the AF_INET family +* 127.0.0.1 + +#### 6) port - The port parameter is only used when binding an AF_INET socket, and designates the port on which to listen for connections. +* from 1024 to 65535 + +#### 7) socket_file - If the socket is of the AF_UNIX family, the address is the path of a Unix-domain socket. You can create own socket file but you must make that you set correct path and this file have read and write rights. Or you can set random name in work dir and here will be created socket file +* /tmp/socket.sock +* socket.sock + +#### 8) read_length - The maximum number of bytes read is specified by the length parameter. +* 2048, 4096 etc + +#### 9) read_flag - The flags responded for reading status. +* MSG_OOB +* MSG_PEEK +* MSG_WAITALL +* MSG_DONTWAIT + +###### For details you can refer to the [PHP](https://php.net) documentation + From d5aaf6479f654a297754a2c8f7d1405725093dc1 Mon Sep 17 00:00:00 2001 From: rubyqorn <51966037+rubyqorn@users.noreply.github.com> Date: Mon, 30 Nov 2020 12:39:08 +0300 Subject: [PATCH 23/41] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 3f42287..68fcf26 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,6 @@ settings: backlog: 1 host: '127.0.0.1' port: '8001' - backlog: 1 read_length: 2048 read_flag: MSG_WAITALL ``` @@ -41,7 +40,6 @@ settings: protocol: 0 backlog: 1 socket_file: socket.sock - backlog: 1 read_length: 2048 read_flag: MSG_WAITALL ``` From 13b93178d9f0b19a91ee206235c40620134ec27b Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 1 Dec 2020 18:50:59 +0300 Subject: [PATCH 24/41] Removed hardcoded read length, flag and listen backlog parameters --- src/ActionFactory.php | 31 +++++++++++++++++++++++++++++-- src/QonsilliumSocket.php | 9 +++++---- src/SocketFacade.php | 1 - src/SocketListener.php | 30 ++++++++++++------------------ src/SocketReader.php | 20 +++++++++++++++++++- 5 files changed, 65 insertions(+), 26 deletions(-) diff --git a/src/ActionFactory.php b/src/ActionFactory.php index 84bb770..2adec15 100644 --- a/src/ActionFactory.php +++ b/src/ActionFactory.php @@ -77,6 +77,33 @@ private function getPort() return 0; } + /** + * Returns number of incoming backlogs + * @return int + */ + private function getBacklog() + { + return $this->credentials->getCredential('backlog'); + } + + /** + * Bytes length which will be fetched from remote host + * @return int + */ + private function getReadLength() + { + return $this->credentials->getCredential('read_length'); + } + + /** + * Return flag value responded for reading status + * @return int + */ + private function getReadFlag() + { + return $this->credentials->getCredential('read_flag'); + } + /** * @return \Qonsillium\SocketCreator */ @@ -106,7 +133,7 @@ public function getConnector(): SocketConnector */ public function getListener(): SocketListener { - return new SocketListener(); + return new SocketListener($this->getBacklog()); } /** @@ -122,7 +149,7 @@ public function getBinder(): SocketBinder */ public function getReader(): SocketReader { - return new SocketReader(); + return new SocketReader($this->getReadLength(), $this->getReadFlag()); } /** diff --git a/src/QonsilliumSocket.php b/src/QonsilliumSocket.php index 31d83be..b2f2fec 100644 --- a/src/QonsilliumSocket.php +++ b/src/QonsilliumSocket.php @@ -2,6 +2,7 @@ namespace Qonsillium; +use Closure; use Qonsillium\Exceptions\ConfigFileDoesntExists; class QonsilliumSocket @@ -49,7 +50,7 @@ protected function getServerSocket(): ServerSocket /** * Run client socket and handle user * setted callback function. - * @param callback $handler + * @param \Closure $handler * * Example: * $socket = QonsilliumSocket('config.yml'); @@ -59,7 +60,7 @@ protected function getServerSocket(): ServerSocket * * @return void */ - public function runClient($handler) + public function runClient(Closure $handler) { call_user_func($handler($this->getClientSocket())); } @@ -67,7 +68,7 @@ public function runClient($handler) /** * Run server socket and handle user * setted callback function. - * @param callback $handler + * @param \Closure $handler * * Example: * $socket = QonsilliumSocket('config.yml'); @@ -77,7 +78,7 @@ public function runClient($handler) * * @return void */ - public function runServer($handler) + public function runServer(Closure $handler) { call_user_func($handler($this->getServerSocket())); } diff --git a/src/SocketFacade.php b/src/SocketFacade.php index 672ea75..9743ad7 100644 --- a/src/SocketFacade.php +++ b/src/SocketFacade.php @@ -82,7 +82,6 @@ protected function listenSocket($socket) { $listener = $this->factory->getListener(); $listener->setCreatedSocket($socket); - $listener->setBacklog(1); $listenAction = $listener(); if (!$listenAction) { diff --git a/src/SocketListener.php b/src/SocketListener.php index e2c7d5e..58a29b8 100644 --- a/src/SocketListener.php +++ b/src/SocketListener.php @@ -19,37 +19,31 @@ class SocketListener extends AbstractSocketAction private int $backlog; /** - * @param \Socket $socket + * Initiate SocketListener constructor method and + * set backlog paramter + * @param int $backlog * @return void */ - public function setCreatedSocket(Socket $socket) - { - $this->socket = $socket; - } - - /** - * @return \Socket - */ - public function getListenedSocket(): Socket + public function __construct(int $backlog = 1) { - return $this->socket; + $this->backlog = $backlog; } /** - * @param int $backlog + * @param \Socket $socket * @return void */ - public function setBacklog(int $backlog) + public function setCreatedSocket(Socket $socket) { - $this->backlog = $backlog; + $this->socket = $socket; } /** - * @return int + * @return \Socket */ - public function getBacklog() + public function getListenedSocket(): Socket { - return $this->backlog; + return $this->socket; } /** @@ -58,6 +52,6 @@ public function getBacklog() */ public function make() { - return socket_listen($this->getListenedSocket(), $this->getBacklog()); + return socket_listen($this->getListenedSocket(), $this->backlog); } } diff --git a/src/SocketReader.php b/src/SocketReader.php index 48aa5df..db0dbba 100644 --- a/src/SocketReader.php +++ b/src/SocketReader.php @@ -12,12 +12,30 @@ class SocketReader extends AbstractSocketAction */ private $socket; + /** + * Bytes length + * @var int + */ + private int $length; + + /** + * Read status + * @var int + */ + private int $flag; + /** * Readed message from socket * @var string */ private string $message = ''; + public function __construct(int $length, int $flag = 0) + { + $this->length = $length; + $this->flag = $flag; + } + /** * @param \Socket $socket * @return void @@ -49,7 +67,7 @@ public function getMessage() */ public function make() { - while(socket_recv($this->getSocket(), $buffer, 2048, 0)) { + while(socket_recv($this->getSocket(), $buffer, $this->length, $this->flag)) { $this->message .= $buffer; } From ce24570dc119ae5894b7c4f504703b9cafc97d0e Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 1 Dec 2020 18:57:20 +0300 Subject: [PATCH 25/41] Moved socket actions in Actions/ dir --- src/ActionFactory.php | 26 +++++++++++++++------- src/{ => Actions}/AbstractSocketAction.php | 2 +- src/{ => Actions}/SocketAcceptor.php | 2 +- src/{ => Actions}/SocketBinder.php | 2 +- src/{ => Actions}/SocketCloser.php | 2 +- src/{ => Actions}/SocketConnector.php | 2 +- src/{ => Actions}/SocketCreator.php | 2 +- src/{ => Actions}/SocketListener.php | 2 +- src/{ => Actions}/SocketReader.php | 2 +- src/{ => Actions}/SocketWriter.php | 2 +- 10 files changed, 27 insertions(+), 17 deletions(-) rename src/{ => Actions}/AbstractSocketAction.php (91%) rename src/{ => Actions}/SocketAcceptor.php (95%) rename src/{ => Actions}/SocketBinder.php (97%) rename src/{ => Actions}/SocketCloser.php (95%) rename src/{ => Actions}/SocketConnector.php (97%) rename src/{ => Actions}/SocketCreator.php (97%) rename src/{ => Actions}/SocketListener.php (97%) rename src/{ => Actions}/SocketReader.php (97%) rename src/{ => Actions}/SocketWriter.php (97%) diff --git a/src/ActionFactory.php b/src/ActionFactory.php index 2adec15..8143e37 100644 --- a/src/ActionFactory.php +++ b/src/ActionFactory.php @@ -3,6 +3,16 @@ namespace Qonsillium; use Qonsillium\Credential\SocketCredentials; +use Qonsillium\Actions\{ + SocketAcceptor, + SocketBinder, + SocketCloser, + SocketConnector, + SocketCreator, + SocketListener, + SocketReader, + SocketWriter +}; class ActionFactory { @@ -105,7 +115,7 @@ private function getReadFlag() } /** - * @return \Qonsillium\SocketCreator + * @return \Qonsillium\Actions\SocketCreator */ public function getCreator(): SocketCreator { @@ -113,7 +123,7 @@ public function getCreator(): SocketCreator } /** - * @return \Qonsillium\SocketAcceptor + * @return \Qonsillium\Actions\SocketAcceptor */ public function getAcceptor(): SocketAcceptor { @@ -121,7 +131,7 @@ public function getAcceptor(): SocketAcceptor } /** - * @return \Qonsillium\SocketConnector + * @return \Qonsillium\Actions\SocketConnector */ public function getConnector(): SocketConnector { @@ -129,7 +139,7 @@ public function getConnector(): SocketConnector } /** - * @return \Qonsillium\SocketListener + * @return \Qonsillium\Actions\SocketListener */ public function getListener(): SocketListener { @@ -137,7 +147,7 @@ public function getListener(): SocketListener } /** - * @return \Qonsillium\SocketBinder + * @return \Qonsillium\Actions\SocketBinder */ public function getBinder(): SocketBinder { @@ -145,7 +155,7 @@ public function getBinder(): SocketBinder } /** - * @return \Qonsillium\SocketReader + * @return \Qonsillium\Actions\SocketReader */ public function getReader(): SocketReader { @@ -153,7 +163,7 @@ public function getReader(): SocketReader } /** - * @return \Qonsillium\SocketWriter + * @return \Qonsillium\Actions\SocketWriter */ public function getWriter(): SocketWriter { @@ -161,7 +171,7 @@ public function getWriter(): SocketWriter } /** - * @return \Qonsillium\SocketCloser + * @return \Qonsillium\Actions\SocketCloser */ public function getCloser(): SocketCloser { diff --git a/src/AbstractSocketAction.php b/src/Actions/AbstractSocketAction.php similarity index 91% rename from src/AbstractSocketAction.php rename to src/Actions/AbstractSocketAction.php index f02380e..76e7e25 100644 --- a/src/AbstractSocketAction.php +++ b/src/Actions/AbstractSocketAction.php @@ -1,6 +1,6 @@ Date: Tue, 1 Dec 2020 19:13:30 +0300 Subject: [PATCH 26/41] Added and configured phpunit.xml file --- .gitignore | 1 + phpunit.xml.dist | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 phpunit.xml.dist diff --git a/.gitignore b/.gitignore index 659c53b..4ffc936 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /vendor/ /.vscode/ composer.lock +phpunit.xml diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..0bafd3a --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,8 @@ + + + + + tests/unit + + + \ No newline at end of file From 238324a9ffa6d5b25cea5bcd20230c2f7a42d437 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 1 Dec 2020 20:30:52 +0300 Subject: [PATCH 27/41] Written tests for Credential, Parsers and Types classes in folders --- .../unit/Credential/SocketCredentialTest.php | 25 ++++++++++++++ .../unit/Parsers/ConfigParsersFactoryTest.php | 22 +++++++++++++ tests/unit/Parsers/JSONConfigParserTest.php | 16 +++++++++ tests/unit/Parsers/YAMLConfigParserTest.php | 16 +++++++++ tests/unit/Types/SocketTypeFactoryTest.php | 25 ++++++++++++++ tests/unit/Types/TypeConfigurationTest.php | 33 +++++++++++++++++++ tests/unit/fixtures/config_tcp.json | 13 ++++++++ tests/unit/fixtures/config_tcp.yaml | 10 ++++++ tests/unit/fixtures/config_unix.json | 12 +++++++ tests/unit/fixtures/config_unix.yaml | 9 +++++ 10 files changed, 181 insertions(+) create mode 100644 tests/unit/Credential/SocketCredentialTest.php create mode 100644 tests/unit/Parsers/ConfigParsersFactoryTest.php create mode 100644 tests/unit/Parsers/JSONConfigParserTest.php create mode 100644 tests/unit/Parsers/YAMLConfigParserTest.php create mode 100644 tests/unit/Types/SocketTypeFactoryTest.php create mode 100644 tests/unit/Types/TypeConfigurationTest.php create mode 100644 tests/unit/fixtures/config_tcp.json create mode 100644 tests/unit/fixtures/config_tcp.yaml create mode 100644 tests/unit/fixtures/config_unix.json create mode 100644 tests/unit/fixtures/config_unix.yaml diff --git a/tests/unit/Credential/SocketCredentialTest.php b/tests/unit/Credential/SocketCredentialTest.php new file mode 100644 index 0000000..3378a89 --- /dev/null +++ b/tests/unit/Credential/SocketCredentialTest.php @@ -0,0 +1,25 @@ +setCredential('host', '127.0.0.1'); + + $this->assertSame('127.0.0.1', $credentials->getCredential('host')); + } + + public function testPropertyExistenceValidatorReturnsBool() + { + $credentials = new SocketCredentials(); + $credentials->setCredential('port', '8001'); + $this->assertTrue( + $credentials->validateExistence('port'), + "SocketCredentials::validateExistence. Expected property 'port', but doesnt exists" + ); + } +} diff --git a/tests/unit/Parsers/ConfigParsersFactoryTest.php b/tests/unit/Parsers/ConfigParsersFactoryTest.php new file mode 100644 index 0000000..9988322 --- /dev/null +++ b/tests/unit/Parsers/ConfigParsersFactoryTest.php @@ -0,0 +1,22 @@ +assertInstanceOf( + ConfigParser::class, + $factory->getParser(), + 'ConfigParserFactory::getParser, Expected type ConfigParser, but getting null' + ); + } +} diff --git a/tests/unit/Parsers/JSONConfigParserTest.php b/tests/unit/Parsers/JSONConfigParserTest.php new file mode 100644 index 0000000..44e5423 --- /dev/null +++ b/tests/unit/Parsers/JSONConfigParserTest.php @@ -0,0 +1,16 @@ +assertIsArray( + $factory->getParser()->parse(), + "JSONConfigParser::parse. Expected type 'array', but getting null" + ); + } +} diff --git a/tests/unit/Parsers/YAMLConfigParserTest.php b/tests/unit/Parsers/YAMLConfigParserTest.php new file mode 100644 index 0000000..85015c8 --- /dev/null +++ b/tests/unit/Parsers/YAMLConfigParserTest.php @@ -0,0 +1,16 @@ +assertIsArray( + $factory->getParser()->parse(), + "YAMLConfigParser::parse. Expected 'array', but getting null" + ); + } +} diff --git a/tests/unit/Types/SocketTypeFactoryTest.php b/tests/unit/Types/SocketTypeFactoryTest.php new file mode 100644 index 0000000..010ea9f --- /dev/null +++ b/tests/unit/Types/SocketTypeFactoryTest.php @@ -0,0 +1,25 @@ +getParser()->parse()['settings']); + $socketTypeFactory = new SocketTypeFactory($configuration); + + // SocketTypeFactory::getSocket will always return SocketType instance + // that's because we have a null object which contain realize interface of + // SocketType. Even if we will pass wrong file will be returned null object + $this->assertInstanceOf( + SocketType::class, + $socketTypeFactory->getSocket('tcp') + ); + } +} diff --git a/tests/unit/Types/TypeConfigurationTest.php b/tests/unit/Types/TypeConfigurationTest.php new file mode 100644 index 0000000..dc70b8e --- /dev/null +++ b/tests/unit/Types/TypeConfigurationTest.php @@ -0,0 +1,33 @@ +getParser()->parse()['settings']); + $configuration->configure(); + + $this->assertTrue( + $configuration->validateSettingsExistence('domain'), + "TypeConfiguration::validateSettingExistence. Setting 'domain' doesn't exists in settings list" + ); + } + + public function testGetConfigurationSettingReturnsSameString() + { + $factorySettings = new ConfigParsersFactory(dirname(__DIR__, 1) . '/fixtures/config_tcp.yaml'); + $configuration = new TypeConfiguration($factorySettings->getParser()->parse()['settings']); + $configuration->configure(); + + $this->assertSame( + '127.0.0.1', + $configuration->getConfigurationSetting('host'), + "TypeConfiguration::getConfigurationSetting. Expected '127.0.0.1', but got not the same string" + ); + } +} diff --git a/tests/unit/fixtures/config_tcp.json b/tests/unit/fixtures/config_tcp.json new file mode 100644 index 0000000..1b590d2 --- /dev/null +++ b/tests/unit/fixtures/config_tcp.json @@ -0,0 +1,13 @@ +{ + "settings": { + "socket_type": "tcp", + "domain": "AF_INET", + "type": "SOCK_STREAM", + "protocol": "SOL_TCP", + "backkog": "1", + "read_length": "2048", + "read_flag": "MSG_WAITALL", + "host": "127.0.0.1", + "port": "8001" + } +} \ No newline at end of file diff --git a/tests/unit/fixtures/config_tcp.yaml b/tests/unit/fixtures/config_tcp.yaml new file mode 100644 index 0000000..c65f533 --- /dev/null +++ b/tests/unit/fixtures/config_tcp.yaml @@ -0,0 +1,10 @@ +settings: + socket_type: tcp + domain: AF_INET + type: SOCK_STREAM + protocol: SOL_TCP + backlog: 1 + read_length: 2048 + read_flag: MSG_WAITALL + host: 127.0.0.1 + port: 8001 \ No newline at end of file diff --git a/tests/unit/fixtures/config_unix.json b/tests/unit/fixtures/config_unix.json new file mode 100644 index 0000000..8b8a964 --- /dev/null +++ b/tests/unit/fixtures/config_unix.json @@ -0,0 +1,12 @@ +{ + "settings": { + "socket_type": "unix", + "domain": "AF_UNIX", + "type": "SOCK_STREAM", + "protocol": "0", + "backkog": "1", + "read_length": "2048", + "read_flag": "MSG_WAITALL", + "socket_file": "socket.sock" + } +} \ No newline at end of file diff --git a/tests/unit/fixtures/config_unix.yaml b/tests/unit/fixtures/config_unix.yaml new file mode 100644 index 0000000..a8d9e87 --- /dev/null +++ b/tests/unit/fixtures/config_unix.yaml @@ -0,0 +1,9 @@ +settings: + socket_type: unix + domain: AF_UNIX + type: SOCK_STREAM + protocol: 0 + backlog: 1 + read_length: 2048 + read_flag: MSG_WAITALL + socket_file: socket.sock \ No newline at end of file From f5b06b4f98702c4dc75e84e8400cf2113c018ab8 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Wed, 2 Dec 2020 19:53:13 +0300 Subject: [PATCH 28/41] Created socket selector action and set types for actions properties --- .gitignore | 1 + src/ActionFactory.php | 9 +++++++ src/Actions/SocketAcceptor.php | 4 +-- src/Actions/SocketBinder.php | 2 +- src/Actions/SocketCloser.php | 2 +- src/Actions/SocketConnector.php | 4 +-- src/Actions/SocketCreator.php | 2 +- src/Actions/SocketListener.php | 4 +-- src/Actions/SocketReader.php | 9 +++---- src/Actions/SocketSelector.php | 44 +++++++++++++++++++++++++++++++++ src/Actions/SocketWriter.php | 8 +++--- src/Bootstrapper.php | 3 +++ src/QonsilliumSocket.php | 4 +-- src/SocketFacade.php | 28 +++++++++++++++------ 14 files changed, 97 insertions(+), 27 deletions(-) create mode 100644 src/Actions/SocketSelector.php diff --git a/.gitignore b/.gitignore index 659c53b..4ffc936 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /vendor/ /.vscode/ composer.lock +phpunit.xml diff --git a/src/ActionFactory.php b/src/ActionFactory.php index 8143e37..d7d36c7 100644 --- a/src/ActionFactory.php +++ b/src/ActionFactory.php @@ -11,6 +11,7 @@ SocketCreator, SocketListener, SocketReader, + SocketSelector, SocketWriter }; @@ -154,6 +155,14 @@ public function getBinder(): SocketBinder return new SocketBinder($this->getAddress(), $this->getPort()); } + /** + * @return \Qonsillium\Actions\SocketSelector + */ + public function getSelector(): SocketSelector + { + return new SocketSelector(); + } + /** * @return \Qonsillium\Actions\SocketReader */ diff --git a/src/Actions/SocketAcceptor.php b/src/Actions/SocketAcceptor.php index 289b549..677027f 100644 --- a/src/Actions/SocketAcceptor.php +++ b/src/Actions/SocketAcceptor.php @@ -10,7 +10,7 @@ class SocketAcceptor extends AbstractSocketAction * Accepted socket connection * @var \Socket */ - private $acceptedSocket; + private ?Socket $acceptedSocket; /** * @param \Socket $socket @@ -31,7 +31,7 @@ public function getAcceptedSocket() /** * Accept socket connection - * @return resource + * @return \Socket */ public function make() { diff --git a/src/Actions/SocketBinder.php b/src/Actions/SocketBinder.php index befbde7..b59f0d3 100644 --- a/src/Actions/SocketBinder.php +++ b/src/Actions/SocketBinder.php @@ -10,7 +10,7 @@ class SocketBinder extends AbstractSocketAction * Created socket connection * @var \Socket */ - private $socket; + private ?Socket $socket; /** * Host name which will be diff --git a/src/Actions/SocketCloser.php b/src/Actions/SocketCloser.php index e3c0b43..bb79598 100644 --- a/src/Actions/SocketCloser.php +++ b/src/Actions/SocketCloser.php @@ -10,7 +10,7 @@ class SocketCloser extends AbstractSocketAction * Accepted or created socket * @var \Socket */ - private $socket; + private ?Socket $socket; /** * @param \Socket $socket diff --git a/src/Actions/SocketConnector.php b/src/Actions/SocketConnector.php index 719901f..245ffca 100644 --- a/src/Actions/SocketConnector.php +++ b/src/Actions/SocketConnector.php @@ -8,9 +8,9 @@ class SocketConnector extends AbstractSocketAction { /** * Created socket connection - * @var resource + * @var \Socket */ - private $socket; + private ?Socket $socket; /** * Host name where will diff --git a/src/Actions/SocketCreator.php b/src/Actions/SocketCreator.php index 1e522bb..f0c202b 100644 --- a/src/Actions/SocketCreator.php +++ b/src/Actions/SocketCreator.php @@ -11,7 +11,7 @@ class SocketCreator extends AbstractSocketAction * socket_create * @var \Socket */ - private $createdSocket; + private ?Socket $createdSocket; /** * Protocol family to be used diff --git a/src/Actions/SocketListener.php b/src/Actions/SocketListener.php index 6e50377..9e40acf 100644 --- a/src/Actions/SocketListener.php +++ b/src/Actions/SocketListener.php @@ -8,9 +8,9 @@ class SocketListener extends AbstractSocketAction { /** * Created socket - * @var resource + * @var \Socket */ - private $socket; + private ?Socket $socket; /** * Maximum incoming connections diff --git a/src/Actions/SocketReader.php b/src/Actions/SocketReader.php index 04202ca..b7468e0 100644 --- a/src/Actions/SocketReader.php +++ b/src/Actions/SocketReader.php @@ -10,7 +10,7 @@ class SocketReader extends AbstractSocketAction * Created or accepted socket * @var \Socket */ - private $socket; + private ?Socket $socket; /** * Bytes length @@ -66,10 +66,9 @@ public function getMessage() * @return \Qonsillium\SocketReader */ public function make() - { - while(socket_recv($this->getSocket(), $buffer, $this->length, $this->flag)) { - $this->message .= $buffer; - } + { + socket_recv($this->getSocket(), $buffer, $this->length, $this->flag); + $this->message .= $buffer; return $this; } diff --git a/src/Actions/SocketSelector.php b/src/Actions/SocketSelector.php new file mode 100644 index 0000000..e24b046 --- /dev/null +++ b/src/Actions/SocketSelector.php @@ -0,0 +1,44 @@ +socket = $socket; + } + + /** + * @return \Socket + */ + public function getSocket() + { + return $this->socket; + } + + /** + * Runs the select() system call on the given + * arrays of sockets with a specified timeout + * @return int + */ + public function make() + { + $read = [$this->getSocket()]; + $write = null; + $except = null; + + return socket_select($read, $write, $except, 0); + } +} diff --git a/src/Actions/SocketWriter.php b/src/Actions/SocketWriter.php index b059291..1d20c7b 100644 --- a/src/Actions/SocketWriter.php +++ b/src/Actions/SocketWriter.php @@ -8,9 +8,9 @@ class SocketWriter extends AbstractSocketAction { /** * Created or accepted socket - * @var resource + * @var \Socket */ - private $socket; + private ?Socket $socket; /** * Message which will be sent @@ -20,7 +20,7 @@ class SocketWriter extends AbstractSocketAction private string $message; /** - * @param resource $socket + * @param \Socket $socket * @return void */ public function setSocket(Socket $socket) @@ -29,7 +29,7 @@ public function setSocket(Socket $socket) } /** - * @return resource + * @return \Socket */ public function getSocket(): Socket { diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php index eb6d3ca..8dbb1ab 100644 --- a/src/Bootstrapper.php +++ b/src/Bootstrapper.php @@ -24,6 +24,9 @@ class Bootstrapper */ protected array $settings; + /** + * @var \Qonsillium\Types\TypeConfiguration + */ protected ?TypeConfiguration $configuration; /** diff --git a/src/QonsilliumSocket.php b/src/QonsilliumSocket.php index b2f2fec..bd8aecc 100644 --- a/src/QonsilliumSocket.php +++ b/src/QonsilliumSocket.php @@ -62,7 +62,7 @@ protected function getServerSocket(): ServerSocket */ public function runClient(Closure $handler) { - call_user_func($handler($this->getClientSocket())); + $handler($this->getClientSocket()); } /** @@ -80,6 +80,6 @@ public function runClient(Closure $handler) */ public function runServer(Closure $handler) { - call_user_func($handler($this->getServerSocket())); + $handler($this->getServerSocket()); } } diff --git a/src/SocketFacade.php b/src/SocketFacade.php index 9743ad7..f5e0351 100644 --- a/src/SocketFacade.php +++ b/src/SocketFacade.php @@ -41,7 +41,7 @@ public function __construct(ActionFactory $factory) /** * Create socket. While can create only * TCP socket - * @return bool|resource + * @return bool|\Socket */ protected function createSocket() { @@ -127,6 +127,20 @@ protected function connectSocket($socket) return $connectionAction; } + /** + * Accepts arrays of sockets and waits for them + * to change status + * @param \Socket $socket + * @return int + */ + public function selectSocket($socket) + { + $selector = $this->factory->getSelector(); + $selector->setSocket($socket); + + return $selector(); + } + /** * Read messages from client or server sockets * @param \Socket $socket @@ -218,10 +232,10 @@ public function sendFromServer(string $message) throw new FailedWriteSocket('Failed to write socket'); } - $readedSocket = $this->readSocket($accept); + $readedSocket = false; - if (!$readedSocket) { - throw new FailedReadSocket('Failed to write socket'); + while ($this->selectSocket($accept)) { + $readedSocket = $this->readSocket($accept); } return $readedSocket; @@ -251,10 +265,10 @@ public function sendFromClient(string $message) throw new FailedWriteSocket('Failed to write socket'); } - $readedSocket = $this->readSocket($this->createdSocket); + $readedSocket = false; - if (!$readedSocket) { - throw new FailedReadSocket('Failed to read socket'); + while ($this->selectSocket($this->createdSocket)) { + $readedSocket = $this->readSocket($this->createdSocket); } return $readedSocket; From ceb19e5f36af5830fbf1a88bf9132746cf48bcba Mon Sep 17 00:00:00 2001 From: rubyqorn <51966037+rubyqorn@users.noreply.github.com> Date: Sat, 5 Dec 2020 18:11:42 +0300 Subject: [PATCH 29/41] Update README.md --- README.md | 126 +----------------------------------------------------- 1 file changed, 1 insertion(+), 125 deletions(-) diff --git a/README.md b/README.md index 68fcf26..aa45afc 100644 --- a/README.md +++ b/README.md @@ -2,128 +2,4 @@ # Socket ## This is a layer for client and server socket connections. - -### PHP extension which have to be installed before to work: -* [Yaml](https://www.php.net/manual/en/book.yaml.php) -* [Sockets](https://www.php.net/manual/en/book.sockets.php) - -### Four actions you have to make: -* Configure your configuration file. -* Create client.php or server.php file -* Call methods -* Run from CLI or extends - -### Examples of TCP and UNIX sockets: - -#### 1) Create configuration file. File can be **ONLY** with yaml(yml) or json extensions - -##### * TCP socket configuration using YAML -``` -settings: - socket_type: tcp - domain: AF_INET - type: SOCK_STREAM - protocol: SOL_TCP - backlog: 1 - host: '127.0.0.1' - port: '8001' - read_length: 2048 - read_flag: MSG_WAITALL -``` - -##### * UNIX socket configuration using YAML -``` -settings: - socket_type: unix - domain: AF_UNIX - type: SOCK_STREAM - protocol: 0 - backlog: 1 - socket_file: socket.sock - read_length: 2048 - read_flag: MSG_WAITALL -``` - -#### 2) Create client and server file handlers. - -##### server.php -``` -runServer(function(ServerSocket $socket) { - echo $socket->send('Hello from server!'); -}); -``` - -##### client.php -``` -runClient(function(ClinetSocket $socket) { - echo $socket->send('Hello from client!'); -}); -``` - -#### 3) Run from CLI -``` - john@doe:/workdir/$ php server.php - john@doe:/workdir/$ php client.php -``` - -## List of available configuration vars: -#### 1) sock_type - Type of socket which will be created. -* tcp -* unix - -#### 2) domain - Specifies the protocol family -* AF_INET -* AF_INET6 -* AF_UNIX - -#### 3) type - Selects the type of communication -* SOCK_STREAM -* SOCK_DGRAM -* SOCK_SEQPACKET -* SOCK_RAW -* SOCK_RDM - -#### 3) protocol - Sets the specific protocol within the specified domain to be used when communicating on the returned socket -* SOL_TCP -* SOL_UDP -* 0 (when use unix) - -#### 4) backlog - A maximum of backlog incoming connections will be queued for processing -* Number of incoming backlogs (1 or 2 etc.) - -#### 5) host - Host name which where will be accepted or created connection. Can be used when if socket is of the AF_INET family -* 127.0.0.1 - -#### 6) port - The port parameter is only used when binding an AF_INET socket, and designates the port on which to listen for connections. -* from 1024 to 65535 - -#### 7) socket_file - If the socket is of the AF_UNIX family, the address is the path of a Unix-domain socket. You can create own socket file but you must make that you set correct path and this file have read and write rights. Or you can set random name in work dir and here will be created socket file -* /tmp/socket.sock -* socket.sock - -#### 8) read_length - The maximum number of bytes read is specified by the length parameter. -* 2048, 4096 etc - -#### 9) read_flag - The flags responded for reading status. -* MSG_OOB -* MSG_PEEK -* MSG_WAITALL -* MSG_DONTWAIT - -###### For details you can refer to the [PHP](https://php.net) documentation +#### [Detailed documentation](http://socket-docs.epizy.com) From 91a1f94009458dd8bccd63a23ddad6ad412018e3 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 8 Dec 2020 01:33:13 +0300 Subject: [PATCH 30/41] Migrated to stream socket functions --- src/ActionFactory.php | 121 +------------ src/Actions/AbstractSocketAction.php | 23 +++ src/Actions/Connections/ClientConnection.php | 19 ++ src/Actions/Connections/Connection.php | 58 ++++++ src/Actions/Connections/ConnectionFactory.php | 20 ++ src/Actions/Connections/ServerConnection.php | 19 ++ src/Actions/SocketAcceptor.php | 31 +--- src/Actions/SocketBinder.php | 68 ------- src/Actions/SocketCloser.php | 29 +-- src/Actions/SocketConnector.php | 57 ++---- src/Actions/SocketCreator.php | 71 -------- src/Actions/SocketListener.php | 57 ------ src/Actions/SocketReader.php | 53 +----- src/Actions/SocketSelector.php | 44 ----- src/Actions/SocketWriter.php | 38 +--- src/SocketFacade.php | 171 ++++-------------- 16 files changed, 215 insertions(+), 664 deletions(-) create mode 100644 src/Actions/Connections/ClientConnection.php create mode 100644 src/Actions/Connections/Connection.php create mode 100644 src/Actions/Connections/ConnectionFactory.php create mode 100644 src/Actions/Connections/ServerConnection.php delete mode 100644 src/Actions/SocketBinder.php delete mode 100644 src/Actions/SocketCreator.php delete mode 100644 src/Actions/SocketListener.php delete mode 100644 src/Actions/SocketSelector.php diff --git a/src/ActionFactory.php b/src/ActionFactory.php index d7d36c7..44a3386 100644 --- a/src/ActionFactory.php +++ b/src/ActionFactory.php @@ -5,13 +5,9 @@ use Qonsillium\Credential\SocketCredentials; use Qonsillium\Actions\{ SocketAcceptor, - SocketBinder, SocketCloser, SocketConnector, - SocketCreator, - SocketListener, SocketReader, - SocketSelector, SocketWriter }; @@ -34,93 +30,20 @@ public function __construct(SocketCredentials $credentials) } /** - * Returns socket domain setting from config file + * Returns socket connection address * @return string */ - private function getDomain() + public function getAddress() { - return $this->credentials->getCredential('domain'); - } - - /** - * Returns socket type setting from config file - * @return string - */ - private function getType() - { - return $this->credentials->getCredential('type'); - } - - /** - * Returns socket protocol setting from config file - * @return string - */ - private function getProtocol() - { - return $this->credentials->getCredential('protocol'); - } - - /** - * Return setted host or socket file name from - * credentials handler - * @return string - */ - private function getAddress() - { - if ($this->credentials->validateExistence('socket_file')) { - return $this->credentials->getCredential('socket_file'); - } - return $this->credentials->getCredential('host'); } /** - * Return setted socket port from - * credentials handler - * @return string - */ - private function getPort() - { - if ($this->credentials->validateExistence('port')) { - return $this->credentials->getCredential('port'); - } - - return 0; - } - - /** - * Returns number of incoming backlogs - * @return int - */ - private function getBacklog() - { - return $this->credentials->getCredential('backlog'); - } - - /** - * Bytes length which will be fetched from remote host - * @return int - */ - private function getReadLength() - { - return $this->credentials->getCredential('read_length'); - } - - /** - * Return flag value responded for reading status - * @return int - */ - private function getReadFlag() - { - return $this->credentials->getCredential('read_flag'); - } - - /** - * @return \Qonsillium\Actions\SocketCreator + * @return \Qonsillium\Actions\SocketConnector */ - public function getCreator(): SocketCreator + public function getConnector(string $type) { - return new SocketCreator($this->getDomain(), $this->getType(), $this->getProtocol()); + return new SocketConnector($this->getAddress(), $type); } /** @@ -131,44 +54,12 @@ public function getAcceptor(): SocketAcceptor return new SocketAcceptor(); } - /** - * @return \Qonsillium\Actions\SocketConnector - */ - public function getConnector(): SocketConnector - { - return new SocketConnector($this->getAddress(), $this->getPort()); - } - - /** - * @return \Qonsillium\Actions\SocketListener - */ - public function getListener(): SocketListener - { - return new SocketListener($this->getBacklog()); - } - - /** - * @return \Qonsillium\Actions\SocketBinder - */ - public function getBinder(): SocketBinder - { - return new SocketBinder($this->getAddress(), $this->getPort()); - } - - /** - * @return \Qonsillium\Actions\SocketSelector - */ - public function getSelector(): SocketSelector - { - return new SocketSelector(); - } - /** * @return \Qonsillium\Actions\SocketReader */ public function getReader(): SocketReader { - return new SocketReader($this->getReadLength(), $this->getReadFlag()); + return new SocketReader(); } /** diff --git a/src/Actions/AbstractSocketAction.php b/src/Actions/AbstractSocketAction.php index 76e7e25..1a3b665 100644 --- a/src/Actions/AbstractSocketAction.php +++ b/src/Actions/AbstractSocketAction.php @@ -4,6 +4,12 @@ abstract class AbstractSocketAction { + /** + * Created socket resource + * @var resource + */ + protected $socket; + /** * Make socket action when need * to make class like function @@ -14,6 +20,23 @@ public function __invoke() return $this->make(); } + /** + * @param resource $socket + * @return void + */ + public function setSocket($socket) + { + $this->socket = $socket; + } + + /** + * @return resource + */ + public function getSocket() + { + return $this->socket; + } + /** * Make socket action * @return mixed diff --git a/src/Actions/Connections/ClientConnection.php b/src/Actions/Connections/ClientConnection.php new file mode 100644 index 0000000..b365ee4 --- /dev/null +++ b/src/Actions/Connections/ClientConnection.php @@ -0,0 +1,19 @@ +getAddress(), + $errno, + $errstr + ); + } +} diff --git a/src/Actions/Connections/Connection.php b/src/Actions/Connections/Connection.php new file mode 100644 index 0000000..8c0a02c --- /dev/null +++ b/src/Actions/Connections/Connection.php @@ -0,0 +1,58 @@ +address = $address; + } + + /** + * @return string + */ + public function getAddress() + { + return $this->address; + } + + /** + * @param int $timeout + * @return void + */ + public function setTimeout(int $timeout) + { + $this->timeout = $timeout; + } + + /** + * @return int + */ + public function getTimeout() + { + return $this->timeout; + } + + /** + * Create client or server socket connection + * @return resource + */ + abstract public function create(); +} diff --git a/src/Actions/Connections/ConnectionFactory.php b/src/Actions/Connections/ConnectionFactory.php new file mode 100644 index 0000000..550679a --- /dev/null +++ b/src/Actions/Connections/ConnectionFactory.php @@ -0,0 +1,20 @@ +getAddress(), + $errno, + $errstr + ); + } +} diff --git a/src/Actions/SocketAcceptor.php b/src/Actions/SocketAcceptor.php index 677027f..00a5a1f 100644 --- a/src/Actions/SocketAcceptor.php +++ b/src/Actions/SocketAcceptor.php @@ -2,39 +2,14 @@ namespace Qonsillium\Actions; -use \Socket; - class SocketAcceptor extends AbstractSocketAction { /** - * Accepted socket connection - * @var \Socket - */ - private ?Socket $acceptedSocket; - - /** - * @param \Socket $socket - * @return void - */ - public function setAcceptSocket(Socket $socket) - { - $this->acceptedSocket = $socket; - } - - /** - * @return \Socket - */ - public function getAcceptedSocket() - { - return $this->acceptedSocket; - } - - /** - * Accept socket connection - * @return \Socket + * Accept socket connections + * @return resource */ public function make() { - return socket_accept($this->getAcceptedSocket()); + return stream_socket_accept($this->getSocket()); } } diff --git a/src/Actions/SocketBinder.php b/src/Actions/SocketBinder.php deleted file mode 100644 index b59f0d3..0000000 --- a/src/Actions/SocketBinder.php +++ /dev/null @@ -1,68 +0,0 @@ -address = $address; - $this->port = $port; - } - - /** - * @param \Socket $socket - * @return void - */ - public function setSocket(Socket $socket) - { - $this->socket = $socket; - } - - /** - * @return \Socket - */ - public function getSocket(): Socket - { - return $this->socket; - } - - /** - * Bind host and port values with - * creatd socket - * @return bool - */ - public function make() - { - return socket_bind($this->getSocket(), $this->address, $this->port); - } -} diff --git a/src/Actions/SocketCloser.php b/src/Actions/SocketCloser.php index bb79598..e69a4d3 100644 --- a/src/Actions/SocketCloser.php +++ b/src/Actions/SocketCloser.php @@ -2,39 +2,14 @@ namespace Qonsillium\Actions; -use \Socket; - class SocketCloser extends AbstractSocketAction { /** - * Accepted or created socket - * @var \Socket - */ - private ?Socket $socket; - - /** - * @param \Socket $socket - * @return void - */ - public function setSocket(Socket $socket) - { - $this->socket = $socket; - } - - /** - * @return \Socket - */ - public function getSocket(): Socket - { - return $this->socket; - } - - /** - * Close created or accepted socket connection + * Close created socket connections * @return void */ public function make() { - return socket_close($this->getSocket()); + return fclose($this->getSocket()); } } diff --git a/src/Actions/SocketConnector.php b/src/Actions/SocketConnector.php index 245ffca..0294993 100644 --- a/src/Actions/SocketConnector.php +++ b/src/Actions/SocketConnector.php @@ -2,67 +2,40 @@ namespace Qonsillium\Actions; -use \Socket; +use Qonsillium\Actions\Connections\ConnectionFactory; class SocketConnector extends AbstractSocketAction { /** - * Created socket connection - * @var \Socket - */ - private ?Socket $socket; - - /** - * Host name where will - * be connected * @var string */ - private string $host; + private string $address; /** - * Socket port where - * will be connected - * @var int + * @var string */ - private int $port; + private string $type; /** - * Initiate SocketConnector constructor method and - * set socket host and port values - * @param string $host - * @param int $port + * Initiate SocketConnector constructor method + * @param string $method + * @param string $type * @return void */ - public function __construct(string $host, int $port) - { - $this->host = $host; - $this->port = $port; - } - - /** - * @param \Socket $socket - * @return void - */ - public function setCreatedSocket(Socket $socket) - { - $this->socket = $socket; - } - - /** - * @return \Socket - */ - public function getConnectedSocket(): Socket + public function __construct(string $address, string $type) { - return $this->socket; + $this->address = $address; + $this->type = $type; } /** - * Connect to created socket and specific host with - * port - * @return bool + * Create client or server socket connection + * @return \Qonsillium\Actions\Connections\Connection */ public function make() { - return socket_connect($this->getConnectedSocket(), $this->host, $this->port); + $connection = ConnectionFactory::getConnection($this->type); + $connection->setAddress($this->address); + return $connection; } } diff --git a/src/Actions/SocketCreator.php b/src/Actions/SocketCreator.php deleted file mode 100644 index f0c202b..0000000 --- a/src/Actions/SocketCreator.php +++ /dev/null @@ -1,71 +0,0 @@ -domain = $domain; - $this->type = $type; - $this->protocol = $protocol; - } - - /** - * Create socket. Lately have to refactor - * hard coded socket_create parameters - * @return \Qonsillium\SocketCreator - */ - public function make() - { - $this->createdSocket = socket_create($this->domain, $this->type, $this->protocol); - return $this; - } - - /** - * @return \Socket - */ - public function getCreatedSocket(): Socket - { - return $this->createdSocket; - } -} diff --git a/src/Actions/SocketListener.php b/src/Actions/SocketListener.php deleted file mode 100644 index 9e40acf..0000000 --- a/src/Actions/SocketListener.php +++ /dev/null @@ -1,57 +0,0 @@ -backlog = $backlog; - } - - /** - * @param \Socket $socket - * @return void - */ - public function setCreatedSocket(Socket $socket) - { - $this->socket = $socket; - } - - /** - * @return \Socket - */ - public function getListenedSocket(): Socket - { - return $this->socket; - } - - /** - * Listen socket connections - * @return book - */ - public function make() - { - return socket_listen($this->getListenedSocket(), $this->backlog); - } -} diff --git a/src/Actions/SocketReader.php b/src/Actions/SocketReader.php index b7468e0..def0e7e 100644 --- a/src/Actions/SocketReader.php +++ b/src/Actions/SocketReader.php @@ -2,55 +2,20 @@ namespace Qonsillium\Actions; -use \Socket; - class SocketReader extends AbstractSocketAction { /** - * Created or accepted socket - * @var \Socket - */ - private ?Socket $socket; - - /** - * Bytes length - * @var int - */ - private int $length; - - /** - * Read status - * @var int - */ - private int $flag; - - /** - * Readed message from socket * @var string */ - private string $message = ''; - - public function __construct(int $length, int $flag = 0) - { - $this->length = $length; - $this->flag = $flag; - } + private string $message; /** - * @param \Socket $socket + * @param string $message * @return void */ - public function setSocket(Socket $socket) - { - $this->socket = $socket; - } - - /** - * @return \Socket - */ - public function getSocket(): Socket + public function setMessage(string $message) { - return $this->socket; + $this->message = $message; } /** @@ -62,14 +27,12 @@ public function getMessage() } /** - * Read messages from createdd or accepted sockets - * @return \Qonsillium\SocketReader + * Read content from connected socket + * @return \Qonsillium\Actions\SocketReader */ public function make() - { - socket_recv($this->getSocket(), $buffer, $this->length, $this->flag); - $this->message .= $buffer; - + { + $this->setMessage(fread($this->getSocket(), 2048)); return $this; } } diff --git a/src/Actions/SocketSelector.php b/src/Actions/SocketSelector.php deleted file mode 100644 index e24b046..0000000 --- a/src/Actions/SocketSelector.php +++ /dev/null @@ -1,44 +0,0 @@ -socket = $socket; - } - - /** - * @return \Socket - */ - public function getSocket() - { - return $this->socket; - } - - /** - * Runs the select() system call on the given - * arrays of sockets with a specified timeout - * @return int - */ - public function make() - { - $read = [$this->getSocket()]; - $write = null; - $except = null; - - return socket_select($read, $write, $except, 0); - } -} diff --git a/src/Actions/SocketWriter.php b/src/Actions/SocketWriter.php index 1d20c7b..44df756 100644 --- a/src/Actions/SocketWriter.php +++ b/src/Actions/SocketWriter.php @@ -2,40 +2,13 @@ namespace Qonsillium\Actions; -use \Socket; - class SocketWriter extends AbstractSocketAction { /** - * Created or accepted socket - * @var \Socket - */ - private ?Socket $socket; - - /** - * Message which will be sent - * on server or client socket * @var string */ private string $message; - /** - * @param \Socket $socket - * @return void - */ - public function setSocket(Socket $socket) - { - $this->socket = $socket; - } - - /** - * @return \Socket - */ - public function getSocket(): Socket - { - return $this->socket; - } - /** * @param string $message * @return void @@ -54,16 +27,11 @@ public function getMessage() } /** - * Send specific message on created - * or accepted socket - * @return int|bool + * Write messages to connected socket + * @return int */ public function make() { - return socket_write( - $this->getSocket(), - $this->getMessage(), - strlen($this->getMessage()) - ); + return fwrite($this->getSocket(), $this->getMessage(), strlen($this->getMessage())); } } diff --git a/src/SocketFacade.php b/src/SocketFacade.php index f5e0351..0c45b01 100644 --- a/src/SocketFacade.php +++ b/src/SocketFacade.php @@ -12,7 +12,6 @@ FailedBindSocket, FailedReadSocket }; -use \Socket; class SocketFacade { @@ -22,10 +21,10 @@ class SocketFacade private ?ActionFactory $factory = null; /** - * Created socket by socket_create - * @var \Socket + * Readed socket content + * @var string */ - private $createdSocket; + private string $content = ''; /** * Initiate SocketFacade constructor method and @@ -39,56 +38,14 @@ public function __construct(ActionFactory $factory) } /** - * Create socket. While can create only - * TCP socket - * @return bool|\Socket + * Connect to client or server socket + * @param string $connectionType (server|client) + * @return resource */ - protected function createSocket() + public function connectSocket(string $connectionType) { - $socket = $this->factory->getCreator()(); - - if(!$socket) { - return false; - } - - $this->createdSocket = $socket->getCreatedSocket(); - return $this->createdSocket; - } - - /** - * Bind socket host and port - * @param \Socket $socket - * @return bool - */ - protected function bindSocket($socket) - { - $binder = $this->factory->getBinder(); - $binder->setSocket($socket); - $bindAction = $binder(); - - if (!$bindAction) { - return false; - } - - return $bindAction; - } - - /** - * Listen socket connections - * @param \Socket $socket - * @return bool - */ - protected function listenSocket($socket) - { - $listener = $this->factory->getListener(); - $listener->setCreatedSocket($socket); - $listenAction = $listener(); - - if (!$listenAction) { - return false; - } - - return $listenAction; + $connector = $this->factory->getConnector($connectionType); + return $connector()->create(); } /** @@ -99,7 +56,7 @@ protected function listenSocket($socket) protected function acceptSocket($socket) { $acceptor = $this->factory->getAcceptor(); - $acceptor->setAcceptSocket($socket); + $acceptor->setSocket($socket); $acceptAction = $acceptor(); if (!$acceptAction) { @@ -109,38 +66,6 @@ protected function acceptSocket($socket) return $acceptAction; } - /** - * Connect to created socket - * @param \Socket $socket - * @return bool - */ - protected function connectSocket($socket) - { - $connector = $this->factory->getConnector(); - $connector->setCreatedSocket($socket); - $connectionAction = $connector(); - - if (!$connectionAction) { - return false; - } - - return $connectionAction; - } - - /** - * Accepts arrays of sockets and waits for them - * to change status - * @param \Socket $socket - * @return int - */ - public function selectSocket($socket) - { - $selector = $this->factory->getSelector(); - $selector->setSocket($socket); - - return $selector(); - } - /** * Read messages from client or server sockets * @param \Socket $socket @@ -184,14 +109,10 @@ protected function writeSocket($socket, string $message) * @throws \Qonsillium\Exceptions\FailedCloseSocket * @return void */ - public function closeSocket() + public function closeSocket($socket) { - if (!$this->createdSocket) { - throw new FailedCloseSocket('Failed close, because doesn\'t exists'); - } - $closer = $this->factory->getCloser(); - $closer->setSocket($this->createdSocket); + $closer->setSocket($socket); return $closer(); } @@ -200,77 +121,63 @@ public function closeSocket() * Here we create, bind, listen, accept, read and * write socket * @param string $message - * @throws \Qonsillium\Exceptions\FailedCreateSocket - * @throws \Qonsillium\Exceptions\FailedBindSocket - * @throws \Qonsillium\Exceptions\FailedListenSocket - * @throws \Qonsillium\Exceptions\FailedAcceptSocket + * @throws \Qonsillium\Exceptions\FailedCconnectSocket * @throws \Qonsillium\Exceptions\FailedWriteSocket - * @throws \Qonsillium\Exceptions\FailedReadSocket - * @return \Qonsillium\SocketReader + * @return string */ public function sendFromServer(string $message) { - if (!$this->createSocket()) { - throw new FailedCreateSocket('Failed to create socket'); - } - - if (!$this->bindSocket($this->createdSocket)) { - throw new FailedBindSocket('Failed to bind socket'); - } + $server = $this->connectSocket('server'); - if (!$this->listenSocket($this->createdSocket)) { - throw new FailedListenSocket('Failed to listen socket'); + if (!$server) { + throw new FailedConnectSocket('Failed to connect server socket'); } - $accept = $this->acceptSocket($this->createdSocket); + while ($client = $this->acceptSocket($server)) { + $written = $this->writeSocket($client, $message); - if (!$accept) { - throw new FailedAcceptSocket('Failed accept socket'); - } + if (!$written) { + throw new FailedWriteSocket('Failed to write to client socket'); + } - if (!$this->writeSocket($accept, $message)) { - throw new FailedWriteSocket('Failed to write socket'); + $this->content .= $this->readSocket($client)->getMessage(); + $this->closeSocket($client); } - $readedSocket = false; - - while ($this->selectSocket($accept)) { - $readedSocket = $this->readSocket($accept); - } + $this->closeSocket($server); - return $readedSocket; + return $this->content; } /** * This method can be used only with ClientSocket. * Here we create, read and write socket * @param string $message - * @throws \Qonsillium\Exceptions\FailedCreateSocket * @throws \Qonsillium\Exceptions\FailedConnectSocket * @throws \Qonsillium\Exceptions\FailedWriteSocket * @throws \Qonsillium\Exceptions\FailedReadSocket - * @return \Qonsillium\SocketReader + * @return string */ public function sendFromClient(string $message) { - if (!$this->createSocket()) { - throw new FailedCreateSocket('Failed to create socket'); - } + $client = $this->connectSocket('client'); - if (!$this->connectSocket($this->createdSocket)) { - throw new FailedConnectSocket('Failed to connect socket'); + if (!$client) { + throw new FailedConnectSocket('Failed to connect client socket'); } - if (!$this->writeSocket($this->createdSocket, $message)) { - throw new FailedWriteSocket('Failed to write socket'); - } + $written = $this->writeSocket($client, $message); - $readedSocket = false; + if (!$written) { + throw new FailedWriteSocket('Failed to write to server socket'); + } - while ($this->selectSocket($this->createdSocket)) { - $readedSocket = $this->readSocket($this->createdSocket); + while(!feof($client)) { + $this->content .= $this->readSocket($client)->getMessage(); } - return $readedSocket; + $this->closeSocket($client); + + return $this->content; } } From 10e3b6c73cf76a0b3c7e3a25c8fbe19727e776c4 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 8 Dec 2020 01:54:07 +0300 Subject: [PATCH 31/41] Removed close method from abstracts credentials settings from bootstrapper --- src/AbstractSocket.php | 17 -------------- src/Bootstrapper.php | 51 +----------------------------------------- src/ClientSocket.php | 12 +--------- src/ServerSocket.php | 12 +--------- 4 files changed, 3 insertions(+), 89 deletions(-) diff --git a/src/AbstractSocket.php b/src/AbstractSocket.php index 06d30a0..0ec67a0 100644 --- a/src/AbstractSocket.php +++ b/src/AbstractSocket.php @@ -26,21 +26,4 @@ public function __construct(SocketFacade $facade) * @return string|bool */ abstract public function send(string $message); - - /** - * Close created socket connection - * @throws \Qonsillium\Exceptions\FailedCloseSocket - * @return void - */ - abstract public function close(); - - /** - * Destruct AbstractSocket class and - * close socket connection - * @return void - */ - public function __destruct() - { - $this->close(); - } } diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php index 8dbb1ab..5835ce8 100644 --- a/src/Bootstrapper.php +++ b/src/Bootstrapper.php @@ -74,58 +74,9 @@ public function setCredentials() $socketTypeFactory = $this->getSocketTypeFactory(); $socketType = $socketTypeFactory->getSocket($this->settings['settings']['socket_type']); - - $credentials->setCredential( - 'domain', - $this->getConstValue('domain', $socketType->get('domain')) - ); - - $credentials->setCredential( - 'type', - $this->getConstValue('type', $socketType->get('type')) - ); - - $credentials->setCredential( - 'protocol', - $this->getConstValue('protocol', $socketType->get('protocol')) - ); - - $credentials->setCredential( - 'backlog', - $socketType->get('backlog') - ); - - $credentials->setCredential( - 'read_length', - $socketType->get('read_length') - ); - - $credentials->setCredential( - 'read_flag', - $this->getConstValue('read_flags', $socketType->get('read_flag')) - ); - - // We have two types of sockets it's TCP or Unix, so also - // we have two handlers which contain this settings - // TCP handler contains host and port and Unix handler - // socket file - if ($socketType->validate('socket_file')) { - $credentials->setCredential( - 'socket_file', - $socketType->get('socket_file') - ); - - return $credentials; - } - $credentials->setCredential( 'host', - $socketType->get('host') - ); - - $credentials->setCredential( - 'port', - $socketType->get('port') + "{$socketType->get('socket_type')}://{$socketType->get('address')}:{$socketType->get('port')}" ); return $credentials; diff --git a/src/ClientSocket.php b/src/ClientSocket.php index 63b08ce..53fdd73 100644 --- a/src/ClientSocket.php +++ b/src/ClientSocket.php @@ -18,16 +18,6 @@ public function send(string $message) return false; } - return $sendedMessage->getMessage(); - } - - /** - * Close socket created socket connection - * @throws \Qonsillium\Exceptions\FailedCloseSocket - * @return void - */ - public function close() - { - return $this->facade->closeSocket(); + return $sendedMessage; } } diff --git a/src/ServerSocket.php b/src/ServerSocket.php index 5b68657..2814ed0 100644 --- a/src/ServerSocket.php +++ b/src/ServerSocket.php @@ -18,16 +18,6 @@ public function send(string $message) return false; } - return $sendedMessage->getMessage(); - } - - /** - * Close socket created socket connection - * @throws \Qonsillium\Exceptions\FailedCloseSocket - * @return void - */ - public function close() - { - return $this->facade->closeSocket(); + return $sendedMessage; } } From e210aa91c08540c8656217f21b8f7ba2d09283c7 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 8 Dec 2020 22:43:43 +0300 Subject: [PATCH 32/41] Removed hardcoded read length and setted timeout setting in client socket connection --- src/ActionFactory.php | 11 ++++++++++- src/Actions/Connections/ClientConnection.php | 3 ++- src/Actions/Connections/Connection.php | 4 ++-- src/Actions/SocketReader.php | 17 ++++++++++++++++- src/Bootstrapper.php | 18 ++++++++++++++++-- src/SocketFacade.php | 6 ------ 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/ActionFactory.php b/src/ActionFactory.php index 44a3386..672bdef 100644 --- a/src/ActionFactory.php +++ b/src/ActionFactory.php @@ -38,6 +38,15 @@ public function getAddress() return $this->credentials->getCredential('host'); } + /** + * Returns socket read legnth + * @return int + */ + private function getReadLength() + { + return $this->credentials->getCredential('content_length'); + } + /** * @return \Qonsillium\Actions\SocketConnector */ @@ -59,7 +68,7 @@ public function getAcceptor(): SocketAcceptor */ public function getReader(): SocketReader { - return new SocketReader(); + return new SocketReader($this->getReadLength()); } /** diff --git a/src/Actions/Connections/ClientConnection.php b/src/Actions/Connections/ClientConnection.php index b365ee4..2db7938 100644 --- a/src/Actions/Connections/ClientConnection.php +++ b/src/Actions/Connections/ClientConnection.php @@ -13,7 +13,8 @@ public function create() return stream_socket_client( $this->getAddress(), $errno, - $errstr + $errstr, + $this->getTimeout() ?? $this->getTimeout() ); } } diff --git a/src/Actions/Connections/Connection.php b/src/Actions/Connections/Connection.php index 8c0a02c..2d33307 100644 --- a/src/Actions/Connections/Connection.php +++ b/src/Actions/Connections/Connection.php @@ -12,9 +12,9 @@ abstract class Connection /** * Socket connection timeout - * @var int + * @var int|null */ - protected int $timeout; + protected ?int $timeout = null; /** * @param string $address diff --git a/src/Actions/SocketReader.php b/src/Actions/SocketReader.php index def0e7e..2110e9f 100644 --- a/src/Actions/SocketReader.php +++ b/src/Actions/SocketReader.php @@ -9,6 +9,21 @@ class SocketReader extends AbstractSocketAction */ private string $message; + /** + * @var int + */ + private int $length; + + /** + * Initiate SocketReader constructor method + * @param int $length + * @return void + */ + public function __construct(int $length) + { + $this->length = $length; + } + /** * @param string $message * @return void @@ -32,7 +47,7 @@ public function getMessage() */ public function make() { - $this->setMessage(fread($this->getSocket(), 2048)); + $this->setMessage(fread($this->getSocket(), $this->length)); return $this; } } diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php index 5835ce8..67f00af 100644 --- a/src/Bootstrapper.php +++ b/src/Bootstrapper.php @@ -74,9 +74,23 @@ public function setCredentials() $socketTypeFactory = $this->getSocketTypeFactory(); $socketType = $socketTypeFactory->getSocket($this->settings['settings']['socket_type']); + // Set socket host credentials. We have only two types + // It's unix and tcp, another will be ignored + if ($socketType->get('socket_type') === 'unix') { + $credentials->setCredential( + 'host', + "{$socketType->get('socket_type')}://{$socketType->get('address')}" + ); + } elseif($socketType->get('socket_type') === 'tcp') { + $credentials->setCredential( + 'host', + "{$socketType->get('socket_type')}://{$socketType->get('address')}:{$socketType->get('port')}" + ); + } + $credentials->setCredential( - 'host', - "{$socketType->get('socket_type')}://{$socketType->get('address')}:{$socketType->get('port')}" + 'content_length', + $socketType->get('content_length') ); return $credentials; diff --git a/src/SocketFacade.php b/src/SocketFacade.php index 0c45b01..3ac59ec 100644 --- a/src/SocketFacade.php +++ b/src/SocketFacade.php @@ -3,14 +3,8 @@ namespace Qonsillium; use Qonsillium\Exceptions\ { - FailedAcceptSocket, FailedConnectSocket, - FailedListenSocket, - FailedCreateSocket, FailedWriteSocket, - FailedCloseSocket, - FailedBindSocket, - FailedReadSocket }; class SocketFacade From 7f0446e12f213e912f89c23c05a2a73520cc7cb8 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 8 Dec 2020 23:04:12 +0300 Subject: [PATCH 33/41] Updated readme file and setted returning values in runServer and runClient methods --- README.md | 91 ++++++++++++++-------------------------- src/QonsilliumSocket.php | 4 +- 2 files changed, 33 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 68fcf26..d1f7dfc 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ ## This is a layer for client and server socket connections. ### PHP extension which have to be installed before to work: +* [PHP 8.0](https://www.php.net/downloads) * [Yaml](https://www.php.net/manual/en/book.yaml.php) * [Sockets](https://www.php.net/manual/en/book.sockets.php) @@ -21,27 +22,17 @@ ``` settings: socket_type: tcp - domain: AF_INET - type: SOCK_STREAM - protocol: SOL_TCP - backlog: 1 - host: '127.0.0.1' - port: '8001' - read_length: 2048 - read_flag: MSG_WAITALL + address: 127.0.0.1 + port: 8000 + content_length: 2048 ``` ##### * UNIX socket configuration using YAML ``` settings: - socket_type: unix - domain: AF_UNIX - type: SOCK_STREAM - protocol: 0 - backlog: 1 - socket_file: socket.sock - read_length: 2048 - read_flag: MSG_WAITALL + socket_type: tcp + address: socket.sock + content_length: 2048 ``` #### 2) Create client and server file handlers. @@ -82,48 +73,28 @@ $server->runClient(function(ClinetSocket $socket) { john@doe:/workdir/$ php client.php ``` -## List of available configuration vars: -#### 1) sock_type - Type of socket which will be created. -* tcp -* unix - -#### 2) domain - Specifies the protocol family -* AF_INET -* AF_INET6 -* AF_UNIX - -#### 3) type - Selects the type of communication -* SOCK_STREAM -* SOCK_DGRAM -* SOCK_SEQPACKET -* SOCK_RAW -* SOCK_RDM - -#### 3) protocol - Sets the specific protocol within the specified domain to be used when communicating on the returned socket -* SOL_TCP -* SOL_UDP -* 0 (when use unix) - -#### 4) backlog - A maximum of backlog incoming connections will be queued for processing -* Number of incoming backlogs (1 or 2 etc.) - -#### 5) host - Host name which where will be accepted or created connection. Can be used when if socket is of the AF_INET family -* 127.0.0.1 - -#### 6) port - The port parameter is only used when binding an AF_INET socket, and designates the port on which to listen for connections. -* from 1024 to 65535 - -#### 7) socket_file - If the socket is of the AF_UNIX family, the address is the path of a Unix-domain socket. You can create own socket file but you must make that you set correct path and this file have read and write rights. Or you can set random name in work dir and here will be created socket file -* /tmp/socket.sock -* socket.sock - -#### 8) read_length - The maximum number of bytes read is specified by the length parameter. -* 2048, 4096 etc - -#### 9) read_flag - The flags responded for reading status. -* MSG_OOB -* MSG_PEEK -* MSG_WAITALL -* MSG_DONTWAIT +#### 4) Extends from QonsilliumSocket +``` +runClient(function(ClientSocket $client) use ($myMessage) { + return $client->send($myMessage); + }); + + if ($serverMessage === 'Hello from server!') { + // handle this action + } + } +} +``` -###### For details you can refer to the [PHP](https://php.net) documentation +But when you will instantiate handler class don't forget to set configuration file with socket settings in constructor method diff --git a/src/QonsilliumSocket.php b/src/QonsilliumSocket.php index bd8aecc..2a5f112 100644 --- a/src/QonsilliumSocket.php +++ b/src/QonsilliumSocket.php @@ -62,7 +62,7 @@ protected function getServerSocket(): ServerSocket */ public function runClient(Closure $handler) { - $handler($this->getClientSocket()); + return $handler($this->getClientSocket()); } /** @@ -80,6 +80,6 @@ public function runClient(Closure $handler) */ public function runServer(Closure $handler) { - $handler($this->getServerSocket()); + return $handler($this->getServerSocket()); } } From 5f02b90483f91a64c0c57ec7dcaabe61e2cc0842 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Wed, 9 Dec 2020 16:47:13 +0300 Subject: [PATCH 34/41] Updated README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d1f7dfc..d91546d 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ settings: ##### * UNIX socket configuration using YAML ``` settings: - socket_type: tcp + socket_type: unix address: socket.sock content_length: 2048 ``` From fcb7c63d32f782c48de6bba4d94fc9924e4e840b Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Wed, 9 Dec 2020 17:13:06 +0300 Subject: [PATCH 35/41] Added constructor property promotion --- src/AbstractSocket.php | 14 +++++--------- src/ActionFactory.php | 14 +++++--------- src/Actions/SocketConnector.php | 27 ++++++++++++++------------- src/Actions/SocketReader.php | 12 ++++-------- src/Bootstrapper.php | 13 +++---------- src/Parsers/ConfigParser.php | 16 +++++----------- src/Parsers/ConfigParsersFactory.php | 24 +++++------------------- src/Parsers/JSONConfigParser.php | 14 +------------- src/Parsers/NullConfigFile.php | 4 ++++ src/Parsers/YAMLConfigParser.php | 9 --------- src/SocketFacade.php | 12 ++++-------- src/Types/SocketType.php | 7 ++++--- src/Types/SocketTypeFactory.php | 12 ++++++------ src/Types/TypeConfiguration.php | 16 +++++----------- 14 files changed, 65 insertions(+), 129 deletions(-) diff --git a/src/AbstractSocket.php b/src/AbstractSocket.php index 0ec67a0..af3a120 100644 --- a/src/AbstractSocket.php +++ b/src/AbstractSocket.php @@ -4,20 +4,16 @@ abstract class AbstractSocket { - /** - * @var \Qonsillium\SocketFacade|null - */ - protected ?SocketFacade $facade = null; - /** * Initiate AbstractSocket constructor method * and set SocketFacade property * @param \Qonsillium\SocketFacade $facade * @return void - */ - public function __construct(SocketFacade $facade) - { - $this->facade = $facade; + */ + public function __construct( + protected SocketFacade $facade + ){ + // } /** diff --git a/src/ActionFactory.php b/src/ActionFactory.php index 672bdef..33e4520 100644 --- a/src/ActionFactory.php +++ b/src/ActionFactory.php @@ -13,20 +13,16 @@ class ActionFactory { - /** - * @var \Qonsillium\Credential\SocketCredentials|null; - */ - private ?SocketCredentials $credentials = null; - /** * Initiate ActionFactory constructor method and * set SocketCredetials property * @param \Qonsillium\Credential\SocketCredentials $credentials * @return void - */ - public function __construct(SocketCredentials $credentials) - { - $this->credentials = $credentials; + */ + public function __construct( + private SocketCredentials $credentials + ){ + // } /** diff --git a/src/Actions/SocketConnector.php b/src/Actions/SocketConnector.php index 0294993..fcc0334 100644 --- a/src/Actions/SocketConnector.php +++ b/src/Actions/SocketConnector.php @@ -6,26 +6,27 @@ class SocketConnector extends AbstractSocketAction { - /** - * @var string - */ - private string $address; + // /** + // * @var string + // */ + // private string $address; - /** - * @var string - */ - private string $type; + // /** + // * @var string + // */ + // private string $type; /** * Initiate SocketConnector constructor method * @param string $method * @param string $type - * @return void + * @return void */ - public function __construct(string $address, string $type) - { - $this->address = $address; - $this->type = $type; + public function __construct( + private string $address, + private string $type + ){ + // } /** diff --git a/src/Actions/SocketReader.php b/src/Actions/SocketReader.php index 2110e9f..3ac5e53 100644 --- a/src/Actions/SocketReader.php +++ b/src/Actions/SocketReader.php @@ -9,19 +9,15 @@ class SocketReader extends AbstractSocketAction */ private string $message; - /** - * @var int - */ - private int $length; - /** * Initiate SocketReader constructor method * @param int $length * @return void */ - public function __construct(int $length) - { - $this->length = $length; + public function __construct( + private int $length + ){ + // } /** diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php index 67f00af..bd263b4 100644 --- a/src/Bootstrapper.php +++ b/src/Bootstrapper.php @@ -10,13 +10,6 @@ class Bootstrapper { - /** - * Configuration file with - * yaml(yml) or json extension - * @var string - */ - protected string $configFile; - /** * List with domain, type, protocol, * host and port socket settings @@ -42,9 +35,9 @@ class Bootstrapper * @param string $configFile * @return void */ - public function __construct(string $configFile) - { - $this->configFile = $configFile; + public function __construct( + protected string $configFile + ){ $this->services = new ServiceProvider(); $this->settings = $this->parseConfigFile(); $this->configuration = $this->configureSettingsFromFile(); diff --git a/src/Parsers/ConfigParser.php b/src/Parsers/ConfigParser.php index 3c50a14..cfc721e 100644 --- a/src/Parsers/ConfigParser.php +++ b/src/Parsers/ConfigParser.php @@ -4,23 +4,17 @@ abstract class ConfigParser { - /** - * Configuration file - * with settings - * @var string - */ - protected string $file; - /** * Initiate ConfigParser constructor method. * Configuration file can be only with json * or yaml(yml) extensions * @param string $file - * @return void + * @return void */ - public function __construct(string $file) - { - $this->file = $file; + public function __construct( + protected string $file + ){ + // } /** diff --git a/src/Parsers/ConfigParsersFactory.php b/src/Parsers/ConfigParsersFactory.php index e7c84bd..f6f3dcd 100644 --- a/src/Parsers/ConfigParsersFactory.php +++ b/src/Parsers/ConfigParsersFactory.php @@ -4,13 +4,6 @@ class ConfigParsersFactory { - /** - * Configuration file which - * will be parsed - * @var string - */ - protected string $configFile; - /** * File extension * @var string @@ -20,20 +13,13 @@ class ConfigParsersFactory /** * Null object which make stub action. * Read: https://en.wikipedia.org/wiki/Null_object_pattern - * @var \Qonsillium\Parsers\NullConfigFile + * @var \Qonsillium\Parsers\ConfigParser */ - protected $nullObj; + protected ConfigParser $nullObj; - /** - * Initiate ConfigParsersFactory constructor - * method and set config file, extension and - * null object - * @param string $configFile - * @return void - */ - public function __construct(string $configFile) - { - $this->configFile = $configFile; + public function __construct( + protected string $configFile, + ){ $this->configFileExtension = pathinfo($this->configFile)['extension']; $this->nullObj = new NullConfigFile($this->configFile); } diff --git a/src/Parsers/JSONConfigParser.php b/src/Parsers/JSONConfigParser.php index 4f73dfe..6096f25 100644 --- a/src/Parsers/JSONConfigParser.php +++ b/src/Parsers/JSONConfigParser.php @@ -6,19 +6,7 @@ class JSONConfigParser extends ConfigParser { /** * Parse json file with settings and return - * it in assoc array interpretation. - * - * JSON config file example: - * { - * "settings": { - * "domain": "AF_INET", - * "type": "SOCK_STREAM", - * "protocol": "SOL_TCP", - * "host": "127.0.0.1", - * "port": "8000", - * } - * } - * + * it in assoc array interpretation * @return array */ public function parse(): array diff --git a/src/Parsers/NullConfigFile.php b/src/Parsers/NullConfigFile.php index 4531fc1..7b72dd8 100644 --- a/src/Parsers/NullConfigFile.php +++ b/src/Parsers/NullConfigFile.php @@ -4,6 +4,10 @@ class NullConfigFile extends ConfigParser { + /** + * Stub method + * @return array + */ public function parse(): array { return []; diff --git a/src/Parsers/YAMLConfigParser.php b/src/Parsers/YAMLConfigParser.php index e705f96..efd84ec 100644 --- a/src/Parsers/YAMLConfigParser.php +++ b/src/Parsers/YAMLConfigParser.php @@ -7,15 +7,6 @@ class YAMLConfigParser extends ConfigParser /** * Parse yaml(yml) file with settings and return * it in assoc array interpretation. - * - * YAML config file example: - * settings: - * domain: "AF_INET" - * type: "SOCK_STREAM" - * protocol: "SOL_TCP" - * host: "127.0.0.1" - * port: "8000" - * * @return array */ public function parse(): array diff --git a/src/SocketFacade.php b/src/SocketFacade.php index 3ac59ec..98014db 100644 --- a/src/SocketFacade.php +++ b/src/SocketFacade.php @@ -9,11 +9,6 @@ class SocketFacade { - /** - * @var \Qonsillium\ActionFactory|null - */ - private ?ActionFactory $factory = null; - /** * Readed socket content * @var string @@ -26,9 +21,10 @@ class SocketFacade * @param \Qonsillium\ActionFactory $factory * @return void */ - public function __construct(ActionFactory $factory) - { - $this->factory = $factory; + public function __construct( + private ActionFactory $factory + ){ + // } /** diff --git a/src/Types/SocketType.php b/src/Types/SocketType.php index 8481193..4a2bfcd 100644 --- a/src/Types/SocketType.php +++ b/src/Types/SocketType.php @@ -12,9 +12,10 @@ abstract class SocketType * @param \Qonsillium\Types\TypeConfiguration * @return void */ - public function __construct(TypeConfiguration $configuration) - { - $this->configuration = $configuration; + public function __construct( + protected TypeConfiguration $configuration + ){ + // } /** diff --git a/src/Types/SocketTypeFactory.php b/src/Types/SocketTypeFactory.php index 85ae4f2..d33db8f 100644 --- a/src/Types/SocketTypeFactory.php +++ b/src/Types/SocketTypeFactory.php @@ -6,9 +6,9 @@ class SocketTypeFactory { /** * Null object - * @var \Qonsillium\Types\NullSocketType + * @var \Qonsillium\Types\SocketType */ - private $nullObj; + private SocketType $nullObj; /** * Initiate SocketTypeFactory and set TypeConfiguration @@ -16,10 +16,10 @@ class SocketTypeFactory * stub method * @param \Qonsillium\Types\TypeConfiguration $configuration * @return void - */ - public function __construct(TypeConfiguration $configuration) - { - $this->configuration = $configuration; + */ + public function __construct( + protected TypeConfiguration $configuration + ){ $this->nullObj = new NullSocketType($this->configuration); } diff --git a/src/Types/TypeConfiguration.php b/src/Types/TypeConfiguration.php index ca0c891..484a396 100644 --- a/src/Types/TypeConfiguration.php +++ b/src/Types/TypeConfiguration.php @@ -4,28 +4,22 @@ class TypeConfiguration { - /** - * Settings which was parsed - * by json_decode or yaml_parse_file - * @var array - */ - protected array $settings; - /** * Configured settings * @var array */ protected array $configured; - + /** * Initiate TypeConfiguration constructor method * and set array with settings * @param array $settings * @return void */ - public function __construct(array $settings) - { - $this->settings = $settings; + public function __construct( + protected array $settings + ){ + // } /** From 74afec4df956e52ed1738e41383912d8dbe92ccd Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Mon, 14 Dec 2020 21:21:52 +0300 Subject: [PATCH 36/41] Written tests for connection handlers, bootstrapper and action factory --- tests/unit/ActionFactoryTest.php | 91 +++++++++++++++++++ .../Connections/ConnectionFactoryTest.php | 15 +++ tests/unit/BootstrapperTest.php | 91 +++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 tests/unit/ActionFactoryTest.php create mode 100644 tests/unit/Actions/Connections/ConnectionFactoryTest.php create mode 100644 tests/unit/BootstrapperTest.php diff --git a/tests/unit/ActionFactoryTest.php b/tests/unit/ActionFactoryTest.php new file mode 100644 index 0000000..39a79da --- /dev/null +++ b/tests/unit/ActionFactoryTest.php @@ -0,0 +1,91 @@ +credentials = new SocketCredentials; + $this->credentials->setCredential('host', 'tcp://127.0.0.1:8000'); + $this->credentials->setCredential('content_length', 2048); + + $this->factory = new ActionFactory($this->credentials); + } + + public function testGetAddressReturnsSameStringAndIsString() + { + $this->assertIsString( + $this->factory->getAddress(), + 'ActionFactory::getAddress is null. Expected string' + ); + + $this->assertSame( + 'tcp://127.0.0.1:8000', + $this->factory->getAddress(), + 'ActionFactory::getAddress expected string with "tcp://127.0.0.1:8000", but getting null' + ); + } + + public function testGetConnectorReturnsSocketConnectorInstance() + { + $this->assertInstanceOf( + SocketConnector::class, + $this->factory->getConnector('server'), + 'ActionFactory::getConnector expected type SocketConnector but getting null' + ); + } + + public function testGetAcceptorReturnsSocketAcceptorInstance() + { + $this->assertInstanceOf( + SocketAcceptor::class, + $this->factory->getAcceptor(), + 'ActionFactory::getAcceptor expected type SocketAcceptor but getting null' + ); + } + + public function testGetReaderReturnsSocketReaderInstance() + { + $this->assertInstanceOf( + SocketReader::class, + $this->factory->getReader(), + 'ActionFactory::getReader expected type SocketReader but getting null' + ); + } + + public function testGetReaderReturnsSocketWriterInstance() + { + $this->assertInstanceOf( + SocketWriter::class, + $this->factory->getWriter(), + 'ActionFactory::getWriter expected type SocketWriter but getting null' + ); + } + + public function testGetReaderReturnsSocketCloserInstance() + { + $this->assertInstanceOf( + SocketCloser::class, + $this->factory->getCloser(), + 'ActionFactory::getWriter expected type SocketCloser but getting null' + ); + } + + public function tearDown(): void + { + unset($this->credentials); + unset($this->factory); + } +} diff --git a/tests/unit/Actions/Connections/ConnectionFactoryTest.php b/tests/unit/Actions/Connections/ConnectionFactoryTest.php new file mode 100644 index 0000000..cad6584 --- /dev/null +++ b/tests/unit/Actions/Connections/ConnectionFactoryTest.php @@ -0,0 +1,15 @@ +assertInstanceOf(Connection::class, $factory->getConnection('server')); + } +} diff --git a/tests/unit/BootstrapperTest.php b/tests/unit/BootstrapperTest.php new file mode 100644 index 0000000..e2a2ec9 --- /dev/null +++ b/tests/unit/BootstrapperTest.php @@ -0,0 +1,91 @@ +setCredentials(); + + $this->assertInstanceOf( + SocketCredentials::class, + $credentials, + 'Bootstrapper::setCredentials returns null, expected SocketCredentials instance' + ); + + // $this->assertSame( + // 'tcp://127.0.0.1:8000', + // $credentials->getCredential('host') + // ); + } + + public function testGetConfigParsersFactoryReturnsSameInstance() + { + $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); + + $this->assertInstanceOf( + ConfigParsersFactory::class, + $boostrapper->getConfigParserFactory() + ); + } + + public function testGetSocketConfiguratorReturnsSameInstance() + { + $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); + + $this->assertInstanceOf( + SocketTypeFactory::class, + $boostrapper->getSocketTypeFactory() + ); + } + + public function testGetSocketActionFactoryReturnsSameInstance() + { + $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); + + $this->assertInstanceOf( + ActionFactory::class, + $boostrapper->getSocketActionFactory() + ); + } + + public function testGetSocketFacadeReturnsSameInstance() + { + $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); + + $this->assertInstanceOf( + SocketFacade::class, + $boostrapper->getSocketFacade() + ); + } + + public function testGetClientSocketReturnsSameInstance() + { + $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); + + $this->assertInstanceOf( + ClientSocket::class, + $boostrapper->getClientSocket() + ); + } + + public function testGetServerSocketReturnsSameInstance() + { + $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); + + $this->assertInstanceOf( + ServerSocket::class, + $boostrapper->getServerSocket() + ); + } +} From 7e5365c037ea025a6801c7b50f83d3b2be34a5cb Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 15 Dec 2020 12:47:16 +0300 Subject: [PATCH 37/41] Removed superfluos settings in fixture files and refactored tests --- tests/unit/BootstrapperTest.php | 27 ++++++++++++------- .../unit/Credential/SocketCredentialTest.php | 10 +++---- tests/unit/Types/TypeConfigurationTest.php | 6 ++--- tests/unit/fixtures/config_tcp.json | 9 ++----- tests/unit/fixtures/config_tcp.yaml | 9 ++----- tests/unit/fixtures/config_unix.json | 11 +++----- tests/unit/fixtures/config_unix.yaml | 9 ++----- 7 files changed, 34 insertions(+), 47 deletions(-) diff --git a/tests/unit/BootstrapperTest.php b/tests/unit/BootstrapperTest.php index e2a2ec9..acd9336 100644 --- a/tests/unit/BootstrapperTest.php +++ b/tests/unit/BootstrapperTest.php @@ -23,10 +23,11 @@ public function testSetCredentialsReturnsSocketCredentialsInstance() 'Bootstrapper::setCredentials returns null, expected SocketCredentials instance' ); - // $this->assertSame( - // 'tcp://127.0.0.1:8000', - // $credentials->getCredential('host') - // ); + $this->assertSame( + 'tcp://127.0.0.1:8000', + $credentials->getCredential('host'), + 'Bootstrapper::setCredentials, expected "tcp://127.0.0.1:8000" but got not the same string' + ); } public function testGetConfigParsersFactoryReturnsSameInstance() @@ -35,7 +36,8 @@ public function testGetConfigParsersFactoryReturnsSameInstance() $this->assertInstanceOf( ConfigParsersFactory::class, - $boostrapper->getConfigParserFactory() + $boostrapper->getConfigParserFactory(), + 'Bootstrapper::getConfigParserFactory expected type ConfigParsersFactory but getting null' ); } @@ -45,7 +47,8 @@ public function testGetSocketConfiguratorReturnsSameInstance() $this->assertInstanceOf( SocketTypeFactory::class, - $boostrapper->getSocketTypeFactory() + $boostrapper->getSocketTypeFactory(), + 'Bootstrapper::getSocketTypeFactory expected type SocketTypeFactory but getting null' ); } @@ -55,7 +58,8 @@ public function testGetSocketActionFactoryReturnsSameInstance() $this->assertInstanceOf( ActionFactory::class, - $boostrapper->getSocketActionFactory() + $boostrapper->getSocketActionFactory(), + 'Bootstrapper::getSocketActionFactory expected type ActionFactory but getting null' ); } @@ -65,7 +69,8 @@ public function testGetSocketFacadeReturnsSameInstance() $this->assertInstanceOf( SocketFacade::class, - $boostrapper->getSocketFacade() + $boostrapper->getSocketFacade(), + 'Bootstrapper::getSocketFacade expected type SocketFacade but getting null' ); } @@ -75,7 +80,8 @@ public function testGetClientSocketReturnsSameInstance() $this->assertInstanceOf( ClientSocket::class, - $boostrapper->getClientSocket() + $boostrapper->getClientSocket(), + 'Bootstrapper::getClientSocket expected type ClientSocket but getting null' ); } @@ -85,7 +91,8 @@ public function testGetServerSocketReturnsSameInstance() $this->assertInstanceOf( ServerSocket::class, - $boostrapper->getServerSocket() + $boostrapper->getServerSocket(), + 'Bootstrapper::getServerSocket expected type getServerSocket but getting null' ); } } diff --git a/tests/unit/Credential/SocketCredentialTest.php b/tests/unit/Credential/SocketCredentialTest.php index 3378a89..a389a3e 100644 --- a/tests/unit/Credential/SocketCredentialTest.php +++ b/tests/unit/Credential/SocketCredentialTest.php @@ -8,18 +8,18 @@ class SocketCredentialTest extends TestCase public function testGetterMethodReturnsSameProperty() { $credentials = new SocketCredentials; - $credentials->setCredential('host', '127.0.0.1'); + $credentials->setCredential('host', 'tcp://127.0.0.1:8000'); - $this->assertSame('127.0.0.1', $credentials->getCredential('host')); + $this->assertSame('tcp://127.0.0.1:8000', $credentials->getCredential('host')); } public function testPropertyExistenceValidatorReturnsBool() { $credentials = new SocketCredentials(); - $credentials->setCredential('port', '8001'); + $credentials->setCredential('host', 'tcp://127.0.0.1:8000'); $this->assertTrue( - $credentials->validateExistence('port'), - "SocketCredentials::validateExistence. Expected property 'port', but doesnt exists" + $credentials->validateExistence('host'), + "SocketCredentials::validateExistence. Expected property 'host', but doesn't exists" ); } } diff --git a/tests/unit/Types/TypeConfigurationTest.php b/tests/unit/Types/TypeConfigurationTest.php index dc70b8e..4a42172 100644 --- a/tests/unit/Types/TypeConfigurationTest.php +++ b/tests/unit/Types/TypeConfigurationTest.php @@ -13,8 +13,8 @@ public function testValidateSettingExistenceReturnsBool() $configuration->configure(); $this->assertTrue( - $configuration->validateSettingsExistence('domain'), - "TypeConfiguration::validateSettingExistence. Setting 'domain' doesn't exists in settings list" + $configuration->validateSettingsExistence('address'), + "TypeConfiguration::validateSettingExistence. Setting 'host' doesn't exists in settings list" ); } @@ -26,7 +26,7 @@ public function testGetConfigurationSettingReturnsSameString() $this->assertSame( '127.0.0.1', - $configuration->getConfigurationSetting('host'), + $configuration->getConfigurationSetting('address'), "TypeConfiguration::getConfigurationSetting. Expected '127.0.0.1', but got not the same string" ); } diff --git a/tests/unit/fixtures/config_tcp.json b/tests/unit/fixtures/config_tcp.json index 1b590d2..152c6ea 100644 --- a/tests/unit/fixtures/config_tcp.json +++ b/tests/unit/fixtures/config_tcp.json @@ -1,13 +1,8 @@ { "settings": { "socket_type": "tcp", - "domain": "AF_INET", - "type": "SOCK_STREAM", - "protocol": "SOL_TCP", - "backkog": "1", - "read_length": "2048", - "read_flag": "MSG_WAITALL", - "host": "127.0.0.1", + "content_length": "2048", + "address": "127.0.0.1", "port": "8001" } } \ No newline at end of file diff --git a/tests/unit/fixtures/config_tcp.yaml b/tests/unit/fixtures/config_tcp.yaml index c65f533..5f103e6 100644 --- a/tests/unit/fixtures/config_tcp.yaml +++ b/tests/unit/fixtures/config_tcp.yaml @@ -1,10 +1,5 @@ settings: socket_type: tcp - domain: AF_INET - type: SOCK_STREAM - protocol: SOL_TCP - backlog: 1 read_length: 2048 - read_flag: MSG_WAITALL - host: 127.0.0.1 - port: 8001 \ No newline at end of file + address: 127.0.0.1 + port: 8000 \ No newline at end of file diff --git a/tests/unit/fixtures/config_unix.json b/tests/unit/fixtures/config_unix.json index 8b8a964..a643793 100644 --- a/tests/unit/fixtures/config_unix.json +++ b/tests/unit/fixtures/config_unix.json @@ -1,12 +1,7 @@ { "settings": { - "socket_type": "unix", - "domain": "AF_UNIX", - "type": "SOCK_STREAM", - "protocol": "0", - "backkog": "1", - "read_length": "2048", - "read_flag": "MSG_WAITALL", - "socket_file": "socket.sock" + "socket_type": "tcp", + "content_length": "2048", + "address": "socket.sock" } } \ No newline at end of file diff --git a/tests/unit/fixtures/config_unix.yaml b/tests/unit/fixtures/config_unix.yaml index a8d9e87..e0b4dc4 100644 --- a/tests/unit/fixtures/config_unix.yaml +++ b/tests/unit/fixtures/config_unix.yaml @@ -1,9 +1,4 @@ settings: - socket_type: unix - domain: AF_UNIX - type: SOCK_STREAM - protocol: 0 - backlog: 1 + socket_type: tcp read_length: 2048 - read_flag: MSG_WAITALL - socket_file: socket.sock \ No newline at end of file + address: socket.sock \ No newline at end of file From 885e82371f6ff87746057c325e57df822b661fa1 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 15 Dec 2020 19:40:19 +0300 Subject: [PATCH 38/41] Removed socket constants locator --- src/Bootstrapper.php | 36 --------------------- src/SocketConstantsLocator.php | 58 ---------------------------------- 2 files changed, 94 deletions(-) delete mode 100644 src/SocketConstantsLocator.php diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php index bd263b4..37d6a54 100644 --- a/src/Bootstrapper.php +++ b/src/Bootstrapper.php @@ -89,26 +89,6 @@ public function setCredentials() return $credentials; } - /** - * Get setting value from from config file and match - * with constants locator constant and finally return - * integer value about this const - * @param string $setting - * @param string $const - * @throws \Qonsillium\Exceptions\ConfigSettingDoesntExists - * @return int - */ - protected function getConstValue(string $setting, string $const) - { - if (!$this->getSocketConstLocator()::hasConst($setting, $const)) { - throw new ConfigSettingDoesntExists( - "Setting with type: {$setting} and const name: {$const} doesn't exists" - ); - } - - return $this->getSocketConstLocator()::getConstValue($setting, $const); - } - /** * Configure settings from config file by * TypeConfiguration and return this instance @@ -121,22 +101,6 @@ protected function configureSettingsFromFile(): TypeConfiguration return $configuration; } - /** - * Returns SocketConstLocator which contain - * all socket settings constants. Usually - * used when need to get socket const integer - * value. - * - * Example: - * $this->getSocketConstLocator()::MODIFIERS - * - * @return string - */ - protected function getSocketConstLocator() - { - return $this->services->getFromList('socket_constants'); - } - /** * Returns TypeConfiguration instance * @return \Qonsillium\Types\TypeConfiguration diff --git a/src/SocketConstantsLocator.php b/src/SocketConstantsLocator.php deleted file mode 100644 index fbed7c8..0000000 --- a/src/SocketConstantsLocator.php +++ /dev/null @@ -1,58 +0,0 @@ - [ - 'AF_INET' => 2, - 'AF_INET6' => 10, - 'AF_UNIX' => 1 - ], - 'type' => [ - 'SOCK_STREAM' => 1, - 'SOCK_DGRAM' => 2, - 'SOCK_SEQPACKET' => 5, - 'SOCK_RAW' => 3, - 'SOCK_RDM' => 4 - ], - 'protocol' => [ - 'SOL_TCP' => 6, - 'SOL_UDP' => 17, - '0' => 0 - ], - 'read_flags' => [ - 'MSG_OOB' => 1, - 'MSG_PEEK' => 2, - 'MSG_WAITALL' => 256, - 'MSG_DONTWAIT' => 64 - ] - ]; - - /** - * Get integer value of socket constant - * @param string $type - * @param string $const - * @return int - */ - public static function getConstValue(string $type, string $const) - { - return self::MODIFIERS[$type][$const]; - } - - /** - * Validate socket constant existence in list - * @param string $type - * @param string $const - * @return bool - */ - public static function hasConst(string $type, string $const): bool - { - if (!isset(self::MODIFIERS[$type], self::MODIFIERS[$type][$const])) { - return false; - } - - return true; - } -} From 9e521c2c512cc7f8bace0be9e8875c6dcca4962d Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 15 Dec 2020 21:27:14 +0300 Subject: [PATCH 39/41] Created DI container --- src/DI/IServiceProvider.php | 8 +++++ src/DI/ServiceContainer.php | 59 +++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/DI/IServiceProvider.php create mode 100644 src/DI/ServiceContainer.php diff --git a/src/DI/IServiceProvider.php b/src/DI/IServiceProvider.php new file mode 100644 index 0000000..b981c7f --- /dev/null +++ b/src/DI/IServiceProvider.php @@ -0,0 +1,8 @@ +services[$offset] = $value; + } + + /** + * @param string $offset + * @return mixed + */ + public function offsetGet($offset) + { + return $this->services[$offset]; + } + + /** + * @param string $offset + * @return bool + */ + public function offsetExists($offset) + { + return isset($this->services[$offset]); + } + + /** + * @param string $offset + * @return void + */ + public function offsetUnset($offset) + { + unset($this->services[$offset]); + } + + /** + * @param \Qonsillium\DI\IServiceProvider $provider + * @return void + */ + public function register(IServiceProvider $provider) + { + return $provider->register($this); + } +} From 77fe400a76383c75544c9653971c1a9926dba9bb Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Tue, 15 Dec 2020 23:15:43 +0300 Subject: [PATCH 40/41] Refactored bootstrap class and implemented SocketServicePRovider --- src/Actions/SocketConnector.php | 10 -- src/Bootstrapper.php | 160 ++++++++------------------------ src/DI/IServiceProvider.php | 5 + src/QonsilliumSocket.php | 4 +- src/ServiceContainer.php | 27 ------ src/ServiceProvider.php | 32 ------- src/SocketServiceProvider.php | 93 +++++++++++++++++++ 7 files changed, 140 insertions(+), 191 deletions(-) delete mode 100644 src/ServiceContainer.php delete mode 100644 src/ServiceProvider.php create mode 100644 src/SocketServiceProvider.php diff --git a/src/Actions/SocketConnector.php b/src/Actions/SocketConnector.php index fcc0334..fb72e26 100644 --- a/src/Actions/SocketConnector.php +++ b/src/Actions/SocketConnector.php @@ -6,16 +6,6 @@ class SocketConnector extends AbstractSocketAction { - // /** - // * @var string - // */ - // private string $address; - - // /** - // * @var string - // */ - // private string $type; - /** * Initiate SocketConnector constructor method * @param string $method diff --git a/src/Bootstrapper.php b/src/Bootstrapper.php index 37d6a54..208f951 100644 --- a/src/Bootstrapper.php +++ b/src/Bootstrapper.php @@ -4,180 +4,100 @@ use Qonsillium\Parsers\ConfigParsersFactory; use Qonsillium\Credential\SocketCredentials; -use Qonsillium\Exceptions\ConfigSettingDoesntExists; +use Qonsillium\DI\ServiceContainer; use Qonsillium\Types\TypeConfiguration; use Qonsillium\Types\SocketTypeFactory; class Bootstrapper { /** - * List with domain, type, protocol, - * host and port socket settings - * @var array + * @var \Qonsillium\SocketServiceProvider */ - protected array $settings; + private SocketServiceProvider $provider; /** - * @var \Qonsillium\Types\TypeConfiguration + * @var \Qonsillium\DI\ServiceContainer */ - protected ?TypeConfiguration $configuration; + private ServiceContainer $container; /** - * @var \Qonsillium\Credential\SocketCredentials - */ - protected ?SocketCredentials $credentials; - - /** - * Initiate Bootstrapper constructor method, set and - * parse config file settings and set this settings - * in SocketCredentials instance. + * Initiate Bootstrapper constructor methoda and register + * socket service provider. + * * Configuration file can be ONLY yaml(yml) or json + * * @param string $configFile * @return void */ public function __construct( protected string $configFile ){ - $this->services = new ServiceProvider(); - $this->settings = $this->parseConfigFile(); - $this->configuration = $this->configureSettingsFromFile(); - $this->credentials = $this->setCredentials(); - } - - /** - * Parse json or yaml(yml) file using using - * factory - * @return array - */ - protected function parseConfigFile(): array - { - return $this->getConfigParserFactory()->getParser()->parse(); + $this->container = new ServiceContainer(); + $this->provider = new SocketServiceProvider($configFile); + $this->provider->register($this->container); } /** - * Set socket domain, type, protocol, host and port, - * backlog, read length and backlog, unix socket file - * and return a SocketCredentials instance. - * @throws \Qonsillium\Exceptions\ConfigSettingDoesntExists * @return \Qonsillium\Credential\SocketCredentials */ - public function setCredentials() + protected function getSocketCredentials(): SocketCredentials { - $credentials = $this->getCredentialsHandler(); - $socketTypeFactory = $this->getSocketTypeFactory(); - $socketType = $socketTypeFactory->getSocket($this->settings['settings']['socket_type']); - - // Set socket host credentials. We have only two types - // It's unix and tcp, another will be ignored - if ($socketType->get('socket_type') === 'unix') { - $credentials->setCredential( - 'host', - "{$socketType->get('socket_type')}://{$socketType->get('address')}" - ); - } elseif($socketType->get('socket_type') === 'tcp') { - $credentials->setCredential( - 'host', - "{$socketType->get('socket_type')}://{$socketType->get('address')}:{$socketType->get('port')}" - ); - } - - $credentials->setCredential( - 'content_length', - $socketType->get('content_length') - ); - - return $credentials; + return $this->container['credentials.socket'](); } /** - * Configure settings from config file by - * TypeConfiguration and return this instance - * @return \Qonsillium\Types\TypeConfiguration - */ - protected function configureSettingsFromFile(): TypeConfiguration + * @return \Qonsillium\Parsers\ConfigParsersFactory + */ + protected function getConfigParsersFactory(): ConfigParsersFactory { - $configuration = $this->getSocketConfigurator(); - $configuration->configure(); - return $configuration; + return $this->container['config.parser'](); } /** - * Returns TypeConfiguration instance * @return \Qonsillium\Types\TypeConfiguration - */ - public function getSocketConfigurator(): TypeConfiguration - { - $configuration = $this->services->getFromList('socket_configuration'); - return new $configuration($this->settings['settings']); - } - - /** - * Returns SocketTypeFactory instance - * @return \Qonsillium\Types\SocketTypeFactory - */ - public function getSocketTypeFactory(): SocketTypeFactory - { - $factory = $this->services->getFromList('socket_type_factory'); - return new $factory($this->configuration); - } - - /** - * Returns ConfigParserFactory factory class - * @return \Qonsillium\Parsers\ConfigParsersFactory - */ - public function getConfigParserFactory(): ConfigParsersFactory + */ + protected function getSocketTypeConfigurator(): TypeConfiguration { - $configParserFactory = $this->services->getFromList('config_parser_factory'); - return new $configParserFactory($this->configFile); + return $this->container['config.socket_type'](); } /** - * Returns SocketCredentials class - * @return \Qonsillium\Credential\SocketCredentials - */ - public function getCredentialsHandler(): SocketCredentials + * @return \Qonsillium\ActionFactory + */ + protected function getSocketActionsFactory(): ActionFactory { - $socketCredentials = $this->services->getFromList('socket_credentials'); - return new $socketCredentials; + return $this->container['socket.actions.factory'](); } /** - * Returns ActionFactory factory class - * @return \Qonsillium\ActionFactory - */ - public function getSocketActionFactory(): ActionFactory + * @return \Qonsillium\Types\SocketTypeFactory + */ + protected function getSocketTypesFactory(): SocketTypeFactory { - $actionFactory = $this->services->getFromList('socket_actions_factory'); - return new $actionFactory($this->credentials); + return $this->container['socket.types.factory'](); } /** - * Returns SocketFacade class * @return \Qonsillium\SocketFacade - */ - public function getSocketFacade(): SocketFacade + */ + protected function getSocketFacade(): SocketFacade { - $socketFacade = $this->services->getFromList('socket_facade'); - return new $socketFacade($this->getSocketActionFactory()); + return $this->provider['socket.facade']; } /** - * Return ClientSocket class - * @return \Qonsillium\ClientSocket - */ - public function getClientSocket(): ClientSocket + * @return \Qonsillium\ClientSocket + */ + public function getClientSocketConnector(): ClientSocket { - $clientSocket = $this->services->getFromList('client_socket'); - return new $clientSocket($this->getSocketFacade()); + return $this->container['socket.connection.client'](); } /** - * Return ServerSocket class - * @return \Qonsillium\ServerSocket - */ - public function getServerSocket(): ServerSocket + * @return \Qonsillium\ServerSocket + */ + public function getServerSocketConnector(): ServerSocket { - $serverSocket = $this->services->getFromList('server_socket'); - return new $serverSocket($this->getSocketFacade()); + return $this->container['socket.connection.server'](); } } diff --git a/src/DI/IServiceProvider.php b/src/DI/IServiceProvider.php index b981c7f..c4e6e2f 100644 --- a/src/DI/IServiceProvider.php +++ b/src/DI/IServiceProvider.php @@ -4,5 +4,10 @@ interface IServiceProvider { + /** + * Register new service provider + * @param \Qonsillium\DI\IServiceContainer + * @return void + */ public function register(ServiceContainer $container); } diff --git a/src/QonsilliumSocket.php b/src/QonsilliumSocket.php index 2a5f112..10aff1c 100644 --- a/src/QonsilliumSocket.php +++ b/src/QonsilliumSocket.php @@ -35,7 +35,7 @@ public function __construct(string $configFile) */ protected function getClientSocket(): ClientSocket { - return $this->bootstrapper->getClientSocket(); + return $this->bootstrapper->getClientSocketConnector(); } /** @@ -44,7 +44,7 @@ protected function getClientSocket(): ClientSocket */ protected function getServerSocket(): ServerSocket { - return $this->bootstrapper->getServerSocket(); + return $this->bootstrapper->getServerSocketConnector(); } /** diff --git a/src/ServiceContainer.php b/src/ServiceContainer.php deleted file mode 100644 index 280e157..0000000 --- a/src/ServiceContainer.php +++ /dev/null @@ -1,27 +0,0 @@ - SocketCredentials::class, - 'client_socket' => ClientSocket::class, - 'server_socket' => ServerSocket::class, - 'config_parser_factory' => ConfigParsersFactory::class, - 'socket_actions_factory' => ActionFactory::class, - 'socket_facade' => SocketFacade::class, - 'socket_constants' => SocketConstantsLocator::class, - 'socket_configuration' => TypeConfiguration::class, - 'socket_type_factory' => SocketTypeFactory::class - ]; -} diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php deleted file mode 100644 index 8ea1415..0000000 --- a/src/ServiceProvider.php +++ /dev/null @@ -1,32 +0,0 @@ -container[$descriptiveName] = $className; - } - - /** - * Return service from services list by unique - * key - * @param string $serviceName - * @return mixed - */ - public function getFromList(string $serviceName) - { - return $this->container[$serviceName]; - } -} diff --git a/src/SocketServiceProvider.php b/src/SocketServiceProvider.php new file mode 100644 index 0000000..13f4d48 --- /dev/null +++ b/src/SocketServiceProvider.php @@ -0,0 +1,93 @@ +configFile = $configFile; + } + + /** + * Register socket services + * @param \Qonsillium\DI\ServiceContainer + */ + public function register(ServiceContainer $container) + { + $container['config.file'] = $this->configFile; + + $container['config.parser'] = function() use ($container) { + return new ConfigParsersFactory($container['config.file']); + }; + + $container['config.socket_type'] = function() use ($container) { + return new TypeConfiguration($container['config.parser']()->getParser()->parse()); + }; + + $container['credentials.socket'] = function() use ($container) { + $credential = new SocketCredentials(); + $parsedConfig = $container['config.parser']()->getParser()->parse()['settings']; + + // Set socket host credentials. We have only two types + // It's unix and tcp, another will be ignored + if ($parsedConfig['socket_type'] === 'unix') { + $credential->setCredential( + 'host', + "{$parsedConfig['socket_type']}://{$parsedConfig['address']}" + ); + } elseif($parsedConfig['socket_type'] === 'tcp') { + $credential->setCredential( + 'host', + "{$parsedConfig['socket_type']}://{$parsedConfig['address']}:{$parsedConfig['port']}" + ); + } + + $credential->setCredential( + 'content_length', + $parsedConfig['content_length'] + ); + + return $credential; + }; + + $container['socket.actions.factory'] = function() use ($container) { + return new ActionFactory($container['credentials.socket']()); + }; + + $container['socket.types.factory'] = function() use ($container) { + return new SocketTypeFactory($container['config.socket_type']()); + }; + + $container['socket.facade'] = function() use ($container) { + return new SocketFacade($container['socket.actions.factory']()); + }; + + $container['socket.connection.client'] = function() use ($container) { + return new ClientSocket($container['socket.facade']()); + }; + + $container['socket.connection.server'] = function() use ($container) { + return new ServerSocket($container['socket.facade']()); + }; + } +} From 733c067c08bc56acdf20fbc239cb2291717559d2 Mon Sep 17 00:00:00 2001 From: Anton Hideger Date: Sat, 19 Dec 2020 18:30:49 +0300 Subject: [PATCH 41/41] Removed Bootstrapper test case and added SocketServiceProvider --- tests/unit/BootstrapperTest.php | 98 ------------------------ tests/unit/SocketServiceProviderTest.php | 23 ++++++ 2 files changed, 23 insertions(+), 98 deletions(-) delete mode 100644 tests/unit/BootstrapperTest.php create mode 100644 tests/unit/SocketServiceProviderTest.php diff --git a/tests/unit/BootstrapperTest.php b/tests/unit/BootstrapperTest.php deleted file mode 100644 index acd9336..0000000 --- a/tests/unit/BootstrapperTest.php +++ /dev/null @@ -1,98 +0,0 @@ -setCredentials(); - - $this->assertInstanceOf( - SocketCredentials::class, - $credentials, - 'Bootstrapper::setCredentials returns null, expected SocketCredentials instance' - ); - - $this->assertSame( - 'tcp://127.0.0.1:8000', - $credentials->getCredential('host'), - 'Bootstrapper::setCredentials, expected "tcp://127.0.0.1:8000" but got not the same string' - ); - } - - public function testGetConfigParsersFactoryReturnsSameInstance() - { - $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); - - $this->assertInstanceOf( - ConfigParsersFactory::class, - $boostrapper->getConfigParserFactory(), - 'Bootstrapper::getConfigParserFactory expected type ConfigParsersFactory but getting null' - ); - } - - public function testGetSocketConfiguratorReturnsSameInstance() - { - $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); - - $this->assertInstanceOf( - SocketTypeFactory::class, - $boostrapper->getSocketTypeFactory(), - 'Bootstrapper::getSocketTypeFactory expected type SocketTypeFactory but getting null' - ); - } - - public function testGetSocketActionFactoryReturnsSameInstance() - { - $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); - - $this->assertInstanceOf( - ActionFactory::class, - $boostrapper->getSocketActionFactory(), - 'Bootstrapper::getSocketActionFactory expected type ActionFactory but getting null' - ); - } - - public function testGetSocketFacadeReturnsSameInstance() - { - $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); - - $this->assertInstanceOf( - SocketFacade::class, - $boostrapper->getSocketFacade(), - 'Bootstrapper::getSocketFacade expected type SocketFacade but getting null' - ); - } - - public function testGetClientSocketReturnsSameInstance() - { - $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); - - $this->assertInstanceOf( - ClientSocket::class, - $boostrapper->getClientSocket(), - 'Bootstrapper::getClientSocket expected type ClientSocket but getting null' - ); - } - - public function testGetServerSocketReturnsSameInstance() - { - $boostrapper = new Bootstrapper(dirname(__DIR__). '/unit/fixtures/config_tcp.yaml'); - - $this->assertInstanceOf( - ServerSocket::class, - $boostrapper->getServerSocket(), - 'Bootstrapper::getServerSocket expected type getServerSocket but getting null' - ); - } -} diff --git a/tests/unit/SocketServiceProviderTest.php b/tests/unit/SocketServiceProviderTest.php new file mode 100644 index 0000000..c03a9ba --- /dev/null +++ b/tests/unit/SocketServiceProviderTest.php @@ -0,0 +1,23 @@ +register($container); + + $this->assertSame( + $configFilePath, + $container['config.file'], + "SocketServiceProvider::register expected {$configFilePath} file, but got wrong" + ); + } +}