def run(self): """ Continuously verify for the correct operation of the registered clients """ import time while True: #sleep for a while at every loop time.sleep(DirectoryChecker.LOOP_WAIT) #generate the list of registered users users = [i[0] for i in self.__directory.directory_query()] self.__logger.debug("%d users are active" % len(users)) for username in users: #retrieve the bind information for each user res = self.__directory.directory_query(username) username, address, port = res[0] if len(res) == 1 else ( username, None, None) if address != None and port != None: try: self.__logger.debug("connecting to %s:%d" % (address, port)) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((address, port)) #use the protocol wrapper to simplify socket handling proto = ProtocolWrapper(sock, (address, port)) #send a ping, and wait for a pong self.__logger.debug("sending ping") proto.send(p.T_PING) msg = proto.recv() if msg != None and msg.type == p.T_PONG: self.__logger.info("USER %s OK" % username) proto.close() else: raise Exception, "no PONG received" except Exception, e: #client is misbehaving, deregister it self.__logger.error("USER %s ERROR (%s)" % (username, str(e))) self.__directory.directory_deregister(username)
def run(self): """ Continuously verify for the correct operation of the registered clients """ import time while True: #sleep for a while at every loop time.sleep(DirectoryChecker.LOOP_WAIT) #generate the list of registered users users=[i[0] for i in self.__directory.directory_query()] self.__logger.debug("%d users are active"%len(users)) for username in users: #retrieve the bind information for each user res=self.__directory.directory_query(username) username,address,port=res[0] if len(res)==1 else (username,None,None) if address!=None and port!=None: try: self.__logger.debug("connecting to %s:%d"%(address,port)) sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.connect((address,port)) #use the protocol wrapper to simplify socket handling proto=ProtocolWrapper(sock,(address,port)) #send a ping, and wait for a pong self.__logger.debug("sending ping") proto.send(p.T_PING) msg=proto.recv() if msg!=None and msg.type==p.T_PONG: self.__logger.info("USER %s OK"%username) proto.close() else: raise Exception, "no PONG received" except Exception,e: #client is misbehaving, deregister it self.__logger.error("USER %s ERROR (%s)"%(username,str(e))) self.__directory.directory_deregister(username)
class DirectoryClient(threading.Thread): """ Separate thread in charge of the communication with each client. """ def __init__(self,directory,clisock,addrinfo): """ The thread takes as input three arguments: 1) the instance of the directory object that accepted the connection 2) the connected socket associated with the client 3) the address info tuple """ threading.Thread.__init__(self) self.username=None self.password=None self.bind_address=None self.bind_port=None self.__directory=directory self.__protocol=ProtocolWrapper(clisock,addrinfo) #we are not interested in joining these threads self.daemon=True #the logger self.__logger=logging.getLogger("client") def __port_test(self): """ Simple check to ensure the reachability of a client before registering it to the directory service. """ try: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((self.bind_address,self.bind_port)) s.close() self.__logger.debug("port test successful %s"%self.username) return True except socket.error: self.__logger.error("port test failed %s"%self.username) return False def run(self): """ The thread executes here. """ #user authentication try: #get the username msg=self.__protocol.recv(True) if msg==None or msg.type!=p.T_USER or len(msg.args)!=1: return self.__protocol.close("a 'USER <username>' command was expected!") self.username=msg.args[0] if not self.__protocol.send(p.T_ACK,[],"hi %s, authentication required"%self.username): return self.__protocol.close() #get the password msg=self.__protocol.recv(True) if msg==None or msg.type!=p.T_PASS or len(msg.args)!=1: return self.__protocol.close("a 'PASS <password>' command was expected!") self.password=msg.args[0] if self.__directory.directory_login(self.username, self.password): if not self.__protocol.send(p.T_ACK,[],"successfully authenticated"): return self.__protocol.close() else: return self.__protocol.close("authentication failed") #if we are here, we are successfully authenticated #from now on, the client can send any sequence of queries, bind or leave commands while True: msg=self.__protocol.recv() if msg==None: return self.__protocol.close() #connection was closed by client if msg.type==p.T_BIND and len(msg.args)==2: self.bind_address=msg.args[0] self.bind_port=int(msg.args[1]) if self.__port_test(): self.__directory.directory_register(self.username, self.bind_address, self.bind_port) if not self.__protocol.send(p.T_ACK,[],"bound successfully to %s:%d"%(self.bind_address,self.bind_port)): return self.__protocol.close() else: return self.__protocol.close("invalid bind notification") elif msg.type==p.T_QUERY and len(msg.args)<=1: username=msg.args[0] if len(msg.args)==1 else None result=self.__directory.directory_query(username) payload="\n".join(["%s,%s,%d"%i for i in result]) if not self.__protocol.send(p.T_RESULT,[],payload): self.__protocol.close() elif msg.type==p.T_LEAVE and len(msg.args)==0: self.__directory.directory_deregister(self.username) if not self.__protocol.send(p.T_ACK,[],"deregistered from directory"): return self.__protocol.close() else: return self.__protocol.close("I did not understand the message %s"%msg.type) except socket.timeout: self.__protocol.close("shutting down idle connection (timeout)") except: self.__protocol.close("unexpected error") self.__logger.exception("something unexpected went wrong!")
class DirectoryClient(threading.Thread): """ Separate thread in charge of the communication with each client. """ def __init__(self, directory, clisock, addrinfo): """ The thread takes as input three arguments: 1) the instance of the directory object that accepted the connection 2) the connected socket associated with the client 3) the address info tuple """ threading.Thread.__init__(self) self.username = None self.password = None self.bind_address = None self.bind_port = None self.__directory = directory self.__protocol = ProtocolWrapper(clisock, addrinfo) #we are not interested in joining these threads self.daemon = True #the logger self.__logger = logging.getLogger("client") def __port_test(self): """ Simple check to ensure the reachability of a client before registering it to the directory service. """ try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((self.bind_address, self.bind_port)) s.close() self.__logger.debug("port test successful %s" % self.username) return True except socket.error: self.__logger.error("port test failed %s" % self.username) return False def run(self): """ The thread executes here. """ #user authentication try: #get the username msg = self.__protocol.recv(True) if msg == None or msg.type != p.T_USER or len(msg.args) != 1: return self.__protocol.close( "a 'USER <username>' command was expected!") self.username = msg.args[0] if not self.__protocol.send( p.T_ACK, [], "hi %s, authentication required" % self.username): return self.__protocol.close() #get the password msg = self.__protocol.recv(True) if msg == None or msg.type != p.T_PASS or len(msg.args) != 1: return self.__protocol.close( "a 'PASS <password>' command was expected!") self.password = msg.args[0] if self.__directory.directory_login(self.username, self.password): if not self.__protocol.send(p.T_ACK, [], "successfully authenticated"): return self.__protocol.close() else: return self.__protocol.close("authentication failed") #if we are here, we are successfully authenticated #from now on, the client can send any sequence of queries, bind or leave commands while True: msg = self.__protocol.recv() if msg == None: return self.__protocol.close( ) #connection was closed by client if msg.type == p.T_BIND and len(msg.args) == 2: self.bind_address = msg.args[0] self.bind_port = int(msg.args[1]) if self.__port_test(): self.__directory.directory_register( self.username, self.bind_address, self.bind_port) if not self.__protocol.send( p.T_ACK, [], "bound successfully to %s:%d" % (self.bind_address, self.bind_port)): return self.__protocol.close() else: return self.__protocol.close( "invalid bind notification") elif msg.type == p.T_QUERY and len(msg.args) <= 1: username = msg.args[0] if len(msg.args) == 1 else None result = self.__directory.directory_query(username) payload = "\n".join(["%s,%s,%d" % i for i in result]) if not self.__protocol.send(p.T_RESULT, [], payload): self.__protocol.close() elif msg.type == p.T_LEAVE and len(msg.args) == 0: self.__directory.directory_deregister(self.username) if not self.__protocol.send(p.T_ACK, [], "deregistered from directory"): return self.__protocol.close() else: return self.__protocol.close( "I did not understand the message %s" % msg.type) except socket.timeout: self.__protocol.close("shutting down idle connection (timeout)") except: self.__protocol.close("unexpected error") self.__logger.exception("something unexpected went wrong!")