Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ratchet push messaging without implementing WampInterface #433

Closed
harveyslash opened this issue May 30, 2016 · 13 comments
Closed

Ratchet push messaging without implementing WampInterface #433

harveyslash opened this issue May 30, 2016 · 13 comments

Comments

@harveyslash
Copy link

I want to implement MessageComponent interface and push notification.(The tutorial in ratchet has WampInterface for push). I do not want to use WampInterface as it is in v1 and there are no libraries for that version for iOS.

I am using this in Laravel, and this was my first try:

$loop   = \React\EventLoop\Factory::create();

        $class = $this->option('class');

        $ratchetServer = new $class($this);

        $this->info(sprintf('Starting ZMQ server on: %s:%s', config('ratchet.zmq.host'), config('ratchet.zmq.port')));

        $context = new \React\ZMQ\Context($loop);
        $pull = $context->getSocket(\ZMQ::SOCKET_PULL);
        $pull->bind(sprintf('tcp://%s:%d', config('ratchet.zmq.host'), config('ratchet.zmq.port')));

         $pull->on('message', function($message) use ($ratchetServer) {
             $ratchetServer->onEntry($message);
         });


        $webSock = new \React\Socket\Server($loop);
        $webSock->listen($this->port, $this->host);
        $webServer = new \Ratchet\Server\IoServer(
            new \Ratchet\Http\HttpServer(
                new \Ratchet\WebSocket\WsServer(
                    new PusherServer()
                )
            ),
            $webSock
        );

        return $loop;

I have a pusher server where I will be handling my own 'topics' and clients.

An example that I tried(that doesn't work) to push data from server to some topic:


$context = new ZMQContext();
        $socket = $context->getSocket(ZMQ::SOCKET_PUSH, null);
        $socket->connect("tcp://localhost:5555");
        $socket->send("this is the message");
        $socket->disconnect("tcp://localhost:5555");

How do I make push notification work (my server should be able to send message to client) without implementing WampInterface (and just MessageComponentInterface).

I would also like to ask how to send authentication details on connection so that my server can close the connection if its invalid(and not have an idle connection open)

@bl4zk0
Copy link

bl4zk0 commented May 30, 2016

You can use websocket client (see: Pawl ) to push messages to server. As for authentication you could have login system with symfony sessions and check session variable on server. For pawl connection check some headers, origin for example.
For idle connections you can write javascript for client side with setTimeout function which sends disconnect command to server if client is idle and resetting timeout if client is not idle.

// your pawl function to push messages to server
function pawlConnect($msg) {
        $loop = \React\EventLoop\Factory::create();
        $connector = new \Ratchet\Client\Connector($loop);

        $connector('ws://yourAddress', [], ['Origin' => 'origin'])
        ->then(function(\Ratchet\Client\WebSocket $conn) use ($msg) {

            $conn->on('close', function($code = null, $reason = null) {
                echo "Connection closed ({$code} - {$reason})\n";
            });

            $conn->send($msg);
            $conn->close();

        }, function(\Exception $e) use ($loop) {
            echo "Could not connect: {$e->getMessage()}\n";
            $loop->stop();
        });

        $loop->run();
    }
// and your $pusher app would look something like this

class Pusher implements MessageComponentInterface 
{   //array or SplObjectStorage
    $topicName = array();

    public function onMessage(ConnectionInterface $from, $msg) 
    {    
         $msg = json_decode($msg, true);
         if (method_exists($this, $msg["do"])) {
             $this->$msg["do"]($from, $msg);
        } else {
            $from->close();
       }
    }

    public function notifySubscribers($conn, $msg)
    {
        foreach ($this->$msg["topic"] as $client) {
            // code...
        }
    }

    public function subscribe($conn, $msg)
    {
        $this->$msg["topic"][] = $conn;
    }
}

//then you'd push message to server like this

$msg = array("do" => "notifySubscribers", "topic" => "topicName", "content" => "content");
pawlConnect(json_encode($msg));

@harveyslash
Copy link
Author

@krekk4 thanks!.
I am getting Could not connect: DNS Request did not return valid answer.
this is my pawl connect:

 $loop = \React\EventLoop\Factory::create();
        $connector = new \Ratchet\Client\Connector($loop);

        $connector('ws://localhost:5555', [], ['Origin' => 'origin'])
            ->then(function(\Ratchet\Client\WebSocket $conn) use ($msg) {

                $conn->on('close', function($code = null, $reason = null) {
                    echo "Connection closed ({$code} - {$reason})\n";
                });

                $conn->send($msg);
                $conn->close();

            }, function(\Exception $e) use ($loop) {
                echo "Could not connect: {$e->getMessage()}\n";
                $loop->stop();
            });

        $loop->run();

And this is my server message:
Starting WampServer server on: 0.0.0.0:8080
Starting ZMQ server on: 127.0.0.1:5555

@cboden
Copy link
Member

cboden commented May 30, 2016

Change localhost to 127.0.0.1. React DNS doesn't use /etc/hosts yet.

@harveyslash
Copy link
Author

harveyslash commented May 30, 2016

@cboden , I think i can get this example to work. I have a few questions

Is there something very inefficient using pawl than the one posted by you in the website under push integration(which uses zeromq) ?

how do I verify that the command sent from my server with some message to certain topics is indeed from my server?

@cboden
Copy link
Member

cboden commented May 30, 2016

With the release of v0.4 I plan on updating the push tutorial to use Pawl instead of ZeroMQ just so developers getting into async land don't have to install a foreign extension, so you're good. When I wrote that tutorial Pawl didn't exist yet and the RFC protocol handler wasn't nicely decoupled yet so ZMQ was easier to write.

If you're looking for security to ensure the message came from your script, off the top of my head you could do one of these two things:

  1. On the server side that listens to messages from Pawl bind to 127.0.0.1, not 0.0.0.0. This ensures at a network level that only sockets can connect that come from the same machine.

  2. Pass some kind of secret token/password in the HTTP header that the server checks to verify the request came from your client script.

@harveyslash
Copy link
Author

@cboden , thanks!.

I am just curious to know why my code is not working though. Since I have already set up zmq (and I don't know how to do number 1 of your previous answer). Is it possible to use zmq exactly the way you have written in your website along with MessageComponentInterface ?
Or, if possible, could you please tell me (in code, please), how number 1 would be set up? I do not want to send a token and verify.

Thank you very much in advance.

@bl4zk0
Copy link

bl4zk0 commented May 30, 2016

just check $conn->remoteAddress on server should be 127.0.0.1 for pawl connection

@harveyslash
Copy link
Author

@krekk4 , could you please tell what is that line is doing ?
I mean, what prevents some malicious user from connecting to my server and trying to send push messages to others?

@bl4zk0
Copy link

bl4zk0 commented May 30, 2016

$conn->remoteAddress
gets the IP address of connection, when you push a message with pawl from your local machine ip address of pawl connection is 127.0.0.1 verify this ip somewhere in your code (for example in the function which sends message to subscribers) to ensure that push message comes from your local machine.

@harveyslash
Copy link
Author

@krekk4 , @cboden .
thank you very much for your help!

@harveyslash
Copy link
Author

harveyslash commented May 30, 2016

@krekk4 , I used your code.
Whenever I try to call a php script that runs the pawl code, that page appears to be stuck(not loading). the onMessage is called though.

The server code that I'm using now is :

$server = IoServer::factory(
            new PusherServer(),
            8080
        );

        $server->run();

What could be the issue here ?

@bl4zk0
Copy link

bl4zk0 commented May 30, 2016

What exactly are u trying to do?
Pawl function in the example doesn't get any message back it just sends

@cboden cboden closed this as completed Jan 1, 2017
@binodpal
Copy link

dont know why i follow ratchet...m stucked

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants