import SocketServer import pickle import threading from . import Signal,Status,Query,Answer from . import SERVER_IOFUNCTIONS from . import SERVER_FIGURES from . import MyFig from . import DBUG,WARN,SPCE,SEVR,INFO from . import MplUnpickler G_RAWDATA = dict() G_FIGURES = dict() DEBUG = True debug = True class MplHandler(SocketServer.StreamRequestHandler): def servPrint(self,x) : # This should be replaced with a proper implementation (s.b.) ? print("SERVER: "+x) def dprint(*args): #likewise for WARN,SPCE,SEVR,INFO :wprint,sprint,sevprint,iprint ? argsl = list(args) if type(argsl[0]) is str : argsl[0] = DBUG + argsl[0] print(''.join([repr(arg) for arg in argsl])) def treatReadData(self,content): '''Treat signals of type readData. 1. unpack signal with instruction size, 2. send receipt, 3. unpack instructions, 4. execute instructions, 5. send dataID. ''' # fct = SERVER_IOFUNCTIONS[content.get('func')] fct = self.server.knownFunctions[content.get('func')] args = content.get('args') kwargs = content.get('kwargs') dataName = content.get('dataname') # Try to execute the instructions try: G_RAWDATA[dataName] = fct(*args, **kwargs) if (DEBUG): print(INFO+"SERVER: I read the data following instructions") # print(str(G_RAWDATA[dataName].data)) # SHOULD BE SUPPRESS LATER except: if(DEBUG): print(WARN+"SERVER: The instructions of readData could not be executed.") print(SPCE+"SERVER: I tried: "+str(fct.__name__)+'('+str(args)+', '+str(kwargs)+')') return Status(False,"The instructions of readData could not be executed. I tried: "+str(fct.__name__)+'('+str(args)+', '+str(kwargs)+')') if dataName in G_RAWDATA : return Status(True,"SERVER: I read the data following instructions"+str(fct.__name__)+'('+str(args)+', '+str(kwargs)+')') return False #should never get here def treatNewSyncFigure(self,content) : # Try to create the requested figure FigClass = self.server.knownFigures[content.get('figClassName')] args = content.get('args') kwargs = content.get('kwargs') datanames = content.get('dataName') datas = [G_RAWDATA[name] for name in datanames] try: # create the figure: fig = FigClass(datas, **kwargs) if (DEBUG): print(INFO+"SERVER: I created the requested Figure") except Exception as e: if (DEBUG): print(WARN+"SERVER: I could not create the requested Figure.") print(SPCE+"SERVER: I tried: "+str(FigClass.__name__)+'('+str(datas)+', '+str(kwargs)+')') print(SPCE+"SERVER: Exception details where:",e.message, e.args ) return Status(False, "I could not create the requested Figure. I tried: "+str(FigClass.__name__)+'('+str(datas)+', '+str(kwargs)+')'+" Exception details where:"+str(e.message)+str(e.args)) # add the figure to the global index G_FIGURES[fig.getFigID()] = fig if fig.getFigID() in G_FIGURES : return Answer(fig.getFigID()) def getFigByID(self,figID) : """ Identify the figure by ID and return it. On error it will return a Status Signal""" # Identify the figure fig = G_FIGURES.get(figID,None) if fig is None : if DEBUG: print(WARN+"The figure ID: "+figID+" does not exist.") return Status(False,"The figure ID: "+figID+" does not exist.") elif isinstance(fig,MyFig) : if DEBUG : print('Figure ',figID,' found in database') return fig def treatUpdateSyncFigure(self,content) : """ If client request an update of the keywords of a figure. This function forwards the request to the corresponding figure""" figID,kwargs = content fig = self.getFigByID(figID) # if an error occured forward the signal if isinstance(fig,Signal) : return fig status = fig.update(**kwargs) if status : return Status(True,'Kewords of figure ID: '+figID+' successfully updated') else : return Status(False,'Kewords of figure ID: '+figID+' could not be updated') def treatSyncFigFormatRawData(self,figID): # Identify the figure fig = self.getFigByID(figID) # if an error occured forward the signal if isinstance(fig,Signal) : return fig # Format the rawdata try: fig.formatRawData() except Exception as e: if DEBUG: print(WARN+"I couldn't format the rawdata.") print(SPCE+"SERVER: Exception details where:",e.message, e.args ) return Status(False,"I couldn't format the rawdata. Exception details where:",e.message, e.args) # compose the answer datas = () for ax in fig.get_axes(): # ax.data is any user defined object # ax.packFormattedData returns it's string representation # to be unpacked by ax.unpackFormattedData # datas.append(ax.packFormattedData(ax.data)) datas = datas + (ax.data,) return Answer(datas) def treatDeleteSyncFigure(self,figID) : """ Deletes the figure with ID figID from G_FIGURES """ if figID in G_FIGURES : del G_FIGURES[figID] return Status(True,'Figure with ID '+str(figID)+' deleted from server.') else : return Status(False,'Figure with ID '+str(figID)+' not found on server side.') def send(self,sig): # pickel the signal # send the str wf = self.server.socket.makefile(mode='wb') if debug: print('sending ',type(sig),' with content \"',sig.content,'\"') try : pickle.dump(sig,wf) except Exception as e: if DEBUG: print(SPCE+"SERVER: Exception details where:",e.message, e.args ) return False wf.close() return True def waitForSignal(self): # wait for signal # unpickel rf = self.server.socket.makefile(mode='rb') try : unpickler = MplUnpickler(rf) response = unpickler.load() if DEBUG and isinstance(response,Signal): print('CLIENT Received: {} with content \"{}\"'.format(type(response),response.content)) except EOFError : print('no answer received - or connection closed unexpectedly') response = None except Exception as e: print('unknown error while waiting for response') print(SPCE+"SERVER: Exception details where:",e.message, e.args ) response = None rf.close() if isinstance(response,Signal) : return response def treatSig(self,sig): if isinstance(sig,Query) : if sig.queryType == sig.READDATA : return self.treatReadData(sig.content) elif sig.queryType == sig.NEWSYNCFIGURE : return self.treatNewSyncFigure(sig.content) elif sig.queryType == sig.UPDATESYNCFIGURE : return self.treatUpdateSyncFigure(sig.content) elif sig.queryType == sig.SYNCFIGFORMATRAWDATA : return self.treatSyncFigFormatRawData(sig.content) elif sig.queryType == sig.DELETESYNCFIGURE : return self.treatDeleteSyncFigure(sig.content) else : self.servPrint('received unknown query type') return Status(False,"received unknown query type") elif isinstance(sig, Status) : if sig.value : pass #if it is just a positiv status message do nothing else : self.servPrint('the client Side reported of an error:') self.servPrint('----'+sig.content) elif isinstance(sig, Answer) : #~ #needed for server??? pass elif isinstance(sig, Signal) : self.servPrint('received unknown signal') return Status(False,"received unknown signal") else : self.servPrint('what is happening here??? received Object of type:') self.servPrint(str(sig)) return Status(False,"received something totally diffenent") def handle(self): # self.rfile is a file-like object created by the handler; # we can now use e.g. readline() instead of raw recv() calls ## self.data = self.rfile.readline()#.strip() while self.server.running : unpickler = MplUnpickler(self.rfile) request = unpickler.load() reply = self.treatSig(request) # Likewise, self.wfile is a file-like object used to write back # to the client ## self.wfile.write(self.data.upper()) if isinstance(reply,Signal) : if DEBUG: self.servPrint("returning {}-Signal:".format(type(reply))) pickle.dump(reply,self.wfile) class MplServer2(SocketServer.TCPServer): allow_reuse_address=True # DEFINE KNOWN I/O FUNCTIONS --------------------------------------- def defineKnownFunctions(self, functions): '''Function to overwrite in order to declare the known I/O functions by the server context.''' self.knownFunctions = functions # DEFINE KNOWN FIGURE CLASSES -------------------------------------- def defineKnownFigures(self, figures): '''Function to overwrite in order to declare the known Figure classes by the server context.''' self.knownFigures = figures def __init__(self, ip='', port=52386, handler=MplHandler, knownFunctions=SERVER_IOFUNCTIONS, knownFigures=SERVER_FIGURES) : '''Intialisation of the server, defines known functions, known figure classes. It needs to be called.''' # Define functions and figure classes self.defineKnownFunctions(knownFunctions) self.defineKnownFigures(knownFigures) SocketServer.TCPServer.__init__(self, (ip, port), handler) self.running = False self.initialized = True def run(self, as_daemon=True): self.server_thread = threading.Thread(target=self.serve_forever) self.server_thread.daemon = as_daemon self.server_thread.start() self.running = True def stop(self): # not yet working print('STOPING...') # self.server_thread.stop() self.running = False