voryx / thruway Goto Github PK
View Code? Open in Web Editor NEWPHP Client and Router Library for Autobahn and WAMP (Web Application Messaging Protocol) for Real-Time Application Messaging
License: MIT License
PHP Client and Router Library for Autobahn and WAMP (Web Application Messaging Protocol) for Real-Time Application Messaging
License: MIT License
I think this relates to #139 but it seems to occur with Publish instructions. I'm using the PawlTransportProvider
if that helps.
Is there a way to access headers/cookies from a Thruway\Peer\Client instance?
Looking to grab session cookies.
Uncaught exception 'React\Socket\ConnectionException' with message 'Could not bind to tcp://0.0.0.0:9090: Address already in use' in thruway/vendor/react/socket/src/Server.php:29
I am working on a sample for Internal Client + Authentication model like the one below.
Now I need to retrieve a list of connected sessions and intercept the close event of a session from Internal Client.
I want to ask if there's any method to archive that task? I was thinking about saving that list in redis, but it means I would have to re-write Thruway\Peer\Router
classes, because the needed variables are now private, we don't have access to them to extends.
<?php
/**
* server.php
*/
require "../bootstrap.php";
require 'InternalClient.php';
require 'SimpleAuthProviderClient.php';
use Thruway\Peer\Router;
use Thruway\Transport\RatchetTransportProvider;
use React\EventLoop\Factory;
use Thruway\Manager\ManagerClient;
use Thruway\Transport\InternalClientTransportProvider;
$manager = new ManagerClient();
$loop = Factory::create();
$router = new Router($loop, $manager);
$router->addTransportProvider(new InternalClientTransportProvider($manager));
$internalTransportProvider = new InternalClientTransportProvider(new \InternalClient());
$router->addTransportProvider($internalTransportProvider);
$authMgr = new \Thruway\Authentication\AuthenticationManager();
$router->setAuthenticationManager($authMgr);
$router->addTransportProvider(new InternalClientTransportProvider($authMgr));
//Provide authentication for the realm: 'somerealm'
$authProvClient = new SimpleAuthProviderClient(["somerealm"]);
$router->addTransportProvider(new InternalClientTransportProvider($authProvClient));
$transportProvider = new RatchetTransportProvider("127.0.0.1", 9090);
$router->addTransportProvider($transportProvider);
$router->start();
<?php
/**
* SimpleAuthProviderClient.php
*/
require "../bootstrap.php";
/**
* Class SimpleAuthProviderClient
*/
class SimpleAuthProviderClient extends \Thruway\Authentication\AbstractAuthProviderClient
{
/**
* @return string
*/
public function getMethodName()
{
return 'simplysimple';
}
/**
* @param mixed $signature
* @param null $extra
* @return array
*/
public function processAuthenticate($signature, $extra = null)
{
if ($signature == "letMeIn") {
return ["SUCCESS"];
} else {
return ["FAILURE"];
}
}
}
<?php
/**
* InternalClient.php
*/
require "../bootstrap.php";
/**
* Class InternalClient
*/
class InternalClient extends Thruway\Peer\Client
{
function __construct()
{
parent::__construct("somerealm");
}
/**
* @param \Thruway\AbstractSession $session
* @param \Thruway\Transport\TransportInterface $transport
*/
public function onSessionStart($session, $transport)
{
echo "--------------- Hello from InternalClient ------------";
$this->getCallee()->register($this->session, 'com.example.getphpversion', [$this, 'getPhpVersion']);
}
function start()
{
}
/**
* @return array
*/
function getPhpVersion()
{
return [phpversion()];
}
}
Hi there,
We have recently started using Crossbar, and Crossbar installs Thruway as the default when using PHP.
However, in the past week or so we think there has been a change. The change is resulting in a stack trace error. You can see the CLI output here - crossbario/crossbar#139
@oberstet looked into the issue and reproduced the error. He recommended we open an issue here. Here is what he said:
This seems to be a Thruway bug. Thruway sends REGISTER messages of the format: [64,83887244,[],"com.example.add2"]. This is wrong, the 3rd item should be a dict, not a list.
Is this something you can help with?
use something like this:
$client->getManager()->setQuiet(true);
Will keep printing messages such as:
We have been welcomed...
2014-11-30T21:01:04.7211170 debug [Thruway\Transport\PawlTransportProvider 82490] Received: [65,1631857669006655,1042148048]
2014-11-30T21:01:04.7213660 info [Thruway\Role\Callee 82490] Setting registration_id
2014-11-30T21:01:04.7217170 debug [Vinelab\Minion\Client 82490] Client onMessage: [Thruway\Message\RegisteredMessage]
Right now, the callee can only return the args array. I would like to create an object type that can be returned that would allow adding the argsKw also.
Hi!
I want to save into a database all messages. I dont really know the right or recommended way to handly this.
At this moment I created a custom router (extending the default router) that saves the messages in the "onMessage" method. In this method I check if the message type is Thruway\Message\PublishMessage and get the content the realm name.
Is that a nice way or there are a better one?
Thank you
There is not a clear delineation in transports and transport providers as to responsibilities (who sends the message to the peer - the transport or the provider?). Also, there are incompatibilities that make transports specific to the Router or the Client (take a look at onClose as an example).
When unregistering - the router should wait until all calls finish before sending the unregistered message.
Hello,
I started using Thruway in my project and came into an obstacle I can't overcome. I need to interface my internal client with asterisk through marcelog/pami, and have no idea how to start client method periodicaly.
I tried to use addPeriodicTimer method in onSessionStart in my client like:
public function onSessionStart($session, $transport)
{
$this->pamiClient = new ClientImpl($this->pamiSettings);
$this->pamiClient->registerEventListener([$this, 'processAsteriskEvent']);
$this->pamiClient->open();
$pamiClient = $this->pamiClient;
$this->getLoop()->addPeriodicTimer(1, [$pamiClient, 'process']);
}
public function processAsteriskEvent(EventMessage $event)
{
$this->getPublisher()->publish($this->session, "com.pami.publish", [[
'from' => 'asterisk',
'message' => $event->getName()
]], [], []);
}
It is sort of working - with
app/console thruway:client:start -vvv
I can see that all events are published:
[2014-10-08 09:50:42] app.DEBUG: Broker onMessage for {"type":"internalClient","transportAddress":"internal"}: [16,2632594463974922,{},"com.pami.publish",[{"from":"asterisk","message":"FullyBooted"}]] [] []
[2014-10-08 09:50:42] app.DEBUG: processing publish message [] []
[2014-10-08 09:50:44] app.DEBUG: Broker onMessage for {"type":"internalClient","transportAddress":"internal"}: [16,2564349979401664,{},"com.pami.publish",[{"from":"asterisk","message":"PeerStatus"}]] [] []
[2014-10-08 09:50:44] app.DEBUG: processing publish message [] []
[2014-10-08 09:50:45] app.DEBUG: Broker onMessage for {"type":"internalClient","transportAddress":"internal"}: [16,5167210401435635,{},"com.pami.publish",[{"from":"asterisk","message":"PeerStatus"}]] [] []
But are unable to connect with router with my web application (angular-wamp). When I comment out addPeriodicTimer line in my client, two web clients are connecting to router and chatting happily. Is this a way to connect some event to session's event loop or create non-blocking event loop in client? I tried to create other loop in client:
$this->pamiLoop = \React\EventLoop\Factory::create()
$this->pamiLoop->addPeriodicTimer(....);
$this->pamiLoop->run();
but it behaves in the same way.
Hi,
shouldn't Role/Subscriber.php, line 85 hand over kwArgs as a second argument?
best
Hello! I have some trouble while trying to make an internal client talk with one on the browser via autobahn js.
That's my setup:
// ws.php
<?php
require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/wsclient.php';
use Thruway\Peer\Router;
use Thruway\Transport\RatchetTransportProvider;
use Thruway\Transport\InternalClientTransportProvider;
$loop = \React\EventLoop\Factory::create();
$router = new Router($loop);
$transportProvider = new RatchetTransportProvider("127.0.0.1", 9090);
$router->addTransportProvider($transportProvider);
$internalClientTransportProvider = new InternalClientTransportProvider(new ChatClient($loop));
$router->addTransportProvider($internalClientTransportProvider);
$router->start();
And the internal client:
//wsclient.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Thruway\Transport\TransportInterface;
use Thruway\Message\Message;
class ChatClient extends Thruway\Peer\Client {
public function __construct($loop)
{
return parent::__construct("realm1", $loop);
}
public function onSessionStart($session, $transport)
{
echo "--------------- Hello from InternalClient ------------\n";
$this->getCallee()->register($this->session, 'com.myapp.version', [$this, 'getPhpVersion']);
}
public function start()
{
}
public function getPhpVersion()
{
return [phpversion()];
}
}
Finally my autobahn client:
var connection = new autobahn.Connection({url: 'ws://127.0.0.1:9090/', realm: 'realm1'});
connection.onopen = function (session) {
session.call('com.myapp.version').then(
function (res) {
console.log(res);
}
);
};
connection.open();
One time out of ten it, someways, works and I see the version logged on the console, the other nine times I got this error:
Uncaught InvalidAccessError: Failed to execute 'close' on 'WebSocket': The code must be either 1000, or between 3000 and 4999. 1002 is neither.
For what I know code 1002 stand for internal error in websocket but I see no error logged anywhere and the websocket just keep going.
The strange thing is that if I create a php client with Thruway, like this:
//testClient.php
<?php
use Thruway\ClientSession;
use Thruway\Connection;
require __DIR__ . '/vendor/autoload.php';
$connection = new Connection(
[
"realm" => 'realm1',
"onClose" => $onClose,
"url" => 'ws://127.0.0.1:9090/',
]
);
$connection->on('open',function (ClientSession $session) {
$session->call('com.myapp.version')->then(
function ($res) {
echo "Result: {$res}";
}
);
});
$connection->open();
it just works, all the times!
I tryed to inject the main $loop into my internal client as suggested in #37 but with no luck...
The fact that it sometimes works made my think about some race conditions that my happen, but even adding a timeout before calling the function on my javascript code didn't work...
Am I missing something? Any help or suggestion is appreciated.
I would like to publish to a topic in the php code that is run within an http request, and it would be great if I can just connect, publish and disconnect in a synchronous way. How would you do that?
It seems, recent Thruway client sends messages like [64,83887244,[],"com.example.add2"]
, which has list
instead of dict
for options.
See Crossbar.io user reporting: crossbario/crossbar#139
Sidenote: Do you think it would make sense to adjust the Thruway app template in Crossbar.io for the following?
If you think this would make sense: could you probably send a PHP dummy the changes required for 1+2? ;)
When two internal client subscribes to the same event, will be caused by two different functions. But if the first function is to publish the second function does not call.
Are there any estimations of when this could be near production-ready ? I'm in the process of migrating a 7000 concurrent users project from NodeJS to PHP and WAMP v2, though the server component is the most of our interest so I wanter to ask whether efforts are being put there as well ? I'll be happy to jump on the collaboration board but need guidance regarding the plan.
Hello!
Do you plan to implement possibility to use custom serializer in RatchetTransportProvider.
I need to switch off JsonSerializer.
Hello to everyone,
I'm playing with crossbar.io examples, and I got stuck when executing php hello example. The main script crashes when calling $connection->doEvents(1). I have checked crossbar.io installation and config.json, and they both are ok, and also tested NodeJs and Python examples succesfully ( windows 8 machine).
Has anyone seen this problem before?
Php main script
while (true) {
// PUBLISH an event
$session->publish('com.example.oncounter', array($counter));
echo "published to 'oncounter' with counter {$counter}\n";
$counter++;
// CALL a remote procedure
$session->call('com.example.mul2', array($counter, 3))->then(
function ($res) {
echo "mul2() called with result: {$res}\n";
},
function ($error) {
if ($error !== 'wamp.error.no_such_procedure') {
echo "call of mul2() failed: {$error}\n";
}
}
);
// Tell the connection to process the events every second
$connection->doEvents(1);
}
Crossbar.io script execution
2014-10-06 22:04:58+0200 [Router 3644] Site starting on 8080 2014-10-06 22:04:58+0200 [Guest 7916] subscribed to topic 'onhello'procedure add2() registered 2014-10-06 22:04:58+0200 [Guest 7916] published to 'oncounter' with counter 0 2014-10-06 22:04:58+0200 [Guest 7916] close 2014-10-06 22:04:59+0200 [Guest 7916] Fatal error: Call to a member function publish() on a non-object in C:..\hello\vendor\voryx\thruway\src\Thruway\ClientSession.php on line 57 2014-10-06 22:04:59+0200 [Guest 7916] PHP Fatal error: Call to a member function publish() on a non-object in C:..\hello\vendor\voryx\thruway\src\Thruway\ClientSession.php on line 57
https://github.com/voryx/Thruway/blob/master/src/Thruway/Realm.php#L116
Should be array("broker" => $this->getBroker()->getFeatures()...
Hi in autobahn we can publish message with option "exclude_me". This option exclude the publisher from the receivers for publication. Why Thruway dont handle message when exclude_me
is false ?
See #37
Thruway should return an Error message if a non fatal exception is throw.
Thruway/Transport/RatchetTransport.php on line 46
"Workaround" (??):
public function getTransportDetails()
{
$request = null;
if (property_exists($this->conn, 'webSocket')) {
if (property_exists($this->conn->webSocket, 'request')) {
$request = $this->conn->webSocket->request;
}
}
return array(
"type" => "ratchet",
"request" => $request
);
}
Please, explain the functions of an AuthenticationProvider.
How it works with Session / ClientSession ?
I work on an example implementation bundle in Symfony 2.5 (https://github.com/mschnide/wamp2-bundle)
hello.
I have a small problem. The client sends request_id (12345678901235, for example) as a loooooong integer, the server converts it to float. It then sends back a "1.2345678901235E + 15". As a result, request_id sometimes varies.
Perhaps we should make it so?
https://github.com/voryx/Thruway/blob/master/src/Thruway/Serializer/JsonSerializer.php#L37
=>
json_decode($serializedData, true, 512, JSON_BIGINT_AS_STRING)
I've been watching this project for WAMPv2 work and I see a lot of comments to this effect but I'm not sure what ot make of it. Does Thruway already have essential WAMPv2 support? If so it would be very helpful if any words could be given as to the current state. I think that Thruway could get more traction if just a small effort was put into communication. As it currently stands it seems to me that mostly only the people who are developing it have any idea what it currently can do.
I try feature Subscriber Black- and Whitelisting with Thruway and it was not implements. Can you help me support this feature early, because it is important and stable.
Thank you.
The handling of dictionary types in Thruway is not consistent throughout. (see #48 - also has been mentioned in other issues)
Currently, the JSON serializer uses json_decode($serializedData, true)
to decode messages. The true
option forces all objects to be decoded into associative arrays.
This works fine at the first level: [4,"some_auth",{}]
changes the third item to be an empty array, and immediately before encoding, we cast it back to an object to force it to encode correctly.
However, empty objects inside other objects or array's are not able to handle being decoded as an array: [4,"some_auth",{"object_option":{}}]
will change to [4,"some_auth",{"object_option":[]}]
after being decoded and then re-encoded.
This causes compatibility problems. To address this, the JSON serializer needs to drop the true
option. This will cause all objects, including empty objects, to be decoded as a stdClass
, which will require using the object operator ($helloMessage->getDetails()->roles
) to access options, details, argumentsKw and any other classes within arguments, options, argumentsKw and details.
The setters on Message objects will still accept associative arrays when setting, but will be cast into objects.
This could potentially break existing code.
My current task is to simplify (hide) JS-client interface communication with internal clients to the router. My idea was for implementation of a proxy based on internal clients. Or create your own Realm.
It is interesting to know your opinion, the best way?
Add support for pattern based subscriptions.
In a callee with an RPC that returns a promise. If Deferred::reject is called, the callee should send invocation error - which should cause the dealer to send a call error to the caller, which should reject the promise returned by Caller::call.
Ok, our users can now get authenticated into our thruway powered WAMP v2 server but... How do we control authorization? I don't want all users to be able to publish or subscribe to any topic, I would like to limit this depending on the role of the user. Is it possible? Are there any onSubcribe and onPublish events? If so, how can I access the logged in user data?
Hi!
Could you give some more info how to operate with wamp protocol on server side (I mean subscribe, unsubscribe and other methods). What I need to do to find out with it?
php vendor/voryx/thruway/Examples/SimpleWsServer.php
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.