Пример #1
0
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)
Пример #3
0
    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()
Пример #4
0
    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()
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
 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"))
Пример #8
0
    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
Пример #9
0
    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
Пример #10
0
 def __init__(self):
     self.parser = MessageParser()
     self.received_messages = {}
     self.resend_list = {}
     self.sequence_no = 0
     self.get_seq_no = 0
Пример #11
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
Пример #12
0
 def __init__(self):
     self.boards = {}
     self.message_handler = MessageHandler(self)
     self.message_parser = MessageParser(self.message_handler)
Пример #13
0
 def __init__(self):
     self.boards = {}
     self.message_handler = MessageHandler(self)
     self.message_parser = MessageParser(self.message_handler)
Пример #14
0
    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])
Пример #15
0
    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])
Пример #16
0
 def setUp(self):
     self.handle = MagicMock()
     self.message_handler = MagicMock()
     self.message_parser = MessageParser(self.message_handler)