示例#1
0
    def init_packetsender(self):

        self._packet_sender = PacketSender(self.sock, self.hostname, self.port,
                                           self.guid, self.transport,
                                           self.nat_type, self.relaying)

        self._rudp_connection = Connection(self._packet_sender)

        self.packetsmasher = {}
        self.message_size = 0
        self.is_listening = True
        self.hello = False
示例#2
0
    def init_packetsender(self):

        self._packet_sender = PacketSender(
            self.sock,
            self.hostname,
            self.port,
            self.guid,
            self.transport,
            self.nat_type,
            self.relaying
        )

        self._rudp_connection = Connection(self._packet_sender)

        self.packetsmasher = {}
        self.message_size = 0
        self.is_listening = True
        self.hello = False
示例#3
0
class PeerConnection(GUIDMixin, object):
    def __init__(self, guid, transport, hostname, port=12345, nickname="",
                 avatar_url="", peer_socket=None, nat_type=None):

        GUIDMixin.__init__(self, guid)

        self.transport = transport

        self.loop = ioloop.IOLoop.current()

        self.log = logging.getLogger(
            '[%s] %s' % (self.transport.market_id, self.__class__.__name__)
        )

        self.log.info('Created a peer connection object')

        self.event_emitter = EventEmitter()
        self.sock = peer_socket
        self.hostname = hostname
        self.port = port
        self.nickname = nickname
        self.avatar_url = avatar_url
        self.nat_type = nat_type
        self.pinging = False
        self.relaying = False
        self.reachable = False
        self.last_reached = time.time()
        self.seed = False

        self.init_packetsender()
        self.setup_emitters()

        if nat_type == 'Symmetric NAT':
            self.reachable = True
            self.relaying = True
            self._rudp_connection._sender._packet_sender.relaying = True
            self.send_relayed_ping()
        else:

            self.pinging = True
            self.send_ping()

            def no_response():

                hello_msg = {
                    'type': 'hello',
                    'pubkey': self.transport.pubkey,
                    'senderGUID': self.transport.guid,
                    'hostname': self.transport.hostname,
                    'nat_type': self.transport.nat_type,
                    'port': self.transport.port,
                    'senderNick': self.transport.nickname,
                    'avatar_url': self.transport.avatar_url,
                    'v': VERSION
                }

                self.log.debug('Hello Content: %s', hello_msg)

                if not self.reachable:
                    self.log.error('No response from peer.')
                    self.reachable = True
                    self.relaying = True
                    self._rudp_connection._sender._packet_sender.relaying = True
                    self._rudp_connection._sender._packet_sender.reachable = True

                    self.log.debug('Relay Hello through Seed')
                    hello_msg['relayed'] = True

                    self.send_to_rudp(json.dumps(hello_msg))
                    self.send_relayed_ping()
                else:
                    self.log.debug('Sending Hello')
                    self.send_raw(
                        json.dumps(hello_msg)
                    )
                    self.send_ping()

                self.pinging = False

            self.loop.call_later(PEERCONNECTION_NO_RESPONSE_DELAY_IN_SECONDS, no_response)

        self.seed = False
        self.punching = False

        # Recurring check for peer accessibility
        def pinger():
            self.log.debug('Pinging: %s', self.guid)

            if time.time() - self.last_reached <= PEERCONNECTION_PINGER_TIMEOUT_IN_SECONDS:
                self.reachable = True
                self.send_ping()
                self.loop.call_later(PEERCONNECTION_PING_TASK_INTERVAL_IN_SECONDS, pinger)
            else:
                self.reachable = False
                # if self.guid:
                    # self.log.error('Peer not responding. Removing.')
                    # TODO: Remove peers who are malicious/unresponsive
                    # self.transport.dht.remove_peer(self.guid)

                # Update GUI if possible
                if self.transport.handler:
                    self.transport.handler.refresh_peers()

                    # yappi.get_thread_stats().print_all()

        self.loop.call_later(PEERCONNECTION_PING_TASK_INTERVAL_IN_SECONDS, pinger)

    def setup_emitters(self):
        self.log.debug('Setting up emitters')
        self.event_emitter = EventEmitter()

        @self._rudp_connection._sender.event_emitter.on('timeout')
        def on_timeout(data):  # pylint: disable=unused-variable
            self.log.debug('Node Sender Timed Out')
            # self.transport.dht.remove_peer(self.guid)

        @self._rudp_connection.event_emitter.on('data')
        def handle_recv(msg):  # pylint: disable=unused-variable

            self.log.debug('Got the whole message: %s', msg.get('payload'))
            payload = msg.get('payload')

            if payload[:1] == '{':
                try:
                    payload = json.loads(msg.get('payload'))
                    self.transport.listener.on_raw_message(payload)
                    return
                except Exception as exc:
                    self.log.debug('Problem with serializing: %s', exc)
            else:
                try:
                    payload = msg.get('payload').decode('hex')
                    self.transport.listener.on_raw_message(payload)
                except Exception as exc:
                    self.log.debug('not yet %s', exc)
                    self.transport.listener.on_raw_message(msg.get('payload'))

    def send_ping(self):
        self.sock.sendto(MSG_PING_ID, (self.hostname, self.port))
        count_outgoing_packet(MSG_PING_ID)
        return True

    def send_relayed_ping(self):
        self.log.debug('Sending Relay Ping to: %s', self)
        for active_peer in self.transport.dht.active_peers:
            if active_peer.hostname == 'seed2.openbazaar.org' or active_peer.hostname == '205.186.156.31':
                self.sock.sendto('send_relay_ping %s' % self.guid, (active_peer.hostname, active_peer.port))
                count_outgoing_packet('send_relay_ping %s' % self.guid)
        return True

    def init_packetsender(self):

        self._packet_sender = PacketSender(
            self.sock,
            self.hostname,
            self.port,
            self.guid,
            self.transport,
            self.nat_type,
            self.relaying
        )

        self._rudp_connection = Connection(self._packet_sender)

        self.packetsmasher = {}
        self.message_size = 0
        self.is_listening = True
        self.hello = False

    def send_to_sock(self, data):
        self.sock.sendto(data, (self.hostname, self.port))
        count_outgoing_packet(data)

    def send(self, data, callback):
        self.send_raw(json.dumps(data), callback)

    def send_raw(self, serialized, callback=None, relay=False):

        if self.transport.seed_mode or relay or self.seed:
            self.send_to_rudp(serialized)
            return

        # if self.relaying:
        # self.log.debug('Relay through seed')
        # self.transport.relay_message(serialized, self.guid)
        #     return

        def sending_out():

            if not self.pinging:
                if self.reachable:
                    self.send_to_rudp(serialized)
                    return
                else:
                    if self.nat_type == 'Restric NAT' and not self.punching and not self.relaying:
                        self.log.debug('Found restricted NAT client')
                        self.transport.start_mediation(self.guid)
                    if self.nat_type == 'Full Cone' and not self.relaying:
                        self.send_to_rudp(serialized)
                        return
                    else:
                        self.log.debug('Relay through seed')
                        # self.transport.relay_message(serialized, self.guid)
                        self.send_to_rudp(serialized)
                        return


            self.loop.call_later(PEERCONNECTION_SENDING_OUT_DELAY_IN_SECONDS, sending_out)

        sending_out()

    def send_to_rudp(self, data):
        self._rudp_connection.send(data)

    def reset(self):
        self.log.debug('Reset 2')
        self._rudp_connection._sender._sending = None
        self._rudp_connection._sender._push()
        self.is_listening = False
示例#4
0
class PeerConnection(GUIDMixin, object):
    def __init__(self,
                 guid,
                 transport,
                 hostname,
                 port=12345,
                 nickname="",
                 avatar_url="",
                 peer_socket=None,
                 nat_type=None):

        GUIDMixin.__init__(self, guid)

        self.transport = transport

        self.log = logging.getLogger(
            '[%s] %s' % (self.transport.market_id, self.__class__.__name__))

        self.log.info('Created a peer connection object')

        self.ee = EventEmitter()
        self.sock = peer_socket
        self.hostname = hostname
        self.port = port
        self.nickname = nickname
        self.avatar_url = avatar_url
        self.nat_type = nat_type
        self.pinging = False
        self.relaying = False
        self.reachable = False
        self.last_reached = time.time()
        self.seed = False

        self.init_packetsender()
        self.setup_emitters()

        if nat_type == 'Symmetric NAT':
            self.reachable = True
            self.relaying = True
            self._rudp_connection._sender._packet_sender.relaying = True
            self.send_relayed_ping()
        else:

            self.pinging = True
            self.send_ping()

            def no_response():

                hello_msg = {
                    'type': 'hello',
                    'pubkey': self.transport.pubkey,
                    'senderGUID': self.transport.guid,
                    'hostname': self.transport.hostname,
                    'nat_type': self.transport.nat_type,
                    'port': self.transport.port,
                    'senderNick': self.transport.nickname,
                    'avatar_url': self.transport.avatar_url,
                    'v': constants.VERSION
                }

                self.log.debug('Hello Content: %s', hello_msg)

                if not self.reachable:
                    self.log.error('No response from peer.')
                    self.reachable = True
                    self.relaying = True
                    self._rudp_connection._sender._packet_sender.relaying = True
                    self._rudp_connection._sender._packet_sender.reachable = True

                    self.log.debug('Relay Hello through Seed')
                    hello_msg['relayed'] = True

                    self.send_to_rudp(json.dumps(hello_msg))
                    self.send_relayed_ping()
                else:
                    self.log.debug('Sending Hello')
                    self.send_raw(json.dumps(hello_msg))
                    self.send_ping()

                self.pinging = False

            ioloop.IOLoop.instance().call_later(2, no_response)

        self.seed = False
        self.punching = False

        # Recurring check for peer accessibility
        def pinger():
            self.log.debug('Pinging: %s', self.guid)

            if time.time() - self.last_reached <= 30:
                self.reachable = True
                self.send_ping()
            else:
                self.send_ping()
                self.reachable = False
                if self.guid:
                    self.log.error('Peer not responding. Removing.')
                    # TODO: Remove peers who are malicious/unresponsive
                    # self.transport.dht.remove_peer(self.guid)

                # Update GUI if possible
                if self.transport.handler:
                    self.transport.handler.refresh_peers()

                    # yappi.get_thread_stats().print_all()

        self.ping_task = ioloop.PeriodicCallback(
            pinger, 5000, io_loop=ioloop.IOLoop.instance())
        self.ping_task.start()

    def setup_emitters(self):
        self.log.debug('Setting up emitters')
        self.ee = EventEmitter()

        @self._rudp_connection._sender.ee.on('timeout')
        def on_timeout(data):  # pylint: disable=unused-variable
            self.log.debug('Node Sender Timed Out')
            # self.transport.dht.remove_peer(self.guid)

        @self._rudp_connection.ee.on('data')
        def handle_recv(msg):  # pylint: disable=unused-variable

            self.log.debug('Got the whole message: %s', msg.get('payload'))
            payload = msg.get('payload')

            if payload[:1] == '{':
                try:
                    payload = json.loads(msg.get('payload'))
                    self.transport.listener.on_raw_message(payload)
                    return
                except Exception as e:
                    self.log.debug('Problem with serializing: %s', e)
            else:
                try:
                    payload = msg.get('payload').decode('hex')
                    self.transport.listener.on_raw_message(payload)
                except Exception as e:
                    self.log.debug('not yet %s', e)
                    self.transport.listener.on_raw_message(msg.get('payload'))

    def send_ping(self):
        self.sock.sendto('ping', (self.hostname, self.port))
        count_outgoing_packet('ping')
        return True

    def send_relayed_ping(self):
        self.log.debug('Sending Relay Ping to: %s', self)
        for x in self.transport.dht.active_peers:
            if x.hostname == 'seed2.openbazaar.org' or x.hostname == '205.186.156.31':
                self.sock.sendto('send_relay_ping %s' % self.guid,
                                 (x.hostname, x.port))
                count_outgoing_packet('send_relay_ping %s' % self.guid)
        return True

    def init_packetsender(self):

        self._packet_sender = PacketSender(self.sock, self.hostname, self.port,
                                           self.guid, self.transport,
                                           self.nat_type, self.relaying)

        self._rudp_connection = Connection(self._packet_sender)

        self.packetsmasher = {}
        self.message_size = 0
        self.is_listening = True
        self.hello = False

    def send_to_sock(self, data):
        self.sock.sendto(data, (self.hostname, self.port))
        count_outgoing_packet(data)

    def send(self, data, callback):
        self.send_raw(json.dumps(data), callback)

    def send_raw(self, serialized, callback=None, relay=False):

        if self.transport.seed_mode or relay or self.seed:
            self.send_to_rudp(serialized)
            return

        # if self.relaying:
        # self.log.debug('Relay through seed')
        # self.transport.relay_message(serialized, self.guid)
        #     return

        def sending_out():

            if not self.pinging:
                if self.reachable:
                    self.send_to_rudp(serialized)
                    return
                else:
                    if self.nat_type == 'Restric NAT' and not self.punching and not self.relaying:
                        self.log.debug('Found restricted NAT client')
                        self.transport.start_mediation(self.guid)
                    if self.nat_type == 'Full Cone' and not self.relaying:
                        self.send_to_rudp(serialized)
                        return
                    else:
                        self.log.debug('Relay through seed')
                        # self.transport.relay_message(serialized, self.guid)
                        self.send_to_rudp(serialized)
                        return

            ioloop.IOLoop.instance().call_later(5, sending_out)

        sending_out()

    def send_to_rudp(self, data):
        self._rudp_connection.send(data)

    def reset(self):
        self.log.debug('Reset 2')
        self._rudp_connection._sender._sending = None
        self._rudp_connection._sender._push()
        self.is_listening = False