コード例 #1
0
ファイル: handlers.py プロジェクト: safl/mifcho
 def tunnel(self, conn, env):
     
     logging.debug('TUNNEL')
     
     if 'HTTP_X_MIFCHO_TUNNEL_ID' in env: # We requested the tunnel
         
         logging.debug('We requested the tunnel...')
         
         tunnel = self.cm.tunnels[env['HTTP_X_MIFCHO_TUNNEL_ID']]
         tunnel.peer_connection = conn
         
         messages.send_response(conn,
             code      = 101,
             message   = 'Switching Protocols',
             headers   = [
               ('X-Mifcho-Id', env['mifcho.id'])
             ]
         )
         
         tunnel.event.set()
         
     else:   # We did not request the tunnel so this is an indirect tunnel carrier.
         
         logging.debug('We did not request it...')
         ep_address = (
             env['HTTP_X_MIFCHO_TUNNEL_ENDPOINTHOST'],
             int(headers['X_MIFCHO_TUNNEL_ENDPOINTPORT'])
         )        
         
         ep_conn = self.cm.connect(ep_address)
         
         if conn and ep_conn:
             
             logging.debug('Successfully contacted endpoint...')
             tunnel    = Tunnel.fromconnections(conn, ep_conn)
             tunnel.id = str(uuid.uuid4())
             
             self.cm.add_tunnel(tunnel)
             
             messages.send_response(conn,
                 code      = 101,
                 message   = 'Switching Protocols',
                 headers   = [
                   ('X-Mifcho-Id', self.cm.identifier)
                 ]
             )            
         
             pipe = Piper(self.cm, conn, ep_conn, 4096, sink_recovery=(ep_address, None))
             pipe.start()
             self.cm.pipes.append(pipe)
         else:
             logging.error('Failed connecting to endpoint [%s].' % repr(address))
             self.cm.teardown(conn)
コード例 #2
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