class ClientHandler(socketserver.BaseRequestHandler): """ This is the ClientHandler class. Everytime a new client connects to the server, a new ClientHandler object will be created. This class represents only connected clients, and not the server itself. If you want to write logic for the server, you must write it outside this class """ def handle(self): """ This method handles the connection between a client and the server. """ self.ip = self.client_address[0] self.port = self.client_address[1] self.connection = self.request # Init self.messageEncoder = MessageEncoder() self.messageParser = MessageParser() # Loop that listens for messages from the client while True: received_string = self.connection.recv(4096).decode() if received_string == "": self.connection.close() del connected_clients[self.connection] break else: payload = self.messageParser.parse(received_string) if 'login' in payload.keys(): if re.match("^[A-Za-z0-9_-]*$", payload['login']): self.connection.send( self.messageEncoder.encode_history( history).encode()) connected_clients[self.connection] = payload['login'] else: self.connection.send( self.messageEncoder.encode_error( "Invalid username").encode()) elif 'logout' in payload.keys(): self.connection.close() del connected_clients[self.connection] return elif 'message' in payload.keys(): message = self.messageEncoder.encode_message( connected_clients[self.connection], payload['message']) history.append(message) for conn in connected_clients.keys(): conn.send(message.encode()) elif 'names' in payload.keys(): self.connection.send( self.messageEncoder.encode_info(', '.join( connected_clients.values())).encode()) elif 'help' in payload.keys(): self.connection.send( self.messageEncoder.encode_info( "This is the help").encode())
def handle(self): """ This method handles the connection between a client and the server. """ self.ip = self.client_address[0] self.port = self.client_address[1] self.connection = self.request # Init self.messageEncoder = MessageEncoder() self.messageParser = MessageParser() # Loop that listens for messages from the client while True: received_string = self.connection.recv(4096).decode() if received_string == "": self.connection.close() del connected_clients[self.connection] break else: payload = self.messageParser.parse(received_string) if 'login' in payload.keys(): if re.match("^[A-Za-z0-9_-]*$", payload['login']): self.connection.send( self.messageEncoder.encode_history( history).encode()) connected_clients[self.connection] = payload['login'] else: self.connection.send( self.messageEncoder.encode_error( "Invalid username").encode()) elif 'logout' in payload.keys(): self.connection.close() del connected_clients[self.connection] return elif 'message' in payload.keys(): message = self.messageEncoder.encode_message( connected_clients[self.connection], payload['message']) history.append(message) for conn in connected_clients.keys(): conn.send(message.encode()) elif 'names' in payload.keys(): self.connection.send( self.messageEncoder.encode_info(', '.join( connected_clients.values())).encode()) elif 'help' in payload.keys(): self.connection.send( self.messageEncoder.encode_info( "This is the help").encode())
def __init__(self, aCritter): """Initializes the post office. Arguments: aCritter: The critter. """ self.mCritter = aCritter settings = self.mCritter.getSettings() # Configuring the logger. self.mLogger = logging.getLogger(self.__class__.__name__) self.mLogger.propagate = False # TODO: Remove the hardcoded value of the path. handler = logging.FileHandler('/tmp/' + self.mCritter.mCrittnick + '.log') # TODO: Remove the hardcoded value of the formatter. formatter = logging.Formatter('[%(asctime)s][%(threadName)28s][%(levelname)8s] - %(message)s') handler.setFormatter(formatter) self.mLogger.addHandler(handler) self.mLogger.setLevel(self.mCritter.mSettings.get('logging', 'level')) policy = settings.get('crittwork', 'policy') addressPublisher = addressSubscriber = '' # TODO: Now this is an ifology, it should be a real policy. if policy == 'multicast': addressPublisher = addressSubscriber = settings.get('crittwork', 'multicast') elif policy == 'broker': addressPublisher = settings.get('crittwork', 'brokerPublisher') addressSubscriber = settings.get('crittwork', 'brokerSubscriber') else: assert False, "Invalid crittwork policy selected." # TODO: Get from the factory. self.mTransport = TransportZMQ(addressPublisher, addressSubscriber) self.mOutgoingAnnouncementsQueue = Queue() self.mIncomingAnnouncementsQueue = Queue() self.mRiteConnector = RiteConnector(aCritter.mRites) self.mMessageEncoder = MessageEncoder() # Spawning the announcement publisher. self.mLogger.debug("Spawning the announcement publisher.") self.mAnnouncementPublisher = AnnouncementPublisher(self) self.mAnnouncementPublisher.setDaemon(True) # Spawning the announcement subscriber. self.mLogger.debug("Spawning the announcement subscriber.") self.mAnnouncementSubscriber = AnnouncementSubscriber(self) self.mAnnouncementSubscriber.setDaemon(True) # Spawning the message router. # FIXME: Jealous. self.mLogger.debug("Spawning the message router.") self.mMessageRouter = MessageRouter(self) self.mMessageRouter.setDaemon(True)
def __init__(self, host, server_port): """ This method is run when creating a new Client object """ # Set up the socket connection to the server self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Init self.host = host self.server_port = server_port self.state = State.LOGIN; self.messageEncoder = MessageEncoder() self.messageParser = MessageParser() self.username = "" # Run client self.run()
class Client: """ This is the chat client class """ def __init__(self, host, server_port): """ This method is run when creating a new Client object """ # Set up the socket connection to the server self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Init self.host = host self.server_port = server_port self.state = State.LOGIN; self.messageEncoder = MessageEncoder() self.messageParser = MessageParser() self.username = "" # Run client self.run() def run(self): try: # Initiate the connection to the server self.connection.connect((self.host, self.server_port)) messageReceiver = MessageReceiver(self, self.connection) messageReceiver.start() except socket.error as e: sys.exit("Connection to server refused.") while (not self.connection._closed): if self.state == State.LOGIN: print("Username:"******"Disconnected from server") def disconnect(self): self.connection.close() def receive_payload(self, payload): message = self.messageParser.parse(payload) if 'error' in message.keys(): print("Error:", message['error']) self.state = State.LOGIN elif 'info' in message.keys(): print("Info:", message['info']) elif 'message' in message.keys(): if self.state == State.CHATROOM: if message['sender'] != self.username: print(message['sender']+":", message['message']) elif 'history' in message.keys(): print("") print("Welcome", self.username, "to CHATROOM!") for msg in message['history']: if msg['sender'] == self.username: print(msg['message']) else: print(msg['sender']+":", msg['message']) self.state = State.CHATROOM def send_payload(self, payload): if not self.connection._closed: self.connection.send(payload.encode())
class PostOffice(object): """The PostOffice that handles all the communication. Attributes: mCritter: The critter. mIncomingAnnouncementsQueue: The queue of incoming announcements. mLogger: The logger. mMessageEncoder: The message encoder. mOutgoingAnnouncementsQueue: The queue of outgoing announcements. mAnnouncementPublisher: The announcement publisher. mAnnouncementSubscriber: The announcement subscriber. mMessageRouter: The message router. mRiteConnector: The rite connector. mTransport: The transport. """ def __init__(self, aCritter): """Initializes the post office. Arguments: aCritter: The critter. """ self.mCritter = aCritter settings = self.mCritter.getSettings() # Configuring the logger. self.mLogger = logging.getLogger(self.__class__.__name__) self.mLogger.propagate = False # TODO: Remove the hardcoded value of the path. handler = logging.FileHandler('/tmp/' + self.mCritter.mCrittnick + '.log') # TODO: Remove the hardcoded value of the formatter. formatter = logging.Formatter('[%(asctime)s][%(threadName)28s][%(levelname)8s] - %(message)s') handler.setFormatter(formatter) self.mLogger.addHandler(handler) self.mLogger.setLevel(self.mCritter.mSettings.get('logging', 'level')) policy = settings.get('crittwork', 'policy') addressPublisher = addressSubscriber = '' # TODO: Now this is an ifology, it should be a real policy. if policy == 'multicast': addressPublisher = addressSubscriber = settings.get('crittwork', 'multicast') elif policy == 'broker': addressPublisher = settings.get('crittwork', 'brokerPublisher') addressSubscriber = settings.get('crittwork', 'brokerSubscriber') else: assert False, "Invalid crittwork policy selected." # TODO: Get from the factory. self.mTransport = TransportZMQ(addressPublisher, addressSubscriber) self.mOutgoingAnnouncementsQueue = Queue() self.mIncomingAnnouncementsQueue = Queue() self.mRiteConnector = RiteConnector(aCritter.mRites) self.mMessageEncoder = MessageEncoder() # Spawning the announcement publisher. self.mLogger.debug("Spawning the announcement publisher.") self.mAnnouncementPublisher = AnnouncementPublisher(self) self.mAnnouncementPublisher.setDaemon(True) # Spawning the announcement subscriber. self.mLogger.debug("Spawning the announcement subscriber.") self.mAnnouncementSubscriber = AnnouncementSubscriber(self) self.mAnnouncementSubscriber.setDaemon(True) # Spawning the message router. # FIXME: Jealous. self.mLogger.debug("Spawning the message router.") self.mMessageRouter = MessageRouter(self) self.mMessageRouter.setDaemon(True) def start(self): """Starts the post office by starting its threads.""" self.mAnnouncementPublisher.start() self.mAnnouncementSubscriber.start() self.mMessageRouter.start() def encode(self, aData): """A facade method to hide message encoder from clients. Arguments: aData: The dictionary of parameters. Returns: A message. """ return self.mMessageEncoder.encode(aData) def putIntoAnEnvelope(self, aMessage): return self.mMessageEncoder.putIntoAnEnvelope(aMessage) def putIncomingAnnouncement(self, aMessage): """Puts an incoming announcement (in the form of a message) into the queue. Arguments: aMessage The message to be processed. """ self.mIncomingAnnouncementsQueue.put(aMessage) def putOutgoingAnnouncement(self, aMessage): """Puts an outgoing announcement (in the form of a message) into the queue. Arguments: aMessage The message to be sent. """ self.mOutgoingAnnouncementsQueue.put(aMessage) def getIncomingAnnouncement(self): """Gets an incoming announcement (in the form of a message) from the queue. Returns The message to be processed. """ return self.mIncomingAnnouncementsQueue.get() def getOutgoingAnnouncement(self): """Gets an outgoing announcement (in the form of a message) from the queue. Returns The message to be sent. """ return self.mOutgoingAnnouncementsQueue.get() def putCommand(self, aRite, aCommand, aPriority=PRIORITY_DEFAULT): self.mRiteConnector.putCommand(aRite, aCommand, aPriority) def putMessage(self, aRite, aMessage, aPriority=PRIORITY_DEFAULT): self.mRiteConnector.putMessage(aRite, aMessage, aPriority) def addSubscriptionChannel(self, aSubscriptionChannel): self.mTransport.addSubscriptionChannel(aSubscriptionChannel) def removeSubscriptionChannel(self, aSubscriptionChannel): self.mTransport.removeSubscriptionChannel(aSubscriptionChannel) def getCorrespondingSubscriptionChannel(self, aMessage): return SUBSCRIPTION_CHANNEL_ALL