Nejde mi poslat zprávu do WebSocket topicu přes ZeroMQ (ipublikuj/websockets-zmq)

crassus
Backer | 78
+
0
-

Ahoj,

implementoval jsem si do projektu knihovnu ipublikuj/websockets-wamp a ipublikuj/websockets-zmq. JS klienti mi fungují, ale nedokážu vložit do topicu zprávu ze serveru pomocí té ZeroMQ fronty.

Žádnou chybu to nepíše.

Po zavolání: php web/index.php ipub:websockets:start

naběhne WebSocket server i ZMQ. Poté pošlu request presenteru, tam se ještě zavolá $this->pusher->push($data, 'RaspberryPi:', ['id' => '1']);, ale poté už se nespustí actionPush() uvnitř RaspberryPiController.php.

Nevíte prosím někdo čím by to mohlo být?

ApiPresenter.php

public function actionAdvert()
{
    $data = [
        'type'    => 'system',
        'content' => 'This is example advertising.',
    ];

    $this->pusher->push($data, 'RaspberryPi:', ['id' => '1']);

    $this->terminate();
}

RaspberryPiController.php

	public function actionPush(array $data, ITopic $topic)
{
    \Tracy\Debugger::log("nezavola se");
    $now = new \DateTime();
    $message = new \stdClass();
    $message->type = $data['type'];
    $message->time = $now->format(DATE_ISO8601);
    $message->content = $data['content'];
    $topic->broadcast(Json::encode($message));
}

Případně jak mám správně nastavit SSL certifikát v configu, abych mohl použit WSS protokol?

webSockets:
    server:
        httpHost: localhost
        port: 8080
        address: 0.0.0.0
        secured:
            enable: true
            sslSettings:
                local_cert : 'C:\Apache24\conf\server.crt'
                local_pk : 'C:\Apache24\conf\server.key'
                allow_self_signed : true
                verify_peer : false
    routes:
        '/raspberrypi/<id>' : 'RaspberryPi:'
    mapping:
        *: App\Controllers\*Controller

Když se zkouším připojit s klientem na WSS protokol, píše to:

Could not establish connection: Connection from tcp://127.0.0.1:61992 failed during TLS handshake:
Unable to complete TLS handshake: SSL operation failed with code 1.
OpenSSL Error messages: error:14094416:SSL
routines:ssl3_read_bytes:sslv3 alert certificate unknown

Editoval crassus (27. 5. 2019 11:52)

crassus
Backer | 78
+
0
-

Rozjel jsem si na lokálu demo: https://github.com/ipublikuj/demo, ve kterém mi také funguje vše kromě té fronty ZeroMQ a WSS protokolu.

Editoval crassus (27. 5. 2019 11:56)

akadlec
Člen | 1326
+
0
-

WSS není tak super easy rozchodit, resp. když jsem to zkoušel během vývoje tak byl problém se SSL handshake na straně reactu :/ řeší se to pomocí proxy (popisoval sem v mailul, nevím zda dorazil)

V apache např takto:

ProxyPass „/sockets/“ „ws://yourdomain.com:9787“

Tedy volá se spojení z klienta na wss://yourdomain.com/sockets a apache to přeroutuje na ws://yourdomain.com:9787

Ad zmq pokud to nic neconsumuje tak možná že nesedly porty :/ každopádně na consumerovi jsou eventy https://github.com/…/en/index.md#… tak je zkus logovat jestli tam něco přijde

zmq je supereasy fronta. Jedině co ještě může dělat problém je obsazenost portu. Ve zkratce to jede tak že se otevře TCP kanál na vybraný port kde poslouchá consumer a pusher/producer se připojí jen pro komunikaci, pošle data a pak se odpojí.

akadlec
Člen | 1326
+
0
-

Jinak pokud nejede demo, tak mě ještě napadá že mohli něco změnit v nějakém reactphp balíku :/

akadlec
Člen | 1326
+
0
-

a malé OT, vidím tam DATE_ISO8601 což je imo špatně: https://www.php.net/…nterface.php#…

crassus
Backer | 78
+
0
-

akadlec napsal(a):

a malé OT, vidím tam DATE_ISO8601 což je imo špatně: https://www.php.net/…nterface.php#…

Ta actionPush() uvnitr kontroleru se vubec nezavola. Eventy to nevyhazuje. Zkusil jsem i jine porty a taky bohuzel nic :(

crassus
Backer | 78
+
0
-

akadlec napsal(a):

WSS není tak super easy rozchodit, resp. když jsem to zkoušel během vývoje tak byl problém se SSL handshake na straně reactu :/ řeší se to pomocí proxy (popisoval sem v mailul, nevím zda dorazil)

V apache např takto:

ProxyPass „/sockets/“ „ws://yourdomain.com:9787“

Tedy volá se spojení z klienta na wss://yourdomain.com/sockets a apache to přeroutuje na ws://yourdomain.com:9787

Ad zmq pokud to nic neconsumuje tak možná že nesedly porty :/ každopádně na consumerovi jsou eventy https://github.com/…/en/index.md#… tak je zkus logovat jestli tam něco přijde

zmq je supereasy fronta. Jedině co ještě může dělat problém je obsazenost portu. Ve zkratce to jede tak že se otevře TCP kanál na vybraný port kde poslouchá consumer a pusher/producer se připojí jen pro komunikaci, pošle data a pak se odpojí.

Povolil jsem v Apache moduly:

mod_proxy.so
mod_proxy_wstunnel.so

A do httpd-vhosts.conf jsem pridal:

ProxyPass        /sockets/ ws://127.0.0.1:8080

Na klientovi pak volam:

IPub.WebSockets.WAMP.initialize('wss://127.0.0.1:8080/sockets/');

A bohuzel handshake nekonci 101, ale request je porad pending a pak vytimeoutuje :(

Editoval crassus (31. 5. 2019 21:27)

crassus
Backer | 78
+
0
-

akadlec napsal(a):

Jinak pokud nejede demo, tak mě ještě napadá že mohli něco změnit v nějakém reactphp balíku :/

Demo po pullnutí jen tak nefungovalo, tak jsem poopravoval chyby: http://leteckaposta.cz/127858839

Staci zavolat composer install a nabehne to, ale bohuzel ani v tom demu se nespousti actionPush().

akadlec
Člen | 1326
+
0
-

nemůžeš volat stejný port IPub.WebSockets.WAMP.initialize('wss://127.0.0.1:8080/sockets/');
Pokud děláš proxy tak voláš jiný port a proxypass ti to přeroutuje takže IPub.WebSockets.WAMP.initialize('wss://127.0.0.1/sockets/');

akadlec
Člen | 1326
+
0
-

Ad zmq, pokud to neodpaluje eventy tak ten consumer vubec nic nedostane. Buď poslouchá na jiném portu než posílá consumer a nebo je ten port obsazeny. Jaký port si tam nakonfil?

    webSocketsZMQ:
        host: '127.0.0.1'
        port: 5555
        persistent: true
        protocol: 'tcp'
crassus
Backer | 78
+
0
-

akadlec napsal(a):

Ad zmq, pokud to neodpaluje eventy tak ten consumer vubec nic nedostane. Buď poslouchá na jiném portu než posílá consumer a nebo je ten port obsazeny. Jaký port si tam nakonfil?

    webSocketsZMQ:
        host: '127.0.0.1'
        port: 5555
        persistent: true
        protocol: 'tcp'

Zkousel jsem 5555, 5554 i treba 9787 a porad nic. Vam ta ZeroMQ fronta funguje? Vsiml jsem si totiz ze ta abstraktni metoda doPush() uvnitr IPub\WebSocketsWAMP\PushMessages\Pusher nikde neni implementovana.

crassus
Backer | 78
+
0
-

akadlec napsal(a):

nemůžeš volat stejný port IPub.WebSockets.WAMP.initialize('wss://127.0.0.1:8080/sockets/');
Pokud děláš proxy tak voláš jiný port a proxypass ti to přeroutuje takže IPub.WebSockets.WAMP.initialize('wss://127.0.0.1/sockets/');

Díky :)

teď už to vypisuje:

autobahn.js:1293 WebSocket connection to ‚wss://127.0.0.1/sockets/‘ failed: Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID

Používám certifikát Internet Widgits Pty Ltd. Na localhostu díky tomu můžu fungovat s https.

Ale kvůli těm WebSocketům budu muset použít jiný certifikát?

crassus
Backer | 78
+
0
-

akadlec napsal(a):

nemůžeš volat stejný port IPub.WebSockets.WAMP.initialize('wss://127.0.0.1:8080/sockets/');
Pokud děláš proxy tak voláš jiný port a proxypass ti to přeroutuje takže IPub.WebSockets.WAMP.initialize('wss://127.0.0.1/sockets/');

Ted jsem jeste zkusil navstivit https://127.0.0.1/sockets/, potvrdil jsem ze chci prejit na stranku, a pak jsem znovu spustil klienta, ktery mi ted pise:

autobahn.js:1293: WebSocket connection to ‚wss://127.0.0.1/sockets/‘ failed: Error during WebSocket handshake: Unexpected response code: 500

akadlec
Člen | 1326
+
0
-

ZMQ jako takovou jsem momentálně implementoval mezi serverem a klientem. Extension pro WAMP momentálně na jednom projektu přidávám. Pusher extenduje pusher z WAMP rozšíření a metoda doPush se volá pomocí public push jako tomu je tady: https://github.com/…resenter.php#…

akadlec
Člen | 1326
+
0
-

@crassus v configu WS serveru vůbec nenastavuj SSL tohle:

        secured:
            enable: true
            sslSettings:
                local_cert : 'C:\Apache24\conf\server.crt'
                local_pk : 'C:\Apache24\conf\server.key'
                allow_self_signed : true
                verify_peer : false

dej pryč. WS server ti poběží bez SSL, o SSL se ti postará právě ta proxy a certifikáty to bude mít takové co máš pro ten vhost

akadlec
Člen | 1326
+
0
-

Jinak sem předevčírem dával update na react socket, takže jak bude čas chci to ssl znova zkusit a případně dořešit s nima

akadlec
Člen | 1326
+
0
-

@crassus hele tak jsem tu zmq zkusil a normálně mě to běhá. V „presenteru“ mám:

		$this->socketsPusher->push($this->getClientsMessage($thing, $channel), 'IOServerExchange:Thing:', [
			'thing' => $thing->getPlainId(),
		]);

a controleru pr WS pak

	public function actionPush(
		array $data,
		IOServerModuleEntities\Things\IThing $thing,
		WebSocketsWAMP\Entities\Topics\ITopic $topic
	) : void {
		if (!$this->entityManagerHelpers->checkEntityManager()) {
			throw new WebSockets\Exceptions\TerminateException('EntityManager is closed.');
		}

		try {
			$topic->broadcast(Utils\Json::encode($data));

		} catch (Utils\JsonException $ex) {
			$this->logger->logException($ex, [
				'type'       => 'controller',
				'controller' => 'thing',
				'action'     => 'encode_payload',
				'thing'      => [
					'id' => $thing->getPlainId(),
				],
			]);
		}
	}
akadlec
Člen | 1326
+
0
-

Ještě mě napadá že to může dělat ta SSL konfigurace. Protože tu zmq extension není nutné vůbec konfigurovat. A druhý tip co by to mohlo dělat ze zakázaní portu na kterém se to snaží naslouchat.

crassus
Backer | 78
+
0
-

akadlec napsal(a):

@crassus v configu WS serveru vůbec nenastavuj SSL tohle:

        secured:
            enable: true
            sslSettings:
                local_cert : 'C:\Apache24\conf\server.crt'
                local_pk : 'C:\Apache24\conf\server.key'
                allow_self_signed : true
                verify_peer : false

dej pryč. WS server ti poběží bez SSL, o SSL se ti postará právě ta proxy a certifikáty to bude mít takové co máš pro ten vhost

Dal jsem celou konfiguraci pryc, ale pise to porad: WebSocket connection to ‚wss://127.0.0.1/sockets/‘ failed: Error during WebSocket handshake: Unexpected response code: 500

Asi budu mit tim padem spatne napsany ten ProxyPass.

crassus
Backer | 78
+
0
-

akadlec napsal(a):

Ještě mě napadá že to může dělat ta SSL konfigurace. Protože tu zmq extension není nutné vůbec konfigurovat. A druhý tip co by to mohlo dělat ze zakázaní portu na kterém se to snaží naslouchat.

Port blokovany neni: https://jpeg.cz/…/screen2.jpg

Az potud se mi kod jeste provede: https://jpeg.cz/…7/screen.jpg

Jako instanci toho pushera pouzivate IPub\WebSocketsZMQ\Pusher\Pusher nebo IPub\WebSocketsWAMP\PushMessages\IPusher?

Pak jsem si vsiml ze nazev topicu uvadite jako: ‚IOServerExchange:Thing:‘ , co to znamena ze za nazev kontroleru uvedu jeste :Thing ?

crassus
Backer | 78
+
0
-

Tady jeste posilam cely ten kontroler:

<?php

namespace App\Controllers;

use IPub\WebSockets\Application\Controller\Controller;
use IPub\WebSockets\Entities\Clients\IClient;
use IPub\WebSocketsWAMP\Entities\Topics\ITopic;
use Nette\Utils\Json;

class RaspberryPiController extends Controller
{
    public function actionSubscribe(IClient $client, ITopic $topic, int $id)
    {
        $topic->broadcast($client->getId() .' joined: ' . ' id: ' . $id);
    }

    public function actionUnsubscribe(IClient $client, ITopic $topic, int $id)
    {
        $topic->broadcast($client->getId() .' left: ' . ' id:' . $id);
    }

    public function actionPublish($event, IClient $client, ITopic $topic, int $id)
    {
        $topic->broadcast($client->getId() .' is saying: '. $event . ' , topic: ' . $topic->getId() . ' id: ' . $id);
    }

    public function actionPush(array $data, ITopic $topic)
    {
        \Tracy\Debugger::log("nezavola se");
        //$now = new \DateTime();
        $message = new \stdClass();
        $message->type = $data['type'];
        //$message->time = $now->format(DATE_ISO8601);
        $message->content = $data['content'];
        $topic->broadcast(Json::encode($message));
    }
}

Vsechny actions krome actionPush funguji.

akadlec
Člen | 1326
+
0
-

Pokud se to nespojí a háže to ssl chyby, tak asi bude špatně nakonfený proxy pass. Chce to mít i instalované apache pluginy

Jako pusher je instance ze zmq: IPub\WebSocketsZMQ\Pusher\Pusher. V pusheru IOServerExchange:Thing: je nepodstatné, já takto mám jen udělaný router. Nicméně i pokud by byla routa špatně a server nedokázal routu najít, tak i tak musí být odpáleny ty události viz výše.

akadlec
Člen | 1326
+
0
-

Zkus update knihoven, vydal jsem nové verze a aktuálně mě fungujou. Ale zaměřil bych se primárně na to odstranění SSL, a promazání cache.

crassus
Backer | 78
+
0
-

akadlec napsal(a):

Zkus update knihoven, vydal jsem nové verze a aktuálně mě fungujou. Ale zaměřil bych se primárně na to odstranění SSL, a promazání cache.

Tak ProxyPass jsem nakonec rozjel, stačilo vložit do httpd.conf toto:

ProxyPassReverse /myws ws://127.0.0.1:8080

V javascriptu pak mám:

IPub.WebSockets.WAMP.initialize('wss://127.0.0.1/myws');

Jedná se o zabezpečený protokol, když takhle použiji ten ProxyPass? Není to pak už jedno zda použiji ws nebo wss s ProxyPass?

Každopádně ZeroMQ jsem stále nevyřešil.

Editoval crassus (29. 5. 2019 15:38)

akadlec
Člen | 1326
+
0
-

ano je to secured, resp spojení klient server je, server pak „interně“ už jede nezabezpečeně

crassus
Backer | 78
+
0
-

Když spustím tento script z příkazové řádky:

$context = new ZMQContext();
$socket = new ZMQSocket($context, ZMQ::SOCKET_PUSH);
$socket->connect("tcp://127.0.0.1:5555");
$socket->send("ahoj tady pusher");

tak consumer zprávu příjme. Když úplně ten stejný kód vložím do action v presenteru a spustím action, tak se zpráva neodešle a aktuálně připojené klienty to odpojí.

Kdybyste kdokoliv věděl co s tím, budu rád když mi poradíte. Proč to z příkazové řádky jede a z requestů přes jdoucích přes Apache nikoliv?

Editoval crassus (29. 5. 2019 15:39)

crassus
Backer | 78
+
0
-

Deploynul jsem projekt s těmi WebSockety na produkci, kde mám linux a tam ta fronta běží v pohodě.

pista5
Člen | 72
+
0
-

Ahoj, též se mi nedaří odeslat zprávu.

Po odeslani se mi vypise chyba: ZMQ socket failed to ack message

Neporadil by mi prosim nekdo, kde hledat problem?


INFO: ZMQ transport listening on 127.0.0.1:5555
DEBUG: Starting IPub\WebSockets
DEBUG: Launching WebSockets WS Server on: 0.0.0.0:8080
DEBUG: INSERT CLIENT 182
DEBUG: GET CLIENT 182
INFO: New connection! (182)
DEBUG: GET CLIENT 182
DEBUG: INSERT TOPIC reminder/1
DEBUG: GET TOPIC reminder/1
DEBUG: GET TOPIC reminder/1
DEBUG: INSERT TOPIC reminder/1
INFO: Connection 182 has subscribed to reminder/1
ERROR! ZMQ socket failed to ack message
akadlec
Člen | 1326
+
0
-

zřejmě nemáš nainstalovanou zeroMq

pista5
Člen | 72
+
0
-

akadlec napsal(a):

zřejmě nemáš nainstalovanou zeroMq

phpInfo

zmq
ZMQ extension enabled
ZMQ extension version 1.1.3
libzmq version 4.3.4

pista5
Člen | 72
+
0
-

akadlec napsal(a):

zřejmě nemáš nainstalovanou zeroMq

Je prosim vyše uvedená knihovna ta spravna?

akadlec
Člen | 1326
+
0
-

Bohužel ti nedokáži odpovědět. zmq nepoužívám už pár let

pista5
Člen | 72
+
0
-

akadlec napsal(a):

Bohužel ti nedokáži odpovědět. zmq nepoužívám už pár let

A muze byt prosim ta chyba (ZMQ socket failed to ack message) jeste zpusobena necim jinym?

akadlec
Člen | 1326
+
0
-

tak můžeš kouknout do kódu, hodit si tam dumpy/logy a uvidíš co je špatně

pista5
Člen | 72
+
0
-

akadlec napsal(a):

tak můžeš kouknout do kódu, hodit si tam dumpy/logy a uvidíš co je špatně

Jasne, na chybu jsem jiz prisel, posunul se dal, ale zde si nevim rady… v logu vypada vse OK, ale v prohlizeci se nic nestane

INFO: ZMQ transport listening on 127.0.0.1:5555
DEBUG: Starting IPub\WebSockets
DEBUG: Launching WebSockets WS Server on: 0.0.0.0:8080
DEBUG: INSERT CLIENT 188
DEBUG: GET CLIENT 188
INFO: New connection! (188)
DEBUG: GET CLIENT 188
DEBUG: INSERT TOPIC phone/1
DEBUG: GET TOPIC phone/1
DEBUG: GET TOPIC phone/1
DEBUG: INSERT TOPIC phone/1
INFO: Connection 188 has subscribed to phone/1
DEBUG: INSERT TOPIC /phone/1
DEBUG: GET TOPIC /phone/1
INFO: Message was pushed to /phone/1 topic

Udelal jsem si dump zde


public function actionPush(array $data, IPub\WebSocketsWAMP\Entities\Topics\ITopic $topic)
{
    Debugger::log($topic->getIterator(), 'WS2');

    $topic->broadcast(json_encode($data));
}

a $topic je pouze prazdny SplObjectStorage


	public function broadcast($message, array $exclude = [], array $eligible = []): void
	{
		if (!is_string($message) && !$message instanceof WebSocketsApplication\Responses\IResponse) {
			throw new Exceptions\InvalidArgumentException(sprintf('Provided message for broadcasting have to be string or instance of "%s"', WebSocketsApplication\Responses\IResponse::class));
		}

		$useEligible = (bool) count($eligible);

		Debugger::log($this->subscribers, 'X');
		/** @var WebSocketsEntities\Clients\IClient $client */
		foreach ($this->subscribers as $client) {
			Debugger::log($client, 'X');
			if (in_array($client->getId(), $exclude, true)) {
				continue;
			}

			if ($useEligible && !in_array($client->getParameter('subscribedTopics'), $eligible, true)) {
				continue;
			}

			$client->send(Utils\Json::encode([Application\Application::MSG_EVENT, $this->id, (string) $message]));
		}
	}

a funkce broadcast ma prazdnou promennou $this->subscribers

Vubec nechapu, kde je problem, ze tam neni prihlaseny uzivatel k topicu, kdyz v prvnim logu vidim, ze prihlaseni probehlo uspesne? :(

pista5
Člen | 72
+
0
-

akadlec napsal(a):

tak můžeš kouknout do kódu, hodit si tam dumpy/logy a uvidíš co je špatně

Ahoj, prosim, nenapada Te neco, proc se zprava neodesle prijemci? Pro mam $this->subscribers prazdne?
Uz jsem z toto zoufaly :(

Diky moc.

dakur
Člen | 493
+
+1
-

Zkus si ten kód prokrokovat, pak uvidíš, co se ve které chvíli děje. Je to poměrně jistý způsob odhalení problému, když člověk už fakt neví.

pista5
Člen | 72
+
0
-

dakur napsal(a):

Zkus si ten kód prokrokovat, pak uvidíš, co se ve které chvíli děje. Je to poměrně jistý způsob odhalení problému, když člověk už fakt neví.

To samozrejme delam, viz kod vyse :))

Ale nechapu, proc neobdrzim v IPub\WebSocketsWAMP\Entities\Topics\ITopic $topic seznam uzivatelu, ktere se tam predtim ulozili. A zde nevim, co bych krokoval…

Jedna funkce zapise uzivatele jako odberetele u topicu a pri zavolani jine funkce se tam nepreda instance $topic s temito uzivateli… moje znalosti nesahaji tak daleko, abych tusil, co se deje mezi tim… kde se uchovava data a proc se mi to nepreda do fukce