import logging
import os
import pickle
import pwd
import socket
import time
import gevent
import gevent.server
from mxcubecore.BaseHardwareObjects import Procedure
from mxcubecore.utils import qt_import
"""
<procedure class="InstanceServer">
<host>myhostname</host>
<port>myport</port>
</procedure>
"""
TERMINATOR = "\0"
INSTANCE_HO = None
SERVER_CLIENTS = {}
CLIENTS = {}
###
# Creates an asynchronous TCP server to manage multiple application instances
###
[docs]class QtInstanceServer(Procedure):
# Initializes the hardware object
[docs] def init(self):
# Read the HO configuration
self.serverPort = self.get_property("port")
self.serverHost = self.get_property("host")
if self.serverHost is None:
self.serverHost = socket.getfqdn("")
self.asyncServer = None
self.instanceClient = None
self.guiConfiguration = None
self.idCount = {} # server only
self.clients = {} # server only
# self.serverId = None # to remove
# self.controlId = None # to remove
# self.myProposal = None # to remove
self.clientId2 = [None, None] # client only
self.serverId2 = [None, None] # client AND server
self.controlId2 = [None, None] # client AND server
self.bricksEventCache = {}
global INSTANCE_HO
INSTANCE_HO = self
# Check the HO configuration
if self.serverPort is None:
self.log.error("InstanceServer: you must specify a port number")
else:
pass
def initialize_instance(self):
for widget in qt_import.QApplication.allWidgets():
try:
if hasattr(widget, "configuration"):
self.guiConfiguration = widget.configuration
break
except NameError:
logging.getLogger().warning(
"Widget {} has no attribute {}".format(widget, "configuration")
)
self.emit("instanceInitializing", ())
if self.isLocal():
self.startServer()
else:
self.connectToServer()
def setProposal(self, proposal):
if self.isServer():
my_id = self.serverId2[0]
old_proposal = self.serverId2[1]
msg = NewClientInstanceMessage()
msg.setClientId(my_id)
msg.setAvailable(True)
msg.setProposal(old_proposal)
msg.setNewProposal(proposal)
data = msg.encode()
broadcast_to_clients(data)
self.serverId2[1] = proposal
if self.controlId2[0] == my_id:
self.controlId2[1] = proposal
elif self.isClient():
my_id = self.clientId2[0]
msg = NewClientInstanceMessage()
msg.setNewProposal(proposal)
data = msg.encode()
send_data_to_server(self.instanceClient, data)
self.clientId2[1] = proposal
if self.controlId2[0] == my_id:
self.controlId2[1] = proposal
def idPrettyPrint(self, user_id, use_proposal=True):
my_nick = ""
pretty_print = ""
if self.isServer():
my_nick = self.serverId2[0]
elif self.isClient():
my_nick = self.clientId2[0]
else:
self.log.warning(
"InstanceServer: printing an id while not server nor client"
)
if user_id is None:
pretty_print = my_nick
else:
nick = user_id[0]
prop = user_id[1]
if my_nick != nick:
if use_proposal:
if prop is not None:
pretty_print = "[%s%s]%s" % (prop["code"], prop["number"], nick)
else:
pretty_print = "[?]%s" % nick
else:
pretty_print = nick
else:
pretty_print = my_nick
return pretty_print
# Starts the server
def startServer(self):
if self.asyncServer is not None:
self.log.error("InstanceServer: server already started")
elif self.serverPort is not None:
try:
async_server = gevent.server.StreamServer(
(self.serverHost, self.serverPort), handleRemoteClient
) # AsyncServer(self,self.serverHost,self.serverPort)
async_server.start()
except Exception:
self.log.warning(
"InstanceServer: cannot create server, so trying to connect to it"
)
self.connectToServer()
else:
self.asyncServer = async_server
server_hostname = self.serverHost.split(".")[0]
self.log.debug(
"InstanceServer: listening to connections on %s:%d"
% (server_hostname, self.serverPort)
)
self.serverId2[0] = server_hostname
self.controlId2 = list(self.serverId2)
self.idCount[server_hostname] = 1
self.emit("serverInitialized", (True, self.serverId2))
else:
self.log.error(
"InstanceServer: not property configured to start the server"
)
self.emit("serverInitialized", (False,))
# Closes the server
def closeServer(self):
self.asyncServer.close()
self.asyncServer = None
def connectToServer(self, quiet=False):
self.emit("clientInitialized", (None,))
self.reconnect(quiet)
# Connects to the server
def reconnect(self, quiet=False):
try:
self.instanceClient = InstanceClient(self.serverHost, self.serverPort)
except Exception:
self.instanceClient = None
if not quiet:
self.log.error("InstanceServer: cannot connect to server")
self.emit("clientInitialized", (False, (None, None), None, quiet))
else:
my_login = pwd.getpwuid(os.getuid())[0]
msg = AskPermissionInstanceMessage()
msg.setClientId(my_login)
msg.setProposal(self.clientId2[1])
data = msg.encode()
send_data_to_server(self.instanceClient, data)
def isLocal(self):
try:
display = os.environ["DISPLAY"].split(":")[0]
except Exception:
return False
if not display:
return True
return socket.getfqdn(display) == self.serverHost
def isServer(self):
return self.asyncServer is not None
def isClient(self):
return self.instanceClient is not None
def inControl(self):
return self.controlId2
def serverClosed(self):
self.log.error("InstanceServer: server has closed the connection!")
self.emit("serverClosed", (self.serverId2,))
def clientConnected(self, addr, req_handler):
return
def clientClosed(self, addr):
# print "CLIENT CLOSED",addr,self.clients
found_id = None
found_prop = None
for cli_id in self.clients:
cli_addr = self.clients[cli_id][0]
cli_prop = self.clients[cli_id][1]
if cli_addr == addr:
self.clients.pop(cli_id)
found_id = cli_id
found_prop = cli_prop
self.emit("clientClosed", ((cli_id, cli_prop),))
break
if found_id is not None:
msg = NewClientInstanceMessage()
msg.setClientId(found_id)
msg.setProposal(found_prop)
msg.setAvailable(False)
data = msg.encode()
broadcast_to_clients(data)
if self.controlId2[0] == found_id:
self.controlId2 = list(self.serverId2)
msg = PassControlInstanceMessage()
msg.setClientId(self.controlId2[0])
msg.setProposal(self.controlId2[1])
data = msg.encode()
broadcast_to_clients(data)
self.emit("haveControl", (True,))
def requestIdChange(self, new_id):
if self.isServer():
msg = NewClientInstanceMessage()
try:
count = self.idCount[new_id]
except KeyError:
self.idCount[new_id] = 1
else:
count += 1
self.idCount[new_id] = count
new_id = "%s-%d" % (new_id, count)
self.idCount[new_id] = 1
msg.setClientNewId(new_id)
msg.setClientId(self.serverId2[0])
msg.setAvailable(True)
msg.setProposal(self.serverId2[1])
data = msg.encode()
broadcast_to_clients(data)
old_id = self.serverId2[0]
old_prop = self.serverId2[1]
self.serverId2[0] = new_id
if self.controlId2[0] == old_id:
self.controlId2[0] = new_id
new_prop = old_prop
self.emit("clientChanged", ((old_id, old_prop), (new_id, new_prop)))
elif self.isClient():
msg = NewClientInstanceMessage()
msg.setClientNewId(new_id)
data = msg.encode()
send_data_to_server(self.instanceClient, data)
else:
self.log.warning(
"InstanceServer: requestIdChange while not server nor client!"
)
def sendChatMessage(self, priority, message):
msg = ChatInstanceMessage()
msg.setChatMessage(priority, message)
if self.isServer():
msg.setChatNick(self.serverId2[0])
msg.setProposal(self.serverId2[1])
my_id = self.serverId2
data = msg.encode()
if self.isServer():
broadcast_to_clients(data)
elif self.isClient():
send_data_to_server(self.instanceClient, data)
my_id = self.clientId2
else:
self.log.warning(
"InstanceServer: sendChatMessage while not server nor client!"
)
self.emit("chatMessageReceived", (priority, my_id, message))
def addEventToCache(self, brick_name, widget_name, message_data):
self.bricksEventCache[(brick_name, widget_name)] = message_data
def synchronizeClientWithEvents(self, client_addr):
for event_data in list(self.bricksEventCache.values()):
send_data_to_client(client_addr, event_data)
def sendBrickUpdateMessage(
self, brick_name, widget_name, widget_method, widget_method_args, masterSync
):
msg = BrickUpdateInstanceMessage()
msg.setBrickUpdate(
brick_name, widget_name, widget_method, widget_method_args, masterSync
)
data = msg.encode()
if self.isServer():
self.addEventToCache(brick_name, widget_name, data)
broadcast_to_clients(data)
elif self.isClient():
send_data_to_server(self.instanceClient, data)
else:
self.log.warning(
"InstanceServer: sendBrickUpdateMessage while not server nor client!"
)
def sendTabUpdateMessage(self, tab_name, tab_index):
msg = TabUpdateInstanceMessage()
msg.setTabUpdate(tab_name, tab_index)
data = msg.encode()
self.addEventToCache(None, tab_name, data)
if self.isServer():
broadcast_to_clients(data)
elif self.isClient():
send_data_to_server(self.instanceClient, data)
else:
self.log.warning(
"InstanceServer: sendTabUpdateMessage while not server nor client!"
)
def giveControl(self, client_id):
if self.isServer():
try:
client_addr = self.clients[client_id[0]][0]
except KeyError:
pass
else:
client_prop = self.clients[client_id[0]][1]
self.controlId2 = [client_id[0], client_prop]
msg = ControlInstanceMessage()
msg.setHasControl(True)
data = msg.encode()
send_data_to_client(client_addr, data)
msg = PassControlInstanceMessage()
msg.setClientId(client_id[0])
msg.setProposal(client_prop)
data = msg.encode()
broadcast_to_clients(data, avoid=(client_addr,))
self.emit("passControl", ((client_id[0], client_prop),))
self.emit("haveControl", (False,))
elif self.isClient():
msg = PassControlInstanceMessage()
msg.setClientId(client_id[0])
msg.setProposal(client_id[1])
data = msg.encode()
send_data_to_server(self.instanceClient, data)
else:
self.log.warning("InstanceServer: giveControl while not server nor client!")
def askForControl(self):
msg = AskControlInstanceMessage()
if self.isClient():
data = msg.encode()
send_data_to_server(self.instanceClient, data)
else:
msg.setClientId(self.serverId2[0])
msg.setProposal(self.serverId2[1])
data = msg.encode()
broadcast_to_clients(data)
def takeControl(self):
if self.isServer():
if self.controlId2[0] != self.serverId2[0]:
client_addr = self.clients[self.controlId2[0]][0]
msg = ControlInstanceMessage()
msg.setHasControl(False)
data = msg.encode()
send_data_to_client(client_addr, data)
self.controlId2 = list(self.serverId2)
msg = PassControlInstanceMessage()
msg.setClientId(self.controlId2[0])
msg.setProposal(self.controlId2[1])
data = msg.encode()
broadcast_to_clients(data)
self.emit("haveControl", (True,))
else:
self.log.warning(
"InstanceServer: takeControl while already in control!"
)
elif self.isClient():
if self.controlId2[0] != self.clientId2[0]:
msg = TakeControlInstanceMessage()
data = msg.encode()
send_data_to_server(self.instanceClient, data)
else:
self.log.warning(
"InstanceServer: takeControl while already in control!"
)
def callInControl(self, brick, method, method_args):
msg = BrickCallInstanceMessage()
brick_name = brick.name()
widget_name = ""
msg.setBrickUpdate(brick_name, widget_name, method, method_args)
data = msg.encode()
if self.isServer():
if self.controlId2[0] != self.serverId2[0]:
client_addr = self.clients[self.controlId2[0]][0]
send_data_to_client(client_addr, data)
else:
self.log.warning(
"InstanceServer: calling a brick while having control!"
)
else:
self.log.warning("InstanceServer: only the server can call a brick!")
def answerToServer(self, brick, method, method_args):
msg = BrickCallInstanceMessage()
brick_name = brick.name()
widget_name = ""
msg.setBrickUpdate(brick_name, widget_name, method, method_args)
data = msg.encode()
if self.isServer():
self.log.warning("InstanceServer: only a client can answer to the server!")
else:
data = msg.encode()
send_data_to_server(self.instanceClient, data)
def parseReceivedMessage(self, data):
# logging.getLogger().debug("******** RECEIVED MESSAGE = %r", data)
msg_obj = None
try:
message = InstanceMessage(data=data)
except Exception:
self.log.exception("InstanceServer: problem parsing received message")
else:
try:
t = message.getType()
except Exception:
self.log.exception("InstanceServer: problem parsing received message")
else:
if t == InstanceMessage.TYPE_CHAT:
msg_obj = ChatInstanceMessage(message)
elif t == InstanceMessage.TYPE_CONTROL:
msg_obj = ControlInstanceMessage(message)
elif t == InstanceMessage.TYPE_ASKPERMISSION:
msg_obj = AskPermissionInstanceMessage(message)
elif t == InstanceMessage.TYPE_GIVEPERMISSION:
msg_obj = GivePermissionInstanceMessage(message)
elif t == InstanceMessage.TYPE_NEWCLIENT:
msg_obj = NewClientInstanceMessage(message)
elif t == InstanceMessage.TYPE_ASKCONTROL:
msg_obj = AskControlInstanceMessage(message)
elif t == InstanceMessage.TYPE_PASSCONTROL:
msg_obj = PassControlInstanceMessage(message)
elif t == InstanceMessage.TYPE_BRICKUPDATE:
msg_obj = BrickUpdateInstanceMessage(message)
elif t == InstanceMessage.TYPE_TABUPDATE:
msg_obj = TabUpdateInstanceMessage(message)
elif t == InstanceMessage.TYPE_TAKECONTROL:
msg_obj = TakeControlInstanceMessage(message)
elif t == InstanceMessage.TYPE_BRICKCALL:
msg_obj = BrickCallInstanceMessage(message)
else:
self.log.warning(
"InstanceServer: unknown message type %s " % str(t)
)
return msg_obj
def clientMessageReceived(self, data):
m = self.parseReceivedMessage(data)
if m is None:
return
if isinstance(m, ChatInstanceMessage):
self.emit(
"chatMessageReceived",
(
m.getChatPriority(),
(m.getChatNick(), m.getProposal()),
m.getChatMessage(),
),
)
elif isinstance(m, ControlInstanceMessage):
has_control = m.getHasControl()
self.emit("haveControl", (has_control,))
elif isinstance(m, NewClientInstanceMessage):
client_id = m.getClientId()
client_proposal = m.getProposal()
try:
new_client_id = m.getClientNewId()
except KeyError:
try:
new_proposal = m.getNewProposal()
except KeyError:
a = m.getAvailable()
if a:
self.emit("newClient", ((client_id, client_proposal),))
else:
self.emit("clientClosed", ((client_id, client_proposal),))
else:
if client_id == self.serverId2[0]:
self.serverId2[1] = new_proposal
self.emit(
"clientChanged",
((client_id, client_proposal), (client_id, new_proposal)),
)
else:
if client_id == self.serverId2[0]:
self.serverId2[0] = new_client_id
self.emit(
"clientChanged",
((client_id, client_proposal), (new_client_id, client_proposal)),
)
elif isinstance(m, GivePermissionInstanceMessage):
self.serverId2 = [m.getServerId(), m.getProposal()]
self.clientId2[0] = m.getClientId()
self.emit(
"clientInitialized",
(True, (m.getServerId(), m.getProposal()), m.getClientId()),
)
elif isinstance(m, AskControlInstanceMessage):
client_id = m.getClientId()
try:
client_prop = m.getProposal()
except Exception:
client_prop = None
self.emit("wantsControl", ((client_id, client_prop),))
elif isinstance(m, PassControlInstanceMessage):
client_id = m.getClientId()
client_proposal = m.getProposal()
self.controlId2 = [client_id, client_proposal]
self.emit("passControl", ((client_id, client_proposal),))
elif isinstance(m, BrickCallInstanceMessage):
try:
timestamp = m.getTimestamp()
brick_name = m.getBrickName()
widget_name = m.getWidgetName()
widget_method = m.getWidgetMethod()
widget_method_args = m.getWidgetMethodArgs()
brick = self.guiConfiguration.findItem(brick_name).brick
if widget_name == "":
exec("method=brick.%s" % widget_method)
else:
exec("method=brick.%s.%s" % (widget_name, widget_method))
self.emit("widgetCall", (timestamp, method, widget_method_args))
except Exception:
self.log.exception("InstanceServer: problem while calling a brick!")
elif isinstance(m, BrickUpdateInstanceMessage):
try:
timestamp = m.getTimestamp()
brick_name = m.getBrickName()
widget_name = m.getWidgetName()
widget_method = m.getWidgetMethod()
widget_method_args = m.getWidgetMethodArgs()
masterSync = m.getMasterSync()
# if necessary check this with Qt3 version
brick = self.guiConfiguration.findItem(brick_name).get("brick")
if widget_name == "":
exec("method=brick.%s" % widget_method)
else:
exec("method=brick.%s.%s" % (widget_name, widget_method))
self.emit(
"widgetUpdate", (timestamp, method, widget_method_args, masterSync)
)
except Exception:
self.log.exception("InstanceServer: problem while updating a brick!")
elif isinstance(m, TabUpdateInstanceMessage):
try:
timestamp = m.getTimestamp()
tab_name = m.getTabName()
tab_index = m.getTabIndex()
tab = self.guiConfiguration.findItem(tab_name).widget
method = tab.setCurrentPage
method_args = (tab_index,)
self.emit("widgetUpdate", (timestamp, method, method_args))
except Exception:
self.log.exception("InstanceServer: problem while updating a tab!")
def serverMessageReceived(self, client_addr, data):
m = self.parseReceivedMessage(data)
if m is None:
return
if isinstance(m, NewClientInstanceMessage):
try:
client_new_id = m.getClientNewId()
except KeyError:
new_proposal = m.getNewProposal()
# print "SERVER NEWCLIENT PROPOSAL",new_proposal,self.clients
found_id = None
for cli_id in self.clients:
cli_addr = self.clients[cli_id][0]
if cli_addr == client_addr:
found_id = cli_id
cli_prop = self.clients[cli_id][1]
msg = NewClientInstanceMessage()
msg.setClientId(cli_id)
msg.setProposal(cli_prop)
msg.setNewProposal(new_proposal)
msg.setAvailable(True)
data = msg.encode()
broadcast_to_clients(data)
self.emit(
"clientChanged",
((cli_id, cli_prop), (cli_id, new_proposal)),
)
break
if found_id is not None:
if self.controlId2[0] == found_id:
self.controlId2[1] = new_proposal
self.clients[cli_id][1] = new_proposal
else:
try:
count = self.idCount[client_new_id]
except KeyError:
self.idCount[client_new_id] = 1
else:
count += 1
self.idCount[client_new_id] = count
client_new_id = "%s-%d" % (client_new_id, count)
self.idCount[client_new_id] = 1
found_id = None
for cli_id in self.clients:
cli_addr = self.clients[cli_id][0]
if cli_addr == client_addr:
found_id = cli_id
cli_prop = self.clients[cli_id][1]
msg = NewClientInstanceMessage()
msg.setClientId(cli_id)
msg.setClientNewId(client_new_id)
msg.setProposal(cli_prop)
msg.setAvailable(True)
data = msg.encode()
broadcast_to_clients(data)
self.emit(
"clientChanged",
((cli_id, cli_prop), (client_new_id, cli_prop)),
)
break
if found_id is not None:
if self.controlId2[0] == found_id:
self.controlId2[0] = client_new_id
self.clients[client_new_id] = self.clients[found_id]
self.clients.pop(found_id)
elif isinstance(m, AskPermissionInstanceMessage):
client_id = m.getClientId()
client_proposal = m.getProposal()
try:
count = self.idCount[client_id]
except KeyError:
self.idCount[client_id] = 1
else:
count += 1
self.idCount[client_id] = count
client_id = "%s-%d" % (client_id, count)
self.idCount[client_id] = 1
self.clients[client_id] = [client_addr, client_proposal]
msg = NewClientInstanceMessage()
msg.setClientId(client_id)
msg.setProposal(client_proposal)
msg.setAvailable(True)
data = msg.encode()
broadcast_to_clients(data, avoid=(client_addr,))
for cli_id in self.clients:
if cli_id != client_id:
msg = NewClientInstanceMessage()
cli_addr = self.clients[cli_id][0]
cli_prop = self.clients[cli_id][1]
msg.setClientId(cli_id)
msg.setProposal(cli_prop)
msg.setAvailable(True)
data = msg.encode()
send_data_to_client(client_addr, data)
self.synchronizeClientWithEvents(client_addr)
msg = GivePermissionInstanceMessage()
msg.setClientId(client_id)
msg.setServerId(self.serverId2[0])
msg.setProposal(self.serverId2[1])
data = msg.encode()
send_data_to_client(client_addr, data)
msg = PassControlInstanceMessage()
msg.setClientId(self.controlId2[0])
msg.setProposal(self.controlId2[1])
data = msg.encode()
send_data_to_client(client_addr, data)
self.emit("newClient", ((client_id, client_proposal),))
elif isinstance(m, ChatInstanceMessage):
found_id = None
for cli_id in self.clients:
cli_addr = self.clients[cli_id][0]
if cli_addr == client_addr:
found_id = cli_id
found_prop = self.clients[cli_id][1]
if found_id is not None:
m.setChatNick(found_id)
m.setProposal(found_prop)
data = m.encode()
broadcast_to_clients(data, avoid=(client_addr,))
self.emit(
"chatMessageReceived",
(m.getChatPriority(), (found_id, found_prop), m.getChatMessage()),
)
elif isinstance(m, AskControlInstanceMessage):
found_id = None
found_prop = None
for cli_id in self.clients:
cli_addr = self.clients[cli_id][0]
if cli_addr == client_addr:
found_id = cli_id
found_prop = self.clients[cli_id][1]
if found_id is not None:
m.setClientId(found_id)
if found_prop is not None:
m.setProposal(found_prop)
data = m.encode()
broadcast_to_clients(data)
self.emit("wantsControl", ((found_id, found_prop),))
elif isinstance(m, PassControlInstanceMessage):
client_id = m.getClientId()
if self.serverId2[0] == client_id:
self.takeControl()
else:
try:
cli_addr = self.clients[client_id][0]
except KeyError:
pass
else:
client_prop = self.clients[client_id][1]
msg = ControlInstanceMessage()
msg.setHasControl(False)
data = msg.encode()
send_data_to_client(client_addr, data)
msg = PassControlInstanceMessage()
msg.setClientId(client_id)
msg.setProposal(client_prop)
data = msg.encode()
broadcast_to_clients(data, avoid=(cli_addr,))
self.controlId2 = [client_id, client_prop]
self.emit("passControl", ((client_id, client_prop),))
msg = ControlInstanceMessage()
msg.setHasControl(True)
data = msg.encode()
send_data_to_client(cli_addr, data)
elif isinstance(m, BrickCallInstanceMessage):
try:
timestamp = m.getTimestamp()
brick_name = m.getBrickName()
widget_name = m.getWidgetName()
widget_method = m.getWidgetMethod()
widget_method_args = m.getWidgetMethodArgs()
brick = self.guiConfiguration.findItem(brick_name).brick
if widget_name == "":
exec("method=brick.%s" % widget_method)
else:
exec("method=brick.%s.%s" % (widget_name, widget_method))
self.emit("widgetCall", (timestamp, method, widget_method_args))
except Exception:
self.log.exception("InstanceServer: problem while calling a brick!")
elif isinstance(m, BrickUpdateInstanceMessage):
broadcast_to_clients(data, avoid=(client_addr,))
try:
timestamp = m.getTimestamp()
brick_name = m.getBrickName()
widget_name = m.getWidgetName()
widget_method = m.getWidgetMethod()
widget_method_args = m.getWidgetMethodArgs()
brick = self.guiConfiguration.findItem(brick_name).brick
masterSync = m.getMasterSync()
if widget_name == "":
exec("method=brick.%s" % widget_method)
else:
exec("method=brick.%s.%s" % (widget_name, widget_method))
self.emit(
"widgetUpdate", (timestamp, method, widget_method_args, masterSync)
)
except Exception:
self.log.exception("InstanceServer: problem while updating a brick!")
elif isinstance(m, TabUpdateInstanceMessage):
broadcast_to_clients(data, avoid=(client_addr,))
try:
timestamp = m.getTimestamp()
tab_name = m.getTabName()
tab_index = m.getTabIndex()
tab = self.guiConfiguration.findItem(tab_name).widget
method = tab.setCurrentPage
method_args = (tab_index,)
self.emit("widgetUpdate", (timestamp, method, method_args))
except Exception:
self.log.exception("InstanceServer: problem while updating a tab!")
elif isinstance(m, TakeControlInstanceMessage):
found_id = None
found_prop = None
for cli_id in self.clients:
cli_addr = self.clients[cli_id][0]
if cli_addr == client_addr:
found_id = cli_id
found_prop = self.clients[cli_id][1]
if found_id is not None:
if self.controlId2[0] == self.serverId2[0]:
self.emit("haveControl", (False,))
else:
control_addr = self.clients[self.controlId2[0]][0]
msg = ControlInstanceMessage()
msg.setHasControl(False)
data = msg.encode()
send_data_to_client(control_addr, data)
msg = PassControlInstanceMessage()
msg.setClientId(found_id)
msg.setProposal(found_prop)
data = msg.encode()
broadcast_to_clients(data)
self.controlId2 = [found_id, found_prop]
self.emit("passControl", ((found_id, found_prop),))
msg = ControlInstanceMessage()
msg.setHasControl(True)
data = msg.encode()
send_data_to_client(cli_addr, data)
def handleRemoteClient(client_socket, addr):
SERVER_CLIENTS[addr] = client_socket
INSTANCE_HO.clientConnected(addr, client_socket)
buffer = ""
while True:
data = client_socket.recv(1024)
if data == "":
try:
SERVER_CLIENTS.pop(addr)
except Exception:
# Huh? socket closed but client is not in SERVER_CLIENTS dict!
# just ignore silently
pass
else:
INSTANCE_HO.clientClosed(addr)
break
buffer += data
msgs = buffer.split(TERMINATOR)
buffer = msgs.pop()
for msg in msgs:
INSTANCE_HO.serverMessageReceived(addr, msg)
def broadcast_to_clients(data, avoid=None):
for client_addr in list(SERVER_CLIENTS.keys()):
if avoid and client_addr in avoid:
continue
send_data_to_client(client_addr, data)
def send_data_to_client(client_addr, data):
client_socket = SERVER_CLIENTS.get(client_addr)
if client_socket:
try:
client_socket.sendall("%s%s" % (data, TERMINATOR))
except Exception:
# broken pipe? client disconnected
SERVER_CLIENTS.pop(client_addr)
def InstanceClient(host, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((host, port))
except Exception:
raise
else:
socketName = s.getsockname()
def handle_incoming_data(client_socket):
buffer = ""
while True:
data = client_socket.recv(1024)
if data == "":
INSTANCE_HO.serverClosed()
break
buffer += data
msgs = buffer.split(TERMINATOR)
buffer = msgs.pop()
for msg in msgs:
INSTANCE_HO.clientMessageReceived(msg)
CLIENTS[socketName] = s
gevent.spawn(handle_incoming_data, s)
return socketName
def send_data_to_server(socket_name, data):
client_socket = CLIENTS[socket_name]
client_socket.sendall("%s%s" % (data, TERMINATOR))
class InstanceMessage:
(
TYPE_CHAT,
TYPE_CONTROL,
TYPE_NEWCLIENT,
TYPE_ASKPERMISSION,
TYPE_GIVEPERMISSION,
TYPE_ASKCONTROL,
TYPE_PASSCONTROL,
TYPE_BRICKUPDATE,
TYPE_TABUPDATE,
TYPE_TAKECONTROL,
TYPE_BRICKCALL,
) = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
def __init__(self, data=None):
self.messageDict = {}
if data is not None:
self.messageDict = pickle.loads(data)
def encode(self):
try:
self.messageDict["type"]
except KeyError:
raise ValueError
return pickle.dumps(self.messageDict)
def getType(self):
try:
t = self.messageDict["type"]
except KeyError:
raise ValueError
return t
class ChatInstanceMessage(InstanceMessage):
(PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH) = (0, 1, 2)
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_CHAT
def setChatMessage(self, priority, message):
self.messageDict["priority"] = priority
self.messageDict["message"] = message
def setChatNick(self, nick):
self.messageDict["nick"] = nick
def getChatMessage(self):
return self.messageDict["message"]
def getChatPriority(self):
return self.messageDict["priority"]
def getChatNick(self):
return self.messageDict["nick"]
def setProposal(self, proposal):
self.messageDict["proposal"] = proposal
def getProposal(self):
return self.messageDict["proposal"]
class ControlInstanceMessage(InstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_CONTROL
def setHasControl(self, has_control):
self.messageDict["control"] = has_control
def getHasControl(self):
return self.messageDict["control"]
class PassControlInstanceMessage(InstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_PASSCONTROL
def setClientId(self, client_id):
self.messageDict["client_id"] = client_id
def getClientId(self):
return self.messageDict["client_id"]
def setProposal(self, proposal):
self.messageDict["proposal"] = proposal
def getProposal(self):
return self.messageDict["proposal"]
class AskControlInstanceMessage(InstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_ASKCONTROL
def setClientId(self, client_id):
self.messageDict["client_id"] = client_id
def getClientId(self):
return self.messageDict["client_id"]
def setProposal(self, proposal):
self.messageDict["proposal"] = proposal
def getProposal(self):
return self.messageDict["proposal"]
class AskPermissionInstanceMessage(InstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_ASKPERMISSION
def setClientId(self, client_id):
self.messageDict["client_id"] = client_id
def getClientId(self):
return self.messageDict["client_id"]
def setProposal(self, proposal):
self.messageDict["proposal"] = proposal
def getProposal(self):
return self.messageDict["proposal"]
class GivePermissionInstanceMessage(InstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_GIVEPERMISSION
def setClientId(self, client_id):
self.messageDict["client_id"] = client_id
def getClientId(self):
return self.messageDict["client_id"]
def setServerId(self, server_id):
self.messageDict["server_id"] = server_id
def getServerId(self):
return self.messageDict["server_id"]
def setProposal(self, proposal):
self.messageDict["proposal"] = proposal
def getProposal(self):
return self.messageDict["proposal"]
class NewClientInstanceMessage(InstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_NEWCLIENT
def setClientId(self, client_id):
self.messageDict["client_id"] = client_id
def getClientId(self):
return self.messageDict["client_id"]
def setClientNewId(self, client_new_id):
self.messageDict["client_new_id"] = client_new_id
def getClientNewId(self):
return self.messageDict["client_new_id"]
def setAvailable(self, available):
self.messageDict["available"] = available
def getAvailable(self):
return self.messageDict["available"]
def setProposal(self, proposal):
self.messageDict["proposal"] = proposal
def getProposal(self):
return self.messageDict["proposal"]
def setNewProposal(self, proposal):
self.messageDict["new_proposal"] = proposal
def getNewProposal(self):
return self.messageDict["new_proposal"]
class BrickUpdateInstanceMessage(InstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_BRICKUPDATE
def setBrickUpdate(
self,
brick_name,
widget_name,
widget_method,
widget_method_args,
masterSync=True,
):
self.messageDict["timestamp"] = time.time()
self.messageDict["brick_name"] = brick_name
self.messageDict["widget_name"] = widget_name
self.messageDict["widget_method"] = widget_method
self.messageDict["widget_method_args"] = widget_method_args
self.messageDict["masterSync"] = masterSync
def getTimestamp(self):
return self.messageDict["timestamp"]
def getBrickName(self):
return self.messageDict["brick_name"]
def getWidgetName(self):
return self.messageDict["widget_name"]
def getWidgetMethod(self):
return self.messageDict["widget_method"]
def getWidgetMethodArgs(self):
return self.messageDict["widget_method_args"]
def getMasterSync(self):
return self.messageDict["masterSync"]
class TabUpdateInstanceMessage(InstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_TABUPDATE
def setTabUpdate(self, tab_name, tab_index):
self.messageDict["timestamp"] = time.time()
self.messageDict["tab_name"] = tab_name
self.messageDict["tab_index"] = tab_index
def getTimestamp(self):
return self.messageDict["timestamp"]
def getTabName(self):
return self.messageDict["tab_name"]
def getTabIndex(self):
return self.messageDict["tab_index"]
class TakeControlInstanceMessage(InstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_TAKECONTROL
class BrickCallInstanceMessage(BrickUpdateInstanceMessage):
def __init__(self, instance_message=None):
InstanceMessage.__init__(self)
if instance_message is not None:
self.messageDict = instance_message.messageDict
self.messageDict["type"] = InstanceMessage.TYPE_BRICKCALL