コード例 #1
0
ファイル: cm.py プロジェクト: safl/mifcho
    def connect(self, address, peer_id=None, use_tls=False):
        """Create a connection to address. Possible via another mifcho instance."""

        logging.debug(
            "Connecting to: %s %s %s." % (pprint.pformat(address), pprint.pformat(peer_id), pprint.pformat(use_tls))
        )
        conn = None
        peer = self.get_peer(peer_id)

        if not peer and not peer_id:  # Connect "directly" to address

            try:
                conn = Connection.fromaddress(address, use_tls)

                if conn:  # Add to opened connections
                    self.opened.append(conn)

            except socket.error:
                logging.error("%s when connecting to %s." % (sys.exc_info()[1], address))
            except:
                logging.error("Unexpected error", exc_info=3)

        elif peer and peer.interface:  # Connect via peer interface

            # Extract address and parameters of peer interface.
            peer_address = (peer.interface[0], peer.interface[1])

            try:
                peer_conn = self.connect(peer_address)  # Socket Connect

                messages.send_request(  # Send TunnelReq
                    peer_conn,
                    type="POST",
                    url="/mifcho/tunnel",
                    headers=[
                        ("X-Mifcho-Id", self.identifier),
                        ("X-Mifcho-Tunnel-EndpointHost", address[0]),
                        ("X-Mifcho-Tunnel-EndpointPort", address[1]),
                    ],
                )

                resp = (version, status, reason, headers) = messages.get_response(peer_conn)  # Wait for response

            except:
                logging.error("Failed connecting to socket!")
                logging.debug("Failed receiving response!", exc_info=3)

                peer_conn = None
                resp = (version, status, reason, headers) = ("", 404, "Not Found", [])

            conn = peer_conn

        elif peer and not peer.interface:  # Connect via peer control-line
            # and "callback".

            peer.lock.acquire()  # CRITICAL ZONE START...
            tunnel = Tunnel.fromconnections(None, None)
            self.add_tunnel(tunnel)

            try:  # Send request for tunnel
                messages.send_request(
                    peer.connection,
                    type="POST",
                    url="/mifcho/tunnel_request",
                    headers=[
                        ("X-Mifcho-Id", self.identifier),
                        ("X-Mifcho-Tunnel-Id", tunnel.id),
                        ("X-Mifcho-Tunnel-EndpointHost", address[0]),
                        ("X-Mifcho-Tunnel-EndpointPort", address[1]),
                    ],
                )
            except:
                logging.error("Error sending request to peer!", exc_info=3)

            try:  # Wait for response
                resp = (version, status, reason, headers) = messages.get_response(peer.connection)
            except:
                logging.error("Failed receiving response!")
                logging.debug("Failed receiving response!", exc_info=3)
                resp = (version, status, reason, headers) = ("", 404, "Not Found", [])

            peer.lock.release()  # CRITICAL ZONE END....

            if int(status) == 200:  # All is good

                # Wait for PeerHandler to set tunnel-event
                wait_for_tunnel = True
                while status == 200 and self.running and wait_for_tunnel:
                    tunnel.event.wait(1)
                    wait_for_tunnel = not tunnel.event.is_set()

                conn = tunnel.peer_connection

            else:
                conn = None

        elif peer_id and not peer:
            logging.error("Could not find peer %s." % repr(peer_id))
            logging.debug("Peers=[%s]" % repr(self.peers))

        else:
            logging.error("Invalid params.")

        return conn