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'
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