def encode_block_preamble(type, flags, eid_offsets, length): """Encode the standard preamble for a block""" eid_data = '' if len(eid_offsets) != 0: flags = flags | BLOCK_FLAG_EID_REFS eid_data = sdnv.encode(len(eid_offsets)) for o in eid_offsets: eid_data += sdnv.encode(o) return ''.join((struct.pack('B', type), sdnv.encode(flags), eid_data, sdnv.encode(length)))
def test_encode(self, val_pair: tuple): expected = bytearray(val_pair[1]) result = sdnv.encode(val_pair[0]) if expected != result: print(expected, result, expected == result) print(bytes(expected), bytes(result)) raise AssertionError("Result does not match expectations, %s != %s", result, expected)
def gen_ack(length): packet = '' #header indicating ack, and empty flags packet += chr(0x2 << 4) #then the length. util.debug("Tagging of length " + str(length)) packet += sdnv.encode(length) return packet
def encode(bundle): """Encodes all the bundle blocks, not including the preamble for the payload block or the payload data itself, into a binary string.""" data = '' #------------------------------ # Primary block #------------------------------ # Put the eid offsets into the dictionary and append their sdnvs # to the data buffer #this seems like an optimization --kurtis dict_offsets = {} dict_buffer = '' for eid in ( bundle.dest, bundle.source, bundle.replyto, bundle.custodian ) : (scheme, ssp) = eid.split(':') if dict_offsets.has_key(scheme): scheme_offset = dict_offsets[scheme] else: dict_offsets[scheme] = scheme_offset = len(dict_buffer) dict_buffer += scheme dict_buffer += '\0' if dict_offsets.has_key(ssp): ssp_offset = dict_offsets[ssp] else: dict_offsets[ssp] = ssp_offset = len(dict_buffer) dict_buffer += ssp dict_buffer += '\0' data += sdnv.encode(scheme_offset) data += sdnv.encode(ssp_offset) # Now append the creation time and expiration sdnvs, the # dictionary length, and the dictionary itself data += sdnv.encode(bundle.creation_secs) data += sdnv.encode(bundle.creation_seqno) data += sdnv.encode(bundle.expiration) data += sdnv.encode(len(dict_buffer)) data += dict_buffer # Now fill in the preamble portion, including the version, # processing flags and whole length of the block preamble = struct.pack('B', VERSION) preamble += sdnv.encode(bundle.bundle_flags | bundle.priority | bundle.srr_flags) preamble += sdnv.encode(len(data)) return preamble + data
def gen_bundle(b, queue): #first the TCPCL header #header indicating the message type, and flags data_len = len(b.payload) data_file = b.payload.get_file() #fencepost! start = True while (data_len > 0): if (start): #start bundle util.debug("In start of bundle creation") start = False primary_block = bp.encode(b) preamble = bp.encode_block_preamble( bp.PAYLOAD_BLOCK, bp.BLOCK_FLAG_LAST_BLOCK, [], data_len) #using data_len, don't reorder this.. if (data_len < BUFFER_SIZE): #fully contained flags = 0 | bp.START | bp.END data = sdnv.encode( len(primary_block) + len(preamble) + len(b.payload)) data += primary_block + preamble + b.payload.data() data_len -= len(b.payload) else: #start bundle flags = 0 | bp.START data = sdnv.encode( len(primary_block) + len(preamble) + BUFFER_SIZE) data += primary_block + preamble + data_file.read(BUFFER_SIZE) data_len -= BUFFER_SIZE elif (data_len < BUFFER_SIZE): #end bundle util.debug("End bundle") flags = 0 | bp.END data = sdnv.encode(data_len) data += data_file.read(data_len) data_len = 0 else: #data bundle flags = 0 data = sdnv.encode(BUFFER_SIZE) data += data_file.read(BUFFER_SIZE) data_len -= BUFFER_SIZE packet = chr((bp.DATA_SEGMENT << 4) + flags) packet += data #this is fuzzy math queue.put(packet) data_file.close()
def connect(link, eid, keepalive): data = '' #first the magic dtn! part data += "dtn!" #then the version data += chr(bp.VERSION) #then the connection flags, which we'd OR with stuff in bp if needed data += chr(0) #keepalive, two bytes data += chr(0) data += chr(keepalive) #then the length of our address, in sdnv format for some reason #i know this a-priori data += sdnv.encode(len(eid)) #then the address itself data += eid link.socket.send(data) #ok, sent. Listen for response res = link.socket.recv(4096) result = __parse_connect_response(res) if not (res): #bad packet raise Error("Bad DTN response") return min(keepalive, result[2])