libmproxy: percorso delle request

  1. Nel main di uno script che usa libmproxy si crea un oggetto “Master” che riceve un “server” come parametro:
    # posso estendere controller.Master oppure flow.FlowMaster
    # dipende se voglio le funzioni estese di FlowMaster o meno
    class MyMaster(controller.Master)
        def handle_request(msg):
            msg.reply()
        def handle_response(msg):
            msg.reply()
    
    config=proxy.ProxyConfig()
    server=proxy.ProxyServer(config, 8081)
    m=MyMaster(server)
    m.run()
    
  2. il metodo run() di controller.Master chiama la funzione
    # self.server è una istanza di proxy.ProxyServer !
    self.server.start_slave(Slave, Channel(self.masterq))
    

    che è definita nella classe genitrice di proxy.ProxyServer

  3. in proxy.ProxyServer trovo:
        def start_slave(self, klass, channel):
            slave = klass(channel, self)
            slave.start()
    
  4. la classe Slave definisce un thread che in run() chiama la funzione self.server.serve_forever(), a sua volta definito nella classe genitrice di ProxyServer: netlib/tcp.TCPServer
    class Slave(threading.Thread):
        """
            Slaves get a channel end-point through which they can send messages to
            the master.
        """
        def __init__(self, channel, server):
            self.channel, self.server = channel, server
            self.server.set_channel(channel)
            threading.Thread.__init__(self)
    
        def run(self):
            self.server.serve_forever()
    
  5. in netlib/tcp.py si trova la classe TCPServer con il suo metodo serve_forever:
    questo chiama la funzione self.request_thread in un thread

        def serve_forever(self, poll_interval=0.1):
            self.__is_shut_down.clear()
            try:
                while not self.__shutdown_request:
                    try:
                        r, w, e = select.select([self.socket], [], [], poll_interval)
                    except select.error, ex:
                            if ex[0] == 4:
                                continue
                            else:
                                raise  
                    if self.socket in r:
                        request, client_address = self.socket.accept()
                        t = threading.Thread(
                                target = self.request_thread,
                                args = (request, client_address)
                            )
                        t.setDaemon(1)
                        t.start()
            finally:
                self.__shutdown_request = False
                self.__is_shut_down.set()
    
  6. self.request_thread chiama altri handler:
        def request_thread(self, request, client_address):
            try:
                self.handle_connection(request, client_address)
                request.close()
            except:
                self.handle_error(request, client_address)
                request.close()
        def handle_error(self, request, client_address, fp=sys.stderr):
            """
                Called when handle_connection raises an exception.
            """
            # If a thread has persisted after interpreter exit, the module might be
            # none.
            if traceback:
                exc = traceback.format_exc()
                print >> fp, '-'*40
                print >> fp, "Error in processing of request from %s:%s"%client_addr
    ess
                print >> fp, exc
                print >> fp, '-'*40
    
        def handle_connection(self, request, client_address): # pragma: no cover
            """
                Called after client connection.
            """
            raise NotImplementedError
    
  7. handle_connection viene definita da ProxyServer:
        def handle_connection(self, request, client_address):
            h = ProxyHandler(self.config, request, client_address, self, self.channel, self.server_version)
            h.handle()
            h.finish()
    
  8. la classe ProxyHandler gestisce le connessioni a basso livello.

        def handle(self):
            cc = flow.ClientConnect(self.client_address)
            self.log(cc, "connect")
            self.channel.ask("clientconnect", cc)
            while self.handle_request(cc) and not cc.close:
                pass
            cc.close = True
            self.del_server_connection()
    
            cd = flow.ClientDisconnect(cc)
            self.log(
                cc, "disconnect",
                [
                    "handled %s requests"%cc.requestcount]
            )
            self.channel.tell("clientdisconnect", cd)
        def handle_request(self, cc):
            try:
                request, err = None, None
                request = self.read_request(cc)
                if request is None:
                    return
                cc.requestcount += 1
    
                request_reply = self.channel.ask("request", request)
                if request_reply is None or request_reply == KILL:
                    return
                elif isinstance(request_reply, flow.Response):
                    request = False
                    response = request_reply
                    response_reply = self.channel.ask("response", response)
                else:
                    request = request_reply
                    ...
            except (IOError, ProxyError, http.HttpError, tcp.NetLibError), e:
                ...
    

    il ProxyServer legge la richiesta dal client e la immette nel “canale”, da cui si aspetta la risposta:
    request_reply = self.channel.ask(“request”, request)

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...