class BoardsController(object): def __init__(self): self.boards = {} self.message_handler = MessageHandler(self) self.message_parser = MessageParser(self.message_handler) def register(self, channel_id, handle): if channel_id in self.boards.keys(): self.boards[channel_id].append(handle) else: self.boards[channel_id] = [handle] def unregister(self, handle, channel_id=None): if channel_id is None: for channel_id in self.boards: if handle in self.boards[channel_id]: self.boards[channel_id].remove(handle) self.message_handler.publish(Message("disconnect"),channel_id) else: self.boards[channel_id].remove(handle) self.message_handler.publish(Message("disconnect"),channel_id) def get_board_handles(self, channel_id): return self.boards.get(channel_id) def count_users(self, channel_id): if channel_id in self.boards.keys(): return len(self.boards.get(channel_id)) return 0 def on_message(self, handle, message): self.message_parser.parse(handle, message)
class MessageHandlerTest(unittest.TestCase): def setUp(self): self.handle = MagicMock() self.message_handler = MagicMock() self.message_parser = MessageParser(self.message_handler) def test_parsing_register_message(self): self.message_parser.parse(self.handle, '{"type":"register", "args": {"channel_id":1}}') self.message_handler.handle.assert_called_with({"type":"register", "args": {"channel_id":1}},self.handle) def test_parsing_new_message(self): self.message_parser.parse(self.handle, '{"type":"new", "args": {}}') self.message_handler.handle.assert_called_with({"type":"new", "args": {}},self.handle) def test_parsing_postit_moved_message(self): self.message_parser.parse(self.handle, '{"type":"move", "args": {}}') self.message_handler.handle.assert_called_with({"type":"move", "args": {}},self.handle) def test_move_is_not_call_with_register_message(self): self.message_parser.parse(self.handle, '{"type":"register", "args": {"channel_id":1}}') assert self.message_handler.move.call_count == 0 def test_register_message_with_arguments(self): self.message_parser.parse(self.handle, '{"type":"register", "args": {"channel_id":1}}') self.message_handler.register.assert_called_with(self.handle, 1)
def connect(self): handshake = self.torrent.get_handshake() self.sock = socket.socket() self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.setblocking(True) try: print('peer info is ', self.peer_info) self.sock.connect(self.peer_info) self.sock.send(handshake) except OSError: raise Exception("Failed to connect") resp = self.sock.recv(2**15) print(resp) if not self.is_handshake_valid(handshake, resp): print("Failed to connect to {} -- invalid handshake".format(self.peer_info)) else: print("{} connected successfully".format(self.peer_info)) self.is_connected = True self.am_interested = True self.outbound_messages.append( MessageParser.encode_msg('interested') ) self.recieved_data_buffer = resp[68:] self.process_read_buffer()
def connect(self): handshake = self.torrent.get_handshake() self.sock = socket.socket() self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.setblocking(True) try: print('peer info is ', self.peer_info) self.sock.connect(self.peer_info) self.sock.send(handshake) except OSError: raise Exception("Failed to connect") resp = self.sock.recv(2**15) print(resp) if not self.is_handshake_valid(handshake, resp): print("Failed to connect to {} -- invalid handshake".format( self.peer_info)) else: print("{} connected successfully".format(self.peer_info)) self.is_connected = True self.am_interested = True self.outbound_messages.append( MessageParser.encode_msg('interested')) self.recieved_data_buffer = resp[68:] self.process_read_buffer()
class BoardsController(object): # Generate a Boards instance def __init__(self): self.boards = {} self.message_handler = MessageHandler(self) self.message_parser = MessageParser(self.message_handler) def register(self, decoded_message, handle): channel_id = decoded_message['args']['channel_id'] if channel_id in self.boards.keys(): self.boards[channel_id][handle] = decoded_message['args']['user'] else: self.boards[channel_id] = {} self.boards[channel_id][handle] = decoded_message['args']['user'] # Remove a board to the Boards instances def unregister(self, handle, channel_id=None): if channel_id is None: for channel_id in self.boards: if handle in self.boards[channel_id]: self.message_handler.publish( Message("disconnect", self.boards[channel_id][handle]), channel_id) del self.boards[channel_id][handle] else: self.message_handler.publish( Message("disconnect", self.boards[channel_id][handle]), channel_id) del self.boards[channel_id][handle] # Get a specific board def get_board_handles(self, channel_id): return self.boards.get(channel_id) def get_board_users(self, channel_id): return self.boards.get(channel_id).values() # Get number of users that are in the board at the moment def count_users(self, channel_id): if channel_id in self.boards.keys(): return len(self.boards.get(channel_id)) return 0 def on_message(self, handle, message): self.message_parser.parse(handle, message)
class BoardsController(object): # Generate a Boards instance def __init__(self): self.boards = {} self.message_handler = MessageHandler(self) self.message_parser = MessageParser(self.message_handler) def register(self, decoded_message, handle): channel_id = decoded_message['args']['channel_id'] if channel_id in self.boards.keys(): self.boards[channel_id][handle] = decoded_message['args']['user'] else: self.boards[channel_id] = {} self.boards[channel_id][handle] = decoded_message['args']['user'] # Remove a board to the Boards instances def unregister(self, handle, channel_id=None): if channel_id is None: for channel_id in self.boards: if handle in self.boards[channel_id]: self.message_handler.publish(Message("disconnect",self.boards[channel_id][handle]),channel_id) del self.boards[channel_id][handle] else: self.message_handler.publish(Message("disconnect",self.boards[channel_id][handle]),channel_id) del self.boards[channel_id][handle] # Get a specific board def get_board_handles(self, channel_id): return self.boards.get(channel_id) def get_board_users(self, channel_id): return self.boards.get(channel_id).values() # Get number of users that are in the board at the moment def count_users(self, channel_id): if channel_id in self.boards.keys(): return len(self.boards.get(channel_id)) return 0 def on_message(self, handle, message): self.message_parser.parse(handle, message)
def do_POST(self): data = json.loads(self.rfile.read(int(self.headers["content-length"]))) self.send_response(200) self.end_headers() if data.get("group_id") == int(group.get("GROUP_ID")) and data.get( "secret") == group.get("WEBHOOK_SECRET"): if data.get("type") == "confirmation": self.wfile.write(group["CONFIRMATION"].encode("utf-8")) else: self.wfile.write(b"ok") if data.get("type") == "message_new": from messages import MessageParser MessageParser(data.get("object"))
def enqueue_piece_requests(self): while len(self.outbound_messages) < self.MAX_OUTBOX_REQUESTS: if self.am_interested and not self.is_choking: req = self.torrent.get_next_request(self.pieces) if not req: return index, begin, length = req payload = struct.pack('>III', index, begin, length) req_msg = MessageParser.encode_msg('request', payload) self.outbound_messages.append(req_msg) else: return
def __init__(self): self.parser = MessageParser() self.received_messages = {} self.resend_list = {} self.sequence_no = 0 self.get_seq_no = 0
class ClientHandler(): def __init__(self): self.parser = MessageParser() self.received_messages = {} self.resend_list = {} self.sequence_no = 0 self.get_seq_no = 0 # need a window start and end for sendlist, can't send unless window has room def get_message(self, source): """queries user and creates new SEND message""" payload = raw_input('Enter message to send : ') while 1: destination = raw_input('Enter destination IP : ') destination = get_ip(destination) check = r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$' valid = re.match(check, destination) if not valid: print "Ill-formed IP address. Please re-enter." else: break seq_no = self.increment_seq_no(0) message_data = self.parser.encode(seq_no,"SEND",source, destination, payload) key = str(seq_no) + str(destination) self.resend_list[key] = message_data #print "DEBUG: resend list:" #print "RESEND_LIST:" + str(self.resend_list) return message_data def increment_seq_no(self, type): """handles counter incrementation""" if type == 0: seq_no = self.sequence_no self.sequence_no = (self.sequence_no + 1) % 1000 elif type == 1: seq_no = self.get_seq_no self.get_seq_no = (self.get_seq_no + 1) % 1000 return seq_no def parse(self, message_list): """Parses and ACKs mesages, prints new messages and removed ACKed or REJected messages""" ack_list = [] sorted_messages = sorted(message_list) for m in sorted_messages: #print "DEBUG: the message is: '" + m + "'." message = self.parser.decode(m) if message["Type"] == "SEND": #acknowledge all messages of Type "SEND" ack_message = {} ack_message["Seq_No"] = message["Seq_No"] ack_message["Type"] = "ACK" ack_message["Source"] = message["Destination"] ack_message["Destination"] = message["Source"] ack_message["Payload"] = "" send_ack = self.parser.encode(ack_message["Seq_No"], ack_message["Type"], ack_message["Source"], ack_message["Destination"], ack_message["Payload"]) ack_list.append(send_ack) if not self.seen_message(message): self.save_message_seq_no(message) print message["Source"] + ", says: " + message["Payload"] elif message["Type"] == "ACK": # message acknoledged we no longer want to resend it. self.remove_from_resend_list(message) elif message["Type"] == "REJ": message["Type"] = "SEND" #reverse destination and source order since server only echoes the message destination = message["Destination"] message["Destination"] = message["Source"] message["Source"] = destination #remove rejected messages self.remove_from_resend_list(message) return ack_list, self.resend_list def save_message_seq_no(self, message): """stores the sequence number and source of messages we have seen""" # message is a dictionary, saves the sequence number save_string = message["Seq_No"] + message["Source"] self.received_messages[save_string] = True return True def seen_message(self, message): """Does a quick check to see if this is a new or old message""" # Check to see if message is in recieved messages list check_string = message["Seq_No"] + message["Source"] if check_string in self.received_messages: #print "DEBUG: !!! we have seen message# " + message["Seq_No"] + " from " + message["Source"] return True else: #print "DEBUG: New message# " + message["Seq_No"] + " from " + message["Source"] + ":" return False def remove_from_resend_list(self, message): """removes messages from the resend list when they are ACKed or REJected""" #be able to remove message based on Seq No and IP only #key = message["Seq_No"] + message["Destination"] key = message["Seq_No"] + message["Source"] '''check_message = self.parser.encode(message["Seq_No"], message["Type"], message["Source"], message["Destination"], message["Payload"])''' # Don't resend these messages try: #print "DEBUG:resend list, before remove:" #print "DEBUG: " + str(self.resend_list) del self.resend_list[key] #print "DEBUG:resend list, after remove:" #print "DEBUG: " + str(self.resend_list) ##print "DEBUG: *** message:'" + key + "' removed from resend list! ***" except KeyError: print key + " is not in resend list" def get_request(self, source, destination): """creates a GET request and returns the message string""" payload = "" message_data = self.parser.encode(self.increment_seq_no(1),"GET",source, destination, payload) return message_data
def __init__(self): self.boards = {} self.message_handler = MessageHandler(self) self.message_parser = MessageParser(self.message_handler)
def process_read_buffer(self): while self.recieved_data_buffer: msg_length = struct.unpack('>I', self.recieved_data_buffer[0:4])[0] packet_length = msg_length + 4 # If the buffer doesn't contain the entirety of the packet then # break and wait until more data is read from socket if len(self.recieved_data_buffer) < packet_length: break message = MessageParser.parse( self.recieved_data_buffer[:packet_length], msg_length ) self.recieved_data_buffer = self.recieved_data_buffer[packet_length:] if message.name != 'piece': print(message) else: print("We got a piece of our file!!!") # print('buffer is: ', self.recieved_data_buffer) # Msg ID 0 if message.name == 'choke': self.is_choking = True # Msg ID 1 if message.name == 'unchoke': self.is_choking = False # Msg ID 2 if message.name == 'interested': # TODO: send unchoke message self.outbound_messages.append( MessageParser.encode_msg('unchoke') ) # Msg ID 3 if message.name == 'not_interested': self.is_interested = False # Msg ID 4 if message.name == 'have': have_piece = struct.unpack('>I', message.payload)[0] self.pieces[have_piece] = True # Msg ID 5 if message.name == 'bitfield': self.pieces = BitArray(bytes=message.payload) self.outbound_messages.append( MessageParser.encode_msg('interested') ) # Msg ID 6 if message.name == 'request': if not self.am_choking: # Find piece from our downloaded torrent and send it back pass # Msg ID 7 if message.name == 'piece': self.inflight_requests -= 1 index, begin = struct.unpack('>I I', message.payload[:8]) print('Piece index: ', index) print(message.payload[:50])
def process_read_buffer(self): while self.recieved_data_buffer: msg_length = struct.unpack('>I', self.recieved_data_buffer[0:4])[0] packet_length = msg_length + 4 # If the buffer doesn't contain the entirety of the packet then # break and wait until more data is read from socket if len(self.recieved_data_buffer) < packet_length: break message = MessageParser.parse( self.recieved_data_buffer[:packet_length], msg_length) self.recieved_data_buffer = self.recieved_data_buffer[ packet_length:] if message.name != 'piece': print(message) else: print("We got a piece of our file!!!") # print('buffer is: ', self.recieved_data_buffer) # Msg ID 0 if message.name == 'choke': self.is_choking = True # Msg ID 1 if message.name == 'unchoke': self.is_choking = False # Msg ID 2 if message.name == 'interested': # TODO: send unchoke message self.outbound_messages.append( MessageParser.encode_msg('unchoke')) # Msg ID 3 if message.name == 'not_interested': self.is_interested = False # Msg ID 4 if message.name == 'have': have_piece = struct.unpack('>I', message.payload)[0] self.pieces[have_piece] = True # Msg ID 5 if message.name == 'bitfield': self.pieces = BitArray(bytes=message.payload) self.outbound_messages.append( MessageParser.encode_msg('interested')) # Msg ID 6 if message.name == 'request': if not self.am_choking: # Find piece from our downloaded torrent and send it back pass # Msg ID 7 if message.name == 'piece': self.inflight_requests -= 1 index, begin = struct.unpack('>I I', message.payload[:8]) print('Piece index: ', index) print(message.payload[:50])
def setUp(self): self.handle = MagicMock() self.message_handler = MagicMock() self.message_parser = MessageParser(self.message_handler)