Skip to content

Commit

Permalink
Move tunnel helper function to be internal
Browse files Browse the repository at this point in the history
  • Loading branch information
trowski committed Feb 11, 2025
1 parent bb76755 commit 06d5a49
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 58 deletions.
49 changes: 2 additions & 47 deletions src/Http1TunnelConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,65 +5,20 @@
use Amp\Cancellation;
use Amp\ForbidCloning;
use Amp\ForbidSerialization;
use Amp\Http\Client\Connection\Http1Connection;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Request;
use Amp\Http\HttpMessage;
use Amp\Http\HttpStatus;
use Amp\Http\Tunnel\Internal\TunnelSocket;
use Amp\NullCancellation;
use Amp\Socket\ConnectContext;
use Amp\Socket\ConnectException;
use Amp\Socket\Socket;
use Amp\Socket\SocketAddress;
use Amp\Socket\SocketConnector;
use function Amp\Http\Client\processRequest;
use function Amp\now;
use function Amp\Socket\socketConnector;

/**
* @psalm-import-type HeaderParamArrayType from HttpMessage
*/
final class Http1TunnelConnector implements SocketConnector
{
use ForbidCloning;
use ForbidSerialization;

/**
* @param HeaderParamArrayType $customHeaders
*/
public static function tunnel(
Socket $socket,
float $connectDuration,
?float $tlsHandshakeDuration,
string $target,
array $customHeaders,
Cancellation $cancellation,
): Socket {
$request = new Request('http://' . \str_replace('tcp://', '', $target), 'CONNECT');
$request->setHeaders($customHeaders);

$request->setUpgradeHandler(static function (Socket $socket) use (&$upgradedSocket): void {
$upgradedSocket = $socket;
});

$connection = new Http1Connection($socket, $connectDuration, $tlsHandshakeDuration, 1);

$response = processRequest($request, [], function (Request $request) use ($connection, $cancellation) {
/** @var Stream $stream */
$stream = $connection->getStream($request);

return $stream->request($request, $cancellation);
});

if ($response->getStatus() !== HttpStatus::OK) {
throw new ConnectException('Failed to connect to proxy: Received a bad status code (' . $response->getStatus() . ')');
}

\assert($upgradedSocket !== null);

return $upgradedSocket;
}

public function __construct(
private readonly string $proxyAddress,
private readonly array $customHeaders = [],
Expand All @@ -82,7 +37,7 @@ public function connect(

$socket = $connector->connect($this->proxyAddress, $context, $cancellation);

return self::tunnel(
return TunnelSocket::tunnel(
socket: $socket,
connectDuration: now() - $start,
tlsHandshakeDuration: null,
Expand Down
4 changes: 2 additions & 2 deletions src/Https1TunnelConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function __construct(
public function connect(
SocketAddress|string $uri,
?ConnectContext $context = null,
?Cancellation $cancellation = null
?Cancellation $cancellation = null,
): Socket {
$socketConnector = $this->socketConnector ?? socketConnector();
$context ??= new ConnectContext();
Expand All @@ -55,7 +55,7 @@ public function connect(

$end = now();

$remoteSocket = Http1TunnelConnector::tunnel(
$remoteSocket = TunnelSocket::tunnel(
socket: $remoteSocket,
connectDuration: $end - $start,
tlsHandshakeDuration: $end - $tlsStart,
Expand Down
62 changes: 53 additions & 9 deletions src/Internal/TunnelSocket.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,70 @@
use Amp\Cancellation;
use Amp\ForbidCloning;
use Amp\ForbidSerialization;
use Amp\Http\Client\Connection\Http1Connection;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Request;
use Amp\Http\HttpMessage;
use Amp\Http\HttpStatus;
use Amp\Socket\ConnectException;
use Amp\Socket\Socket;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use Amp\Socket\TlsState;
use function Amp\Http\Client\processRequest;

/** @internal */
/**
* @internal
*
* @psalm-import-type HeaderParamArrayType from HttpMessage
*/
final class TunnelSocket implements Socket
{
use ForbidCloning;
use ForbidSerialization;

private Socket $localSocket;
private Socket $remoteSocket;
/**
* @internal
*
* @param HeaderParamArrayType $customHeaders
*/
public static function tunnel(
Socket $socket,
float $connectDuration,
?float $tlsHandshakeDuration,
string $target,
array $customHeaders,
Cancellation $cancellation,
): Socket {
$request = new Request('http://' . \str_replace('tcp://', '', $target), 'CONNECT');
$request->setHeaders($customHeaders);

public function __construct(Socket $local, Socket $remote)
{
$this->localSocket = $local;
$this->remoteSocket = $remote;
$request->setUpgradeHandler(static function (Socket $socket) use (&$upgradedSocket): void {
$upgradedSocket = $socket;
});

$connection = new Http1Connection($socket, $connectDuration, $tlsHandshakeDuration, 1);

$response = processRequest($request, [], function (Request $request) use ($connection, $cancellation) {
/** @var Stream $stream */
$stream = $connection->getStream($request);

return $stream->request($request, $cancellation);
});

if ($response->getStatus() !== HttpStatus::OK) {
throw new ConnectException('Failed to connect to proxy: Received a bad status code (' . $response->getStatus() . ')');
}

\assert($upgradedSocket !== null);

return $upgradedSocket;
}

public function __construct(
private readonly Socket $localSocket,
private readonly Socket $remoteSocket,
) {
}

public function setupTls(?Cancellation $cancellation = null): void
Expand Down Expand Up @@ -61,7 +107,6 @@ public function end(): void
$this->localSocket->end();
}

/** @api */
public function reference(): void
{
\assert($this->localSocket instanceof ResourceStream);
Expand All @@ -70,7 +115,6 @@ public function reference(): void
$this->remoteSocket->reference();
}

/** @api */
public function unreference(): void
{
\assert($this->localSocket instanceof ResourceStream);
Expand Down

0 comments on commit 06d5a49

Please sign in to comment.