def select_poller(timeout=0.0, map=None):
    """A poller which uses select(), available on most platforms."""
    # pylint: disable=redefined-builtin

    if map is None:
        map = socket_map
    if map:
        r = []
        w = []
        e = []
        for fd, obj in list(map.items()):
            is_r = obj.readable()
            is_w = obj.writable()
            if is_r:
                r.append(fd)
            # accepting sockets should not be writable
            if is_w and not obj.accepting:
                w.append(fd)
            if is_r or is_w:
                e.append(fd)
        if [] == r == w == e:
            time.sleep(timeout)
            return

        try:
            r, w, e = select.select(r, w, e, timeout)
        except KeyboardInterrupt:
            return
        except socket.error as err:
            if err.args[0] in (EBADF, EINTR):
                return
        except Exception as err:
            if err.args[0] in (WSAENOTSOCK, ):
                return

        for fd in helper_random.randomsample(r, len(r)):
            obj = map.get(fd)
            if obj is None:
                continue
            read(obj)

        for fd in helper_random.randomsample(w, len(w)):
            obj = map.get(fd)
            if obj is None:
                continue
            write(obj)

        for fd in e:
            obj = map.get(fd)
            if obj is None:
                continue
            _exception(obj)
    else:
        current_thread().stop.wait(timeout)
Beispiel #2
0
    def randomKeys(self, count=1):
        """Retrieve count random keys from the dict
        that haven't already been retrieved"""
        if self.len == 0 or (
            (self.pendingLen >= self.maxPending or self.pendingLen == self.len)
                and self.lastPoll + self.pendingTimeout > time()):
            raise KeyError

        # pylint: disable=redefined-outer-name
        with self.lock:
            # reset if we've requested all
            # and if last object received too long time ago
            if self.pendingLen == self.len and self.lastObject + \
                    self.pendingTimeout < time():
                self.pendingLen = 0
                self.setLastObject()
            available = self.len - self.pendingLen
            if count > available:
                count = available
            randomIndex = helper_random.randomsample(
                range(self.len - self.pendingLen), count)
            retval = [self.indexDict[i] for i in randomIndex]

            for i in sorted(randomIndex, reverse=True):
                # swap with one below lowest pending
                self._swap(i, self.len - self.pendingLen - 1)
                self.pendingLen += 1
            self.lastPoll = time()
            return retval
Beispiel #3
0
    def sendAddr(self):
        """Send a partial list of known addresses to peer."""
        # We are going to share a maximum number of 1000 addrs (per overlapping
        # stream) with our peer. 500 from overlapping streams, 250 from the
        # left child stream, and 250 from the right child stream.
        maxAddrCount = BMConfigParser().safeGetInt("bitmessagesettings",
                                                   "maxaddrperstreamsend", 500)

        templist = []
        addrs = {}
        for stream in self.streams:
            with knownnodes.knownNodesLock:
                for n, s in enumerate((stream, stream * 2, stream * 2 + 1)):
                    nodes = knownnodes.knownNodes.get(s)
                    if not nodes:
                        continue
                    # only if more recent than 3 hours
                    # and having positive or neutral rating
                    filtered = [(k, v) for k, v in nodes.iteritems()
                                if v["lastseen"] > int(time.time()) -
                                shared.maximumAgeOfNodesThatIAdvertiseToOthers
                                and v["rating"] >= 0 and len(k.host) <= 22]
                    # sent 250 only if the remote isn't interested in it
                    elemCount = min(len(filtered),
                                    maxAddrCount / 2 if n else maxAddrCount)
                    addrs[s] = helper_random.randomsample(filtered, elemCount)
        for substream in addrs:
            for peer, params in addrs[substream]:
                templist.append((substream, peer, params["lastseen"]))
        if templist:
            self.append_write_buf(BMProto.assembleAddr(templist))
Beispiel #4
0
    def sendAddr(self):
        # We are going to share a maximum number of 1000 addrs (per overlapping
        # stream) with our peer. 500 from overlapping streams, 250 from the
        # left child stream, and 250 from the right child stream.
        maxAddrCount = BMConfigParser().safeGetInt("bitmessagesettings", "maxaddrperstreamsend", 500)

        # init
        addressCount = 0
        payload = b''

        templist = []
        addrs = {}
        for stream in self.streams:
            with knownnodes.knownNodesLock:
                if len(knownnodes.knownNodes[stream]) > 0:
                    filtered = {k: v for k, v in knownnodes.knownNodes[stream].items()
                        if v["lastseen"] > (int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers)}
                    elemCount = len(filtered)
                    if elemCount > maxAddrCount:
                        elemCount = maxAddrCount
                    # only if more recent than 3 hours
                    addrs[stream] = helper_random.randomsample(filtered.items(), elemCount)
                # sent 250 only if the remote isn't interested in it
                if len(knownnodes.knownNodes[stream * 2]) > 0 and stream not in self.streams:
                    filtered = {k: v for k, v in knownnodes.knownNodes[stream*2].items()
                        if v["lastseen"] > (int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers)}
                    elemCount = len(filtered)
                    if elemCount > maxAddrCount / 2:
                        elemCount = int(maxAddrCount / 2)
                    addrs[stream * 2] = helper_random.randomsample(filtered.items(), elemCount)
                if len(knownnodes.knownNodes[(stream * 2) + 1]) > 0 and stream not in self.streams:
                    filtered = {k: v for k, v in knownnodes.knownNodes[stream*2+1].items()
                        if v["lastseen"] > (int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers)}
                    elemCount = len(filtered)
                    if elemCount > maxAddrCount / 2:
                        elemCount = int(maxAddrCount / 2)
                    addrs[stream * 2 + 1] = helper_random.randomsample(filtered.items(), elemCount)
        for substream in addrs.keys():
            for peer, params in addrs[substream]:
                templist.append((substream, peer, params["lastseen"]))
        if len(templist) > 0:
            self.append_write_buf(BMProto.assembleAddr(templist))
def epoll_poller(timeout=0.0, map=None):
    """A poller which uses epoll(), supported on Linux 2.5.44 and newer."""
    # pylint: disable=redefined-builtin

    if map is None:
        map = socket_map
    try:
        epoll_poller.pollster
    except AttributeError:
        epoll_poller.pollster = select.epoll()
    if map:
        for fd, obj in map.items():
            flags = newflags = 0
            if obj.readable():
                flags |= select.POLLIN | select.POLLPRI
                newflags |= OP_READ
            else:
                newflags &= ~OP_READ
            # accepting sockets should not be writable
            if obj.writable() and not obj.accepting:
                flags |= select.POLLOUT
                newflags |= OP_WRITE
            else:
                newflags &= ~OP_WRITE
            if newflags != obj.poller_flags:
                obj.poller_flags = newflags
                # Only check for exceptions if object was either readable
                # or writable.
                flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL
                try:
                    if obj.poller_registered:
                        epoll_poller.pollster.modify(fd, flags)
                    else:
                        epoll_poller.pollster.register(fd, flags)
                        obj.poller_registered = True
                except IOError:
                    pass
        try:
            r = epoll_poller.pollster.poll(timeout)
        except IOError as e:
            if e.errno != EINTR:
                raise
            r = []
        except select.error as err:
            if err.args[0] != EINTR:
                raise
            r = []
        for fd, flags in helper_random.randomsample(r, len(r)):
            obj = map.get(fd)
            if obj is None:
                continue
            readwrite(obj, flags)
    else:
        current_thread().stop.wait(timeout)
def poll_poller(timeout=0.0, map=None):
    """A poller which uses poll(), available on most UNIXen."""
    # pylint: disable=redefined-builtin

    if map is None:
        map = socket_map
    if timeout is not None:
        # timeout is in milliseconds
        timeout = int(timeout * 1000)
    try:
        poll_poller.pollster
    except AttributeError:
        poll_poller.pollster = select.poll()
    if map:
        for fd, obj in list(map.items()):
            flags = newflags = 0
            if obj.readable():
                flags |= select.POLLIN | select.POLLPRI
                newflags |= OP_READ
            else:
                newflags &= ~OP_READ
            # accepting sockets should not be writable
            if obj.writable() and not obj.accepting:
                flags |= select.POLLOUT
                newflags |= OP_WRITE
            else:
                newflags &= ~OP_WRITE
            if newflags != obj.poller_flags:
                obj.poller_flags = newflags
                try:
                    if obj.poller_registered:
                        poll_poller.pollster.modify(fd, flags)
                    else:
                        poll_poller.pollster.register(fd, flags)
                        obj.poller_registered = True
                except IOError:
                    pass
        try:
            r = poll_poller.pollster.poll(timeout)
        except KeyboardInterrupt:
            r = []
        except socket.error as err:
            if err.args[0] in (EBADF, WSAENOTSOCK, EINTR):
                return
        for fd, flags in helper_random.randomsample(r, len(r)):
            obj = map.get(fd)
            if obj is None:
                continue
            readwrite(obj, flags)
    else:
        current_thread().stop.wait(timeout)
Beispiel #7
0
    def randomKeys(self, count=1):
        if self.len == 0 or (
            (self.pendingLen >= self.maxPending or self.pendingLen == self.len)
                and self.lastPoll + self.pendingTimeout > time()):
            raise KeyError
        with self.lock:
            # reset if we've requested all
            # or if last object received too long time ago
            if self.pendingLen == self.len or self.lastObject + self.pendingTimeout > time(
            ):
                self.pendingLen = 0
            available = self.len - self.pendingLen
            if count > available:
                count = available
            randomIndex = helper_random.randomsample(
                range(self.len - self.pendingLen), count)
            retval = [self.indexDict[i] for i in randomIndex]

            for i in sorted(randomIndex, reverse=True):
                # swap with one below lowest pending
                self._swap(i, self.len - self.pendingLen - 1)
                self.pendingLen += 1
            self.lastPoll = time()
            return retval
def kqueue_poller(timeout=0.0, map=None):
    """A poller which uses kqueue(), BSD specific."""
    # pylint: disable=redefined-builtin,no-member

    if map is None:
        map = socket_map
    try:
        kqueue_poller.pollster
    except AttributeError:
        kqueue_poller.pollster = select.kqueue()
    if map:
        updates = []
        selectables = 0
        for fd, obj in map.items():
            kq_filter = 0
            if obj.readable():
                kq_filter |= 1
                selectables += 1
            if obj.writable() and not obj.accepting:
                kq_filter |= 2
                selectables += 1
            if kq_filter != obj.poller_filter:
                # unlike other pollers, READ and WRITE aren't OR able but have
                # to be set and checked separately
                if kq_filter & 1 != obj.poller_filter & 1:
                    poller_flags = select.KQ_EV_ADD
                    if kq_filter & 1:
                        poller_flags |= select.KQ_EV_ENABLE
                    else:
                        poller_flags |= select.KQ_EV_DISABLE
                    updates.append(
                        select.kevent(fd,
                                      filter=select.KQ_FILTER_READ,
                                      flags=poller_flags))
                if kq_filter & 2 != obj.poller_filter & 2:
                    poller_flags = select.KQ_EV_ADD
                    if kq_filter & 2:
                        poller_flags |= select.KQ_EV_ENABLE
                    else:
                        poller_flags |= select.KQ_EV_DISABLE
                    updates.append(
                        select.kevent(fd,
                                      filter=select.KQ_FILTER_WRITE,
                                      flags=poller_flags))
                obj.poller_filter = kq_filter

        if not selectables:
            # unlike other pollers, kqueue poll does not wait if there are no
            # filters setup
            current_thread().stop.wait(timeout)
            return

        events = kqueue_poller.pollster.control(updates, selectables, timeout)
        if len(events) > 1:
            events = helper_random.randomsample(events, len(events))

        for event in events:
            fd = event.ident
            obj = map.get(fd)
            if obj is None:
                continue
            if event.flags & select.KQ_EV_ERROR:
                _exception(obj)
                continue
            if event.flags & select.KQ_EV_EOF and event.data and event.fflags:
                obj.handle_close()
                continue
            if event.filter == select.KQ_FILTER_READ:
                read(obj)
            if event.filter == select.KQ_FILTER_WRITE:
                write(obj)
    else:
        current_thread().stop.wait(timeout)