예제 #1
0
    def write(self, data):
        """
        Arranges to have data sent.

        @type data: str or bytearray
        """
        data = bytearray(data)

        if self.retransmission_mode == RTM_NONE:
            self.tx_requests.appendleft(Packet(data, self.channel_id, 0))

        elif self.retransmission_mode in (RTM_AUTO, RTM_AUTO_ORDERED):
            self.buffer.appendleft(data)

        elif self.retransmission_mode == RTM_MANUAL:
            self.buffer.clear()
            self.buffer.appendleft(data)

        else:
            raise LNX2Exception, 'Invalid retransmission mode'
예제 #2
0
    def on_sendable(self):
        """
        Called when something can be sent. 

        Returns a packet when it wants something to be sent,
        or raises L{lnx2.NothingToSend} if nothing is to be sent

        @return: L{lnx2.Packet}
        """
        # tx_requests take precedence
        # RTM_NONE write()s directly to tx_requests
        if len(self.tx_requests) > 0:
            return self.tx_requests.pop()

        if self.retransmission_mode == RTM_MANUAL:
            # Two cases are possible: either a new packet
            # can be dispatched, or retransmission should be considered

            if len(self.packs_in_transit) == 0:
                # It seems that a new packet can be sent

                if len(self.buffer) == 0:
                    # There's nothing to send
                    raise NothingToSend

                # A packet can be sent
                data = self.buffer.pop()
                pk = Packet(data, self.channel_id, self.next_send_window_id)
                self.next_send_window_id = (self.next_send_window_id + 1) % 64
                self.packs_in_transit[pk.window_id] = time.time(), pk
                return pk

            else:
                # Consider a retransmission
                ctime = time.time()

                time_sent, pack = self.packs_in_transit.itervalues().next()
                if ctime - time_sent > self.retransmission_timeout:
                    # Yes, a retransmission is in works
                    if len(self.buffer) > 0:
                        # User ordered a change to packet in meantime
                        pack = Packet(self.buffer.pop(), \
                                      self.channel_id, pack.window_id)

                    self.packs_in_transit[pack.window_id] = ctime, pack
                    return pack

                raise NothingToSend  # no retransmission needed

        elif self.retransmission_mode in (RTM_AUTO, RTM_AUTO_ORDERED):
            if len(self.buffer) > 0:
                # We can consider sending a new packet
                if len(self.packs_in_transit) < self.max_bundle_size:
                    # We seem to be allowed to sent a new packet
                    nwid = self.next_send_window_id

                    # Check if there's an unsent window ID that has not
                    # been confirmed
                    naxid = nwid - self.max_bundle_size
                    if naxid < 0: naxid += 64

                    if naxid not in self.packs_in_transit:
                        # there are no missing windows. Go on.
                        self.next_send_window_id = (self.next_send_window_id +
                                                    1) % 64

                        pk = Packet(self.buffer.pop(), self.channel_id, nwid)
                        self.packs_in_transit[nwid] = time.time(), pk
                        return pk

            ctime = time.time()
            # Check for retransmissions then
            for time_sent, pack in self.packs_in_transit.itervalues():
                if ctime - time_sent > self.retransmission_timeout:
                    # A retransmission needs to be made
                    self.packs_in_transit[pack.window_id] = ctime, pack
                    return pack

        raise NothingToSend