Giter Site home page Giter Site logo

websocket's Introduction

Hoa


Build status Code coverage Packagist License

Hoa is a modular, extensible and structured set of PHP libraries.
Moreover, Hoa aims at being a bridge between industrial and research worlds.

Hoa\Websocket

Help on IRC Help on Gitter Documentation Board

This library allows to manipulate the WebSocket protocol and proposes a server and a client. It supports two specifications RFC6455 and Hybi (at the same time).

Learn more.

Installation

With Composer, to include this library into your dependencies, you need to require hoa/websocket:

$ composer require hoa/websocket '~3.0'

For more installation procedures, please read the Source page.

Testing

Before running the test suites, the development dependencies must be installed:

$ composer install

Then, to run all the test suites:

$ vendor/bin/hoa test:run

For more information, please read the contributor guide.

Quick usage

As a quick overview, we propose to start a websocket server and echo messages. The class Hoa\Websocket\Server proposes six listeners: open, message, binary-message, ping, close and error. Thus:

$websocket = new Hoa\Websocket\Server(
    new Hoa\Socket\Server('ws://127.0.0.1:8889')
);
$websocket->on('open', function (Hoa\Event\Bucket $bucket) {
    echo 'new connection', "\n";

    return;
});
$websocket->on('message', function (Hoa\Event\Bucket $bucket) {
    $data = $bucket->getData();
    echo '> message ', $data['message'], "\n";
    $bucket->getSource()->send($data['message']);
    echo '< echo', "\n";

    return;
});
$websocket->on('close', function (Hoa\Event\Bucket $bucket) {
    echo 'connection closed', "\n";

    return;
});
$websocket->run();

Finally, we have to write a client in HTML and Javascript:

<input type="text" id="input" placeholder="Message…" />
<hr />
<pre id="output"></pre>

<script>
  var host   = 'ws://127.0.0.1:8889';
  var socket = null;
  var input  = document.getElementById('input');
  var output = document.getElementById('output');
  var print  = function (message) {
      var samp       = document.createElement('samp');
      samp.innerHTML = message + '\n';
      output.appendChild(samp);

      return;
  };

  input.addEventListener('keyup', function (evt) {
      if (13 === evt.keyCode) {
          var msg = input.value;

          if (!msg) {
              return;
          }

          try {
              socket.send(msg);
              input.value = '';
              input.focus();
          } catch (e) {
              console.log(e);
          }

          return;
      }
  });

  try {
      socket = new WebSocket(host);
      socket.onopen = function () {
          print('connection is opened');
          input.focus();

          return;
      };
      socket.onmessage = function (msg) {
          print(msg.data);

          return;
      };
      socket.onclose = function () {
          print('connection is closed');

          return;
      };
  } catch (e) {
      console.log(e);
  }
</script>

Here we are. All sent messages are echoed.

Awecode

The following awecodes show this library in action:

  • Hoa\Websocket: why and how to use Hoa\Websocket\Server and Hoa\Websocket\Client? A simple example will illustrate the WebSocket protocol.

Documentation

The hack book of Hoa\Websocket contains detailed information about how to use this library and how it works.

To generate the documentation locally, execute the following commands:

$ composer require --dev hoa/devtools
$ vendor/bin/hoa devtools:documentation --open

More documentation can be found on the project's website: hoa-project.net.

Getting help

There are mainly two ways to get help:

Contribution

Do you want to contribute? Thanks! A detailed contributor guide explains everything you need to know.

License

Hoa is under the New BSD License (BSD-3-Clause). Please, see LICENSE for details.

Related projects

The following projects are using this library:

  • Marvirc, A dead simple, extremely modular and blazing fast IRC bot,
  • WellCommerce, Modern e-commerce engine built on top of Symfony 3 full-stack framework.

websocket's People

Contributors

flip111 avatar hywan avatar jubianchi avatar metalaka avatar osaris avatar pierozi avatar shulard avatar stephpy avatar tomzx avatar vonglasow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

websocket's Issues

class not found

i am following the same thing but still i am geting like this

error:PHP Fatal error: Class 'Hoa\Websocket\Server' not found
and even i checked in vendor ther is hoa folder present

Only one char read to buffer on secure connection

Hi.

I've got a websocket server and I connect to it both with a PHP client and a browser JS client. On localhost, with unsecure connection it works fine. On production however, where wss:// is used, the PHP client can talk to the server normally, the browser client however encounters "Connection closed before receiving a handshake response".

I dug a bit into it, and found out, that the request from the PHP client looks like this:

GET /{accessToken} HTTP/1.1\r\n
Host: {host.com}\r\n
User-Agent: Hoa\r\n
Upgrade: WebSocket\r\n
Connection: Upgrade\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
Sec-WebSocket-Key: {key}==\r\n
Sec-WebSocket-Version: 13\r\n
\r\n

The request from the browser looks like this

G

But if I read from the buffer again (after https://github.com/hoaproject/Websocket/blob/master/Server.php#L98), I'm getting all the rest: ET /{accessToken} ...

I did an ugly hotfix in my project. I extended the Server class and added in doHandshake:

    $buffer = $connection->read(2048);
    if ($buffer === 'G') {
        $buffer .= $connection->read(2048);
    }
    $request = $this->getRequest();
    $request->parse($buffer);

And this way it works. But I have no idea, what the underlying issue is.

Bucket Send problem

Hello, iam trying to save users in special room using
SplObjectStorage
For example
$data->room[$room_id]->attach($bucket);
foreach($data->room[$room_id] as $buck)
{

$buck->getSource()->send("new user");
}
The problem that this method send the msg each time for the same user inserted in first line
...
I need to save the users and send msg for each

Https Symfony2

Hi all,
Does this bundle support ssl certificate ?

I have create my server push, when i communicate my app with the server via http, its work perfectly.
But it's not the case with https !

What can i do ?
i use Mamp Pro on localhost, this is the url of my app, https://ispace:8890/admin/ .
Thanks

Creating topics for classified of broadcasting message...

Creating topics for classified of broadcasting message

Hello again.
Other things is about the creation of topics, of thread for sending message at one or more groups of recipients, for example, create some tags, example, notify.admins, chat.public, chat.private.{thread_id}, etc, and opened this threads from the javascript client, and validate this connect using php. For example:

use HoaTopic;
...
    public function getLogin()
    {
        HoaTopic::send('Login rendered', 'notify.admin');
        return view('auth.login');
    }
...

and in the class HoaWebSocket, or other, do this.

class HoaTopic extend HoaWebSocket {
    ...
    public function send($message, $topic) {
        $user = Sentinel::getUser();
        if ($topic == 'notify.admin') {
            if (!$user->hasAccess('admin')) {
                self::send('Access Denied at user '.$user->id, 'notify.admin');
                return;
            }
            $nodes = $bucket->getSource()->getTopics($topic)->getConnection()->getNodes();
            foreach ($nodes as $node) {
                $node->send($message);
            }
        }
    }
    ...
}

Thanks

YnievesDotNet

How to deal with "disconnections" and "keep alive" stuff?

I didn't find, in the documentation (including "hack book"), a way to properly deal with client disconnections (network issues, etc.) and how to reconnect then.

Have you some additional informations to share about any disconnection related things?

Thanks for the good work!

Send message to a specific Client from another place than $server->on('message'..)

Hi guys. I'm working on a app that manage some IoT devices. Devices are WebSockets client connected to my app.
Is there any method to send a message to a specific client from other place than $server->on(..) ?
I want to send messages to device from my controller class.

<?php
namespace App\Http\Controllers;
use App\Models\DeviceModel;

class DeviceController extends Controller
{
    public function turnOn(DeviceModel $deviceModel)
    {
        if($deviceModel->state == 'OFF'){
           $message = 'ON';
            ...
            Something::send(
                $deviceModel->websocketNodeId,
                $message
            );
            ...
        }
    }
}

Here I try to link client connection with a unique node instance.

$ws->on('message', function (\Hoa\Event\Bucket $ev) {

    $message = json_decode($ev->getData()['message'] ?? '{}');
    $node  = $ev->getSource()->getConnection()->getCurrentNode();

    //assign client to a specific node, in my case, to a DeviceNode.

    if($node instanceof \Hoa\Websocket\Node && $message->deviceToken){

        $ev->getSource()->getConnection()->setNodeName(\App\TiCTRL\DeviceNode::class);
        $node = $ev->getSource()->getConnection()->getCurrentNode();

        $nodeId = $node->getId;

        $deviceModel = \App\Models\DeviceModel::updateNodeIdByTokenAndGet($message->deviceToken,$nodeId);

        $node->setDeviceModel($deviceModel);
    }

});

How to broadcast events to websocket server with URL wss://xxx.xx

Hello,

I'm currently trying to implement slack bot stuff using PHP. I found that there is an awesome Real Time Messaging API which using websockets (https://api.slack.com/rtm).

I tried to implement a method which can follow the given steps :

I found that Hoaproject as an awesome WebSocket client/server but I can't find a way to do that...

A websocket URL given by Slack API (they have a lifetime of 30sec): wss://ms177.slack-msgs.com/websocket/GEjhTU7tHl3C90SwJuKaF71Orb8F9HZgdv-HIwf4HxIMygveAW9xc2X_bZb_LtDXLVAapy7nTJ7qh9Oz0zYnyrr7Gn2kD4635oihxNh3ZTM=.

Here the code I used to do that :

<?php
require_once __DIR__.'/vendor/autoload.php';

$rtmStart = "https://slack.com/api/rtm.start?token=".$argv[1];
$content = json_decode(file_get_contents($rtmStart));

$client = new Hoa\Websocket\Client( new Hoa\Socket\Client($url) );
$client->connect();

$client->send('{
     "type": "message",
     "channel": "XXX",
     "user": "XXX",
     "text": "Hello world",
     "ts": "'.microtime(true).'"
}');

$client->close();

Thanks :)

websocket launch on remote host

hi, I'm sorry to open ticket for my question , but actually I'm not pro in php and with your instruction not figure out how to install it in my remote directory host , and really appreciate for couple of hints , in fact I've tried to hook url on my host to the Telegram webhoock call back bot, so at first step new update data inserted to MySQL database then websoket server give the update data to designated live client .
the problem is I bought the domain & host which is has Cpanel and I don't know how to configure my php server to lunch websocket service
can you tell me which files should be copy in designated host URL and what files should be modified?
Thanks
My Cpanel images
image

image

TLS Support

The TLS support of WebSocket is partially working.
The enableEncryption method was forgot in Server side.

I've open a PR with demo on my Fork for trying to make it work. (certificate included)
Once the enableEncryption are fix; the php client are working, but not a web browser.

https://github.com/Pierozi/Websocket/pull/1/files#diff-5a72b4fa5efc1217f53f085c8580c79eR94

Maybe this is due to my certificate, self-signed, works great with php client because i've set context who allow self-signed and not verify peer.

If anyone have time to test it with real certificate, that could be good.

Documentation wss

Hello,

i would be thankful for the service that is really great but in your documentation about wss:// i see only to set the url wss:// on server side and client side but it is not enough, cause chrome does not connect to hoa websocket.

I think it is needed to have SSL certificates on server but it is not explained how to configure Hoa to choose the path for that certificate.

Thank you.
Andrea Bernardi

Query string parameters seem unsupported?

It seems that query string parameters are unsupported. If I have a websocket URL like:

wss://br3-teapot.br.de/socket.io/?EIO=3&transport=websocket

I get an error

Handshake has failed, the server did not return a valid response.

Client:
    GET /socket.io/ HTTP/1.1
    ...

The query string is not in the HTTP request, but it is required. For example, if I test it on http://www.websocket.org/echo.html it works just fine with the complete url but not when the query string part is stripped.

This is a part of my code at the moment:

$socketClient = new SocketClient($url);
$webSocketClient = new WebSocketClient($socketClient);

What can I do to make this work?

Problem when the connection is closed to early for the client to know it

Hello,

I'm currently writing a WebSocket daemon to notify users when some data are updating. I want to retrieve some context from the WebSocket connection so I use the socket url to pass parameters. For example: ws://127.0.0.1:8889/campaign/1/user/1

To check that URL contains valid informations, I wrote a simple onOpen handler on my server. If the check does not pass, I close the connection. The next time the client need to read through the socket, it's already closed and I got the following php error :

[ErrorException]
stream_socket_shutdown(): supplied resource is not a valid stream resource

Server code

$server = new Websocket\Server(
    new Socket\Server($url)
);
$server->getConnection()->setNodeName(UserNode::class);
$server->on('open', function() {
    $request = $bucket->getSource()->getRequest();
    if (!preg_match('#/campaign/([0-9]+)/user/([0-9]+)#', $request->getUrl(), $matches)) {
        $bucket->getSource()->send('Go away hacker !');
        $bucket->getSource()->close(Websocket\Connection::CLOSE_POLICY_ERROR);

        return;
    }
    try {
        $campaign = Campaign::findOrFail((int)$matches[1]);
        $user     = User::findOrFail((int)$matches[2]);
    } catch (\Exception $e) {
        $bucket->getSource()->send('Invalid User / Campaign given');
        $bucket->getSource()->close(Websocket\Connection::CLOSE_DATA_ERROR);
        return;
    }

    $node = $bucket->getSource()->getConnection()->getCurrentNode();
    $node->setUser($user);
    $node->setCampaign($campaign);
    $this->line(sprintf('server::onopen > %s: %s', $user->id, $campaign->name));

    $this->triggerFirstStep($node, $bucket->getSource());
});
$server->run();

Client code

$client = new Websocket\Client(
    new Socket\Client($url)
);
$client->getConnection()->setNodeName(UserNode::class);
$client->setHost($host);

$client->run();

If I gave a valid URL to the client, no problem but if I gave a wrong one, the connection is closed by the server and the client know it only the next time he try to read on it.

I've checked in library code and it seems that the getStream method on the socket connection return null (so the ErrorException thrown is just logic here...).

Is it the right way to handle that kind of verification ?

Many messages are lost if there are concurrent clients sending them

Hello,

I've been playing with many concurrent clients calling a server so that it rebroadcasts the sent message to other clients. However, the sad news is that it appears I'm losing almost 20%-30% of those messages when I have 5 or more concurrent connections.

A simple test case is as follow:

server.php

$i = 0;
$j = 0;
$k = 0;

$websocket = new Hoa\Websocket\Server(
    new Hoa\Socket\Server('tcp://127.0.0.1:8889')
);
$websocket->on('open', function (Hoa\Core\Event\Bucket $bucket) use (&$i) {
    echo 'connection ' . ++$i . PHP_EOL;
});
$websocket->on('message', function (Hoa\Core\Event\Bucket $bucket) use (&$j) {
    echo 'message ' .++$j.PHP_EOL;
});
$websocket->on('close', function (Hoa\Core\Event\Bucket $bucket) use (&$k) {
    echo 'connection closed ' . ++$k . PHP_EOL;
});
$websocket->run();

client.php

$client   = new Hoa\Websocket\Client(
    new Hoa\Socket\Client('tcp://127.0.0.1:8889')
);
$client->setHost('test');
$client->connect();

$client->send('HELLO WORLD');

test command

ab -n 500 -c 5 -B 127.0.0.1 http://localhost/client.php

Here's what I see at the end of a run:

connection 500
message 372
connection closed 369

What I'd expect:

connection 500
message 500
connection closed 500

I haven't investigated yet as to what the issue is, but considering that all connection are properly made, something occurs between the time the connection is made and the time a message is supposed to be sent. It is also interesting to note that many connections aren't closed as well, which doesn't sound good.

Tested different concurrency levels:

Concurrency messages retransmitted/connections messages delivered overall
1 500/500 100%
2 464/500 93%
3 433/500 87%
4 398/500 80%
5 362/500 72%
500 250/500 50%

Edit 1: After some more testing and playing around, it seems very critical for the client code to call $client->close();. Doing so increases the rate of message delivered to almost 100% (but not 100%).

Suggested: Implement the __destruct method in Clients classes so that they may close their connection cleanly (if the user didn't call close() himself).

Furthermore, it appears that the connections that do not end up triggering a close event are actually triggering an error event. It has to do with the fact that we try to write to a socket that has been closed.

add support for subprotocols

websocket is the underlying layer for several protocols.
There should be a way for another library to register a sub-protocol with Hoa\WebSocket

the first sub-protocol could be wamp (see #26)

Install question - Newbie

I tried to follow all this composer stuff, but could get it to work. Not even sure this is what I want. Is there any easier way just to install the lib to get it to work. The install seems quite difficult. Any simple install help would be useful. Thanks.

Test failure

I run tests on my server and got this errors

There are 4 failures
Hoa\Math\Test\Unit\Visitor\Arithmetic::case_visitor_exhaustively():
In file /usr/share/nginx/html/vendor/hoa/math/Test/Unit/Visitor/Arithmetic.php on line 98, mageekguy\atoum\asserters\phpFloat() failed: float(1610074.7993529) is not nearly equal to float(1610074.799353) with epsilon 1.0E-14
-Expected
+Actual
@@ -1 +1 @@
-float(1610074.799353)
+float(1610074.7993529)
Hoa\Protocol\Test\Unit\Protocol::case_resolve_unfold_to_non_existing_resources():
In file /usr/share/nginx/html/vendor/hoa/protocol/Test/Unit/Protocol.php on line 144, mageekguy\atoum\asserters\phpArray() failed: array(2) is not equal to array(2)
-Expected
+Actual
@@ -3 +3 @@

  • string(57) "/usr/share/nginx/html/vendor/hoathis"
  • string(58) "/usr/share/nginx/html/vendor/hoathis/"
    Hoa\Ustring\Test\Unit\Ustring::case_check_no_mbstring():
    In file /usr/share/nginx/html/vendor/hoa/ustring/Test/Unit/Ustring.php on line 71, mageekguy\atoum\asserters\exception() failed: null is not an exception
    Hoa\Ustring\Test\Unit\Ustring::case_to_ascii_no_transliterator_no_normalizer_try():
    In file /usr/share/nginx/html/vendor/hoa/ustring/Test/Unit/Ustring.php on line 967, mageekguy\atoum\asserters\phpString() failed: strings are not equal
    -Expected
    +Actual
    @@ -1 +1 @@
    -string(26) "Un ete brulant sur la cote"
    +string(22) "Un t brlant sur la cte"
    There is 1 output
    In Hoa\Math\Test\Unit\Visitor\Arithmetic::case_visitor_exhaustively():
    Failed expression: .

There are 11 exceptions
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_server():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 121:
~~> Hoa\Websocket\Connection::_run(): (42) An exception has been thrown. We have tried to close the connection but another exception has been thrown.
~~> in /usr/share/nginx/html/vendor/hoa/websocket/Connection.php at line 486.
~~>
~~> Contains the following exceptions:
~~>
~~> • Hoa\Socket\Connection\Connection::write(): (5) Pipe is broken, cannot write data.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Connection/Connection.php at line 853.
~~>
~~> • Hoa\Socket\Connection\Connection::write(): (5) Pipe is broken, cannot write data.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Connection/Connection.php at line 853.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_unsolicited_pong_with_payload_of_size_42():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 282:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_fragmented_message():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 296:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_empty_text_frame_with_an_empty_payload():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 320:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_fragmented_text_frame_with_an_empty_payload():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 333:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_text_frame_with_a_valid_UTF_8_payload():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 353:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_text_frame_with_a_full_UTF_8_payload():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 360:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_fragmented_text_frame_with_a_valid_UTF_8_payload():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 386:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_fragmented_text_frame_of_1_bytes_with_a_valid_UTF_8_payload():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 405:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_fragmented_text_frame_of_1_bytes_with_a_full_UTF_8_payload():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 412:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.
Hoa\Websocket\Test\Integration\Protocol\Rfc6455::case_send_a_message_and_close():
~~> An exception has been thrown in file /usr/share/nginx/html/vendor/hoa/websocket/Test/Integration/Protocol/Rfc6455.php on line 462:
~~> Hoa\Socket\Client::_open(): (1) Client returns an error (number 111): Connection refused while trying to join tcp://127.0.0.1:1234.
~~> in /usr/share/nginx/html/vendor/hoa/socket/Client.php at line 191.

Websocket closure: incompatible with tomcat's expectations(RFC6455).

When Websocket client closes, RF6455 recommends that it to wait for closure message from server. But Hoa\Websocket does not wait. As a result of this, tomcat throws an error exception "java.io.IOException: An established connection was aborted by the software in your host machine" while replying to CLOSURE message from client.

Migrating or writing test suites

Hello :-),

Currently, these are 2 test suites: A unit one and an integration one.

The unit test suite is very smalll and does not cover everything. There is no test suite to migrate. We have to write it.

The integration test suite of the one provided by Autobahn.ws. This is great but not easy to deploy and use. Moreover, not all test cases are interesting for us. The goal would be to “compile” the Autobahn test suite to a Hoa\Test suite.

About audio streaming

Best Regards HOA Project.

Some time ago I read, dont remenber where, about use of Hoa Websocket for audio and video streaming?

I have some devices connected to an websocket, running with laravel as backend. I need send audio, from a mic to this devices, any idea about this??

Thanks.

Yoinier.

Connected clients on the server id

Is there a way to get a list/$buckets/bucket_id from all current connected clients?
Trying to do an implementation where once client #1 sends a message the server sends another to clients #2 and #3, so is not a broadcast and not to origin.
Can I accomplish that with HoaWebsocket?

Problem when using broadcast() in the 'close' event

Hi,

When i try to Use the broadcast() function on a close event in the server, if a client disconnect himself, the first remaining connected client gets disconnected and he's the only one to receive the broadcast message . Others don't receive anything.

$websocket->on('close', function ( Hoa\Core\Event\Bucket $bucket )  {
    echo "connection closed\n";
    $bucket->getSource()->broadcast("A client disconnect himself from server"));
    return;
});

To understand, here's an example :

  • Client 1 connect himself to server
  • Client 2 connect himself to server
  • Client 3 connect himself to server
  • Client 1 disconnect himself from server
  • Client 2 receive message "A client disconnect from server" , and immediatly get disconnected from server
  • Client 3 doesn't get any message and is still connected

Supports WSS (encrypted connection to run with HTTPS server)

What is the current state of the support of encrypted websocket connection?

What is the typical solution to run a websocket server wich is able to run an encrypted connection (which will be able to support a new WebSocket('wss://my.host.com') in javascript within a HTTPS connection) ?

Actually, the only thing I do in PHP is run() a Hoa WebsocketServer on tcp://my.host.com:8889.

"Get rsv1: 0, rsv2: 1, rsv3: 0, they all must be equal to 0" with large arrays sent

I'm trying to send big arrays filled with floats to Hoa\WebSocket\Server.
I wrote a client for testing purposes : https://squadclient-html5-etiennewan-1.c9.io/test.html

There is no problem with little arrays (with a length of 1, 10 or an hundred items)
When sending bigger arrays, the WebSocket connection closes unexpectedly without errors server-side and with this reason sent to the client :
"Get rsv1: 0, rsv2: 1, rsv3: 0, they all must be equal to 0" with one or more rsv equal to 1.

Here is the PHP server code (as simple as codes in examples):

<?php
require_once 'vendor/autoload.php';

$server = new Hoa\Websocket\Server(
    new Hoa\Socket\Server('tcp://'.$argv[1].':'.$argv[2])
);

$server->on('message', function (Hoa\Core\Event\Bucket $bucket) {
    $data = $bucket->getData();

    $received = count(explode(",", $data['message']))-1;

    echo $received, PHP_EOL;

    $source = $bucket->getSource();

    $source->send($received);

    return;
});

$server ->on('open', function (){
    echo 'new client connection', PHP_EOL;

});

echo "Server is starting", PHP_EOL;
$server->run();

Note : the client and server are hosted on Cloud9 and will be running for debugging purposes.
A live-debugging sessions is possible on the server workspace. Please tell me if you want to have access to it.

Addendum: The size of the array needed to reproduce the error can vary, but 800 seems to be the minimum sometimes.
Here, I only work with normal arrays, but it seemed to happened more often with typed arrays (I was trying to send Float32Array (1024 items) when the error occured for the first time)

Data read from socket doesn't match expected length

Hello!

I've been using Hoa\Websocket to interface with Chromium's debugging protocol in order to print PDFs. Chromium returns the PDF data in the response as a base64-encoded string, which can grow quite long (several MiB). I found that the response that i was getting back was the wrong size, usually severely truncated (tens of KiB).

To rule out an issue with Chromium, i created a server.php that simply sends 5 MB of base64-encoded garbage back to the client on connect, and i made a client.php to just print the length of the bucket message it receives. This is my result:

~ % php server.php &
[1] 5224
~ % php client.php
server: Sending 5000000 bytes
client: Received 22390 bytes
~ % php client.php
server: Sending 5000000 bytes
client: Received 22390 bytes
~ % php client.php
server: Sending 5000000 bytes
client: Received 22390 bytes
~ % php client.php
server: Sending 5000000 bytes
client: Received 1749065 bytes
~ % php client.php
server: Sending 5000000 bytes
client: Received 789220 bytes
~ % php client.php
server: Sending 5000000 bytes
client: Received 789220 bytes
~ % php client.php
server: Sending 5000000 bytes
client: Received 4411468 bytes

Ultimately the issue seems to lie in the call to stream_socket_recvfrom() within Hoa\Socket\Connection\Connection::read(). I've confirmed that it receives the correct $length, but the result never matches it.

I'm creating the issue here rather than under Hoa\Socket because i'm assuming this has something to do with blocking or buffering settings rather than any flaw in the read() method itself... but i'm not sure. Am i doing something wrong?

Code to replicate:

server.php

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Hoa\Event;
use Hoa\Socket;
use Hoa\Websocket;

$bytes  = $argv[1] ?? 5000000;
$server = new Websocket\Server(new Socket\Server('ws://127.0.0.1:8889'));

$server->on('open', function (Event\Bucket $bucket) use ($bytes) {
    $data = substr(base64_encode(random_bytes($bytes)), 0, $bytes);
    printf("server: Sending %d bytes\n", strlen($data));
    $bucket->getSource()->send($data);
});

$server->run();

client.php

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Hoa\Event;
use Hoa\Socket;
use Hoa\Websocket;

$client = new Websocket\Client(new Socket\Client('ws://127.0.0.1:8889'));

$client->on('message', function (Event\Bucket $bucket) {
    printf("client: Received %d bytes\n", strlen($bucket->getData()['message']));
});

$client->setHost('127.0.0.1');
$client->connect();
$client->receive();

Long cookie leads to handshake fail

Hello guys.

When create websocket request with long long cookie, i will get a handshake fail error as the following.
WebSocket connection to 'ws://xxx.com:8088/' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET

I found out the reason: read 2048 bytes only, cannot get the header "sec-websocket-key".

protected function doHandshake()
    {
        $connection = $this->getConnection();
        $buffer     = $connection->read(2048);
        $request    = $this->getRequest();
        //...
}

Any ideas ?

Set header buffer size

Refer to issue #72

Today the library will take arbitrary first 2048 bytes of stream and send them to Http library.
Until we design better interface on Hoa\Http we can still make the buffer size configurable.

Did we implement this parameter with Hoa\Zformat and array as argument of constructor ?

Problem trying do Custom Node

In my project I try do this(only for test).

namespace YnievesDotNet\FourStream\Models;

use Hoa\Websocket\Node as Node;
use Sentinel;

class FourStreamClientNode extends Node {

    protected $_user = null;

    public function setUser ($user)
    {
        $old         = $this->_user;
        $this->_user = $user;

        return $old;
    }

    public function getUser()
    {
        $this->_user = Sentinel::check();
        return $this->_user;
    }
}

Now, how to I can connect this class with my class FourStreamServer. I try thats:

namespace YnievesDotNet\FourStream\FourStream;

use Hoa\Websocket\Server as WebSocket;
use Hoa\Socket\Server as Socket;
use Hoa\Core\Event\Bucket as Bucket;
use YnievesDotNet\FourStream\Models\FourStreamClientNode as ClientNode;
...
class FourStreamServer {
    ...
    public function start($tcpid) {
        $this->server = new Websocket(
            new Socket($tcpid)
        );
        $this->server->getConnection()->setNodeName('ClientNode');
        $this->server->on('open', function (Bucket $bucket) {
            echo 'connection opened', "\n";
            $node = $bucket->getSource()->getConnection()->getCurrentNode();
            echo var_dump($node->getUser());
            return;
        });
        ...
    }
    ...
}

The server start OK, but when the client intent connect, server shutdown with this message:

[ReflectionException]
  Class ClientNode does not exist

How I fix this..

Thanks

YnievesDotNet

Vue and websocket

I try to use the demo code, on one app and I use vue in this app, but the code is broken and I recive this error

Uncaught TypeError: Cannot read property 'addEventListener' of null

Thanks.

Yoinier.

Need a socket factory

Will fix #41.

  1. People are likely to use ws:// or wss:// directly. They don't understand that we must use a tcp:// URL. I can't blame them. HTTP Upgrade is just… confusing.
  2. Moreover, there is a need for automatic encryption, because with wss://, we need to instanciate a Hoa\Socket\Client object with tcp://…:443 and then call enableEncryption. Most of the time with ENCRYPTION_TLS (maybe with SSLv2 or SSLv3 sometimes, how to know?).
  3. In addition, we have to deal with URL endpoint (in the Websocket client).

So, yup, this is more like a factory. The same way we have Hoa\Socket\Socket to parse tcp:// and udp:// URL, maybe we can extend it to support ws:// and wss://. It could be great to have an enhanced Hoa\Socket\Socket object where we could be able to register new schemes (like ws:// or wss://) in order to automatically transform a string into a real Hoa\Socket\Socket valid object (with a real tcp:// or udp:// URL). So it requires a little bit of work on Hoa\Socket.

Here is the work I propose:

  1. On Hoa\Socket\Socket:
    1. Introduce a “socket wrapper” interface that declares a factory to transform a URL into a valid Hoa\Socket\Socket object (or a child of),
    2. Introduce the registerWrapper and unregisterWrapper static methods that take a “socket wrapper” interface as an argument,
    3. Declare tcp:// and udp:// as socket wrappers.
  2. On Hoa\Socket\Connection:
    1. In the setSocket method, we receive a URL; we then have to find and apply the appropriated stream wrapper to get a valid Hoa\Socket\Socket object (or a child of).
  3. On Hoa\Websocket\Connection:
    1. We must create Hoa\Websocket\Socket (the “socket wrapper”) that extends Hoa\Socket\Socket,
    2. We must declare the “socket wrapper” ws:// and wss://.

When executing:

new Hoa\Websocket\Client(
    new Hoa\Socket\Client('ws://…')
)

What is going to happen?
The ws:// and wss:// URLs are going to be transform into a Hoa\Websocket\Socket object because Hoa\Socket\Client is extending Hoa\Socket\Connection\Connection. This latter will call the setSocket method: It will look for a valid “socket wrapper”, execute it and a valid Hoa\Websocket\Socket will be created. It will be used by Hoa\Websocket\Client very smootly thanks to inheritance, but we will have more information on it, such as: Should it be encrypted? for instance (in the Hoa\Websocket\Client, we would just need to call $connection->getSocket()->isSecure() for instance). Finally, we will have to act accordingly.

Well, that's easier that what I thought!

Finally: We will have to update the documentation.

Injecting data at the WebSocket/Node object...

Injecting data at the WebSocket/Node object

Hello, I try including this library at my project in Laravel. In this moment I can manage the running of server from Laravel using Artisan command, but I need vinculate one or some nodes for each client, when the client connect at the system.

Other things what I need is configure the listeners on one abstract class, but inside the server connection, while it is running.
For example, I need create one class calling HoaWebSocket, and I can configure for example, this:

class HoaWebSocket extend [hoa way point class] {
    ...
    public function onOpen($node, $user) {
        //Assing one node at one user.
    }

    public function send($message, $user) {
        //Send one message at one node.
    }
    ...
}

This is a fictitious idea, is only for comment the flow with I need.

In this moment, I can send the system message at our user using this method

use Hoa\Websocket\Client as WsClient;
use Hoa\Socket\Client as SClient;
...
    public function getLogin()
    {
        $client = new WsClient(
            new SClient('tcp://127.0.0.1:8080')
        );
        $client->connect();
        $client->send('Login rendered');
        $client->close();

        return view('auth.login');
    }
...

And the idea final is it:

use HoaWebSocket;
...
    public function getLogin()
    {
        HoaWebSocket::send('Login rendered', User::findById(1));
        return view('auth.login');
    }
...

But, doing this action without Hoa\Websocket\Client and/or Hoa\Socket\Client.

Thanks

YnievesDotNet

Sending messages from server to clients

Hi, I have some problems, unfortunately I can't find this in documentation, so hope you will help me.

I have own API, that receive message and this message I need to show.

Incoming message from API, I saved in DB on one day.

Message can be for everyone users, for some group or just for one.

I send user data from javascript to the socket once, when a page is rendered.

socket.send(JSON.stringify({'user_id': 'cf3wfdf3', 'user_nickname': 'nickname'}));

On server side I need to add my business logic.
I trying like this:

    $web_socket->on('message', function (Bucket $bucket) {
        $data = $bucket->getData();

        while (true) {
            if ($this->personalMessage()) {
                $bucket->getSource()->send('Personal message');

            } else if ($this->groupMessage()) {
                $bucket->getSource()->broadcastIf(function() {}, 'For all');

            } else if ($this->broadcastMessage()) {
                $bucket->getSource()->broadcast('For all');
            }

            sleep(3);
        }
        return;
    });

But while (true) {} will blocking SocketServer, and it will be works only for first client.

And trying like this:

    $web_socket = new WebsocketServer(
        new SocketServer('ws://127.0.0.1:8889')
    );
    $web_socket->run();

    while (true) {
        sleep(1);
        $web_socket->broadcast('For all');
    }

But it not works too =(

Questions:
1) How I can send message from server to client, not only when client send message?
2) How I can identify user as node, to filter it in future and how to filter it by user_id?
2) Where I need to adding while(true) {} ?

Thanks for any advice!

Pipe is broken on Windows

After some investigations with @camael24 about an issue encountered by Harssha on IRC, we have detected a broken pipe on Windows. In order to fix this issue, we have to call the setStreamBlocking(true) method on the socket client. Need to understand why before fixing this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.