def _run_binary(self, inter, radius, grid_size=20):
        """Runs binary on area

        Args:
            @inter: the projected polygon in which we are running
                    the binary attack algorithm
            @radius: the radius of the disk to perform the cuts
        """

        vb.vb_print(self.verbose, "Running Binary", "UDP", True)

        last_inter_area = float('inf')
        while (inter.area > self.BINARY_STOP_AREA and
               self.attack_queries < self.query_limit):

            vb.vb_print(self.verbose, "Estimating cut", "UDP", True)
            # find projected coordinates that cut inter in half
            proj_coords = cells.cut(inter, self.proj, radius, grid_size)
            circle = Point(proj_coords[0], proj_coords[1]).buffer(radius * 1000)

            self.json_out["DUDP"].append({"query": self.attack_queries,
                                          "disk": self._log_kml("disk",
                                                                circle),
                                          "active_area": self._log_kml("inter",
                                                                       inter),
                                         })

            # calculate the coordinates for the new cut query
            (query_lon, query_lat) = self.proj(proj_coords[0],
                                               proj_coords[1],
                                               inverse=True)

            self._place_at_coords(self.attacker,
                                  query_lat,
                                  query_lon,
                                  self.test_id)

            if self.oracle is None:
                raise SystemExit("oracle should not be None after coverage")

            oracle_rspn = [None, None]
            attempts = 0
            while oracle_rspn[0] is None:
                # ask the oracle if the victim is in proximity
                oracle_rspn = self.oracle.in_proximity(self.attacker,
                                                       self.victim,
                                                       self.test_id)
                # increase queries
                self.attack_queries += oracle_rspn[1]
                if oracle_rspn[0] is None and attempts > 5:
                    self._update_attacker()
                attempts += 1

            if oracle_rspn[0] is True:
                # if in proximity take the intersection
                inter_new = inter.intersection(circle)
            else:
                # else take the difference
                inter_new = inter.difference(circle)

            if inter_new.is_empty:
                print "\n\n\t ***WARNING!! EMPTY INTERSECTION***\n\n"
                inter = circle
            else:
                inter = inter_new

            # log kml
            self._log_kml("inter", inter)

            # if area is not reduced after intersection
            # break to avoid an infinite loop.
            area = inter.area
            if math.fabs(last_inter_area - area) < self.MIN_REDUCTION * area:
                vb.vb_print(self.verbose,
                            "Area not significantly reduced ..stopping",
                            "UDP",
                            True)
                break
            else:
                last_inter_area = inter.area

        est_location = cells.poly_centroid(inter, self.proj)
        vb.vb_print(self.verbose,
                    "Estimated Location: " + str(est_location),
                    "UDP",
                    True)

        real_est_distance = earth.distance_on_unit_sphere(self.victim.loc[0],
                                                          self.victim.loc[1],
                                                          est_location[0],
                                                          est_location[1])
        # convert to m
        real_est_distance *= 1000
        vb.vb_print(self.verbose,
                    "Distance from real loc: " + str(real_est_distance) + "m",
                    "UDP",
                    True)

        self.json_out["est_location"].append({"query": self.attack_queries,
                                              "area" : inter.area,
                                              "coords": [est_location[0],
                                                         est_location[1]]})
        self.json_out["real_location"].append({"query": -1,
                                               "coords": [self.victim.loc[0],
                                                          self.victim.loc[1]]})

        output_json = ''.join(os.getcwd() + "/" + self.JSON_DIR)
        output_json += self.service_name + "_UDP_"
        with open(output_json + str(self.test_id) + ".json", "w") as outfile:
            json.dump(self.json_out, outfile)

        return real_est_distance
예제 #2
0
    def auditor_handled_place_at_coords(self, user, lat, lon, test_id,
                                       query_id=None):
        """Place a user of the auditing testsuite  at [lat, lon] if that is
        allowed by the speed constraints

        Notice that @auditor_user is not the user passed by the inherited class
        but an instance of the AuditorUser class used by the auditing framework


        Args:
            user: the user to be placed in a new location (AuditorUser instance)
            dist: distance further from the user's location in km
            lat, lon: latitude & longitude
            test_id: the test_id of the test being run

        Return Value:
            Returns a tuple (@result, @queries) where @result is True or False
            depending on whether the location was updated successfully or not.
            @queries is the total queries towards the service required to
            perform the update.

        Raises:
            AuditorException(with optional log data) if inh. class raises it.
            AuditorExceptionUnknown in case an unknown error error occurs
        """

        if not (isinstance(lat, float) and isinstance(lon, float)):
            raise TypeError("lat and lon parameters should be of type float!")

        # get the max distance the user is allowed to travel
        max_distance = self._get_max_distance(user)

        # get the distance of the current location with the new location
        if user.loc[0] is not None and user.loc[1] is not None:
            dist = earth.distance_on_unit_sphere(user.loc[0],
                                                 user.loc[1],
                                                 lat,
                                                 lon)
        else:
            # it's our first update
            dist = 0

        # If we have a speed limit and the distance is bigger than what
        # we are allowed to cross, sleep until we are allowed
        if dist > max_distance:
            sleep_time = (dist - max_distance) / self.speed_limit
            sleep(sleep_time + 1)

        try:
            # given that the clocks won't change and we don't
            # run stuff in parallel, have time as primary key
            if query_id is None:
                query_id = int(time())

            # if we have full logging create query record
            # create it here in case any exception is raised
            if self.logging == const.LOG.ALL:
                query_info = "auditor_set_location: "
                query_info += "[" + str(lat) + "," + str(lon) + "]"
                self._db.insert_query(query_id,
                                     test_id,
                                     user.user_id,
                                     user.service_id,
                                     query_info)

            # do not catch any exceptions here, let the caller handle it
            set_loc_rspn = self.auditor_set_location(user.user,
                                                     lat,
                                                     lon)
            sleep(5)
            if len(set_loc_rspn) != 2:
                raise SystemExit("auditor_set_location must return a tuple!")

            (result, queries) = set_loc_rspn
            if not isinstance(result, bool) and not isinstance(queries, int):
                error = "Wrong return type: Expecting (bool, int) or None"
                raise TypeError(error)

            # if no exception was raised but we failed log it
            if result is False and self.logging == const.LOG.ALL:
                self._db.log_query_fail(query_id)

        except AuditorException:
            if self.logging == const.LOG.ALL:
                self._db.log_query_fail(query_id)
                # handle any data that has been passed by the user
                self._db.exception_recovery(query_id)
            # user has been removed from the pool already
            # so no need to update queries, just return
            return (False, 1)
        except Exception as exception:
            # remove user from active users
            self.users.remove(user.user)
            self._db.log_query_fail(query_id)
            # else raise exception and record failure
            raise AuditorExceptionUnknown(str(exception), user.user_id)

        user.update_queries(queries)
        user.loc = [lat, lon]

        return (result, queries)