Commit 16aa56c8 authored by Stavros Sachtouris's avatar Stavros Sachtouris Committed by Giorgos Korfiatis
Browse files

Ensure server is up before launching GUI

Also, create an application token, unique for each run
parent bfffdf9d
......@@ -7,6 +7,9 @@ from tempfile import NamedTemporaryFile
import subprocess
import json
from os.path import abspath
from threading import Thread
from hashlib import sha256
from os import urandom
from ws4py.client import WebSocketBaseClient
......@@ -14,51 +17,58 @@ from ws4py.client import WebSocketBaseClient
class GUILauncher(WebSocketBaseClient):
"""Launch the GUI when the helper server is ready"""
def __init__(self, port, gui_exec_path, token):
super(GUILauncher, self).__init__('ws://localhost:%s' % port)
self.port = port
def __init__(self, addr, gui_exec_path, token):
"""Initialize the GUI Launcher"""
super(GUILauncher, self).__init__(addr)
self.addr = addr
self.gui_exec_path = gui_exec_path
self.token = token
def handshake_ok(self):
"""If handshake is OK, the helper is UP, so the GUI can be launched
If the GUI is terminated for some reason, the WebSocket is closed"""
with NamedTemporaryFile(mode='a+') as fp:
json.dump(dict(token=self.token, port=self.port), fp)
json.dump(dict(token=self.token, address=self.addr), fp)
fp.flush()
# subprocess.call blocks the execution
subprocess.call([
'/home/saxtouri/node-webkit-v0.11.6-linux-x64/nw',
abspath('gui/gui.nw'),
fp.name])
self.close()
class Helper(object):
"""Coordination between the GUI and the Syncer instances
def setup_server(token, port=0):
"""Setup and return the helper server"""
WebSocketProtocol.token = token
server = make_server(
'', port,
server_class=WSGIServer,
handler_class=WebSocketWSGIRequestHandler,
app=WebSocketWSGIApplication(handler_cls=WebSocketProtocol))
server.initialize_websockets_manager()
# self.port = server.server_port
return server
Setup a minimal server at a ephemeral port, create a random token, dump
this information in a local file and launch the GUI with this file as a
parameter.
Then the GUI connects and a WebSocket is established.
"""
def random_token():
return 'random token'
def __init__(self, gui_exec_path, port=0):
self.server = self.setup_server(port)
self.port = self.server.server_port
self.token = 'some random token'
self.gui_exec_path = gui_exec_path
def setup_server(self, port=0):
server = make_server(
'', port,
server_class=WSGIServer,
handler_class=WebSocketWSGIRequestHandler,
app=WebSocketWSGIApplication(handler_cls=WebSocketProtocol))
server.initialize_websockets_manager()
# self.port = server.server_port
return server
def run(gui_exec_path):
"""Prepare helper and GUI and run them in the proper order"""
token = sha256(urandom(256)).hexdigest()
server = setup_server(token)
addr = 'ws://localhost:%s' % server.server_port
gui = GUILauncher(addr, gui_exec_path, token)
Thread(target=gui.connect).start()
def run(self):
gui = GUILauncher(self.port, self.gui_exec_path, self.token)
gui.connect()
self.server.serve_forever()
try:
server.serve_forever()
except KeyboardInterrupt:
print 'Shutdown GUI'
gui.close()
Helper('ls').run()
if __name__ == '__main__':
run('/home/saxtouri/node-webkit-v0.11.6-linux-x64/nw gui.nw')
......@@ -4,95 +4,93 @@ var gui = require('nw.gui');
var fs = require('fs');
var cnf = JSON.parse(fs.readFileSync(gui.App.argv[0], encoding='utf-8'));
setTimeout(function() {
// Connect to helper
var socket = new WebSocket('ws://localhost:' + cnf['port']);
socket.onopen = function() {
console.log('Connecting to helper');
this.send(cnf['token']);
}
socket.onmessage = function(e) {
console.log('message', e.data);
};
socket.onerror = function () {
console.log('GUI and helper cannot communicate, quiting');
gui.Window.get().close();
}
// Connect to helper
var socket = new WebSocket(cnf['address']);
socket.onopen = function() {
console.log('Connecting to helper');
this.send(cnf['token']);
}
socket.onmessage = function(e) {
console.log('message', e.data);
};
socket.onerror = function () {
console.log('GUI and helper cannot communicate, quiting');
gui.Window.get().close();
}
// Setup GUI
var windows = {
"settings": null,
"about": null,
"index": gui.Window.get()
}
function closeWindows() {
for (win in windows) if (windows[win]) windows[win].close();
}
// Setup GUI
var windows = {
"settings": null,
"about": null,
"index": gui.Window.get()
}
function closeWindows() {
for (win in windows) if (windows[win]) windows[win].close();
}
// GUI components
var tray = new gui.Tray({
tooltip: 'Paused (0% synced)',
title: 'Agkyra syncs with Pithos+',
icon: 'icons/tray.png'
});
// GUI components
var tray = new gui.Tray({
tooltip: 'Paused (0% synced)',
title: 'Agkyra syncs with Pithos+',
icon: 'icons/tray.png'
});
var menu = new gui.Menu();
var menu = new gui.Menu();
// See contents
menu.append(new gui.MenuItem({type: 'separator'}));
menu.append(new gui.MenuItem({
label: 'Open local folder',
icon: 'icons/folder.png',
click: function () {gui.Shell.showItemInFolder('.');}
}));
// See contents
menu.append(new gui.MenuItem({type: 'separator'}));
menu.append(new gui.MenuItem({
label: 'Open local folder',
icon: 'icons/folder.png',
click: function () {gui.Shell.showItemInFolder('.');}
}));
menu.append(new gui.MenuItem({
label: 'Launch Pithos+ page',
icon: 'icons/pithos.png',
click: function () {
gui.Shell.openExternal('https://pithos.okeanos.grnet.gr');
}
}));
menu.append(new gui.MenuItem({
label: 'Launch Pithos+ page',
icon: 'icons/pithos.png',
click: function () {
gui.Shell.openExternal('https://pithos.okeanos.grnet.gr');
}
}));
menu.append(new gui.MenuItem({
label: 'Recently changed files',
icon: 'icons/logs.png',
click: function () {gui.Shell.openItem('logs.txt');}
}));
menu.append(new gui.MenuItem({
label: 'Recently changed files',
icon: 'icons/logs.png',
click: function () {gui.Shell.openItem('logs.txt');}
}));
// Settings and About
menu.append(new gui.MenuItem({type: 'separator'}));
menu.append(new gui.MenuItem({
label: 'Settings',
icon: 'icons/settings.png',
click: function () {
if (windows['settings']) windows['settings'].close();
windows['settings'] = gui.Window.open("settings.html", {
"toolbar": false, "focus": true});
}
}));
// Settings and About
menu.append(new gui.MenuItem({type: 'separator'}));
menu.append(new gui.MenuItem({
label: 'Settings',
icon: 'icons/settings.png',
click: function () {
if (windows['settings']) windows['settings'].close();
windows['settings'] = gui.Window.open("settings.html", {
"toolbar": false, "focus": true});
}
}));
menu.append(new gui.MenuItem({
label: 'About',
icon: 'icons/about.png',
click: function () {
if (windows['about']) windows['about'].close();
windows['about'] = gui.Window.open("about.html", {
"toolbar": false, "resizable": false, "focus": true});
}
}));
menu.append(new gui.MenuItem({
label: 'About',
icon: 'icons/about.png',
click: function () {
if (windows['about']) windows['about'].close();
windows['about'] = gui.Window.open("about.html", {
"toolbar": false, "resizable": false, "focus": true});
}
}));
// Quit
menu.append(new gui.MenuItem({type: 'separator'}));
menu.append(new gui.MenuItem({
label: 'Quit Agkyra',
icon: 'icons/exit.png',
click: function () {
console.log('Exiting client');
console.log('Exiting GUI');
closeWindows()
}
}));
// Quit
menu.append(new gui.MenuItem({type: 'separator'}));
menu.append(new gui.MenuItem({
label: 'Quit Agkyra',
icon: 'icons/exit.png',
click: function () {
console.log('Exiting client');
console.log('Exiting GUI');
closeWindows()
}
}));
tray.menu = menu;
}, 100); // Timeout in milliseconds
tray.menu = menu;
......@@ -36,6 +36,14 @@ class WebSocketProtocol(WebSocket):
{"ERROR": <error code>, "MESSAGE": <message>}
"""
def __init__(self, *args, **kwargs):
super(WebSocketProtocol, self).__init__(*args, **kwargs)
print 'lala'
token = None
def opened(self):
print 'A connection is open', self.token
def closed(self, *args):
print 'A connection is closed', args
def received_message(self, message):
print 'Got message', message
self.send(message)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment