예제 #1
0
 def _on_internal_error(self, stream, request):
     LOG.exception()
     response = Message()
     response.compose(code="500", reason="Internal Server Error",
                      body="500 Internal Server Error", keepalive=0)
     stream.send_response(request, response)
     stream.close()
예제 #2
0
 def _update_queue(self, lost_stream, ignored):
     ''' Invoked when a connection is lost '''
     queue, found = collections.deque(), False
     position = 0
     for stream in self.queue:
         if not found:
             if lost_stream != stream:
                 position += 1
                 queue.append(stream)
             else:
                 found = True
                 self.known.remove(stream)
         elif not stream.opaque:
             position += 1
             queue.append(stream)
         else:
             request, stream.opaque = stream.opaque, None
             try:
                 self._do_negotiate((stream, request, position))
                 position += 1
                 queue.append(stream)
             except (KeyboardInterrupt, SystemExit):
                 raise
             except:
                 LOG.exception()
                 stream.unregister_atclose(self._update_queue)
                 self.known.remove(stream)
                 stream.close()
     self.queue = queue
예제 #3
0
def main(args):
    ''' Run a subcommand's main() '''

    # Args[0] must be the subcommand name
    subcommand = args[0]

    # Users are not supposed to prefix commands with 'neubot.'
    subcommand = 'neubot.' + subcommand

    # Dinamically load the selected subcommand's main() at runtime
    __import__(subcommand)
    mainfunc = sys.modules[subcommand].main

    # Fix args[0]
    args[0] = 'neubot ' + subcommand

    # Run main()
    try:
        mainfunc(args)
    except KeyboardInterrupt:
        sys.exit(1)
    except SystemExit:
        raise
    except:
        LOG.exception()
        sys.exit(1)
예제 #4
0
 def process_request(self, stream, request):
     try:
         self._serve_request(stream, request)
     except ConfigError, error:
         reason = re.sub(r"[\0-\31]", "", str(error))
         reason = re.sub(r"[\x7f-\xff]", "", reason)
         LOG.exception(func=LOG.info)
         response = Message()
         response.compose(code="500", reason=reason,
                 body=StringIO.StringIO(reason))
         stream.send_response(request, response)
예제 #5
0
def _loop_once(args):
    message = ""

    # Check for updates
    try:
        connection = httplib.HTTPConnection("127.0.0.1", "9774")
        connection.request("GET", "/api/state")

        response = connection.getresponse()
        if response.status != 200:
            raise RuntimeError("Unexpected response")

        body = response.read()
        dictionary = json.loads(body)

        update = dictionary["events"]["update"]
        tpl = update["version"], update["uri"]
        message += "New version %s available at <%s> " % tpl
    except:
        LOG.exception()

    # Check whether we need to update privacy settings
    try:
        connection = httplib.HTTPConnection("127.0.0.1", "9774")
        connection.request("GET", "/api/config")

        response = connection.getresponse()
        if response.status != 200:
            raise RuntimeError("Unexpected response")

        body = response.read()
        dictionary = json.loads(body)

        if (not "privacy.informed" in dictionary or not
          dictionary["privacy.informed"]):
            uri = "http://127.0.0.1:9774/privacy.html"
            message += " Please update your privacy settings at <%s>" % uri

        # TODO Does the Law allow to force that at the /api level?
        if ("privacy.informed" in dictionary and
          "privacy.can_collect" in dictionary and
          dictionary["privacy.informed"] and
          not dictionary["privacy.can_collect"]):
            uri = "http://127.0.0.1:9774/privacy.html"
            message += " How is Neubot supposed to work if it cannot\n" \
                       "save the results of your tests?  Please update\n" \
                       "your privacy settings at <%s>" % uri
    except:
        LOG.exception()

    # Spam the user
    if message:
        InfoBox(message, 300)
예제 #6
0
    def got_response(self, stream, request, response):
        if response.code != "200":
            LOG.complete("bad response")
            self._schedule()
        else:
            LOG.complete()
            s = response.body.read()
            try:
                m1 = marshal.unmarshal_object(s, "application/json", compat.RendezvousResponse)
            except ValueError:
                LOG.exception()
                self._schedule()
            else:
                if "version" in m1.update and "uri" in m1.update:
                    ver, uri = m1.update["version"], m1.update["uri"]
                    LOG.info("Version %s available at %s" % (ver, uri))
                    STATE.update("update", {"version": ver, "uri": uri})
                    _open_browser_on_windows("update.html")

                # Update tests known by the runner
                runner_lst.update(m1.available)

                #
                # Choose the test we would like to run even if
                # we're not going to run it because we're running
                # in debug mode or tests are disabled.
                # This allows us to print to the logger the test
                # we /would/ have choosen if we were allowed to run
                # it.
                #
                test = runner_lst.get_next_test()
                if not test:
                    LOG.warning("No test available")
                    self._schedule()
                    return

                LOG.info("* Chosen test: %s" % test)

                # Are we allowed to run a test?
                if not CONFIG["enabled"] or CONFIG["rendezvous.client.debug"]:
                    LOG.info("Tests are disabled... not running")
                    self._schedule()
                else:

                    # Do we have negotiate URI for test?
                    negotiate_uri = runner_lst.test_to_negotiate_uri(test)
                    if not negotiate_uri:
                        LOG.warning("No negotiate URI for test")
                        self._schedule()
                    else:

                        # Actually run the test
                        runner_core.run(test, negotiate_uri, self._schedule)
예제 #7
0
    def got_response(self, stream, request, response):

        try:
            self.check_response(response)
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            LOG.exception()
            time.sleep(3)

        del request
        del response

        self.start_transaction(stream)
예제 #8
0
 def got_response(self, stream, request, response):
     if self.finished:
         stream.close()
         return
     if response.code not in ("200", "206"):
         stream.close()
         self.cleanup("bad response code")
     else:
         try:
             self.child.got_response(stream, request, response)
         except (KeyboardInterrupt, SystemExit):
             raise
         except:
             LOG.exception()
             stream.close()
             self.cleanup("unexpected exception")
         else:
             self.streams.append(stream)
             self.update()
예제 #9
0
    def handle_close(self):
        if self.close_complete:
            return

        self.close_complete = True

        self.connection_lost(None)
        self.parent.connection_lost(self)

        atclosev, self.atclosev = self.atclosev, set()
        for func in atclosev:
            try:
                func(self, None)
            except (KeyboardInterrupt, SystemExit):
                raise
            except:
                LOG.exception("Error in atclosev")

        self.send_octets = None
        self.sock.soclose()
예제 #10
0
def run(argv):

    # /usr/bin/neubot module ...
    del argv[0]
    module = argv[0]

    if module == "help":
        sys.stdout.write("Neubot help -- prints available commands\n")

        commands = " ".join(sorted(MODULES.keys()))
        lines =  textwrap.wrap(commands, 60)
        sys.stdout.write("Commands: " + lines[0] + "\n")
        for s in lines[1:]:
            sys.stdout.write("          " + s + "\n")

        sys.stdout.write("Try `neubot CMD --help` for more help on CMD.\n")
        sys.exit(0)

    if not module in MODULES:
        sys.stderr.write("Invalid module: %s\n" % module)
        sys.stderr.write("Try `neubot help` to list the available modules\n")
        sys.exit(1)

    # Dinamically load the selected module's main() at runtime
    module = "neubot.%s" % MODULES[module]
    __import__(module)
    MAIN = sys.modules[module].main

    # neubot module ...
    argv[0] = "neubot " + argv[0]

    try:
        MAIN(argv)
    except KeyboardInterrupt:
        pass
    except SystemExit:
        raise
    except:
        LOG.exception()
        sys.exit(1)
    sys.exit(0)
예제 #11
0
    logging.debug("DEBUG w/ logging.debug")
    logging.warning("WARNING w/ logging.warning")
    logging.error("ERROR w/ logging.error")

    LOG.error("testing neubot logger -- This is an error message")
    LOG.warning("testing neubot logger -- This is an warning message")
    LOG.info("testing neubot logger -- This is an info message")
    LOG.debug("testing neubot logger -- This is a debug message")
    print compat.json.dumps(LOG.listify())

    try:
        raise Exception("Testing LOG.exception")
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        LOG.exception()
        LOG.exception(func=LOG.warning)

    LOG.start("Testing the in-progress feature")
    LOG.progress("...")
    LOG.progress()
    LOG.complete("success!")

    LOG.oops("Testing the new oops feature")

    # Testing variadic args
    logging.warning("WARNING %s", "variadic warning")
    LOG.warning("WARNING %s", "variadic warning")

    LOG.redirect()
예제 #12
0
 def soclose(self):
     try:
         self.sock.close()
     except ssl.SSLError:
         LOG.exception()
예제 #13
0
 def soclose(self):
     try:
         self.sock.close()
     except socket.error:
         LOG.exception()
예제 #14
0
    def got_response(self, stream, request, response):
        if response.code != "200":
            LOG.complete("bad response")
            self._schedule()
        else:
            LOG.complete()
            s = response.body.read()
            try:
                m1 = marshal.unmarshal_object(s, "application/json",
                  compat.RendezvousResponse)
            except ValueError:
                LOG.exception()
                self._schedule()
            else:
                if "version" in m1.update and "uri" in m1.update:
                    ver, uri = m1.update["version"], m1.update["uri"]
                    LOG.info("Version %s available at %s" % (ver, uri))
                    STATE.update("update", {"version": ver, "uri": uri})

                #
                # Choose the test we would like to run even if
                # we're not going to run it because we're running
                # in debug mode or tests are disabled.
                # This allows us to print to the logger the test
                # we /would/ have choosen if we were allowed to run
                # it.
                #
                tests = []
                if "speedtest" in m1.available:
                    tests.append("speedtest")
                if "bittorrent" in m1.available:
                    tests.append("bittorrent")
                #XXX alternate the two tests
                if self._latest:
                    tests.remove(self._latest)
                test = random.choice(tests)
                self._latest = test
                LOG.info("* Chosen test: %s" % test)

                # Are we allowed to run a test?
                if not CONFIG["enabled"] or CONFIG["rendezvous.client.debug"]:
                    LOG.info("Tests are disabled... not running")
                    self._schedule()
                else:

                    if (CONFIG["privacy.informed"] and
                      not CONFIG["privacy.can_collect"]):
                        LOG.warning("cannot run test without permission "
                          "to save the results")
                        self._schedule()
                    else:

                        conf = self.conf.copy()

                        #
                        # Subscribe _before_ connecting.  This way we
                        # immediately see "testdone" if the connection fails
                        # and we can _schedule the next attempt.
                        #
                        NOTIFIER.subscribe("testdone", lambda *a, **kw: \
                                                         self._schedule())

                        if test == "speedtest":
                            conf["speedtest.client.uri"] =  m1.available[
                                                              "speedtest"][0]
                            client = ClientSpeedtest(POLLER)
                            client.configure(conf)
                            client.connect_uri()

                        elif test == "bittorrent":
                            conf["bittorrent._uri"] =  m1.available[
                                                        "bittorrent"][0]
                            bittorrent.run(POLLER, conf)

                        else:
                            NOTIFIER.publish("testdone")
예제 #15
0
def main(argv):

    slowpath = False
    webgui = False
    start = False
    status = False
    stop = False

    if sys.version_info[0] > 2 or sys.version_info[1] < 5:
        sys.stderr.write("fatal: wrong Python version\n")
        sys.stderr.write("please run neubot using Python >= 2.5 and < 3.0\n")
        sys.exit(1)

    if os.environ.get("NEUBOT_DEBUG", ""):
        from neubot import utils
        if utils.intify(os.environ["NEUBOT_DEBUG"]):
            sys.stderr.write("Running in debug mode\n")
            from neubot.debug import PROFILER
            sys.setprofile(PROFILER.notify_event)

    if os.environ.get("NEUBOT_MEMLEAK", ""):
        from neubot import utils
        if utils.intify(os.environ["NEUBOT_MEMLEAK"]):
            sys.stderr.write("Running in leak-detection mode\n")
            import gc
            gc.set_debug(gc.DEBUG_LEAK)

    # Quick argv classification

    if len(argv) == 1:
        start = True
        webgui = True

    elif len(argv) == 2:
        command = argv[1]
        if command == "--help":
            sys.stdout.write(USAGE)
            sys.exit(0)
        elif command == "-V":
            sys.stdout.write(VERSION + "\n")
            sys.exit(0)
        elif command == "start":
            start = True
        elif command == "status":
            status = True
        elif command == "stop":
            stop = True
        else:
            slowpath = True

    else:
        slowpath = True

    # Slow / quick startup

    if slowpath:
        from neubot.main import module
        module.run(argv)

    else:
        running = False

        # Running?
        if start or status or stop:
            try:
                import httplib

                connection = httplib.HTTPConnection("127.0.0.1", "9774")
                connection.request("GET", "/api/version")
                response = connection.getresponse()
                if response.status == 200:
                    running = True
                response.read()
                connection.close()

            except (SystemExit, KeyboardInterrupt):
                raise
            except:
                pass

        if status:
            if not running:
                sys.stdout.write("Not running\n")
            else:
                sys.stdout.write("Running\n")
            sys.exit(0)

        if running and start:
            sys.stdout.write("Already running\n")
        if not running and stop:
            sys.stdout.write("Not running\n")

        # Stop
        if running and stop:
            try:

                connection = httplib.HTTPConnection("127.0.0.1", "9774")
                connection.request("POST", "/api/exit")
                response = connection.getresponse()
                connection.close()

            except (SystemExit, KeyboardInterrupt):
                raise
            except:
                from neubot.log import LOG
                LOG.exception()
                sys.exit(1)

        # start / webbrowser

        if os.name == "posix":

            #
            # Fork off a child and use it to start the
            # Neubot agent.  The parent process will
            # open the browser, if needed.  Otherwise
            # it will exit.
            #
            if not running and start:
                if os.fork() == 0:
                    from neubot import agent
                    arguments = [ argv[0] ]
                    agent.main(arguments)
                    sys.exit(0)

            #
            # It's not wise at all to open the browser when
            # we are running as root.  Assume that when we
            # are root the user wants just to start the agent.
            #
            if webgui and "DISPLAY" in os.environ:
                if os.getuid() != 0:
                    from neubot.main import browser
                    browser.open_patient("127.0.0.1", "9774")

        elif os.name == "nt":

            if webgui:
                from neubot.main import browser

                if not running and start:
                    browser.open_patient("127.0.0.1", "9774", True)
                else:
                    browser.open_patient("127.0.0.1", "9774")

            if not running and start:
                from neubot import agent
                agent.main([argv[0]])

        else:
            sys.stderr.write("Your operating system is not supported\n")
            sys.exit(1)