Passed
Push — master ( 5dc58b...30ae6f )
by Sam
03:05
created

Forwarder::forwardAll()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 0
cts 4
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 3
crap 2
1
<?php
2
3
namespace SamIT\Proxy;
4
5
use React\Promise\Promise;
6
use React\Socket\Connection;
7
use React\Socket\ConnectionInterface;
8
use React\Socket\Server;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, SamIT\Proxy\Server.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
use React\Socket\ServerInterface;
10
use React\SocketClient\TcpConnector;
11
use React\Stream\Stream;
12
13
/**
14
 * Class Forwarder
15
 * Implements a connection where the remote end thinks it is talking to another server.
16
 * @package SamIT\Proxy
17
 */
18
class Forwarder
19
{
20
    protected $connector;
21
22 1
    public function __construct(TcpConnector $connector)
23
    {
24 1
        $this->connector = $connector;
25 1
    }
26
27
    /**
28
     * Forwards a connection to the specified host / port using the proxy protocol.
29
     * @param ProxyConnection $connection
30
     * @param string $forwardAddress The host to forward to
31
     * @param int $forwardPort The port to forward to
32
     * @return Promise
33
     */
34
    public function forward(Connection $connection, $forwardAddress, $forwardPort)
35
    {
36
        list($sourceAddress, $sourcePort) = explode(':', stream_socket_get_name($connection->stream, true));
37
        list($targetAddress, $targetPort) = explode(':', stream_socket_get_name($connection->stream, false));
38
        $header = Header::createForward4($sourceAddress, $sourcePort, $targetAddress, $targetPort);
39
        /** @var Promise $promise */
40
        $promise = $this->connector->create($forwardAddress, $forwardPort);
41
        return $promise
42
            ->then(function(Stream $forwardedConnection) use (
43
                $connection, $header,
44
                $sourceAddress, $sourcePort,
45
                $targetAddress, $targetPort
46
            ) {
47
                $forwardedConnection->getBuffer()->once('full-drain', function() use ($connection, $forwardedConnection) {
48
                    $connection->pipe($forwardedConnection);
49
                    $forwardedConnection->pipe($connection);
50
                    $forwardedConnection->emit('init', [$forwardedConnection]);
51
                });
52
                $forwardedConnection->write($header);
53
        });
54
    }
55
56
    public function forwardAll(ServerInterface $server, $forwardAddress, $forwardPort)
57
    {
58
        $server->on('connection', function(ConnectionInterface $connection) use ($forwardAddress, $forwardPort) {
59
           $this->forward($connection, $forwardAddress, $forwardPort);
0 ignored issues
show
Compatibility introduced by
$connection of type object<React\Socket\ConnectionInterface> is not a sub-type of object<React\Socket\Connection>. It seems like you assume a concrete implementation of the interface React\Socket\ConnectionInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
60
        });
61
    }
62
63
}