Skip to content
This repository has been archived by the owner on Aug 25, 2022. It is now read-only.

initialize() method start a processes without ends #190

Closed
alissonpelizaro opened this issue May 10, 2019 · 23 comments
Closed

initialize() method start a processes without ends #190

alissonpelizaro opened this issue May 10, 2019 · 23 comments
Labels

Comments

@alissonpelizaro
Copy link

alissonpelizaro commented May 10, 2019

Hello!

I can connect on my Socket Server with this library, but the method initialize() never ends on browser... It keep a proccess running and dont call the next methods ( emit() and close() ).

How can I solve that?

$client = new Client(new Version2X('https://myurl.com:2021', [
  'context' => [
    'ssl' => [
      'verify_peer' => false,
      "verify_peer_name"=>false,
      'allow_self_signed'=> false
    ]
  ]
]));
      
$client->initialize();
$client->emit('alert', 'Hello world!');
$client->close();

Thanks a lot!

@peter279k
Copy link
Contributor

peter279k commented May 10, 2019

Fix typo: the title should change into initialize() method start a processes without ends.

@alissonpelizaro alissonpelizaro changed the title inicialize() method start a proccess without ends inicialize() method starts a proccess without ends May 10, 2019
@alissonpelizaro alissonpelizaro changed the title inicialize() method starts a proccess without ends initialize() method start a processes without ends May 10, 2019
@peter279k
Copy link
Contributor

@alissonpelizaro, thank you for your reply.

Do you run the example codes on elephant.io/example/socket.io/2.x/emitter-with-private-socket-id?

It's worked for me that it can initialize connection, emit headers and close connection.

@alissonpelizaro
Copy link
Author

alissonpelizaro commented May 10, 2019

@peter279k, I dont run because in my case the Socket Server isn't Socket.io of JS. I built it with PHPSocket.io library.

Clients from Sokect.io.js can connect in this server without problems... But clients os this library keep this process when is called initializae() method.

@peter279k
Copy link
Contributor

@alissonpelizaro, thank you for your reply.

If possible, could you provide sample codes that you execute socket server/client?

And I can try reproducing issue.

@alissonpelizaro
Copy link
Author

alissonpelizaro commented May 10, 2019

@peter279k, sure.

Server (working):

require_once '../vendor/autoload.php';
use Workerman\Worker;
use Workerman\WebServer;
use Workerman\Autoloader;
use PHPSocketIO\SocketIO;

// ssl context
$context = array(
  'ssl' => array(
    'local_cert'  => '/etc/letsencrypt/live/security/cert.pem',
    'local_pk'    => '/etc/letsencrypt/live/security/privkey.pem',
    'verify_peer' => false,
  )
);

$io = new SocketIO(2021, $context);
$io->on('connection', function($socket){
  echo "[info]: New client (".$socket->id.")\n";

  $socket->on('alert', function ($data)use($socket){
    echo "[info]: I received an alert!\n";
  });
});

Worker::runAll();

Client JavaScript Socket.io (working):
[running on client side]

var hostname = "https://myurl.com:2021";
var socket = io.connect(hostname, {
  secure: true,
  reconnect: true,
  rejectUnauthorized : false
});

socket.on('connect', function () {
  socket.on('alert', function (data) {
    alert(data);
  });

  socket.on('disconnect', function () {
    console.log('disconnected');
  });
});

Client PHP Elephant.io (not work):
[running on server side]

require_once 'vendor/autoload.php';
use ElephantIO\Client;
use ElephantIO\Engine\SocketIO\Version2X AS Version2X;

$client = new Client(new Version2X('https://localhost:2021', [
  'context' => [
    'ssl' => [
      'verify_peer' => false,
      "verify_peer_name"=>false,
      'allow_self_signed'=> false
      ]
    ]
  ]));

$client->initialize();
$client->emit('alert', 'Hello world!');
$client->close();

I've tried with the three versions. The Version0X not work, the Version1X and Version2X can connect on the server, but keep the process alive at initialize() method.

Thanks a lot for your time with this issue. 😊

@peter279k
Copy link
Contributor

@alissonpelizaro, thank you for your reply.

I try reproducing issue and got the following errors. The approach is as follows:

Firstly, we create the web socket server without SSL.

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

use Workerman\Worker;
use PHPSocketIO\SocketIO;

$io = new SocketIO(2021, []);
$io->on('connection', function($socket){
  echo "[info]: New client (".$socket->id.")\n";

  $socket->on('alert', function ($data)use($socket){
    echo "[info]: I received an alert!\n";
  });
});

Worker::runAll();

Second, create the client with elephant.io.

<?php

require_once './vendor/autoload.php';
use ElephantIO\Client;
use ElephantIO\Engine\SocketIO\Version2X AS Version2X;

$client = new Client(new Version2X('http://localhost:2021', []));

$data = [
    'message' => 'Hello world!',
];

var_dump($client->initialize());
var_dump($client->emit('alert', $data));
$client->close();

Finally, I got the following fatal error message:

PHP Fatal error:  Uncaught UnexpectedValueException: The server returned an unexpected value. Expected "HTTP/1.1 101", had "HTTP/1.1 403" in /home/lee/elephant.io/src/Engine/SocketIO/Version1X.php:290
Stack trace:
#0 /home/lee/elephant.io/src/Engine/SocketIO/Version1X.php(77): ElephantIO\Engine\SocketIO\Version1X->upgradeTransport()
#1 /home/lee/elephant.io/src/Client.php(59): ElephantIO\Engine\SocketIO\Version1X->connect()
#2 /home/lee/elephant.io/client.php(13): ElephantIO\Client->initialize()
#3 {main}
  thrown in /home/lee/elephant.io/src/Engine/SocketIO/Version1X.php on line 290

It looks like the elephant.io client is only available for the socket.io server at this moment.

If we want to support the workerman socker server, we have to add other methods about building another requests to support the workerman server.

@Taluu
Copy link
Contributor

Taluu commented May 12, 2019

Yup, only socket.io is supported at the moment. Feel free to provide an implementation for workerman.

@Taluu Taluu added the support label May 12, 2019
@Taluu
Copy link
Contributor

Taluu commented May 12, 2019

Actually (didn't read the whole ticket...) this shouldn't be a problem, as js clients can properly connect. From @peter279k's "debug", we can see that it returns a 403, which is another matter... Is there any logs from the workerman / phpsocketio ?

@peter279k
Copy link
Contributor

peter279k commented May 13, 2019

@Taluu, thank you for your reply. The Worker server message log is as follows:

Workerman[server.php] start in DEBUG mode
------------------------------------------- WORKERMAN -------------------------------------------
Workerman version:3.5.19          PHP version:7.3.5-1+ubuntu18.04.1+deb.sury.org+1
-------------------------------------------- WORKERS --------------------------------------------
proto   user            worker          listen                     processes    status           
tcp     lee             PHPSocketIO     socketIO://0.0.0.0:2021    1             [OK]            
-------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
[info]: New client (5585bbf03b36d74103b63d34)

The server has received connection message correctly.

And it looks like the client send the incorrect requests to worker socket server.

@alissonpelizaro
Copy link
Author

Yes @peter279k. The method initialize() keep a procecess in the foreground on the client and the PHP Fatal error (HTTP/1.1 403) appears after the connection timeout. While this procecess is running, if we stop the server, the client Elephant.io is closed instantly before this Fatal error. In other words, the connection was successful. Isn't it?

Should I change the title to "Workerman connection problem", or somethig like this?

Once again, thank you very much for your personal help.

@peter279k
Copy link
Contributor

peter279k commented May 13, 2019

Yes @peter279k. The method initialize() keep a procecess in the foreground on the client and the PHP Fatal error (HTTP/1.1 403) appears after the connection timeout. While this procecess is running, if we stop the server, the client Elephant.io is closed instantly before this Fatal error. In other words, the connection was successful. Isn't it?

Should I change the title to "Workerman connection problem", or somethig like this?

Once again, thank you very much for your personal help.

I think it's about the Workerman connection problem.

The HTTP response result is 403 means some requests are invalid for Workerman server.

@alissonpelizaro
Copy link
Author

I really agree that Workerman service is not compatible with this library, I'll fork and send a pull request if I find a solution.

Thank you very much for your help once again.

God blesses.

@catomik
Copy link

catomik commented Jul 8, 2019

I found where the problem came from. It is the handshake function in file Version1X.php(196). Function file_get_contents executing too long, so connection is timeout and server returns 403 on connection update. If replace file_get_contents with curl or something like that, then all seems to work fine.

@Taluu
Copy link
Contributor

Taluu commented Jul 8, 2019

Hum, yeah at the time fgc was the least bothersome to use. What you should be asking yourself is why it takes so much time.

But then using curl can be a solution, but imo it doesn't solve your problem... it just goes around it.

@Taluu
Copy link
Contributor

Taluu commented Jul 8, 2019

... and seeing what is now done in the handshake, using curl (or a proper http client, such as a PSR-18 or symfony's) would be better IMO (maintenance wise).

@Karamellwuerfel
Copy link

@catomik How do you replace the fgc function with curl? Do you have an example?
Thanks!

@catomik
Copy link

catomik commented Jun 16, 2020

@Karamellwuerfel in my case I replaced this:

        if (isset($this->options['headers'])) {
            $headers = isset($context[$protocol]['header']) ? $context[$protocol]['header'] : [];
            $context[$protocol]['header'] = \array_merge($headers, $this->options['headers']);
        }

        $url    = \sprintf(
            '%s://%s:%d/%s/?%s',
            $this->url['scheme'],
            $this->url['host'],
            $this->url['port'],
            \trim($this->url['path'], '/'),
            \http_build_query($query)
        );

        $result = @\file_get_contents($url, false, \stream_context_create($context));

with this:

         $hrs = [];
        if (isset($this->options['headers'])) {
            $headers = isset($context[$protocol]['header']) ? $context[$protocol]['header'] : [];
            $context[$protocol]['header'] = \array_merge($headers, $this->options['headers']);
        }

        foreach ($context[$protocol]['header'] as $item) {
            if (\preg_match('/^([^:]*):\s*([^;]*)/i', $item, $matches)) {
                $hrs[$matches[1]] = $matches[2];
            }
        }

        $url    = \sprintf(
            '%s://%s:%d/%s/?%s',
            $this->url['scheme'],
            $this->url['host'],
            $this->url['port'],
            \trim($this->url['path'], '/'),
            \http_build_query($query)
        );

        $client = new \GuzzleHttp\Client([]);

        $response = $client->request('GET',$url,['headers'=>$hrs]);
        $result = $response->getBody()->getContents();

@Karamellwuerfel
Copy link

Oh wow, thanks for the quick answer @catomik.
I think I got it working, but Its shows me this error:
Warning: stream_socket_client(): unable to connect to ssl://ws.xxxxxxxxxx.de:3301 (Connection refused)

The apache server is configured for https and the domain ws.xxxxxxxxxx.de points to the port 3301 without adding it to the end of the url.
Have I add something in the apace site conf?

I recognized that it tries to connect to "ssl://...." why that? Whats this "ssl"-URL?

Thank you many times!

@catomik
Copy link

catomik commented Jun 16, 2020

@Karamellwuerfel Did you provide the ssl context, like this, when starting socket server?

// ssl context
$context = array(
  'ssl' => array(
    'local_cert'  => '/etc/letsencrypt/live/security/cert.pem',
    'local_pk'    => '/etc/letsencrypt/live/security/privkey.pem',
    'verify_peer' => false,
  )
);

$io = new SocketIO(2021, $context);

@Karamellwuerfel
Copy link

Karamellwuerfel commented Jun 16, 2020

@catomik In my server.js it's like this:

var express = require('express');
var app = express();
var https = require('https');

var server = https.createServer({ 
    key: fs.readFileSync('/etc/letsencrypt/live/xxxxxxxx.de/privkey.pem'),
    cert: fs.readFileSync('/etc/letsencrypt/live/xxxxxxxx.de/fullchain.pem')
},app);

var io = require('socket.io').listen(server);

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Headers", "Content-Type");
    res.header("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS");
    next();
});

let port = 3001;
server.listen(port);
console.log('Server running on port '+port+'...');

A connection via javascript gives me this message:
index.js:83 WebSocket connection to 'wss://ws.xxxxxxxx.de/socket.io/?EIO=3&transport=websocket&sid=e1lUWB7gxaQ8aTVHAAAA' failed: Error during WebSocket handshake: Unexpected response code: 400

and
Failed to load resource: the server responded with a status of 400 (Bad Request)

Thank you.

@catomik
Copy link

catomik commented Jun 16, 2020

@Karamellwuerfel Sorry, but I never test it with node.js socket server, so I can`t help you with it.

@Karamellwuerfel
Copy link

@catomik damn.. ok thank you for your time and help.

@rodrigoaguilera
Copy link

@catomik I hope you don't mind I opened a PR with your code
#203

This modification makes the client work with phpsocket.io

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

No branches or pull requests

6 participants