reactphp-legacy / socket-client Goto Github PK
View Code? Open in Web Editor NEW[Legacy] Async, streaming plaintext TCP/IP and secure TLS based connections for ReactPHP.
License: MIT License
[Legacy] Async, streaming plaintext TCP/IP and secure TLS based connections for ReactPHP.
License: MIT License
Let's face it, this project is stable and has been used in production for years
However, we're currently following a v0.X.Y release scheme (http://sentimentalversioning.org/).
We should finally make this explicit and fully adhere to SemVer and release a stable v1.0.0.
To a large extend, a stable v1.0.0 helps making BC breaks more explicit and thus the whole project more reliable from a consumer perspective. This project is actively maintained and has received some major updates in the last weeks and has some major updates planned in the next weeks. Given our current versioning scheme, we'd like to ensure all anticipated BC breaks will be merged before the planned v1.0.0 release.
As such, I've set up a roadmap that enlists only the major changes for each version among with planned release dates towards a stable v1.0.0 release:
This ticket aims to serve as a basic overview and does not contain every single change. Please also see the milestone links and the CHANGELOG for more details.
Obviously, this roadmap is subject to change and I'll try to keep it updated as we progress. In order to avoid cluttering this, please keep discussion in this ticket to a minimum and consider reaching out to us through new tickets or Twitter etc.
Opening this for the reference and to raise awareness. Note that there's an ongoing discussion as to whether this component should be merged into the Socket component.
See reactphp/socket#74 for details.
Is there anything I can do, to create a synchronize call and get the result inline?
$stream->write('TESTING');
$line = $stream->read(1024); // Response
$stream->write('ONE');
$line = $stream->read(1024); // Response
$stream->write('TWO');
$line = $stream->read(1024); // Response
Is there a way to instantiate a pushing client which doesnt care about incoming messages? The current socket client requires a StreamSelectLoop argument..
This is in support of phergie/phergie-irc-bot-react#42
i noticed the code never goes into this line https://github.com/reactphp/socket-client/blob/v0.4.4/src/SecureConnector.php#L22 because there is isn't a write event coming while it seems to be waiting for that https://github.com/reactphp/socket-client/blob/v0.4.4/src/Connector.php#L58
can someone confirm this and also explain why a write event is expected and what kind of write event is suppose to trigger this?
while getting https://groups.google.com/forum/feed/elm-discuss/msgs/atom.xml?num=50 i get this:
Error executing request: exception 'UnexpectedValueException' with message 'Unable to complete SSL/TLS handshake: SNI_server_name is deprecated in favor of peer_name' in vendor\react\socket-client\src\StreamEncryption.php:108
I'm not using this library directly but as a dependency of https://github.com/phergie/phergie-irc-plugin-react-feedticker
We should register a Promise cancellation handler so that the following code actually cleans up the underlying socket resource:
$promise = $connector->create('reactphp.org', 80);
$promise->cancel();
This can eventually also be used as the basis for timeout support (#28), similar to this:
$promise = $connector->create('reactphp.org', 80);
$loop->addTimer(3.0, function () use ($promise) {
$promise->cancel();
});
In regards to this thread on reactphp/stream: reactphp/stream#17
It was found that the Stream TLS Bugfix was reverted (https://bugs.php.net/bug.php?id=65137), making TLS Streams block again.
Per @cboden the wrapSecure version check will need to be removed. Just moving this issue over to the correct project :)
There's currently no way to connect to "localhost" or any other host names listed in the local /etc/hosts file. We could provide a hard-coded default for some common host names (like "localhost"), but this is bound to break.
In particular, this also affects usage with linked Docker containers where one container references another container by its host name. This means that there's currently no way to connect to other containers by their name.
Opening this ticket as a reminder - this actually depends on reactphp/dns#10
HHVM does not (currently) implement the required stream_socket_enable_crypto()
function (facebook/hhvm#1647).
Trying to establish a SSL/TLS connection via the SecureConnector
results in a fatal error:
Fatal error: Call to undefined function stream_socket_enable_crypto() […]
Opening this ticket as a reminder and for reference in related issues.
Server Name Indication (SNI) works just fine on any recent PHP version and HHVM.
However, this is currently broken for legacy PHP versions (PHP < 5.6). This was introduced by #43 which landed in v0.5.0 and v0.4.5 (older versions work fine on legacy PHP versions). I stumbled upon this while trying to issue HTTPS requests against a host that requires proper SNI support.
This is a known issue for PHP < 5.6, see also https://github.com/amphp/socket/blob/aa784fe3a18fa8514e57714142488f629073c7a9/lib/functions.php#L87-90
<?php
require __DIR__ . '/vendor/autoload.php';
$loop = \React\EventLoop\Factory::create();
$tcpConnector = new React\SocketClient\TcpConnector($loop);
$tcpConnector->create('127.0.0.1', 8080)->then(function (React\Stream\Stream $stream) {
echo "Connected\n";
}, function() {
echo "Failed\n";
});
$loop->run();
Have no service listening to port 8080 (or any port to attempt to connect to), run script. Result is Connected
, expected Failed
.
...so I can connect to an ip address if I do something locally
It is already possible to call createSocketForAddress
with the desired ip address, but it doesn't feel right that I need a dns resolver for that. One solution would be to have a resolving connector and non resolving connector. Or are there other suggestions?
I'm willing to try something in code if I know what the opinions are...
SecureStream is hard coded into StreamEncryption and there is no easy ability to replace it with extended class.
Reason for replacement: I need to catch and correctly proceed exception " stream_get_contents(): SSL: Connection reset by peer " in method SecureStream::handleData();
Or would be nice updte code with correct catch;
try {
$this->handleData($stream);
} catch (\Exception $e) {
$this->emit('error', array($e, $this));
}
\React\Stream\Stream
Hi,
I have question regarding the capability of this library. Does this library works for Http Streaming connections?
Currently, I'm using a solution with fockopen and while($feof($fp)) to wait until server closes the connection or timeout.
Hi!
I would like to exchange some data on a stream before enabling TLS on it. Currently, the SecureConnector doesn't allow this, and there is no clean way of enabling TLS on Streams after the connection.
Use cases:
I'm going to implement this, however I would like your opinion on these solutions:
Add a DelayedSecureConnector class. Its create() method would result in a DelayedSecureStream instance, with a connect() method
Add a createDelayed() method on SecureConnector, returning the stream and a callback that would allow to enable TLS. Also add a SecureConnectorInterface.
list ($stream, $enableTLS) = $connector->connectDelayed();
// Do something with the stream
// Then, enable TLS:
$enableTLS()->then(...);
Add a "prologue" callback argument to create(), allowing the callback to manipulate the stream before encryption is enabled
WDYT ?
In a terminal, I'm running netcat listening on port 3001, and expecting to to see "hello from react" in that terminal when I run the following php script, which is essential a copy of the example from the readme:
<?php
$loop = React\EventLoop\Factory::create();
$dnsResolverFactory = new React\Dns\Resolver\Factory();
$dns = $dnsResolverFactory->createCached('8.8.8.8', $loop);
$connector = new React\SocketClient\Connector($loop, $dns);
$connector->create('127.0.0.1', 3001)
->then(function (React\Stream\Stream $stream) {
$stream->write("hello from react.\n");
$stream->close();
};
?>
Instead, the script exits silently and nothing is recieved in the netcat window.
FWIW, using telnet to manually connect to port 3001 and type messages DOES cause them to be echoed in the nc terminal, as expected.
What am I doing wrong?
Hello!
May be I`m noob, but how may I read (use) response in loop?
My server broadcasts every 5-30 sec some data. How to cache this data?
All recent SSL context updates will land in the upcoming v0.5.0 release. This is done because they build on #46, which contains a (rather small) BC break.
Given that there are quite a few consumers which rely on version ~0.4.0
of this library, we should consider backporting the SSL context updates to a v0.4.x
release.
Relevant tickets:
@clue Shouldn't we mark react/socket-client
as abandoned
on packagist.org and redirect people to react/socket
?
PR #14 by @cboden introduced a new SecureStream
class to work around an SSL buffering issue.
The workaround is only applied to affected versions, i.e. to any but the newest PHP versions.
This workaround has been shipped with the latest v0.4.2 release.
I absolutely agree that we should provide this workaround.
However, the workaround introduces a subtle BC break - something that should not happen in a minor release.
The documentation of this project states that every call to create()
resolves with a Stream
instance. The (undocumented) workaround changes this to return a SecureStream
instead.
The SecureStream
currently does not extend the Stream
class.
This breaks our backwards compatibility with all packages that depend on this project that explicitly expect a Stream
instance. Arguably, we should have provided an interface to depend on to begin with.
The easiest fix would be to modify the SecureStream
to extend the Stream
class and release a v0.4.3 tag.
An alternative would be to update the documentation and state that we only return an object that implements the DuplexStreamInterface
and release a v0.5.0 tag. In that case we would have to depend on react/stream: >= 0.4.2, < 0.5.0
.
For comparison curl provides you with two options:
CURLOPT_CONNECTTIMEOUT
the time it may take to establish the connection.CURLOPT_TIMEOUT
the time the total execution of the request is allowed to take.Both of these I'm currently using to "probe" ~150 servers per day and test their connect and response time. Since this is about speed, I'm not interested in keeping the connection open for more than a couple of seconds, so I would like to tweak both these parameters.
The timeout branch seemed to be aimed at the total execution time equivalent.
And the connection timeout is available in stream_socket_client, currently a fixed value Connector.php:43.
It's not currently possible to pass in context options (e.g. bindto) when creating a socket.
Each connector currently resolves with a Stream
instance from the react/stream component. We should look into resolving with a Connection
instance (which likely extends the Stream
class) which should expose the remote address like this:
$connector->create('google.com', 80)->then(function (Connection $conn) {
echo 'connected to ' . $conn->getRemoteAddress();
$conn->close();
});
Note that the react/socket component already has a similar class (https://github.com/reactphp/socket/blob/master/src/Connection.php) which represents the server-side end of a connection.
I am trying to write a load balancer to change the proxy clients. The problem is that the results are being concatenated.
The good part is that this works, but for some reason the results are being concatenated in the same output.
Example of results. I don't understand what cache is in there, and why it keeps it even if I am initializing a new client connection every time + setup the new $server...
"HTTP/1.1 200 OK Server: nginx/1.6.2 Date: Mon, 10 Nov 2014 12:35:22 GMT Content-Type: text/plain Transfer-Encoding: chunked Connection: close Cache-Control: no-cache f 176.10.100.228 0 HTTP/1.1 200 OK Server: nginx/1.6.2 Date: Mon, 10 Nov 2014 12:35:22 GMT Content-Type: text/plain Transfer-Encoding: chunked Connection: close Cache-Control: no-cache f 188.138.17.248 0 ";
$loop = React\EventLoop\Factory::create();
$dnsResolverFactory = new React\Dns\Resolver\Factory();
$dns = $dnsResolverFactory->createCached('8.8.8.8', $loop);
$socket = new React\Socket\Server($loop);
$socket->listen('2500','127.0.0.1');
$factory = new Socks\Factory($loop, $dns);
// set next SOCKS server as target
$target = $factory->createClient('127.0.0.1', '1020'); // initial port
$target->setResolveLocal(false);
// Extra
$server = new Socks\Server($socket, $loop, $target->createConnector());
$server->on('connection', function($conn)
{
global $start, $stop, $factory, $loop, $socket, $target, $server;
echo $conn->getRemoteAddress().' connected!'.PHP_EOL;
$rand = rand(1020, 1050); // random selection of ports (socks5 proxy)
echo "connected to [".$rand."]".PHP_EOL;
$target2 = $factory->createClient('127.0.0.1', $rand );
$server = new Socks\Server($socket, $loop, $target2->createConnector() );
});
$server->setProtocolVersion(5);
Connector 怎么实现重连机制
Hey, Not sure if this is desired behaviour or not, but I've run into an issue where the data in the buffer doesn't ever get written.
As per example:
$connector->create('www.google.com', 80)->then(function (React\Stream\Stream $stream) {
$stream->write('...');
$stream->close();
});
From what I can see, the $stream->write()
appends the data to the buffer and doesn't do a lot else at that point; it waits for the next tick of the event loop to come and write the buffer out. Because of that, when you follow it immediately with $stream->close()
, it closes it and flushes the buffer.
As I said, I'm not sure if this is expected behaviour, and I can see benefits in both. As a work around, I'm doing this:
$connector->create('www.google.com', 80)->then(function (Stream $stream) use ($template) {
$stream->write('…');
$stream->getBuffer()->on('full-drain', function() use($stream) {
$stream->close();
});
});
Is this as simple as a doc update?
Here in readme it says:
Before you can actually transmit and receive data to/from a remote server, you have to establish a connection to the remote end. Establishing this connection through the internet/network takes some time as it requires several steps in order to complete:
But it was never explained how to recieve data from scoket server?
I Use Secure Gateway service on bluemix thus I connect to the securegateway by using SecureConnector.
It shows connection estabilished.
So can I query LDAP using $stream or anything after connecting?
Thanks
Let's face it, our API might be clean (arguably), but it's cumbersome to work with.
IMO we should first figure out some use cases for our API to see how this is actually going to be used.
The socket-client component is quite lowlevel, so it's unlikely to be used by many users directly. It's probably more likely going to be used as part of some high level abstractions (say, a Redis or MySQL client implementation). See also https://libraries.io/packagist/react%2Fsocket-client/dependents
These high level components depend on a ConnectorInterface
and will likely use DI to inject this. They probably care little about how the connector works. Neither should they care about any "additional" parameters. They do care about the target (hostname and port). Hence (IMHO) they should not have to take care of context options, connection timeouts or even selecting the "right" connector.
Afaict all they (essentially) need to do is to establish a connection to a given remote location. As such, I'm suggesting a simplified API similar to this:
// probably one of the most common use cases
$api->createConnection('tcp://www.google.com:80');
// automatically assumes TCP transport, as does fsockopen()
$api->createConnection('www.google.com:80');
// automatically picks use secure connector
$api->createConnection('tls://www.google.com:443');
Also, once we support Unix domain sockets (#37):
// create Unix domain socket, as does fsockopen()
$api->createConnection('unix:///var/tmp/demo.sock');
The implementation of such a facade would be pretty easy, it could accept a Connector
and SecureConnector
(or any other classes implementing the ConnectorInterface
for that matter).
This facade would probably become the one class that every consumer of this component is going to use. The other classes should probably be left as-is and can still be used in advanced scenarios.
Please add support for unix socket.
Hi how can i parse gzip compressed response?
Yesterday, I updated a project to v0.4.4
, and was disappointed to find the SSL buffer issue rearing its ugly head, again. So much so, in fact, that I wanted to see if I could pinpoint which specific versions were affected. I've compiled a table here: https://gist.github.com/mcrumm/49d6ba5e5647429b9689
The list is by no means exhaustive, but it was a bit exhausting... 😃
To test this issue, I'm connecting to Slack's RealTime Messaging API via Pawl, and then waiting for messages. This has been discussed at length in other tickets, so the short version is that at least php-5.6.9
still suffers from the SSL buffer drain problem, and should likely be using fread
. Additionally, there are versions < 5.6.8
that work without wrapSecure
, but I don't know how much concern there is for targeting behavior for specific minor point releases.
PHP7 does not appear to suffer from this issue. Hurray.
The most problematic versions (of those tested):
The fact that I couldn't get 5.6.8 working at all made me start to question the integrity of my tests, since that was the version that I had thought fixed the issue, so if someone else confirms 5.6.8 as working, I'll assume my build is the problem.
Is anyone else seeing similar results?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.