Skip to content

Commit 75b20f2

Browse files
created new connection class with ssl support. Changed Bolt construct to accept connection instead of connecting arguments.
1 parent d5f1744 commit 75b20f2

File tree

4 files changed

+166
-10
lines changed

4 files changed

+166
-10
lines changed

src/Bolt.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,12 @@ final class Bolt
7171

7272
/**
7373
* Bolt constructor
74-
* @param string $ip
75-
* @param int $port
76-
* @param int $timeout
74+
* @param IConnection $connection
7775
* @throws Exception
7876
*/
79-
public function __construct(string $ip = '127.0.0.1', int $port = 7687, int $timeout = 15)
77+
public function __construct(IConnection $connection)
8078
{
81-
$this->connection = new \Bolt\connection\Socket($ip, $port, $timeout);
79+
$this->connection = $connection;
8280

8381
$packerClass = "\\Bolt\\PackStream\\v" . $this->packStreamVersion . "\\Packer";
8482
if (!class_exists($packerClass)) {

src/connection/IConnection.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
*/
1212
interface IConnection
1313
{
14+
public function __construct(string $ip = '127.0.0.1', int $port = 7687, int $timeout = 15);
15+
1416
public function connect(): bool;
1517

1618
public function write(string $buffer);

src/connection/Socket.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Bolt\connection;
44

55
use Bolt\Bolt;
6+
use Exception;
67

78
/**
89
* Socket class
@@ -38,9 +39,9 @@ class Socket implements IConnection
3839
* @param string $ip
3940
* @param int $port
4041
* @param int $timeout
41-
* @throws \Exception
42+
* @throws Exception
4243
*/
43-
public function __construct(string $ip, int $port, int $timeout)
44+
public function __construct(string $ip = '127.0.0.1', int $port = 7687, int $timeout = 15)
4445
{
4546
if (!extension_loaded('sockets')) {
4647
Bolt::error('PHP Extension sockets not enabled');
@@ -54,7 +55,7 @@ public function __construct(string $ip, int $port, int $timeout)
5455
/**
5556
* Create socket connection
5657
* @return bool
57-
* @throws \Exception
58+
* @throws Exception
5859
*/
5960
public function connect(): bool
6061
{
@@ -87,7 +88,7 @@ public function connect(): bool
8788
/**
8889
* Write buffer to socket
8990
* @param string $buffer
90-
* @throws \Exception
91+
* @throws Exception
9192
*/
9293
public function write(string $buffer)
9394
{
@@ -119,7 +120,7 @@ public function write(string $buffer)
119120
* Read buffer from socket
120121
* @param int $length
121122
* @return string
122-
* @throws \Exception
123+
* @throws Exception
123124
*/
124125
public function read(int $length = 2048): string
125126
{

src/connection/StreamSocket.php

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
<?php
2+
3+
4+
namespace Bolt\connection;
5+
6+
use Bolt\Bolt;
7+
use Exception;
8+
9+
class StreamSocket implements IConnection
10+
{
11+
12+
/**
13+
* @var string
14+
*/
15+
private $ip;
16+
17+
/**
18+
* @var int
19+
*/
20+
private $port;
21+
22+
/**
23+
* @var int
24+
*/
25+
private $timeout;
26+
27+
/**
28+
* @var array
29+
*/
30+
private $sslContextOptions = [];
31+
32+
/**
33+
* @var resource
34+
*/
35+
private $stream;
36+
37+
/**
38+
* StreamSocket constructor.
39+
* @param string $ip
40+
* @param int $port
41+
* @param int $timeout
42+
*/
43+
public function __construct(string $ip = '127.0.0.1', int $port = 7687, int $timeout = 15)
44+
{
45+
$this->ip = $ip;
46+
$this->port = $port;
47+
$this->timeout = $timeout;
48+
}
49+
50+
/**
51+
* Set SSL Context options
52+
* @link https://www.php.net/manual/en/context.ssl.php
53+
* @param array $options
54+
*/
55+
public function setSslContextOptions(array $options)
56+
{
57+
$this->sslContextOptions = $options;
58+
}
59+
60+
/**
61+
* Connect
62+
* @return bool
63+
* @throws Exception
64+
*/
65+
public function connect(): bool
66+
{
67+
$context = stream_context_create([
68+
'socket' => [
69+
'tcp_nodelay' => true,
70+
],
71+
'ssl' => $this->sslContextOptions
72+
]);
73+
74+
$this->stream = stream_socket_client( 'tcp://' . $this->ip . ':' . $this->port, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context);
75+
76+
if ($this->stream === false) {
77+
Bolt::error($errstr . ' (' . $errno . ')');
78+
return false;
79+
}
80+
81+
if (!stream_set_blocking($this->stream, true)) {
82+
Bolt::error('Cannot set socket into blocking mode');
83+
return false;
84+
}
85+
86+
if (!empty($this->sslContextOptions)) {
87+
if (stream_socket_enable_crypto($this->stream, true, STREAM_CRYPTO_METHOD_ANY_CLIENT) !== true) {
88+
Bolt::error('Enable encryption error');
89+
return false;
90+
}
91+
}
92+
93+
return true;
94+
}
95+
96+
/**
97+
* Write to connection
98+
* @param string $buffer
99+
* @throws Exception
100+
*/
101+
public function write(string $buffer)
102+
{
103+
if (Bolt::$debug)
104+
$this->printHex($buffer);
105+
106+
107+
if (fwrite($this->stream, $buffer) === false)
108+
Bolt::error('Write error');
109+
}
110+
111+
/**
112+
* Read from connection
113+
* @param int $length
114+
* @return string
115+
* @throws Exception
116+
*/
117+
public function read(int $length = 2048): string
118+
{
119+
$res = fread($this->stream, $length);
120+
if (empty($res))
121+
Bolt::error('Read error');
122+
123+
if (Bolt::$debug)
124+
$this->printHex($res, false);
125+
126+
return (string)$res;
127+
}
128+
129+
/**
130+
* Close connection
131+
*/
132+
public function disconnect()
133+
{
134+
if (is_resource($this->stream))
135+
stream_socket_shutdown($this->stream, STREAM_SHUT_RDWR);
136+
}
137+
138+
/**
139+
* Print buffer as HEX
140+
* @param string $str
141+
* @param bool $write
142+
*/
143+
private function printHex(string $str, bool $write = true)
144+
{
145+
$str = implode(unpack('H*', $str));
146+
echo '<pre>';
147+
echo $write ? '> ' : '< ';
148+
foreach (str_split($str, 8) as $chunk) {
149+
echo implode(' ', str_split($chunk, 2));
150+
echo ' ';
151+
}
152+
echo '</pre>';
153+
}
154+
155+
}

0 commit comments

Comments
 (0)