Browse Source
- First raw import of the daemon in Movim
- First raw import of the daemon in Movim
- Adapt RPC to be called with the linker - Create the MovimWebsocket javascript class to handle the websocket connectionpull/16/head
11 changed files with 377 additions and 14 deletions
-
2app/assets/js/movim_base.js
-
91app/assets/js/movim_websocket.js
-
3app/views/page.tpl
-
5bootstrap.php
-
12composer.json
-
20daemon.php
-
100linker.php
-
134src/Movim/Daemon/Behaviour.php
-
20system/RPC.php
-
2system/controllers/AjaxController.php
-
2system/controllers/BaseController.php
@ -0,0 +1,91 @@ |
|||
/** |
|||
* Movim Websocket |
|||
* |
|||
* This file define the websocket behaviour and handle its connection |
|||
*/ |
|||
|
|||
WebSocket.prototype.link = function(body) { |
|||
this.send(JSON.stringify({'func' : 'link'})); |
|||
}; |
|||
WebSocket.prototype.register = function() { |
|||
this.send(JSON.stringify({'func' : 'register', 'sid' : localStorage.movimSession})); |
|||
}; |
|||
|
|||
/** |
|||
* @brief Definition of the MovimWebsocket object |
|||
* @param string error |
|||
*/ |
|||
function MovimWebsocket() { |
|||
var connection; |
|||
} |
|||
|
|||
MovimWebsocket.prototype.init = function() { |
|||
this.connection = new WebSocket('ws://localhost:8080'); |
|||
|
|||
this.connection.onopen = function(e) { |
|||
console.log("Connection established!"); |
|||
|
|||
if(localStorage.movimSession === undefined) { |
|||
this.send(JSON.stringify({'func' : 'ask'})); |
|||
} else { |
|||
this.register(); |
|||
} |
|||
|
|||
// And we launch the Javascript
|
|||
movim_onload(); |
|||
}; |
|||
|
|||
this.connection.onmessage = function(e) { |
|||
console.log(e.data); |
|||
var obj = JSON.parse(e.data); |
|||
|
|||
if(obj.id) { |
|||
localStorage.movimSession = obj.id; |
|||
this.register(); |
|||
} |
|||
|
|||
websocket.handle(e.data); |
|||
}; |
|||
}; |
|||
|
|||
MovimWebsocket.prototype.send = function(widget, func, params) { |
|||
this.connection.send( |
|||
JSON.stringify( |
|||
{'func' : 'message', 'body' : |
|||
{ |
|||
'widget' : widget, |
|||
'func' : func, |
|||
'params' : params |
|||
} |
|||
} |
|||
) |
|||
); |
|||
}; |
|||
|
|||
MovimWebsocket.prototype.handle = function(json) { |
|||
var funcalls = eval(json); |
|||
|
|||
if(funcalls != null) { |
|||
for(h = 0; h < funcalls.length; h++) { |
|||
var funcall = funcalls[h]; |
|||
|
|||
if(funcall.func != null && eval("typeof " + funcall.func) == "function") { |
|||
var funcs = funcall.func.split('.'); |
|||
|
|||
try { |
|||
if(funcs.length == 1) |
|||
window[funcs[0]](funcall.params); |
|||
else if(funcs.length == 2) |
|||
window[funcs[0]][funcs[1]](funcall.params); |
|||
} |
|||
catch(err) { |
|||
console.log("Error caught: " + err.toString() + " - " +funcall.func); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// And we start it
|
|||
var websocket = new MovimWebsocket; |
|||
websocket.init(); |
|||
@ -0,0 +1,20 @@ |
|||
<?php |
|||
use Ratchet\Server\IoServer; |
|||
use Ratchet\Http\HttpServer; |
|||
use Ratchet\WebSocket\WsServer; |
|||
use Movim\Daemon\Behaviour; |
|||
|
|||
require dirname(__FILE__) . '/vendor/autoload.php'; |
|||
|
|||
$server = new Behaviour; |
|||
|
|||
$server = IoServer::factory( |
|||
new HttpServer( |
|||
new WsServer( |
|||
$server |
|||
) |
|||
), |
|||
8080 |
|||
); |
|||
|
|||
$server->run(); |
|||
@ -0,0 +1,100 @@ |
|||
<?php |
|||
require __DIR__ . '/vendor/autoload.php'; |
|||
|
|||
define('DOCUMENT_ROOT', dirname(__FILE__)); |
|||
require_once(DOCUMENT_ROOT.'/bootstrap.php'); |
|||
|
|||
$bootstrap = new Bootstrap(); |
|||
$booted = $bootstrap->boot(); |
|||
|
|||
set_time_limit(200); |
|||
|
|||
$polling = true; |
|||
|
|||
$loop = React\EventLoop\Factory::create(); |
|||
|
|||
$logger = new \Zend\Log\Logger(); |
|||
$writer = new \Zend\Log\Writer\Syslog(array('application' => 'movim')); |
|||
$logger->addWriter($writer); |
|||
|
|||
$client_xmpp = new \Devristo\Phpws\Client\WebSocket("ws://movim.eu:5290/", $loop, $logger); |
|||
$client_local = new \Devristo\Phpws\Client\WebSocket("ws://127.0.0.1:8080/", $loop, $logger); |
|||
|
|||
// CLIENT 1
|
|||
|
|||
$client_xmpp->on("request", function($headers) use ($logger){ |
|||
$logger->notice("XMPP : Request object created!"); |
|||
}); |
|||
|
|||
$client_xmpp->on("handshake", function() use ($logger) { |
|||
$logger->notice("XMPP : Handshake received!"); |
|||
}); |
|||
|
|||
$client_xmpp->on("connect", function($headers = false) use ($client_xmpp, $logger) { |
|||
$logger->notice("XMPP : Connected"); |
|||
}); |
|||
|
|||
$client_xmpp->on("disconnect", function($headers = false) use ($client_xmpp) { |
|||
$logger->notice("XMPP : Disconnected"); |
|||
|
|||
$client_local->close(); |
|||
}); |
|||
|
|||
$client_xmpp->on("message", function($message) use ($client_local, $logger){ |
|||
$logger->notice("XMPP : Got message"); |
|||
|
|||
$obj = new \StdClass; |
|||
$obj->func = 'message'; |
|||
$obj->body = $message->getData(); |
|||
|
|||
$client_local->send(json_encode($obj)); |
|||
}); |
|||
|
|||
// CLIENT 2
|
|||
|
|||
$client_local->on("request", function($headers) use ($logger){ |
|||
$logger->notice("LOOP : Request object created!"); |
|||
}); |
|||
|
|||
$client_local->on("handshake", function() use ($logger) { |
|||
$logger->notice("LOOP : Handshake received!"); |
|||
}); |
|||
|
|||
$client_local->on("connect", function($headers = false) use ($client_local, $logger) { |
|||
$logger->notice("LOOP : Connected!"); |
|||
|
|||
$obj = new \StdClass; |
|||
$obj->func = 'register_linker'; |
|||
$obj->sid = getenv('sid'); |
|||
|
|||
$client_local->send(json_encode($obj)); |
|||
}); |
|||
|
|||
$client_local->on("disconnect", function($headers = false) use ($client_local) { |
|||
$logger->notice("LOOP : Disconnected"); |
|||
|
|||
$client_xmpp->close(); |
|||
}); |
|||
|
|||
$client_local->on("message", function($message) use ($client_local, $client_xmpp, $logger){ |
|||
|
|||
if($message->getData() != '') { |
|||
$rpc = new RPC(); |
|||
$rpc->handle_json($message->getData()); |
|||
$logger->notice("LOOP : Got message"); |
|||
|
|||
$obj = new \StdClass; |
|||
$obj->func = 'message'; |
|||
$obj->body = RPC::commit(); |
|||
RPC::clear(); |
|||
|
|||
$client_local->send(json_encode($obj)); |
|||
} |
|||
|
|||
//$client_xmpp->send($message->getData());
|
|||
}); |
|||
|
|||
$client_local->open(); |
|||
$client_xmpp->open(); |
|||
|
|||
$loop->run(); |
|||
@ -0,0 +1,134 @@ |
|||
<?php |
|||
namespace Movim\Daemon; |
|||
|
|||
use Ratchet\MessageComponentInterface; |
|||
use Ratchet\ConnectionInterface; |
|||
|
|||
class Behaviour implements MessageComponentInterface { |
|||
protected $sessions = array(); // Store the sessions
|
|||
|
|||
public function __construct() { |
|||
echo "Movim daemon launched\n"; |
|||
} |
|||
|
|||
public function onOpen(ConnectionInterface $conn) { |
|||
echo "{$conn->resourceId} connected\n"; |
|||
} |
|||
|
|||
public function onMessage(ConnectionInterface $from, $msg) { |
|||
$msg = json_decode($msg); |
|||
|
|||
switch ($msg->func) { |
|||
// The browser ask for a new session
|
|||
case 'ask': |
|||
$id = $this->generateId(); |
|||
|
|||
$obj = new \StdClass; |
|||
$obj->id = $id; |
|||
$from->send(json_encode($obj)); |
|||
break; |
|||
|
|||
// A browser websocket ask to be linked to an existent session
|
|||
case 'register': |
|||
$from->sid = $msg->sid; |
|||
|
|||
if(!array_key_exists($from->sid, $this->sessions)) { |
|||
$this->sessions[$from->sid] = array(); |
|||
} |
|||
|
|||
$this->sessions[$from->sid][$from->resourceId] = $from; |
|||
|
|||
// If a linker doesn't exist for the current session
|
|||
if(!array_key_exists('linker', $this->sessions[$from->sid])) { |
|||
$from->send(json_encode('session linked')); |
|||
|
|||
$loop = \React\EventLoop\Factory::create(); |
|||
$process = new \React\ChildProcess\Process('php linker.php', null, array('sid' => $from->sid)); |
|||
$process->start($loop); |
|||
} |
|||
|
|||
$session_size = count($this->sessions[$from->sid]); |
|||
echo "{$from->sid} : {$from->resourceId} registered - session size {$session_size}\n"; |
|||
break; |
|||
|
|||
// A linker ask to be linked to a session
|
|||
case 'register_linker': |
|||
if(array_key_exists($msg->sid, $this->sessions) && |
|||
!array_key_exists('linker', $this->sessions[$msg->sid])) { |
|||
$from->sid = $msg->sid; |
|||
$this->sessions[$from->sid]['linker'] = $from; |
|||
} |
|||
|
|||
$session_size = count($this->sessions[$from->sid]); |
|||
echo "{$from->sid} : {$from->resourceId} linker registered - session size {$session_size}\n"; |
|||
break; |
|||
|
|||
// A message is received !
|
|||
case 'message': |
|||
// Forbid any incoming messages if the session is not linked to XMPP
|
|||
if(!array_key_exists('linker', $this->sessions[$from->sid])) { |
|||
$from->send(json_encode('linker not connected')); |
|||
return; |
|||
} |
|||
|
|||
$msg->body = (string)json_encode($msg->body); |
|||
|
|||
// A message from the linker to the clients
|
|||
if($from === $this->sessions[$from->sid]['linker']) { |
|||
echo "{$from->sid} : {$msg->body} got from the linker\n"; |
|||
foreach($this->sessions[$from->sid] as $key => $client) { |
|||
if($from !== $client) { |
|||
//The sender is not the receiver, send to each client connected
|
|||
if(isset($msg->body)) { |
|||
$client->send($msg->body); |
|||
} |
|||
} |
|||
} |
|||
// A message from the browser to the linker
|
|||
} else { |
|||
echo "{$from->sid} : {$msg->body} sent to the linker\n"; |
|||
$this->sessions[$from->sid]['linker']->send((string)$msg->body); |
|||
} |
|||
break; |
|||
default: |
|||
$from->send('no function specified'); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
public function onClose(ConnectionInterface $conn) { |
|||
$session_size = count($this->sessions[$conn->sid]); |
|||
|
|||
// The connection is closed, remove it, as we can no longer send it messages
|
|||
if($conn === $this->sessions[$conn->sid]['linker']) { |
|||
foreach($this->sessions[$conn->sid] as $key => $client) { |
|||
$client->close(); |
|||
} |
|||
|
|||
unset($this->sessions[$conn->sid]); |
|||
} else { |
|||
unset($this->sessions[$conn->sid][$conn->resourceId]); |
|||
} |
|||
|
|||
echo "{$conn->resourceId} disconnected - session size {$session_size}\n"; |
|||
} |
|||
|
|||
public function onError(ConnectionInterface $conn, \Exception $e) { |
|||
echo "An error has occurred: {$e->getMessage()}\n"; |
|||
|
|||
$conn->close(); |
|||
} |
|||
|
|||
private function generateId() { |
|||
// Generating the session cookie's hash.
|
|||
$hash_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; |
|||
$hash = ""; |
|||
|
|||
for($i = 0; $i < 16; $i++) { |
|||
$r = mt_rand(0, strlen($hash_chars) - 1); |
|||
$hash.= $hash_chars[$r]; |
|||
} |
|||
|
|||
return $hash; |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue