Skip to content

Commit f61a491

Browse files
committed
created protocol factory
1 parent 1d97574 commit f61a491

File tree

4 files changed

+148
-66
lines changed

4 files changed

+148
-66
lines changed

src/Bolt/SslConfigurator.php renamed to src/Bolt/AConnectionFactory.php

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,59 @@
1111

1212
namespace Laudis\Neo4j\Bolt;
1313

14+
use Bolt\connection\AConnection;
15+
use Bolt\connection\Socket;
16+
use Bolt\connection\StreamSocket;
1417
use function explode;
18+
use function extension_loaded;
1519
use const FILTER_VALIDATE_IP;
1620
use function filter_var;
1721
use Laudis\Neo4j\Databags\SslConfiguration;
22+
use Laudis\Neo4j\Databags\TransactionConfiguration;
1823
use Laudis\Neo4j\Enum\SslMode;
1924
use Psr\Http\Message\UriInterface;
2025

21-
final class SslConfigurator
26+
class AConnectionFactory
2227
{
28+
private bool $socketsLoaded;
29+
private UriInterface $uri;
30+
31+
public function __construct(UriInterface $uri)
32+
{
33+
$this->socketsLoaded = extension_loaded('sockets');
34+
$this->uri = $uri;
35+
}
36+
37+
public function sameEncryptionLevel(string $level, UriInterface $uri, SslConfiguration $config): bool
38+
{
39+
return $level === $this->configure($uri, $config)[0];
40+
}
41+
42+
/**
43+
* @param SslConfiguration $config
44+
*
45+
* @return array{0: AConnection, 1: ''|'s'|'ssc'}
46+
*/
47+
public function create(SslConfiguration $config): array
48+
{
49+
[$encryptionLevel, $sslConfig] = $this->configure($this->uri, $config);
50+
$port = $this->uri->getPort() ?? 7687;
51+
if ($this->socketsLoaded && $sslConfig === null) {
52+
$connection = new Socket($this->uri->getHost(), $port, TransactionConfiguration::DEFAULT_TIMEOUT);
53+
} else {
54+
$connection = new StreamSocket($this->uri->getHost(), $port, TransactionConfiguration::DEFAULT_TIMEOUT);
55+
if ($sslConfig !== null) {
56+
$connection->setSslContextOptions($sslConfig);
57+
}
58+
}
59+
60+
return [$connection, $encryptionLevel];
61+
}
62+
2363
/**
2464
* @return array{0: ''|'s'|'ssc', 1: array|null}
2565
*/
26-
public function configure(UriInterface $uri, SslConfiguration $config): array
66+
private function configure(UriInterface $uri, SslConfiguration $config): array
2767
{
2868
$mode = $config->getMode();
2969
$sslConfig = '';

src/Bolt/BoltConnection.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
namespace Laudis\Neo4j\Bolt;
1515

16-
use Bolt\connection\AConnection;
16+
use Bolt\connection\IConnection;
1717
use Bolt\error\IgnoredException;
1818
use Bolt\error\MessageException;
1919
use Bolt\protocol\V3;
@@ -33,7 +33,7 @@
3333
use WeakReference;
3434

3535
/**
36-
* @implements ConnectionInterface<array{0: V3, 1: AConnection}>
36+
* @implements ConnectionInterface<array{0: V3, 1: IConnection}>
3737
*
3838
* @psalm-import-type BoltMeta from FormatterInterface
3939
*/
@@ -59,26 +59,28 @@ final class BoltConnection implements ConnectionInterface
5959
*/
6060
private array $subscribedResults = [];
6161
private AuthenticateInterface $auth;
62-
private AConnection $connection;
62+
private IConnection $connection;
6363
private string $encryptionLevel;
64+
private string $userAgent;
6465

6566
/**
6667
* @psalm-mutation-free
6768
*/
68-
public function __construct(V3 $protocol, AConnection $connection, ConnectionConfiguration $config, AuthenticateInterface $auth, string $encryptionLevel)
69+
public function __construct(V3 $protocol, IConnection $connection, ConnectionConfiguration $config, AuthenticateInterface $auth, string $encryptionLevel, string $userAgent)
6970
{
7071
$this->boltProtocol = $protocol;
7172
$this->config = $config;
7273
$this->serverState = 'READY';
7374
$this->auth = $auth;
7475
$this->connection = $connection;
7576
$this->encryptionLevel = $encryptionLevel;
77+
$this->userAgent = $userAgent;
7678
}
7779

7880
/**
7981
* @psalm-mutation-free
8082
*
81-
* @return array{0: V3, 1: AConnection}
83+
* @return array{0: V3, 1: IConnection}
8284
*/
8385
public function getImplementation(): array
8486
{
@@ -453,4 +455,9 @@ private function countResults(): int
453455

454456
return $ctr;
455457
}
458+
459+
public function getUserAgent(): string
460+
{
461+
return $this->userAgent;
462+
}
456463
}

src/Bolt/ProtocolFactory.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Neo4j PHP Client and Driver package.
5+
*
6+
* (c) Nagels <https://nagels.tech>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Laudis\Neo4j\Bolt;
13+
14+
use Bolt\Bolt;
15+
use Bolt\connection\IConnection;
16+
use Bolt\error\ConnectException;
17+
use Bolt\error\MessageException;
18+
use Bolt\protocol\V3;
19+
use Laudis\Neo4j\Contracts\AuthenticateInterface;
20+
use Laudis\Neo4j\Exception\Neo4jException;
21+
use RuntimeException;
22+
23+
class ProtocolFactory
24+
{
25+
/**
26+
* @param IConnection $connection
27+
* @param AuthenticateInterface $auth
28+
* @param string $userAgent
29+
*
30+
* @return array{0: V3, 1: array{server: string, connection_id: string, hints: list}}
31+
*/
32+
public function createProtocol(IConnection $connection, AuthenticateInterface $auth, string $userAgent): array
33+
{
34+
$bolt = new Bolt($connection);
35+
try {
36+
$bolt->setProtocolVersions(4.4, 4.3, 4.2, 3);
37+
try {
38+
$protocol = $bolt->build();
39+
} catch (ConnectException $exception) {
40+
$bolt->setProtocolVersions(4.1, 4.0, 4, 3);
41+
$protocol = $bolt->build();
42+
}
43+
44+
if (!$protocol instanceof V3) {
45+
throw new RuntimeException('Client only supports bolt version 3 and up.');
46+
}
47+
48+
$response = $auth->authenticateBolt($protocol, $userAgent);
49+
} catch (MessageException $e) {
50+
throw Neo4jException::fromMessageException($e);
51+
}
52+
53+
return [$protocol, $response];
54+
}
55+
}

src/BoltFactory.php

Lines changed: 39 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -14,102 +14,75 @@
1414
namespace Laudis\Neo4j;
1515

1616
use Bolt\Bolt;
17-
use Bolt\connection\AConnection;
18-
use Bolt\connection\Socket;
19-
use Bolt\connection\StreamSocket;
20-
use Bolt\error\ConnectException;
21-
use Bolt\error\MessageException;
17+
use Bolt\connection\IConnection;
2218
use Bolt\protocol\V3;
2319
use function explode;
24-
use function extension_loaded;
20+
use Laudis\Neo4j\Bolt\AConnectionFactory;
2521
use Laudis\Neo4j\Bolt\BoltConnection;
26-
use Laudis\Neo4j\Bolt\SslConfigurator;
22+
use Laudis\Neo4j\Bolt\ProtocolFactory;
2723
use Laudis\Neo4j\Common\ConnectionConfiguration;
2824
use Laudis\Neo4j\Contracts\AuthenticateInterface;
2925
use Laudis\Neo4j\Contracts\ConnectionFactoryInterface;
3026
use Laudis\Neo4j\Contracts\ConnectionInterface;
3127
use Laudis\Neo4j\Databags\DatabaseInfo;
3228
use Laudis\Neo4j\Databags\SessionConfiguration;
3329
use Laudis\Neo4j\Databags\SslConfiguration;
34-
use Laudis\Neo4j\Databags\TransactionConfiguration;
3530
use Laudis\Neo4j\Enum\ConnectionProtocol;
36-
use Laudis\Neo4j\Exception\Neo4jException;
3731
use Psr\Http\Message\UriInterface;
38-
use RuntimeException;
3932

4033
/**
4134
* Small wrapper around the bolt library to easily guarantee only bolt version 3 and up will be created and authenticated.
4235
*
43-
* @implements ConnectionFactoryInterface<array{0: V3, 1: AConnection}>
36+
* @implements ConnectionFactoryInterface<array{0: V3, 1: IConnection}>
4437
*/
4538
final class BoltFactory implements ConnectionFactoryInterface
4639
{
4740
private UriInterface $uri;
48-
private SslConfigurator $sslConfigurator;
41+
private AConnectionFactory $connectionFactory;
42+
private ProtocolFactory $protocolFactory;
4943

5044
/**
5145
* @psalm-external-mutation-free
5246
*/
53-
public function __construct(
54-
UriInterface $uri,
55-
SslConfigurator $sslConfigurator
56-
) {
47+
public function __construct(UriInterface $uri, AConnectionFactory $connectionFactory, ProtocolFactory $protocolFactory)
48+
{
5749
$this->uri = $uri;
58-
$this->sslConfigurator = $sslConfigurator;
50+
$this->connectionFactory = $connectionFactory;
51+
$this->protocolFactory = $protocolFactory;
5952
}
6053

61-
public function createConnection(string $userAgent, SslConfiguration $sslConfig, SessionConfiguration $sessionConfig, AuthenticateInterface $auth): ConnectionInterface
62-
{
63-
[$encryptionLevel, $sslConfig] = $this->sslConfigurator->configure($this->uri, $sslConfig);
64-
$port = $this->uri->getPort() ?? 7687;
65-
if (extension_loaded('sockets') && $sslConfig === null) {
66-
$connection = new Socket($this->uri->getHost(), $port, TransactionConfiguration::DEFAULT_TIMEOUT);
67-
} else {
68-
$connection = new StreamSocket($this->uri->getHost(), $port, TransactionConfiguration::DEFAULT_TIMEOUT);
69-
if ($sslConfig !== null) {
70-
$connection->setSslContextOptions($sslConfig);
71-
}
72-
}
73-
74-
$bolt = new Bolt($connection);
75-
76-
try {
77-
$bolt->setProtocolVersions(4.4, 4.3, 4.2, 3);
78-
try {
79-
$protocol = $bolt->build();
80-
} catch (ConnectException $exception) {
81-
$bolt->setProtocolVersions(4.1, 4.0, 4, 3);
82-
$protocol = $bolt->build();
83-
}
84-
85-
if (!$protocol instanceof V3) {
86-
throw new RuntimeException('Client only supports bolt version 3 and up.');
87-
}
88-
89-
$response = $auth->authenticateBolt($protocol, $userAgent);
90-
} catch (MessageException $e) {
91-
throw Neo4jException::fromMessageException($e);
92-
}
54+
public function createConnection(
55+
string $userAgent,
56+
SslConfiguration $sslConfig,
57+
SessionConfiguration $sessionConfig,
58+
AuthenticateInterface $auth
59+
): ConnectionInterface {
60+
[$connection, $encryptionLevel] = $this->connectionFactory->create($sslConfig);
61+
[$protocol, $authResponse] = $this->protocolFactory->createProtocol($connection, $userAgent);
9362

9463
$sessionConfig = new ConnectionConfiguration(
95-
$response['server'],
64+
$authResponse['server'],
9665
$this->uri,
97-
explode('/', $response['server'])[1] ?? '',
66+
explode('/', $authResponse['server'])[1] ?? '',
9867
ConnectionProtocol::determineBoltVersion($protocol),
9968
$sessionConfig->getAccessMode(),
10069
$sessionConfig->getDatabase() === null ? null : new DatabaseInfo($sessionConfig->getDatabase())
10170
);
10271

103-
return new BoltConnection($protocol, $connection, $sessionConfig, $auth, $encryptionLevel);
72+
return new BoltConnection($protocol, $connection, $sessionConfig, $auth, $encryptionLevel, $userAgent);
10473
}
10574

106-
public function canReuseConnection(ConnectionInterface $connection, string $userAgent, SslConfiguration $sslConfig, AuthenticateInterface $auth): bool
107-
{
75+
public function canReuseConnection(
76+
ConnectionInterface $connection,
77+
string $userAgent,
78+
SslConfiguration $sslConfig,
79+
AuthenticateInterface $auth
80+
): bool {
10881
return $connection->getAuthentication()->toString($this->uri) === $auth->toString($this->uri) &&
109-
$connection->getEncryptionLevel() === $this->sslConfigurator->configure($this->uri, $sslConfig)[0] &&
110-
$connection->getUserAgent() === $userAgent &&
111-
$connection->getServerAddress()->getHost() === $this->uri->getHost() &&
112-
$connection->getServerAddress()->getPort() === $this->uri->getPort();
82+
$this->connectionFactory->sameEncryptionLevel($connection->getEncryptionLevel(), $this->uri, $sslConfig) &&
83+
$connection->getUserAgent() === $userAgent &&
84+
$connection->getServerAddress()->getHost() === $this->uri->getHost() &&
85+
$connection->getServerAddress()->getPort() === $this->uri->getPort();
11386
}
11487

11588
public function reuseConnection(ConnectionInterface $connection, SessionConfiguration $config): ConnectionInterface
@@ -125,6 +98,13 @@ public function reuseConnection(ConnectionInterface $connection, SessionConfigur
12598

12699
[$protocol, $connectionImpl] = $connection->getImplementation();
127100

128-
return new BoltConnection($protocol, $connectionImpl, $config, $connection->getAuthentication(), $connection->getEncryptionLevel());
101+
return new BoltConnection(
102+
$protocol,
103+
$connectionImpl,
104+
$config,
105+
$connection->getAuthentication(),
106+
$connection->getEncryptionLevel(),
107+
$connection->getUserAgent()
108+
);
129109
}
130110
}

0 commit comments

Comments
 (0)