def get_name(self): #do this until we have a name while self.name == '': #prompt user msg_name_prompt = message.Message() msg_name_prompt.clear() msg_name_prompt.set_text('Please input your name') self.send(message.pack(msg_name_prompt)) #get name from socket msg_client_name = message.Message(data=message.unpack(self.conn.recv(DATA_SIZE))) while msg_client_name.get_type() == 'ping': self.handle_ping() msg_client_name = message.Message(data=message.unpack(self.conn.recv(DATA_SIZE))) name_from_client = msg_client_name.get_text() #check name length if len(name_from_client) > NAME_SIZE_LIMIT: msg_name_too_long = message.Message() msg_name_too_long.set_text('That name is too long') self.send(message.pack(msg_name_too_long)) else: #check name isnt already taken name_taken = False for c in CLIENTS: if name_from_client == c.name: name_taken = True if name_taken: msg_name_taken = message.Message() msg_name_taken.set_text('That name is already taken') self.send(message.pack(msg_name_taken)) else: #if we pass all the tests then set the clien name self.name = name_from_client
def run(self): try: #get the name from the client self.get_name() #tell everyone there is a new client msg_user_join = message.Message() msg_user_join.set_type('text') msg_user_join.set_text('{} has joined the chat!'.format(self.name)) msg_user_join.set_time(get_time()) print(message.pack(msg_user_join)) broadcast(message.pack(msg_user_join)) #add this client to the client list CLIENTS.append(self) msg_data = self.conn.recv(DATA_SIZE) while msg_data: msg = message.Message(data=message.unpack(msg_data)) if msg.get_text() != None: msg.set_time(time.strftime('%H:%M:%S', time.localtime())) msg.set_sender(self.name, color=self.name_color, clan=self.clan) if msg.get_type() == 'ping': self.handle_ping() elif msg.get_type() == 'leave': self.leave() elif msg.get_type() == 'text': if msg.get_text().split()[0] in USER_COMMANDS: if not handle_user_command(self, msg): msg_invalid_command = message.Message() msg_invalid_command.set_type('text') msg_invalid_command.set_text('Invalid command. view /help') self.send(message.pack(msg_invalid_command)) print('PASS') else: if len(msg.get_text()) > MSG_SIZE_MAX: error_msg = message.Message() error_msg.set_type('error') error_msg.set_sender('[SERVER]') error_msg.set_time(get_time()) error_msg.set_text('Your message was too long. Max is 200 characters.') self.send(message.pack(error_msg)) print('{} attempted to send a LARGE message'.format(self.address)) else: #the formatted message as it will be sent to all users msg.print() broadcast(message.pack(msg)) else: print('Unknown message type: {}'.format(message.unpack(msg))) msg_data = self.conn.recv(DATA_SIZE) except Exception as e: print(e) print("Connection Lost to {}".format(self.address)) self.leave()
def get_name(self): #do this until we have a name while self.name == '': #prompt user msg_name_prompt = message.Message() msg_name_prompt.clear() msg_name_prompt.set_text('Please input your name') self.send(message.pack(msg_name_prompt)) try: #get name from socket while the message received is not a ping msg_client_name = message.Message(data=message.unpack(self.conn.recv(DATA_SIZE))) while msg_client_name.get_type() == 'ping': self.handle_ping() msg_client_name = message.Message(data=message.unpack(self.conn.recv(DATA_SIZE))) name_from_client = msg_client_name.get_text() except: #if the data from the client is malformed then restart this process break #verify name length if len(name_from_client) > NAME_SIZE_LIMIT: # if the name is too long restart msg_name_too_long = message.Message() msg_name_too_long.set_type('text') msg_name_too_long.set_text('That name is too long. Max: {} characters'.format(NAME_SIZE_LIMIT)) self.send(message.pack(msg_name_too_long)) else: #verify name isnt already taken name_taken = False for c in CLIENTS: if name_from_client == c.name: name_taken = True # if the name is taken then restart if name_taken: msg_name_taken = message.Message() msg_name_taken.set_type('text') msg_name_taken.set_text('That name is already taken') self.send(message.pack(msg_name_taken)) else: #if we pass all the tests then set the clien name self.name = name_from_client
def listen_loop(socket): try: msg_data = socket.recv(DATA_SIZE) while RUNNING and msg_data: #msg = message.Message(data=message.unpack(data)) #msg.print() msg_recv = message.Message(data=message.unpack(msg_data)) if msg_recv.get_type() != 'ping': print(msg_recv) msg_data = socket.recv(DATA_SIZE) except Exception as e: print(e) print('Connection to server lost!!!')
def passage_outbound_messages(outbound_socket, userland_outbound_queue, driver): try: outbound_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) peer = outbound_socket.getpeername() outbound_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) outbound_socket.setsockopt(socket.SOL_TCP, socket.TCP_KEEPCNT, KEEPALIVE_PROBE_COUNT) outbound_socket.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, KEEPALIVE_IDLE_TIMEOUT) outbound_socket.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, KEEPALIVE_RETRY_SEND_PROBE) while True: try: syslog.syslog(syslog.LOG_INFO, "Pulling packet from output queue (down)...") id, payload = message.unpack(userland_outbound_queue.pull()) if id not in TYPE_BY_ID: raise InvalidApplicationMessage("The type of the message in the queue is invalid.", id) if len(payload) > MAX_PAYLOAD: raise InvalidApplicationMessage("The lenght of the payload is greater than the expected.", payload) type = TYPE_BY_ID[id] if type == 'LOOP' and struct.unpack(">B", payload[2])[0] == LOOP_SUBTYPE_BY_NAME['BreakLinkForced']: syslog.syslog(syslog.LOG_INFO, "Breaking the link forced. Shutdown the socket...") return if type == 'LOOP' and not driver.handle_loop_message(payload[2:]): continue #loop message dicarted size = struct.pack('>H', len(payload)) assert len(type) == 4 assert len(size) == 2 syslog.syslog(syslog.LOG_DEBUG, "Sending %s packet to the remote node %s: %s [%s]" % (type, str(peer), " ".join(map(lambda c: hex(ord(c)), type+size+payload)), "".join([(c if ord('0') <= ord(c) <= ord('Z') else '.') for c in type+size+payload]) )) _send(outbound_socket, type+size+payload, peer) ack = _recv(outbound_socket, 1, peer) if ack != "A": raise InvalidNetworkMessage("The ACK has is invalid '%s' for the message sent" % hex(ord(ack)), type+size+payload, peer) except InvalidApplicationMessage, e: syslog.syslog(syslog.LOG_CRIT, "%s\n%s" % (traceback.format_exc(), str(e))) except socket.error, e: raise UnstableChannel("The other side (other peer) is not responding. It seem to be down.", peer, e)
def listen_loop(socket): try: #receive data msg_data = socket.recv(DATA_SIZE) while RUNNING and msg_data: #msg = message.Message(data=message.unpack(data)) #msg.print() msg_recv = message.Message(data=message.unpack(msg_data)) #print the message if it isnt a ping if msg_recv.get_type() != 'ping': print(msg_recv) #continue to receive data msg_data = socket.recv(DATA_SIZE) except Exception as e: #handle exceptions print(e) print('Connection to server lost!!!')
def run(self): try: #get the name from the client self.get_name() #tell everyone there is a new client msg_user_join = message.Message() msg_user_join.set_type('text') msg_user_join.set_text('{} has joined the chat!'.format(self.name)) msg_user_join.set_time(get_time()) broadcast(message.pack(msg_user_join)) #add this client to the client list CLIENTS.append(self) # main data listen loop msg_data = self.conn.recv(DATA_SIZE) while msg_data: # turn the data into a message msg = message.Message(data=message.unpack(msg_data)) if msg.get_text() != None: # set the values of the message such as the time and the sender msg.set_time(get_time()) msg.set_sender(self.name, color=self.name_color, clan=self.clan) #handle message types if msg.get_type() == 'ping': self.handle_ping() elif msg.get_type() == 'leave': self.leave() elif msg.get_type() == 'text': #check if the msg the user sent is a command if msg.get_text().split()[0] in USER_COMMANDS: #handle the user command if not handle_user_command(self, msg): #if the user command fails #tell the user msg_invalid_command = message.Message() msg_invalid_command.set_type('text') msg_invalid_command.set_text('Invalid command. view /help') self.send(message.pack(msg_invalid_command)) else: #check the text from the user is smaller than the max acceptable size if len(msg.get_text()) > MSG_SIZE_MAX: error_msg = message.Message() error_msg.set_type('error') error_msg.set_sender('[SERVER]') error_msg.set_time(get_time()) error_msg.set_text('Your message was too long. Max is 200 characters.') self.send(message.pack(error_msg)) print('{} attempted to send a LARGE message'.format(self.address)) else: #broadcast the message to the clients broadcast(message.pack(msg)) if SHOW_CLIENT_MESSAGES: print(msg) else: #handle unknown cases print('Unknown message type: {}'.format(message.unpack(msg))) #continue to listen for data from the client msg_data = self.conn.recv(DATA_SIZE) except Exception as e: #handle exceptions #i am not the most familiar with the python exceptions #so im printing as much information to both learn and debug #this does lead to a messy server console exc_information = sys.exc_info() print(exc_information) print("Connection Lost to {}".format(self.address)) self.leave()
def passage_outbound_messages(outbound_socket, userland_outbound_queue, driver): try: outbound_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) peer = outbound_socket.getpeername() outbound_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) outbound_socket.setsockopt(socket.SOL_TCP, socket.TCP_KEEPCNT, KEEPALIVE_PROBE_COUNT) outbound_socket.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, KEEPALIVE_IDLE_TIMEOUT) outbound_socket.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, KEEPALIVE_RETRY_SEND_PROBE) while True: try: syslog.syslog(syslog.LOG_INFO, "Pulling packet from output queue (down)...") id, payload = message.unpack(userland_outbound_queue.pull()) if id not in TYPE_BY_ID: raise InvalidApplicationMessage( "The type of the message in the queue is invalid.", id) if len(payload) > MAX_PAYLOAD: raise InvalidApplicationMessage( "The lenght of the payload is greater than the expected.", payload) type = TYPE_BY_ID[id] if type == 'LOOP' and struct.unpack( ">B", payload[2] )[0] == LOOP_SUBTYPE_BY_NAME['BreakLinkForced']: syslog.syslog( syslog.LOG_INFO, "Breaking the link forced. Shutdown the socket...") return if type == 'LOOP' and not driver.handle_loop_message( payload[2:]): continue #loop message dicarted size = struct.pack('>H', len(payload)) assert len(type) == 4 assert len(size) == 2 syslog.syslog( syslog.LOG_DEBUG, "Sending %s packet to the remote node %s: %s [%s]" % (type, str(peer), " ".join( map(lambda c: hex(ord(c)), type + size + payload)), "".join([(c if ord('0') <= ord(c) <= ord('Z') else '.') for c in type + size + payload]))) _send(outbound_socket, type + size + payload, peer) ack = _recv(outbound_socket, 1, peer) if ack != "A": raise InvalidNetworkMessage( "The ACK has is invalid '%s' for the message sent" % hex(ord(ack)), type + size + payload, peer) except InvalidApplicationMessage, e: syslog.syslog(syslog.LOG_CRIT, "%s\n%s" % (traceback.format_exc(), str(e))) except socket.error, e: raise UnstableChannel( "The other side (other peer) is not responding. It seem to be down.", peer, e)