--- a/apps/dtnrespond/dtnrespond.c Tue Oct 18 11:52:07 2011 +0100
+++ b/apps/dtnrespond/dtnrespond.c Mon Oct 24 18:28:33 2011 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2006 Intel Corporation
+ * Copyright 2010-2011 Trinity College Dublin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,8 +34,6 @@
#define BLOCKSIZE 8192
#define COUNTER_MAX_DIGITS 9
-#define DTN_BPQ_BLOCK_TYPE 0xC8
-
// Find the maximum commandline length
#ifdef __FreeBSD__
/* Needed for PATH_MAX, Linux doesn't need it */
@@ -241,11 +239,17 @@
exit(1); \
}
+ FILE* file;
+
REQUIRE(strlen(local_eid_name) > 0, "-l <local eid> required\n");
REQUIRE(strlen(reply_eid_name) > 0, "-r <reply eid> required\n");
REQUIRE(strlen(matching_filename) > 0, "-f <matching filename> required\n");
+ REQUIRE((file = fopen(matching_filename, "r")) != 0, "matching file not found");
- return 0;
+ fclose (file);
+ return DTN_SUCCESS;
+
+#undef REQUIRE
}
/*******************************************************************************
@@ -338,7 +342,6 @@
* parse eid:
*
* code lifted from dtnsend
-* todo: check this
*******************************************************************************/
dtn_endpoint_id_t *
parse_eid(dtn_handle_t handle,
@@ -367,7 +370,7 @@
/*******************************************************************************
* trim whitespace:
* first move past any leading whitespace
-* after the first non-whitespace char bef=gin copying to output
+* after the first non-whitespace char begin copying to output
* finish by setting any trailing whitespace to 0
* @return 0 on success or -1 if input not completely read
*******************************************************************************/
@@ -375,32 +378,33 @@
trim_whitespace(const char * in, char * out, int out_len)
{
int i=0, j=0;
- char space = ' ';
- char tab = '\t';
+ int in_len;
+ char whitespace[] = " \t\n\r";
memset(out, 0, out_len);
// move past any leading whitespace
- while (i<strlen(in) && in[i] == space ||
- i<strlen(in) && in[i] == tab)
- ++i;
+ // by testing if the current char is in the whitespace string
+ while ( i<strlen(in) && strchr(whitespace, in[i]) != NULL )
+ ++i;
+
+ in_len = strlen(&(in[i]));
+ if (in_len > out_len) {
+ fprintf(stderr, "Error trimming whitespace, input string [%d] is longer"
+ " than output string [%d]\n", in_len, out_len);
+ return -1;
+ }
- // body case
- for ( ; i<strlen(in) && j<out_len-2; ++i){
- out[j++] = in[i];
- }
+ // copy the body
+ strncpy(out, &(in[i]), in_len);
// remove any trailing whitespace
- // out[j] now points to the null char that terminates the string
- j--;
- while (j >= 0 && out[j] == space ||
- j >= 0 && out[j] == tab)
- out[j--] = 0;
+ // by testing if the current char is in the whitespace string
+ for (j = strlen(out)-1; strchr(whitespace, in[i]) != NULL; --j)
+ out[j--] = 0;
- if (i < strlen(in))
- return -1;
- else
- return 0;
+ return 0;
+
}
/*******************************************************************************
@@ -439,48 +443,29 @@
}
/*******************************************************************************
-* find query
-* search all files in 'dir' for a query match
-* test against query len & query val and update found
-* @return 0 or -1 if error
+* response_path_exists
+* first escape any spaces in the path name
+* then try to open the file for reading
+* @return 0 if exists or -1 if not found
*******************************************************************************/
int
-find_query(const char * dir, const char * query, int * found)
+response_path_exists(const char * path)
{
FILE *file;
- int i, status;
- char ls_result[PATH_MAX];
- char ls_cmd[PATH_MAX];
- char esc_dir[PATH_MAX];
-
- *found = 0;
+ char esc_path[PATH_MAX];
// trim & escape spaces in dir before calling ls
- if (escape_spaces(dir, esc_dir, PATH_MAX) != DTN_SUCCESS)
+ if (escape_spaces(path, esc_path, PATH_MAX) != DTN_SUCCESS)
return -1;
- snprintf (ls_cmd, PATH_MAX, "ls %s", esc_dir);
- file = popen (ls_cmd, "r");
-
- if (file == NULL)
- return -1;
-
- for (i=0; fgets(ls_result, PATH_MAX, file) != NULL; ++i) {
- if (ls_result[strlen(ls_result)-1] == '\n')
- ls_result[strlen(ls_result)-1] = 0;
-
- if (strlen(query) == strlen(ls_result) &&
- strncmp (query, ls_result, strlen(query)) == 0) {
- *found = 1;
- break;
- }
+ if ((file = fopen(esc_path, "r")) == 0) {
+ fprintf(stderr, "Error: the path %s specified in the matching file"
+ " could not be found\n", path);
+ return -1;
+ } else {
+ fclose (file);
+ return 0;
}
-
- status = pclose(file);
- if (status == -1)
- return -1;
-
- return 0;
}
@@ -488,50 +473,69 @@
* match bpq:
* read in paths to search for query in from 'matching file'
* for each record in the matching file, extract the response path
-* matching file format: [matching_rule, encoding, query, response_path, expiry]
+* matching file format: [matching_rule, query, response_path, response_type, expiry]
*******************************************************************************/
int
match_bpq(const dtn_bpq_extension_block_data_t * bpq,
const char * matching_filename,
- char * pathname,
- int * found)
+ u_int * response_kind,
+ char * response_path,
+ int response_path_len,
+ int * response_expiry,
+ int * found)
{
char line[PATH_MAX];
- char trim_response_path[PATH_MAX];
- char * response_path;
+ char trim_path[PATH_MAX];
+ char * matching_rule;
+ char * query;
+ char * path;
+ char * kind;
+ char * expiry;
FILE * file;
-
- *found = 0;
if ((file = fopen(matching_filename, "r")) == 0)
return -1;
- memset(line, 0 , PATH_MAX);
- while (fgets(line, PATH_MAX, file) != NULL) {
- strtok(line, ",");
- strtok(NULL, ",");
- strtok(NULL, ",");
- response_path = strtok(NULL, ",");
-// expiry = strtok(NULL, ",");
+ while (1) {
+ memset(line, 0 , PATH_MAX);
+ *found = 0;
+
+ // read line from matching file
+ // TODO: handle malformed input from matching file
+ if (fgets(line, PATH_MAX, file) == NULL) {
+ break;
+ } else {
+ matching_rule = strtok(line, ",");
+ query = strtok(NULL, ",");
+ path = strtok(NULL, ",");
+ kind = strtok(NULL, ",");
+ expiry = strtok(NULL, ",");
+ }
+
+ // match query
+ if (atoi(matching_rule) != (int)bpq->matching_rule ||
+ BPQ_MATCHING_RULE_EXACT != bpq->matching_rule ||
+ strlen(query) != bpq->query.query_len ||
+ strncmp(query, bpq->query.query_val, bpq->query.query_len) != 0) {
+
+ continue;
+ }
+
// trim whitespace from response path
- trim_whitespace(response_path, trim_response_path, PATH_MAX);
-
- if (find_query(trim_response_path, bpq->query.query_val, found) != DTN_SUCCESS)
- return -1;
+ trim_whitespace(path, trim_path, PATH_MAX);
- // if found build pathname and stop looking
- if (*found == 1) {
- // ensure path ends in slash
- if (trim_response_path[strlen(trim_response_path)-1] == '/'){
- snprintf(pathname, PATH_MAX, "%s%s", trim_response_path, bpq->query.query_val);
- } else {
- snprintf(pathname, PATH_MAX, "%s/%s", trim_response_path, bpq->query.query_val);
- }
+ // make sure the file exists
+ if (response_path_exists(trim_path)) {
+ *found = 1;
+ *response_kind = (u_int) atoi(kind);
+ *response_expiry = atoi(response_expiry);
+ strncpy(response_path, trim_path, response_path_len);
- break;
+ break;
+ } else {
+ continue;
}
- memset(line, 0 , PATH_MAX);
}
fclose (file);
@@ -539,15 +543,23 @@
}
/*******************************************************************************
-* bpq to char array:
-* encode as SDNVs,
-* BPQ-kind 1-byte
-* matching rule type 1-byte
-* BPQ-value-length SDNV
-* BPQ-value n-bytes
-* number of fragments SDNV
-* fragment offsets SDNV
-* fragment lengths SDNV
+* bpq to char array
+* encode the following information:
+*
+* BPQ-kind 1-byte
+* Matching rule 1-byte
+*
+* Creation time-stamp sec SDNV
+* Creation time-stamp seq SDNV
+* Source EID length SDNV
+* Source EID n-bytes
+*
+* Query value length SDNV
+* Query value n-bytes
+*
+* Number of fragments SDNV
+* Fragment offsets SDNV
+* Fragment lengths SDNV
*
* @return The number of bytes or -1 on error
*******************************************************************************/
@@ -561,49 +573,117 @@
int q_encoding_len, f_encoding_len, encoding_len;
char encoding[PATH_MAX];
+ memset(buf, 0, buf_len);
+
// BPQ-kind 1-byte
if (i < buf_len) buf[i++] = (char) bpq->kind;
// matching rule type 1-byte
if (i < buf_len) buf[i++] = (char) bpq->matching_rule;
- // BPQ-value-length SDNV
- if ( (q_encoding_len = sdnv_encode (bpq->query.query_len, encoding, PATH_MAX)) == -1 )
+ // Timestamp secs (SDNV)
+ if ( (q_encoding_len = sdnv_encode (bpq->original_id.creation_ts.secs,
+ encoding, PATH_MAX)) == -1 ) {
+ fprintf (stderr, "Error encoding creation timestamp secs\n");
+ return -1;
+ } else {
+ for (j=0; i<buf_len && j<q_encoding_len; ++j)
+ buf[i++] = encoding[j];
+ }
+
+ // Timestamp seqno (SDNV)
+ if ( (q_encoding_len = sdnv_encode (bpq->original_id.creation_ts.seqno,
+ encoding, PATH_MAX)) == -1 ) {
+ fprintf (stderr, "Error encoding creation timestamp seqno\n");
+ return -1;
+ } else {
+ for (j=0; i<buf_len && j<q_encoding_len; ++j)
+ buf[i++] = encoding[j];
+ }
+
+ // Source EID len (SDNV)
+ if ( (q_encoding_len = sdnv_encode (bpq->original_id.source_len,
+ encoding, PATH_MAX)) == -1 ) {
+ fprintf (stderr, "Error encoding source EID len\n");
+ return -1;
+ } else {
+ for (j=0; i<buf_len && j<q_encoding_len; ++j)
+ buf[i++] = encoding[j];
+ }
+
+ // Source EID n-bytes
+ for (j=0; i<buf_len && j<bpq->original_id.source_len; ++j)
+ buf[i++] = bpq->original_id.source.uri[j];
+
+
+
+ // Query length (SDNV)
+ if ( (q_encoding_len = sdnv_encode (bpq->query.query_len,
+ encoding, PATH_MAX)) == -1 ) {
+ fprintf (stderr, "Error encoding query len\n");
return -1;
- for (j=0; i<buf_len && j<q_encoding_len; ++j)
- buf[i++] = encoding[j];
+ } else {
+ for (j=0; i<buf_len && j<q_encoding_len; ++j)
+ buf[i++] = encoding[j];
+ }
- // BPQ-value n-bytes
+ // Query value n-bytes
for (j=0; i<buf_len && j<bpq->query.query_len; ++j)
buf[i++] = bpq->query.query_val[j];
+
+
// number of fragments SDNV
- if ( (f_encoding_len = sdnv_encode (bpq->fragments.num_frag_returned, encoding, PATH_MAX)) == -1 )
+ if ( (f_encoding_len = sdnv_encode (bpq->fragments.num_frag_returned,
+ encoding, PATH_MAX)) == -1 ){
+ fprintf (stderr, "Error encoding number of fragments\n");
return -1;
- for (j=0; i<buf_len && j<f_encoding_len; ++j)
- buf[i++] = encoding[j];
+ } else {
+ for (j=0; i<buf_len && j<f_encoding_len; ++j)
+ buf[i++] = encoding[j];
+ }
for (k=0; k<bpq->fragments.num_frag_returned; ++k) {
// fragment offsets SDNV
- if ( (encoding_len = sdnv_encode (bpq->fragments.frag_offsets[k], encoding, PATH_MAX)) == -1 )
- return -1;
- for (j=0; i<buf_len && j<encoding_len; ++j)
- buf[i++] = encoding[j];
+ if ( (encoding_len = sdnv_encode (bpq->fragments.frag_offsets[k],
+ encoding, PATH_MAX)) == -1 ) {
+ fprintf (stderr, "Error encoding fragment offset[%d]\n", k);
+ return -1;
+ } else {
+ for (j=0; i<buf_len && j<encoding_len; ++j)
+ buf[i++] = encoding[j];
+ }
// fragment lengths SDNV
- if ( (encoding_len = sdnv_encode (bpq->fragments.frag_lenghts[k], encoding, PATH_MAX)) == -1 )
- return -1;
- for (j=0; i<buf_len && j<encoding_len; ++j)
- buf[i++] = encoding[j];
+ if ( (encoding_len = sdnv_encode (bpq->fragments.frag_lenghts[k],
+ encoding, PATH_MAX)) == -1 ) {
+ fprintf (stderr, "Error encoding fragment length[%d]\n", k);
+ return -1;
+ } else {
+ for (j=0; i<buf_len && j<encoding_len; ++j)
+ buf[i++] = encoding[j];
+ }
}
+
if (verbose) {
fprintf (stdout, "\nbpq_to_char_array (buf_len:%d, i:%d):\n",buf_len,i);
fprintf (stdout, " kind: %d\n", (int) buf[0]);
fprintf (stdout, " matching rule: %d\n", (int) buf[1]);
+
+ fprintf (stdout, " creation ts sec: %d\n",
+ (int) bpq->original_id.creation_ts.secs);
+ fprintf (stdout, " creation ts seq: %d\n",
+ (int) bpq->original_id.creation_ts.seqno);
+ fprintf (stdout, " source eid len: %d\n",
+ (int) bpq->original_id.source_len);
+ fprintf (stdout, " source eid: %s\n",
+ (int) bpq->original_id.source.uri);
+
fprintf (stdout, " query len: %d\n", bpq->query.query_len);
fprintf (stdout, " q_encoding_len: %d\n", q_encoding_len);
fprintf (stdout, " query val: %s\n", bpq->query.query_val);
+
fprintf (stdout, " fragment len: %d\n", bpq->fragments.num_frag_returned);
fprintf (stdout, " f_encoding_len: %d\n\n", f_encoding_len);
}
@@ -612,17 +692,25 @@
}
/*******************************************************************************
-* char array to bpq:
-* decode as SDNVs,
-* BPQ-kind 1-byte
-* matching rule type 1-byte
-* BPQ-value-length SDNV
-* BPQ-value n-bytes
-* number of fragments SDNV
-* fragment offsets SDNV
-* fragment lengths SDNV
+* char array to bpq
+* decode the following information:
+*
+* BPQ-kind 1-byte
+* Matching rule 1-byte
*
-* @return DTN_SUCCESS or -1 on error
+* Creation time-stamp sec SDNV
+* Creation time-stamp seq SDNV
+* Source EID length SDNV
+* Source EID n-bytes
+*
+* Query value length SDNV
+* Query value n-bytes
+*
+* Number of fragments SDNV
+* Fragment offsets SDNV
+* Fragment lengths SDNV
+*
+* @return The number of bytes or -1 on error
*******************************************************************************/
int
char_array_to_bpq(const char* buf,
@@ -639,8 +727,50 @@
// matching rule type 1-byte
if (i<buf_len) bpq->matching_rule = (u_int) buf[i++];
+
+
+ // Creation time-stamp sec SDNV
+ if ( (q_decoding_len = sdnv_decode (&(buf[i]),
+ buf_len - i,
+ &(bpq->original_id.creation_ts.secs))) == -1 ) {
+ fprintf (stderr, "Error decoding creation time-stamp sec\n");
+ return -1;
+ }
+ i += q_decoding_len;
+
+ // Creation time-stamp seq SDNV
+ if ( (q_decoding_len = sdnv_decode (&(buf[i]),
+ buf_len - i,
+ &(bpq->original_id.creation_ts.seqno))) == -1 ) {
+ fprintf (stderr, "Error decoding creation time-stamp seq\n");
+ return -1;
+ }
+ i += q_decoding_len;
+
+ // Source EID length SDNV
+ if ( (q_decoding_len = sdnv_decode (&(buf[i]),
+ buf_len - i,
+ &(bpq->original_id.source_len))) == -1 ) {
+ fprintf (stderr, "Error decoding source EID length\n");
+ return -1;
+ }
+ i += q_decoding_len;
+
+ // Source EID n-bytes
+ if (i<buf_len && bpq->original_id.source_len <= DTN_MAX_ENDPOINT_ID) {
+ strncpy(bpq->original_id.source.uri, &(buf[i]), bpq->original_id.source_len);
+ i += bpq->original_id.source_len;
+ } else {
+ fprintf (stderr, "Error copying source EID\n");
+ return -1;
+ }
+
+
+
// BPQ-value-length SDNV
- if ( (q_decoding_len = sdnv_decode (&(buf[i]), buf_len - i, &(bpq->query.query_len))) == -1 ) {
+ if ( (q_decoding_len = sdnv_decode (&(buf[i]),
+ buf_len - i,
+ &(bpq->query.query_len))) == -1 ) {
fprintf (stderr, "Error decoding BPQ-value-length\n");
return -1;
}
@@ -648,10 +778,13 @@
// BPQ-value n-bytes
if (i<buf_len) bpq->query.query_val = &(buf[i]);
- i += bpq->query.query_len;
+ i += bpq->query.query_len;
+
// number of fragments SDNV
- if ( (f_decoding_len = sdnv_decode (&(buf[i]), buf_len - i, &(bpq->fragments.num_frag_returned))) == -1 ) {
+ if ( (f_decoding_len = sdnv_decode (&(buf[i]),
+ buf_len - i,
+ &(bpq->fragments.num_frag_returned))) == -1 ) {
fprintf (stderr, "Error decoding number of fragments\n");
return -1;
}
@@ -660,14 +793,18 @@
for (j=0; i<buf_len && j<bpq->fragments.num_frag_returned; ++j) {
// fragment offsets SDNV
- if ( (decoding_len = sdnv_decode (&(buf[i]), buf_len - i, &(bpq->fragments.frag_offsets[j]))) == -1 ) {
+ if ( (decoding_len = sdnv_decode (&(buf[i]),
+ buf_len - i,
+ &(bpq->fragments.frag_offsets[j]))) == -1 ) {
fprintf (stderr, "Error decoding fragment[%d] offset\n", j);
return -1;
}
i += decoding_len;
// fragment lengths SDNV
- if ( (decoding_len = sdnv_decode (&(buf[i]), buf_len - i, &(bpq->fragments.frag_lenghts[j]))) == -1 ) {
+ if ( (decoding_len = sdnv_decode (&(buf[i]),
+ buf_len - i,
+ &(bpq->fragments.frag_lenghts[j]))) == -1 ) {
fprintf (stderr, "Error decoding fragment[%d] length\n", j);
return -1;
}
@@ -681,9 +818,20 @@
fprintf (stdout, "\nchar_array_to_bpq (buf_len:%d, i:%d):\n",buf_len, i);
fprintf (stdout, " kind: %d\n", (int) buf[0]);
fprintf (stdout, " matching rule: %d\n", (int) buf[1]);
+
+ fprintf (stdout, " creation ts sec: %d\n",
+ (int) bpq->original_id.creation_ts.secs);
+ fprintf (stdout, " creation ts seq: %d\n",
+ (int) bpq->original_id.creation_ts.seqno);
+ fprintf (stdout, " source eid len: %d\n",
+ (int) bpq->original_id.source_len);
+ fprintf (stdout, " source eid: %s\n",
+ (int) bpq->original_id.source.uri);
+
fprintf (stdout, " query len: %d\n", bpq->query.query_len);
fprintf (stdout, " q_decoding_len: %d\n", q_decoding_len);
fprintf (stdout, " query val: %s\n", bpq->query.query_val);
+
fprintf (stdout, " fragment len: %d\n", bpq->fragments.num_frag_returned);
fprintf (stdout, " f_decoding_len: %d\n\n", f_decoding_len);
}
@@ -701,6 +849,7 @@
int
send_response_bpq(dtn_handle_t * handle,
dtn_reg_id_t regid,
+ u_int response_kind,
dtn_bundle_spec_t * query_bundle_spec,
const dtn_endpoint_id_t * reply_eid,
dtn_bpq_extension_block_data_t * query_bpq_block_data,
@@ -718,8 +867,6 @@
dtn_extension_block_t response_bpq_block;
dtn_bpq_extension_block_data_t response_bpq_block_data;
dtn_bundle_payload_t response_payload;
- u_int offsets[1];
- u_int lengths[1];
memset(buf, 0, PATH_MAX);
memset(&response_bundle_spec, 0, sizeof(dtn_bundle_spec_t));
@@ -731,19 +878,11 @@
dtn_set_payload(&response_payload, DTN_PAYLOAD_FILE, pathname, strlen(pathname));
// set the bpq block data
- response_bpq_block_data.kind = BPQ_BLOCK_KIND_RESPONSE;
+ response_bpq_block_data.kind = response_kind;
response_bpq_block_data.matching_rule = query_bpq_block_data->matching_rule;
response_bpq_block_data.query.query_len = query_bpq_block_data->query.query_len;
response_bpq_block_data.query.query_val = query_bpq_block_data->query.query_val;
- offsets[0] = 0;
- lengths[0] = 100; //todo: add payload length here
-
-/* REMOVING TODO - CHECK THE RFC TO MAKE SURE THIS IS OK
- response_bpq_block_data.fragments.num_frag_returned = 1;
- response_bpq_block_data.fragments.frag_offsets = offsets;
- response_bpq_block_data.fragments.frag_lenghts = lengths;
-*/
if ( (buf_len = bpq_to_char_array(&response_bpq_block_data, buf, PATH_MAX, verbose)) == -1 ) {
fprintf (stderr, "error encoding bpq: %d", buf_len);
return -1;
@@ -804,6 +943,7 @@
int verbose)
{
int i, j, num_blocks, found, ret = 0;
+ u_int response_kind;
char pathname[PATH_MAX];
dtn_bundle_spec_t bundle_spec;
dtn_extension_block_t * bpq_blocks;
@@ -811,7 +951,7 @@
dtn_bundle_payload_t payload;
// start listening for bpq bundles
- for (i = 0; count == -1 || i < count; ++i) {
+ for (i = 0; count == 0 || i < count; ++i) {
found = 0;
memset(&bundle_spec, 0, sizeof(dtn_bundle_spec_t));
memset(&bpq_block_data, 0, sizeof(dtn_bpq_extension_block_data_t));
@@ -856,7 +996,14 @@
return ret;
}
- match_bpq(&bpq_block_data, matching_filename, pathname, &found);
+ match_bpq( &bpq_block_data,
+ matching_filename,
+ &response_kind,
+ pathname,
+ PATH_MAX,
+ &bundle_expiry,
+ &found);
+
break;
}
}
@@ -868,6 +1015,7 @@
ret = send_response_bpq(handle,
regid,
+ response_kind,
&bundle_spec,
reply_eid,
&bpq_block_data,
@@ -900,7 +1048,7 @@
char local_eid_name[PATH_MAX];
char reply_eid_name[PATH_MAX];
char matching_filename[PATH_MAX];
- int count = -1; //forever
+ int count = 0; //forever
dtn_timeval_t bundle_expiry = 3600; //one hour
dtn_reg_id_t regid = DTN_REGID_NONE;
dtn_timeval_t reg_expiry = 30;
@@ -965,7 +1113,7 @@
delivery_options,
verbose);
-// UNREACHABLE CODE if count = -1 //////////////////////////////////////////////
+// UNREACHABLE CODE if count = 0 //////////////////////////////////////////////
// close the ipc handle
if (verbose) fprintf(stdout, "closing connection to dtn router...\n");
@@ -974,6 +1122,6 @@
return 0;
-// UNREACHABLE CODE if count = -1 //////////////////////////////////////////////
+// UNREACHABLE CODE if count = 0 //////////////////////////////////////////////
}