static int bundle_encode_block(struct bundle_block_t *block, uint8_t *buffer, int max_len) { uint32_t offs = 0; int ret; uint32_t value; /* Encode the next block */ buffer[offs] = block->type; offs++; /* Flags */ ret = sdnv_encode(block->flags, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Blocksize */ value = block->block_size; ret = sdnv_encode(value, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Payload */ memcpy(&buffer[offs], block->payload, block->block_size); offs += block->block_size; return offs; }
int dtntp_discovery_add_service(uint8_t * ipnd_buffer, int length, int * offset) { char string_buffer[60]; int len; udtn_timeval_t tv; float rating; // get local clock rating rating = dtntp_get_rating(); // do not send sync beacons if clock rating is zero if (rating == 0.0) return 0; // get local time udtn_gettimeofday(&tv); // do not send sync beacons if the clock timestamp is wrong if (tv.tv_sec < UDTN_CLOCK_DTN_EPOCH_OFFSET) return 0; // Convert timestamp into DTN time tv.tv_sec -= UDTN_CLOCK_DTN_EPOCH_OFFSET; len = sprintf(string_buffer, DTNTP_SERVICE_TAG); (*offset) += sdnv_encode(len, ipnd_buffer + (*offset), length - (*offset)); memcpy(ipnd_buffer + (*offset), string_buffer, len); (*offset) += len; if (rating < 1.0f) { len = sprintf(string_buffer, "version=2;quality=0.%lu;timestamp=%li;", \ (unsigned long)(rating * 1000000), tv.tv_sec); } else { len = sprintf(string_buffer, "version=2;quality=1.0;timestamp=%li;", \ tv.tv_sec); } (*offset) += sdnv_encode(len, ipnd_buffer + (*offset), length - (*offset)); memcpy(ipnd_buffer + (*offset), string_buffer, len); (*offset) += len; return 1; }
/** * \brief Encodes the age extension block * \param bundlemem Bundle MMEM Pointer * \param buffer Block Payload Pointer * \param max_len Block Payload Length * \return Length of encoded block payload */ uint8_t bundle_ageing_encode_age_extension_block(struct mmem *bundlemem, uint8_t *buffer, int max_len) { struct bundle_t *bundle; uint32_t length = 0; uint8_t offset = 0; uint8_t tmpbuffer[10]; uint32_t flags = 0; int ret; if( bundlemem == NULL ) { return 0; } bundle = (struct bundle_t *) MMEM_PTR(bundlemem); if( bundle == NULL ) { return 0; } #if UDTN_SUPPORT_LONG_AEB /* Update the age value * 4294967 = 0xFFFFFFFF / 1000 */ if( bundle_ageing_get_age(bundlemem) > 4294967 ) { // Keep use of 64 bit data types as low as possible for performance reasons uint64_t age = 0; age = ((uint64_t) bundle_ageing_get_age(bundlemem)) * ((uint64_t) 1000); length = sdnv_encode_long(age, tmpbuffer, 10); } else { uint32_t age = 0; age = bundle_ageing_get_age(bundlemem) * 1000; length = sdnv_encode(age, tmpbuffer, 10); } #else uint32_t age = 0; age = bundle_ageing_get_age(bundlemem) * 1000; length = sdnv_encode(age, tmpbuffer, 10); #endif /* Encode the next block */ buffer[offset] = BUNDLE_BLOCK_TYPE_AEB; offset++; /* Flags */ flags = BUNDLE_BLOCK_FLAG_REPL; ret = sdnv_encode(flags, &buffer[offset], max_len - offset); if (ret < 0) { return 0; } offset += ret; /* Blocksize */ ret = sdnv_encode(length, &buffer[offset], max_len - offset); if (ret < 0) { return 0; } offset += ret; /* Payload */ memcpy(&buffer[offset], tmpbuffer, length); offset += length; return offset; }
int main(int argc, char* argv[]) { size_t i; memset(buf, 0, sizeof(buf)); progname = strrchr(argv[0], '/'); if (progname == 0) { progname = argv[0]; } else { progname++; } if (!strcmp(progname, "num2sdnv")) { mode = ENCODE; } else if (!strcmp(progname, "sdnv2num")) { mode = DECODE; } argv++; argc--; while (argc > 1) { char* arg = argv[0]; argv++; argc--; if (!strcmp(arg, "-e")) { mode = ENCODE; } else if (!strcmp(arg, "-d")) { mode = DECODE; } else { fprintf(stderr, "unknown argument %s\n", arg); exit(1); } } if (argc != 1 || mode == 0) { fprintf(stderr, "usage: %s [-de] <num>\n" " -e encode number to sdnv\n" " -d decode sdnv to number\n", progname); exit(1); } numstr = argv[0]; if (mode == ENCODE) { if (numstr[0] == '0' && numstr[1] == 'x') { val = strtoull(numstr + 2, &end, 16); } else { val = strtoull(numstr, &end, 10); } if (*end != '\0') { fprintf(stderr, "invalid number %s\n", numstr); exit(1); } len = sdnv_encode(val, buf, sizeof(buf)); } else { if (numstr[0] == '0' && numstr[1] == 'x') { numstr += 2; } if ((strlen(numstr) % 2) != 0) { fprintf(stderr, "number string %s must contain full bytes\n", numstr); exit(1); } for (i = 0; i < strlen(numstr) / 2; ++i) { buf[i] = (HEXTONUM(numstr[2*i]) << 4) + HEXTONUM(numstr[2*i + 1]); } len = sdnv_decode(buf, strlen(numstr)/2, &val); } printf("val: %llu (0x%llx)\n", (unsigned long long)val, (unsigned long long)val); printf("len: %d\n", len); printf("sdnv: "); if (len > 0) { for (i = 0; i < (size_t)len; ++i) { printf("%c%c", hex[(buf[i] >> 4) & 0xf], hex[buf[i] & 0xf]); } } printf("\n"); return 0; }
int bundle_encode_bundle(struct mmem *bundlemem, uint8_t *buffer, int max_len) { uint8_t i; uint32_t value, offs = 0, blklen_offs; int ret, blklen_size; struct bundle_t *bundle = (struct bundle_t *) MMEM_PTR(bundlemem); struct bundle_block_t *block; /* Hardcode the version to 0x06 */ buffer[0] = 0x06; offs++; /* Flags */ ret = sdnv_encode(bundle->flags, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Block length will be calculated later * reserve one byte for now */ blklen_offs = offs; offs++; /* Destination node + SSP */ ret = sdnv_encode(bundle->dst_node, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; ret = sdnv_encode_long(bundle->dst_srv, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Source node + SSP */ ret = sdnv_encode(bundle->src_node, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; ret = sdnv_encode_long(bundle->src_srv, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Report-to node + SSP */ ret = sdnv_encode(bundle->rep_node, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; ret = sdnv_encode(bundle->rep_srv, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Custodian node + SSP */ ret = sdnv_encode(bundle->cust_node, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; ret = sdnv_encode(bundle->cust_srv, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Creation Timestamp */ ret = sdnv_encode_long(bundle->tstamp, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Creation Timestamp Sequence Number */ ret = sdnv_encode(bundle->tstamp_seq, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Lifetime */ ret = sdnv_encode(bundle->lifetime, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Directory Length */ ret = sdnv_encode(0l, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; if (bundle->flags & BUNDLE_FLAG_FRAGMENT) { LOG(LOGD_DTN, LOG_BUNDLE, LOGL_INF, "Bundle is a fragment"); /* Fragment Offset */ ret = sdnv_encode(bundle->frag_offs, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; /* Total App Data Unit Length */ ret = sdnv_encode(bundle->app_len, &buffer[offs], max_len - offs); if (ret < 0) return -1; offs += ret; } /* Calculate block length value */ value = offs - blklen_offs - 1; blklen_size = sdnv_encoding_len(value); /* Move the data around */ if (blklen_size > 1) { memmove(&buffer[blklen_offs+blklen_size], &buffer[blklen_offs+1], value); } ret = sdnv_encode(value, &buffer[blklen_offs], blklen_size); offs += ret-1; /* Encode Bundle Age Block - always as first block */ offs += bundle_ageing_encode_age_extension_block(bundlemem, &buffer[offs], max_len - offs); block = (struct bundle_block_t *) bundle->block_data; for (i=0;i<bundle->num_blocks;i++) { offs += bundle_encode_block(block, &buffer[offs], max_len - offs); /* Reference the next block */ block = (struct bundle_block_t *) &block->payload[block->block_size]; } return offs; }