def write_empty_tunnel_packet(s: socket.socket, send_lock: threading.Lock, seq: int, mtu: int): m = emptym mlen = mtu put32(m.start, seq) seq += 1 with send_lock: n = s.sendmsg([m.start[:mlen]]) if n != mlen: logger.error("write: bad empty write %d of %d on TFS link", n, mlen) # elif TRACE: # logger.debug("write: %d bytes (%s) on TFS Link", n, binascii.hexlify(m.start[:8])) return None, seq
def sendmsg( socket: Socket, data: bytes, ancillary: List[Tuple[int, int, bytes]] = [], flags: int = 0, ) -> int: """ Send a message on a socket. @param socket: The socket to send the message on. @param data: Bytes to write to the socket. @param ancillary: Extra data to send over the socket outside of the normal datagram or stream mechanism. By default no ancillary data is sent. @param flags: Flags to affect how the message is sent. See the C{MSG_} constants in the sendmsg(2) manual page. By default no flags are set. @return: The return value of the underlying syscall, if it succeeds. """ return socket.sendmsg([data], ancillary, flags)
def send_ack_infos(s: socket.socket, send_lock: threading.Lock, rate: float, outq: MQueue): m = MBuf(MAXBUF, HDRSPACE) start = m.start[4:] periodic = Periodic(rate) # No sequence number put32(m.start, 0xFFFFFFFF) time.sleep(3) m.end = m.start[24:] while periodic.wait(): # cv.acquire() # cv.wait() # cv.release() with outq.lock: # If we haven't seen any sequence (since last reset): if outq.startseq == 0: continue dropcnt = outq.dropcnt outq.dropcnt = 0 ackstart = outq.startseq outq.startseq = 0 ackend = outq.lastseq if dropcnt > 0xFFFFFF: dropcnt = 0xFFFFFF ns = monotonic_ns() # We use the 2nd bit to indicate this is an ACK this normally goes in IKEv2 put32(start, (0x40000000 | dropcnt)) put32(start[4:], (ns >> 32) & 0xFFFFFFFF) put32(start[8:], (ns & 0xFFFFFFFF)) put32(start[12:], ackstart) put32(start[16:], ackend) with send_lock: n = s.sendmsg([m.start[:24]]) if n != 24: logger.error("write: bad ack write %d of %d on TFS link", n, 24) if DEBUG: logger.debug("write ack: %d bytes (%s) on TFS Link", n, binascii.hexlify(m.start[4:24]))
def write_tfs_packet( # pylint: disable=R0912,R0913,R0914,R0915 s: socket.socket, send_lock: threading.Lock, seq: int, mtu: int, leftover: MBuf, inq: MQueue, freeq: MQueue): # if TRACE: # logger.debug("write_tfs_packet seq: %d, mtu %d", seq, mtu) mtuenter = mtu iov = [] freem = [] if leftover: if DEBUG: logger.debug("write_tfs_packet seq: %d, mtu %d leftover %d", seq, mtu, id(leftover)) # This is an mbuf we didn't finish sending last time. m = leftover leftover = None # Set the offset to after this mbuf data. offset = m.len() else: # Try and get a new mbuf to embed m = inq.trypop() offset = 0 if (DEBUG and m): # or TRACE: logger.debug("write_tfs_packet: seq: %d, mtu %d m %d", seq, mtu, id(m)) if not m: return write_empty_tunnel_packet(s, send_lock, seq, mtu) # Prepend our framing to first mbuf. # Would be nice but is broken. put back when we fix mbuf # m.prepend(8) assert (mtu <= mtuenter) # XXX create first IOV of header hdr = memoryview(bytearray(8)) iov.append(hdr) mtu -= len(hdr) assert (mtu <= mtuenter) put32(hdr, seq) put16(hdr[4:], 0) put16(hdr[6:], offset) while mtu > 0: # We need a minimum of 6 bytes to include IPv6 length field. if mtu <= 6 or m is None: if DEBUG: logger.debug("write_tfs_packet: seq %d mtu %d < 6 ", seq, mtu) iov.append(PADBYTES[8:8 + mtu]) assert (mtu <= mtuenter) mtu = 0 break mlen = m.len() assert mlen >= 0 if mlen > mtu: # Room for partial MBUF iov.append(m.start[:mtu]) m.start = m.start[mtu:] leftover = m if DEBUG: logger.debug( "write_tfs_packet: seq %d Add partial(1) MBUF mtu %d of mlen %d mtuenter %d", seq, mtu, mlen, mtuenter) mtu = 0 break # Room for full MBUF iov.append(m.start[:mlen]) freem.append(m) m = None if DEBUG: logger.debug("write_tfs_packet: seq %d Add initial MBUF mlen %d of mtu %d mtuenter %d", seq, mlen, mtu, mtuenter) mtu -= mlen if mtu > 6: m = inq.trypop() iovl = iovlen(iov) if iovl != mtuenter: logger.error("write: bad length %d of mtu %d on TFS link", iovl, mtuenter) with send_lock: n = s.sendmsg(iov) seq += 1 # Update sequence number now that we've written it out. if n != iovl: logger.error("write: bad write %d of %d on TFS link", n, mlen) if leftover: freem.append(leftover) leftover = None elif DEBUG: logger.debug("write: wrote %d bytes on TFS Link", n) # Free any MBufs we are done with. for m in freem: freeq.push(m, True) if leftover: assert (leftover.len() > 0) return leftover, seq
def _send_listening_fd(self, target_sock: socket.socket): msgs = (b'a', ) cmsgs = ((socket.SOL_SOCKET, socket.SCM_RIGHTS, bytes(array.array("i", (self._socket.fileno(), )))), ) target_sock.sendmsg(msgs, cmsgs)