import socket import ssl import multiprocessing import logging as log from hashtree import hashBlock from netnode import BaseConnection,NetNode import config as conf import status from datafile import DataFile class Connection(BaseConnection): def __init__(self,serverSocket,sslContext): super().__init__() sock, address = serverSocket.accept() try: self._socket=sslContext.wrap_socket(sock,server_side=True) except ssl.SSLError as e: log.warning("Failed to establish an SSL connection from {0}.".format(sock.getpeername())) raise e log.info('Connected by {0}'.format(address)) self.createNetworkers() class Miniserver: def __init__(self,filename,treeFile=""): self._filename=filename self._treeFile=treeFile self._ssl=ssl.create_default_context(ssl.Purpose.CLIENT_AUTH,cafile=conf.peers) self._ssl.verify_mode=ssl.CERT_REQUIRED self._ssl.load_cert_chain(conf.certfile,conf.keyfile) self._ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._ss.bind(("", conf.port)) self._ss.listen(1) def serve(self): p=None with self._ss: while True: try: connection=Connection(self._ss,self._ssl) except ssl.SSLError: continue if p and p.is_alive(): with connection as c: c[0].readMsg() c[1].writeMsg({"command":"deny","status":status.locked}) continue p=multiprocessing.Process(target=Server.run,args=(connection,self._filename,self._treeFile)) p.start() class Server(NetNode): def __init__(self,connection,filename,treeFile=""): super().__init__(filename,treeFile) (self._incoming,self._outcoming)=connection self.BLOCK_SIZE=self._tree.BLOCK_SIZE self._dataFileObj=None @staticmethod def run(connection,*args): with connection as c: s=Server(c,*args) s.serve() @property def _dataFile(self): if not self._dataFileObj: self._dataFileObj=DataFile.open(self._filename, mode="rb+") return self._dataFileObj def serve(self): try: while self._serveOne(): pass except (AssertionError,ConnectionResetError) as e: log.warning(e) def _serveOne(self): jsonData,binData=self._incoming.readMsg() if jsonData["command"]=="init": if jsonData["blockSize"]!=self.BLOCK_SIZE or jsonData["blockCount"]!=self._tree.leafCount: self._outcoming.writeMsg({"command":"deny","status":status.incompatible.parameters}) if jsonData["version"]