apps/dtnrespond/dtnrespond.c
changeset 64 1296a0283271
parent 63 9a8be24c5037
child 65 333724f2f7cf
equal deleted inserted replaced
63:9a8be24c5037 64:1296a0283271
     1 /*
     1 /*
     2  *    Copyright 2004-2006 Intel Corporation
     2  *    Copyright 2010-2011 Trinity College Dublin
     3  * 
     3  * 
     4  *    Licensed under the Apache License, Version 2.0 (the "License");
     4  *    Licensed under the Apache License, Version 2.0 (the "License");
     5  *    you may not use this file except in compliance with the License.
     5  *    you may not use this file except in compliance with the License.
     6  *    You may obtain a copy of the License at
     6  *    You may obtain a copy of the License at
     7  * 
     7  * 
    31 #include "sdnv-c.h"
    31 #include "sdnv-c.h"
    32 
    32 
    33 #define BUFSIZE 16
    33 #define BUFSIZE 16
    34 #define BLOCKSIZE 8192
    34 #define BLOCKSIZE 8192
    35 #define COUNTER_MAX_DIGITS 9
    35 #define COUNTER_MAX_DIGITS 9
    36 
       
    37 #define DTN_BPQ_BLOCK_TYPE 0xC8
       
    38 
    36 
    39 // Find the maximum commandline length
    37 // Find the maximum commandline length
    40 #ifdef __FreeBSD__
    38 #ifdef __FreeBSD__
    41 /* Needed for PATH_MAX, Linux doesn't need it */
    39 /* Needed for PATH_MAX, Linux doesn't need it */
    42 #include <sys/syslimits.h>
    40 #include <sys/syslimits.h>
   239         fprintf(stderr, err_msg); \
   237         fprintf(stderr, err_msg); \
   240         usage(); \
   238         usage(); \
   241         exit(1); \
   239         exit(1); \
   242     }
   240     }
   243 
   241 
       
   242     FILE* file;
       
   243 
   244     REQUIRE(strlen(local_eid_name) > 0, "-l <local eid> required\n");
   244     REQUIRE(strlen(local_eid_name) > 0, "-l <local eid> required\n");
   245     REQUIRE(strlen(reply_eid_name) > 0, "-r <reply eid> required\n");
   245     REQUIRE(strlen(reply_eid_name) > 0, "-r <reply eid> required\n");
   246     REQUIRE(strlen(matching_filename) > 0, "-f <matching filename> required\n");
   246     REQUIRE(strlen(matching_filename) > 0, "-f <matching filename> required\n");
       
   247     REQUIRE((file = fopen(matching_filename, "r")) != 0, "matching file not found");
   247     
   248     
   248     return 0;
   249 	fclose (file);
       
   250 	return DTN_SUCCESS;
       
   251 
       
   252 #undef REQUIRE
   249 }
   253 }
   250 
   254 
   251 /*******************************************************************************
   255 /*******************************************************************************
   252 * register with dtn:
   256 * register with dtn:
   253 * 
   257 * 
   336 
   340 
   337 /*******************************************************************************
   341 /*******************************************************************************
   338 * parse eid:
   342 * parse eid:
   339 *  
   343 *  
   340 * code lifted from dtnsend
   344 * code lifted from dtnsend
   341 * todo: check this
       
   342 *******************************************************************************/
   345 *******************************************************************************/
   343 dtn_endpoint_id_t *
   346 dtn_endpoint_id_t *
   344 parse_eid(dtn_handle_t handle,
   347 parse_eid(dtn_handle_t handle,
   345     dtn_endpoint_id_t * eid,
   348     dtn_endpoint_id_t * eid,
   346     const char * str,
   349     const char * str,
   365 }
   368 }
   366 
   369 
   367 /*******************************************************************************
   370 /*******************************************************************************
   368 * trim whitespace:
   371 * trim whitespace:
   369 * first move past any leading whitespace 
   372 * first move past any leading whitespace 
   370 * after the first non-whitespace char bef=gin copying to output
   373 * after the first non-whitespace char begin copying to output
   371 * finish by setting any trailing whitespace to 0
   374 * finish by setting any trailing whitespace to 0
   372 * @return 0 on success or -1 if input not completely read
   375 * @return 0 on success or -1 if input not completely read
   373 *******************************************************************************/
   376 *******************************************************************************/
   374 int
   377 int
   375 trim_whitespace(const char * in, char * out, int out_len)
   378 trim_whitespace(const char * in, char * out, int out_len)
   376 {
   379 {
   377     int i=0, j=0;
   380     int i=0, j=0;
   378     char space = ' ';
   381     int in_len;
   379     char tab = '\t';
   382     char whitespace[] = " \t\n\r";
   380 
   383 
   381     memset(out, 0, out_len);
   384     memset(out, 0, out_len);
   382 
   385 
   383     // move past any leading whitespace
   386     // move past any leading whitespace
   384     while (i<strlen(in) && in[i] == space ||
   387     // by testing if the current char is in the whitespace string
   385            i<strlen(in) && in[i] == tab)
   388     while ( i<strlen(in) && strchr(whitespace, in[i]) != NULL )
   386         ++i;
   389     	++i;
       
   390 
       
   391     in_len = strlen(&(in[i]));
       
   392     if (in_len > out_len) {
       
   393     	fprintf(stderr, "Error trimming whitespace, input string [%d] is longer"
       
   394     			" than output string [%d]\n", in_len, out_len);
       
   395     	return -1;
       
   396     }
   387     
   397     
   388     // body case
   398     // copy the body
   389     for ( ; i<strlen(in) && j<out_len-2; ++i){
   399     strncpy(out, &(in[i]), in_len);
   390             out[j++] = in[i];
       
   391     }
       
   392 
   400 
   393     // remove any trailing whitespace
   401     // remove any trailing whitespace
   394     // out[j] now points to the null char that terminates the string
   402     // by testing if the current char is in the whitespace string
   395     j--;
   403     for (j = strlen(out)-1; strchr(whitespace, in[i]) != NULL; --j)
   396     while (j >= 0 && out[j] == space ||
   404     	out[j--] = 0;
   397            j >= 0 && out[j] == tab)
   405 
   398         out[j--] = 0;
   406     return 0;
   399 
   407 
   400     if (i <  strlen(in))
       
   401         return -1;
       
   402     else
       
   403         return 0;
       
   404 }   
   408 }   
   405 
   409 
   406 /*******************************************************************************
   410 /*******************************************************************************
   407 * escape spaces:
   411 * escape spaces:
   408 * first move past any leading whitespace 
   412 * first move past any leading whitespace 
   437     else
   441     else
   438         return 0;
   442         return 0;
   439 }   
   443 }   
   440 
   444 
   441 /*******************************************************************************
   445 /*******************************************************************************
   442 * find query
   446 * response_path_exists
   443 * search all files in 'dir' for a query match
   447 * first escape any spaces in the path name
   444 * test against query len & query val and update found
   448 * then try to open the file for reading
   445 * @return 0 or -1 if error
   449 * @return 0 if exists or -1 if not found
   446 *******************************************************************************/
   450 *******************************************************************************/
   447 int
   451 int
   448 find_query(const char * dir, const char * query, int * found)
   452 response_path_exists(const char * path)
   449 {
   453 {
   450     FILE *file;
   454     FILE *file;
   451     int i, status;
   455     char esc_path[PATH_MAX];
   452     char ls_result[PATH_MAX];
       
   453     char ls_cmd[PATH_MAX];
       
   454     char esc_dir[PATH_MAX];
       
   455 
       
   456     *found = 0;
       
   457 
   456 
   458     // trim & escape spaces in dir before calling ls
   457     // trim & escape spaces in dir before calling ls
   459     if (escape_spaces(dir, esc_dir, PATH_MAX) != DTN_SUCCESS)
   458     if (escape_spaces(path, esc_path, PATH_MAX) != DTN_SUCCESS)
   460         return -1;
   459         return -1;
   461     
   460     
   462     snprintf (ls_cmd, PATH_MAX, "ls %s", esc_dir);
   461     if ((file = fopen(esc_path, "r")) == 0) {
   463     file = popen (ls_cmd, "r");
   462     	fprintf(stderr, "Error: the path %s specified in the matching file"
   464 
   463     			" could not be found\n", path);
   465     if (file == NULL)
   464 		return -1;
   466         return -1;
   465     } else {
   467 
   466     	fclose (file);
   468     for (i=0; fgets(ls_result, PATH_MAX, file) != NULL; ++i) {
   467 		return 0;
   469         if (ls_result[strlen(ls_result)-1] == '\n')
   468     }
   470             ls_result[strlen(ls_result)-1] = 0;
       
   471 
       
   472         if (strlen(query) == strlen(ls_result) &&
       
   473             strncmp (query, ls_result, strlen(query)) == 0) {
       
   474             *found = 1;
       
   475             break;
       
   476         }
       
   477     }
       
   478 
       
   479     status = pclose(file);
       
   480     if (status == -1) 
       
   481         return -1;
       
   482 
       
   483     return 0;
       
   484 }
   469 }
   485 
   470 
   486 
   471 
   487 /*******************************************************************************
   472 /*******************************************************************************
   488 * match bpq:
   473 * match bpq:
   489 * read in paths to search for query in from 'matching file'
   474 * read in paths to search for query in from 'matching file'
   490 * for each record in the matching file, extract the response path
   475 * for each record in the matching file, extract the response path
   491 * matching file format: [matching_rule, encoding, query, response_path, expiry]
   476 * matching file format: [matching_rule, query, response_path, response_type, expiry]
   492 *******************************************************************************/
   477 *******************************************************************************/
   493 int
   478 int
   494 match_bpq(const dtn_bpq_extension_block_data_t * bpq,
   479 match_bpq(const dtn_bpq_extension_block_data_t * bpq,
   495     const char * matching_filename,
   480     const char * matching_filename,
   496     char * pathname,
   481     u_int * response_kind,
   497     int * found)
   482     char  * response_path,
       
   483     int     response_path_len,
       
   484     int   * response_expiry,
       
   485     int   * found)
   498 {
   486 {
   499     char line[PATH_MAX];
   487     char line[PATH_MAX];
   500     char trim_response_path[PATH_MAX];
   488     char trim_path[PATH_MAX];
   501     char * response_path;
   489     char * matching_rule;
       
   490     char * query;
       
   491     char * path;
       
   492     char * kind;
       
   493     char * expiry;
   502     FILE * file;
   494     FILE * file;
   503     
       
   504     *found = 0;
       
   505 
   495 
   506     if ((file = fopen(matching_filename, "r")) == 0)
   496     if ((file = fopen(matching_filename, "r")) == 0)
   507         return -1;
   497         return -1;
   508     
   498     
   509     memset(line, 0 , PATH_MAX);
   499     while (1) {
   510     while (fgets(line, PATH_MAX, file) != NULL) {
   500     	memset(line, 0 , PATH_MAX);
   511         strtok(line, ",");
   501     	*found = 0;
   512         strtok(NULL, ",");
   502 
   513         strtok(NULL, ",");
   503     	// read line from matching file
   514         response_path = strtok(NULL, ",");  
   504     	// TODO: handle malformed input from matching file
   515 //      expiry = strtok(NULL, ",");                 
   505     	if (fgets(line, PATH_MAX, file) == NULL) {
       
   506     		break;
       
   507     	} else {
       
   508     		matching_rule 	= strtok(line, ",");
       
   509     		query 			= strtok(NULL, ",");
       
   510     		path 	        = strtok(NULL, ",");
       
   511     		kind  			= strtok(NULL, ",");
       
   512     		expiry			= strtok(NULL, ",");
       
   513     	}
       
   514 
       
   515     	// match query
       
   516         if (atoi(matching_rule) != (int)bpq->matching_rule		||
       
   517 			BPQ_MATCHING_RULE_EXACT != bpq->matching_rule		||
       
   518 			strlen(query) != bpq->query.query_len 				||
       
   519         	strncmp(query, bpq->query.query_val, bpq->query.query_len) != 0) {
       
   520 
       
   521         	continue;
       
   522         }
       
   523 
   516 
   524 
   517         // trim whitespace from response path
   525         // trim whitespace from response path
   518         trim_whitespace(response_path, trim_response_path, PATH_MAX);
   526         trim_whitespace(path, trim_path, PATH_MAX);
   519 
   527 
   520         if (find_query(trim_response_path, bpq->query.query_val, found) != DTN_SUCCESS)
   528         // make sure the file exists
   521             return -1;
   529         if (response_path_exists(trim_path)) {
   522 
   530         	*found = 1;
   523         // if found build pathname and stop looking
   531         	*response_kind = (u_int) atoi(kind);
   524         if (*found == 1) {
   532         	*response_expiry = atoi(response_expiry);
   525             // ensure path ends in slash
   533         	strncpy(response_path, trim_path, response_path_len);
   526             if (trim_response_path[strlen(trim_response_path)-1] == '/'){
   534 
   527                 snprintf(pathname, PATH_MAX, "%s%s", trim_response_path, bpq->query.query_val);
   535 			break;
   528             } else {
   536         } else {
   529                 snprintf(pathname, PATH_MAX, "%s/%s", trim_response_path, bpq->query.query_val);
   537         	continue;
   530             }
   538         }
   531 
       
   532             break;
       
   533         }
       
   534         memset(line, 0 , PATH_MAX);
       
   535     }
   539     }
   536     fclose (file);
   540     fclose (file);
   537 
   541 
   538     return 0;
   542     return 0;
   539 }
   543 }
   540 
   544 
   541 /*******************************************************************************
   545 /*******************************************************************************
   542 * bpq to char array:
   546 * bpq to char array
   543 * encode as SDNVs,
   547 * encode the following information:
   544 *   BPQ-kind             1-byte
   548 *
   545 *   matching rule type   1-byte
   549 *   BPQ-kind             		1-byte
   546 *   BPQ-value-length     SDNV
   550 *   Matching rule 				1-byte
   547 *   BPQ-value            n-bytes
   551 *
   548 *   number of fragments  SDNV
   552 *   Creation time-stamp	sec		SDNV
   549 *   fragment offsets     SDNV
   553 *   Creation time-stamp	seq		SDNV
   550 *   fragment lengths     SDNV
   554 *   Source EID length			SDNV
       
   555 *   Source EID 					n-bytes
       
   556 *
       
   557 *   Query value length     		SDNV
       
   558 *   Query value            		n-bytes
       
   559 *
       
   560 *   Number of fragments  		SDNV
       
   561 *   Fragment offsets    		SDNV
       
   562 *   Fragment lengths     		SDNV
   551 *
   563 *
   552 * @return The number of bytes or -1 on error
   564 * @return The number of bytes or -1 on error
   553 *******************************************************************************/
   565 *******************************************************************************/
   554 int
   566 int
   555 bpq_to_char_array(const dtn_bpq_extension_block_data_t * bpq,
   567 bpq_to_char_array(const dtn_bpq_extension_block_data_t * bpq,
   559 {
   571 {
   560     int i=0, j=0, k=0;
   572     int i=0, j=0, k=0;
   561     int q_encoding_len, f_encoding_len, encoding_len;
   573     int q_encoding_len, f_encoding_len, encoding_len;
   562     char encoding[PATH_MAX];
   574     char encoding[PATH_MAX];
   563 
   575 
       
   576     memset(buf, 0, buf_len);
       
   577 
   564     // BPQ-kind             1-byte
   578     // BPQ-kind             1-byte
   565     if (i < buf_len)    buf[i++] = (char) bpq->kind;
   579     if (i < buf_len)    buf[i++] = (char) bpq->kind;
   566 
   580 
   567     // matching rule type   1-byte
   581     // matching rule type   1-byte
   568     if (i < buf_len)    buf[i++] = (char) bpq->matching_rule;
   582     if (i < buf_len)    buf[i++] = (char) bpq->matching_rule;
   569 
   583 
   570     // BPQ-value-length     SDNV
   584     // Timestamp secs (SDNV)
   571     if ( (q_encoding_len = sdnv_encode (bpq->query.query_len, encoding, PATH_MAX)) == -1 )
   585 	if ( (q_encoding_len = sdnv_encode (bpq->original_id.creation_ts.secs,
       
   586 										encoding, PATH_MAX)) == -1 ) {
       
   587 		fprintf (stderr, "Error encoding creation timestamp secs\n");
       
   588 		return -1;
       
   589 	} else {
       
   590 		for (j=0; i<buf_len && j<q_encoding_len; ++j)
       
   591 	        buf[i++] = encoding[j];
       
   592 	}
       
   593 
       
   594     // Timestamp seqno (SDNV)
       
   595 	if ( (q_encoding_len = sdnv_encode (bpq->original_id.creation_ts.seqno,
       
   596 										encoding, PATH_MAX)) == -1 ) {
       
   597 		fprintf (stderr, "Error encoding creation timestamp seqno\n");
       
   598 		return -1;
       
   599 	} else {
       
   600 		for (j=0; i<buf_len && j<q_encoding_len; ++j)
       
   601 	        buf[i++] = encoding[j];
       
   602 	}
       
   603 
       
   604     // Source EID len (SDNV)
       
   605 	if ( (q_encoding_len = sdnv_encode (bpq->original_id.source_len,
       
   606 										encoding, PATH_MAX)) == -1 ) {
       
   607 		fprintf (stderr, "Error encoding source EID len\n");
       
   608 		return -1;
       
   609 	} else {
       
   610 		for (j=0; i<buf_len && j<q_encoding_len; ++j)
       
   611 	        buf[i++] = encoding[j];
       
   612 	}
       
   613 
       
   614     // Source EID n-bytes
       
   615     for (j=0; i<buf_len && j<bpq->original_id.source_len; ++j)
       
   616         buf[i++] = bpq->original_id.source.uri[j];
       
   617 
       
   618 
       
   619 
       
   620     // Query length (SDNV)
       
   621     if ( (q_encoding_len = sdnv_encode (bpq->query.query_len,
       
   622     									encoding, PATH_MAX)) == -1 ) {
       
   623     	fprintf (stderr, "Error encoding query len\n");
   572         return -1;
   624         return -1;
   573     for (j=0; i<buf_len && j<q_encoding_len; ++j)
   625     } else {
   574         buf[i++] = encoding[j];
   626     	for (j=0; i<buf_len && j<q_encoding_len; ++j)
   575 
   627     		buf[i++] = encoding[j];
   576     // BPQ-value            n-bytes
   628     }
       
   629 
       
   630     // Query value n-bytes
   577     for (j=0; i<buf_len && j<bpq->query.query_len; ++j)
   631     for (j=0; i<buf_len && j<bpq->query.query_len; ++j)
   578         buf[i++] = bpq->query.query_val[j];
   632         buf[i++] = bpq->query.query_val[j];
   579 
   633 
       
   634 
       
   635 
   580     // number of fragments  SDNV
   636     // number of fragments  SDNV
   581     if ( (f_encoding_len = sdnv_encode (bpq->fragments.num_frag_returned, encoding, PATH_MAX)) == -1 )
   637     if ( (f_encoding_len = sdnv_encode (bpq->fragments.num_frag_returned,
       
   638     									encoding, PATH_MAX)) == -1 ){
       
   639     	fprintf (stderr, "Error encoding number of fragments\n");
   582         return -1;
   640         return -1;
   583     for (j=0; i<buf_len && j<f_encoding_len; ++j)
   641     } else {
   584         buf[i++] = encoding[j];
   642     	for (j=0; i<buf_len && j<f_encoding_len; ++j)
       
   643     		buf[i++] = encoding[j];
       
   644     }
   585 
   645 
   586     for (k=0; k<bpq->fragments.num_frag_returned; ++k) {
   646     for (k=0; k<bpq->fragments.num_frag_returned; ++k) {
   587 
   647 
   588         // fragment offsets     SDNV
   648         // fragment offsets     SDNV
   589         if ( (encoding_len = sdnv_encode (bpq->fragments.frag_offsets[k], encoding, PATH_MAX)) == -1 )
   649         if ( (encoding_len = sdnv_encode (bpq->fragments.frag_offsets[k],
   590             return -1;
   650         								  encoding, PATH_MAX)) == -1 ) {
   591         for (j=0; i<buf_len && j<encoding_len; ++j)
   651         	fprintf (stderr, "Error encoding fragment offset[%d]\n", k);
   592             buf[i++] = encoding[j];
   652         	return -1;
       
   653         } else {
       
   654         	for (j=0; i<buf_len && j<encoding_len; ++j)
       
   655         		buf[i++] = encoding[j];
       
   656         }
   593 
   657 
   594         // fragment lengths     SDNV
   658         // fragment lengths     SDNV
   595         if ( (encoding_len = sdnv_encode (bpq->fragments.frag_lenghts[k], encoding, PATH_MAX)) == -1 )
   659         if ( (encoding_len = sdnv_encode (bpq->fragments.frag_lenghts[k],
   596             return -1;
   660         								  encoding, PATH_MAX)) == -1 ) {
   597         for (j=0; i<buf_len && j<encoding_len; ++j)
   661         	fprintf (stderr, "Error encoding fragment length[%d]\n", k);
   598             buf[i++] = encoding[j];
   662         	return -1;
   599     }
   663         } else {
       
   664         	for (j=0; i<buf_len && j<encoding_len; ++j)
       
   665         		buf[i++] = encoding[j];
       
   666         }
       
   667     }
       
   668 
   600     if (verbose) {
   669     if (verbose) {
   601         fprintf (stdout, "\nbpq_to_char_array (buf_len:%d, i:%d):\n",buf_len,i);
   670         fprintf (stdout, "\nbpq_to_char_array (buf_len:%d, i:%d):\n",buf_len,i);
   602         fprintf (stdout, "             kind: %d\n", (int) buf[0]);
   671         fprintf (stdout, "             kind: %d\n", (int) buf[0]);
   603         fprintf (stdout, "    matching rule: %d\n", (int) buf[1]);
   672         fprintf (stdout, "    matching rule: %d\n", (int) buf[1]);
       
   673 
       
   674         fprintf (stdout, "  creation ts sec: %d\n",
       
   675         		 (int) bpq->original_id.creation_ts.secs);
       
   676         fprintf (stdout, "  creation ts seq: %d\n",
       
   677         		 (int) bpq->original_id.creation_ts.seqno);
       
   678         fprintf (stdout, "   source eid len: %d\n",
       
   679         		 (int) bpq->original_id.source_len);
       
   680         fprintf (stdout, "       source eid: %s\n",
       
   681         		 (int) bpq->original_id.source.uri);
       
   682 
   604         fprintf (stdout, "        query len: %d\n", bpq->query.query_len);
   683         fprintf (stdout, "        query len: %d\n", bpq->query.query_len);
   605         fprintf (stdout, "   q_encoding_len: %d\n", q_encoding_len);
   684         fprintf (stdout, "   q_encoding_len: %d\n", q_encoding_len);
   606         fprintf (stdout, "        query val: %s\n", bpq->query.query_val);
   685         fprintf (stdout, "        query val: %s\n", bpq->query.query_val);
       
   686 
   607         fprintf (stdout, "     fragment len: %d\n", bpq->fragments.num_frag_returned);
   687         fprintf (stdout, "     fragment len: %d\n", bpq->fragments.num_frag_returned);
   608         fprintf (stdout, "   f_encoding_len: %d\n\n", f_encoding_len);
   688         fprintf (stdout, "   f_encoding_len: %d\n\n", f_encoding_len);
   609     }
   689     }
   610 
   690 
   611     return i;
   691     return i;
   612 }
   692 }
   613 
   693 
   614 /*******************************************************************************
   694 /*******************************************************************************
   615 * char array to bpq:
   695 * char array to bpq
   616 * decode as SDNVs,
   696 * decode the following information:
   617 *   BPQ-kind             1-byte
       
   618 *   matching rule type   1-byte
       
   619 *   BPQ-value-length     SDNV
       
   620 *   BPQ-value            n-bytes
       
   621 *   number of fragments  SDNV
       
   622 *   fragment offsets     SDNV
       
   623 *   fragment lengths     SDNV
       
   624 *
   697 *
   625 * @return DTN_SUCCESS or -1 on error
   698 *   BPQ-kind             		1-byte
       
   699 *   Matching rule 				1-byte
       
   700 *
       
   701 *   Creation time-stamp	sec		SDNV
       
   702 *   Creation time-stamp	seq		SDNV
       
   703 *   Source EID length			SDNV
       
   704 *   Source EID 					n-bytes
       
   705 *
       
   706 *   Query value length     		SDNV
       
   707 *   Query value            		n-bytes
       
   708 *
       
   709 *   Number of fragments  		SDNV
       
   710 *   Fragment offsets    		SDNV
       
   711 *   Fragment lengths     		SDNV
       
   712 *
       
   713 * @return The number of bytes or -1 on error
   626 *******************************************************************************/
   714 *******************************************************************************/
   627 int
   715 int
   628 char_array_to_bpq(const char* buf,
   716 char_array_to_bpq(const char* buf,
   629     size_t buf_len,
   717     size_t buf_len,
   630     dtn_bpq_extension_block_data_t * bpq,
   718     dtn_bpq_extension_block_data_t * bpq,
   637     if (i<buf_len) bpq->kind = (u_int) buf[i++];
   725     if (i<buf_len) bpq->kind = (u_int) buf[i++];
   638 
   726 
   639     // matching rule type   1-byte
   727     // matching rule type   1-byte
   640     if (i<buf_len) bpq->matching_rule = (u_int) buf[i++];
   728     if (i<buf_len) bpq->matching_rule = (u_int) buf[i++];
   641 
   729 
       
   730 
       
   731 
       
   732     // Creation time-stamp sec     SDNV
       
   733     if ( (q_decoding_len = sdnv_decode (&(buf[i]),
       
   734     									buf_len - i,
       
   735     									&(bpq->original_id.creation_ts.secs))) == -1 ) {
       
   736         fprintf (stderr, "Error decoding creation time-stamp sec\n");
       
   737         return -1;
       
   738     }
       
   739     i += q_decoding_len;
       
   740 
       
   741     // Creation time-stamp seq     SDNV
       
   742     if ( (q_decoding_len = sdnv_decode (&(buf[i]),
       
   743     									buf_len - i,
       
   744     									&(bpq->original_id.creation_ts.seqno))) == -1 ) {
       
   745         fprintf (stderr, "Error decoding creation time-stamp seq\n");
       
   746         return -1;
       
   747     }
       
   748     i += q_decoding_len;
       
   749 
       
   750     // Source EID length     SDNV
       
   751     if ( (q_decoding_len = sdnv_decode (&(buf[i]),
       
   752     									buf_len - i,
       
   753     									&(bpq->original_id.source_len))) == -1 ) {
       
   754         fprintf (stderr, "Error decoding source EID length\n");
       
   755         return -1;
       
   756     }
       
   757     i += q_decoding_len;
       
   758 
       
   759     // Source EID            n-bytes
       
   760     if (i<buf_len && bpq->original_id.source_len <= DTN_MAX_ENDPOINT_ID) {
       
   761     	strncpy(bpq->original_id.source.uri, &(buf[i]), bpq->original_id.source_len);
       
   762     	i += bpq->original_id.source_len;
       
   763     } else {
       
   764     	fprintf (stderr, "Error copying source EID\n");
       
   765 		return -1;
       
   766     }
       
   767 
       
   768 
       
   769 
   642     // BPQ-value-length     SDNV
   770     // BPQ-value-length     SDNV
   643     if ( (q_decoding_len = sdnv_decode (&(buf[i]), buf_len - i, &(bpq->query.query_len))) == -1 ) {
   771     if ( (q_decoding_len = sdnv_decode (&(buf[i]),
       
   772     									buf_len - i,
       
   773     									&(bpq->query.query_len))) == -1 ) {
   644         fprintf (stderr, "Error decoding BPQ-value-length\n");
   774         fprintf (stderr, "Error decoding BPQ-value-length\n");
   645         return -1;
   775         return -1;
   646     }
   776     }
   647     i += q_decoding_len;
   777     i += q_decoding_len;
   648 
   778 
   649     // BPQ-value            n-bytes
   779     // BPQ-value            n-bytes
   650     if (i<buf_len) bpq->query.query_val = &(buf[i]);
   780     if (i<buf_len) bpq->query.query_val = &(buf[i]);
   651     i += bpq->query.query_len;
   781     	i += bpq->query.query_len;
       
   782 
   652 
   783 
   653     // number of fragments  SDNV
   784     // number of fragments  SDNV
   654     if ( (f_decoding_len = sdnv_decode (&(buf[i]), buf_len - i, &(bpq->fragments.num_frag_returned))) == -1 ) {
   785     if ( (f_decoding_len = sdnv_decode (&(buf[i]),
       
   786     									buf_len - i,
       
   787     									&(bpq->fragments.num_frag_returned))) == -1 ) {
   655         fprintf (stderr, "Error decoding number of fragments\n");
   788         fprintf (stderr, "Error decoding number of fragments\n");
   656         return -1;
   789         return -1;
   657     }
   790     }
   658     i += f_decoding_len;
   791     i += f_decoding_len;
   659 
   792 
   660     for (j=0; i<buf_len && j<bpq->fragments.num_frag_returned; ++j) {
   793     for (j=0; i<buf_len && j<bpq->fragments.num_frag_returned; ++j) {
   661 
   794 
   662         // fragment offsets     SDNV
   795         // fragment offsets     SDNV
   663         if ( (decoding_len = sdnv_decode (&(buf[i]), buf_len - i, &(bpq->fragments.frag_offsets[j]))) == -1 ) {
   796         if ( (decoding_len = sdnv_decode (&(buf[i]),
       
   797         								  buf_len - i,
       
   798         								  &(bpq->fragments.frag_offsets[j]))) == -1 ) {
   664             fprintf (stderr, "Error decoding fragment[%d] offset\n", j);
   799             fprintf (stderr, "Error decoding fragment[%d] offset\n", j);
   665             return -1;
   800             return -1;
   666         }
   801         }
   667         i += decoding_len;
   802         i += decoding_len;
   668 
   803 
   669         // fragment lengths     SDNV
   804         // fragment lengths     SDNV
   670         if ( (decoding_len = sdnv_decode (&(buf[i]), buf_len - i, &(bpq->fragments.frag_lenghts[j]))) == -1 ) {
   805         if ( (decoding_len = sdnv_decode (&(buf[i]),
       
   806         								  buf_len - i,
       
   807         								  &(bpq->fragments.frag_lenghts[j]))) == -1 ) {
   671             fprintf (stderr, "Error decoding fragment[%d] length\n", j);
   808             fprintf (stderr, "Error decoding fragment[%d] length\n", j);
   672             return -1;
   809             return -1;
   673         }
   810         }
   674         i += decoding_len;
   811         i += decoding_len;
   675     }
   812     }
   679 
   816 
   680     if (verbose) {
   817     if (verbose) {
   681         fprintf (stdout, "\nchar_array_to_bpq (buf_len:%d, i:%d):\n",buf_len, i);
   818         fprintf (stdout, "\nchar_array_to_bpq (buf_len:%d, i:%d):\n",buf_len, i);
   682         fprintf (stdout, "             kind: %d\n", (int) buf[0]);
   819         fprintf (stdout, "             kind: %d\n", (int) buf[0]);
   683         fprintf (stdout, "    matching rule: %d\n", (int) buf[1]);
   820         fprintf (stdout, "    matching rule: %d\n", (int) buf[1]);
       
   821 
       
   822         fprintf (stdout, "  creation ts sec: %d\n",
       
   823         		 (int) bpq->original_id.creation_ts.secs);
       
   824         fprintf (stdout, "  creation ts seq: %d\n",
       
   825         		 (int) bpq->original_id.creation_ts.seqno);
       
   826         fprintf (stdout, "   source eid len: %d\n",
       
   827         		 (int) bpq->original_id.source_len);
       
   828         fprintf (stdout, "       source eid: %s\n",
       
   829         		 (int) bpq->original_id.source.uri);
       
   830 
   684         fprintf (stdout, "        query len: %d\n", bpq->query.query_len);
   831         fprintf (stdout, "        query len: %d\n", bpq->query.query_len);
   685         fprintf (stdout, "   q_decoding_len: %d\n", q_decoding_len);
   832         fprintf (stdout, "   q_decoding_len: %d\n", q_decoding_len);
   686         fprintf (stdout, "        query val: %s\n", bpq->query.query_val);
   833         fprintf (stdout, "        query val: %s\n", bpq->query.query_val);
       
   834 
   687         fprintf (stdout, "     fragment len: %d\n", bpq->fragments.num_frag_returned);
   835         fprintf (stdout, "     fragment len: %d\n", bpq->fragments.num_frag_returned);
   688         fprintf (stdout, "   f_decoding_len: %d\n\n", f_decoding_len);
   836         fprintf (stdout, "   f_decoding_len: %d\n\n", f_decoding_len);
   689     }
   837     }
   690 
   838 
   691     return DTN_SUCCESS;
   839     return DTN_SUCCESS;
   699 * @return 0 if successful or -1 if error
   847 * @return 0 if successful or -1 if error
   700 *******************************************************************************/
   848 *******************************************************************************/
   701 int
   849 int
   702 send_response_bpq(dtn_handle_t * handle,
   850 send_response_bpq(dtn_handle_t * handle,
   703     dtn_reg_id_t regid,
   851     dtn_reg_id_t regid,
       
   852     u_int response_kind,
   704     dtn_bundle_spec_t * query_bundle_spec,
   853     dtn_bundle_spec_t * query_bundle_spec,
   705     const dtn_endpoint_id_t * reply_eid,
   854     const dtn_endpoint_id_t * reply_eid,
   706     dtn_bpq_extension_block_data_t * query_bpq_block_data,
   855     dtn_bpq_extension_block_data_t * query_bpq_block_data,
   707     const char * pathname,
   856     const char * pathname,
   708     int bundle_expiry,
   857     int bundle_expiry,
   716     dtn_bundle_id_t                 response_bundle_id;
   865     dtn_bundle_id_t                 response_bundle_id;
   717     dtn_bundle_spec_t               response_bundle_spec;
   866     dtn_bundle_spec_t               response_bundle_spec;
   718     dtn_extension_block_t           response_bpq_block;
   867     dtn_extension_block_t           response_bpq_block;
   719     dtn_bpq_extension_block_data_t  response_bpq_block_data;
   868     dtn_bpq_extension_block_data_t  response_bpq_block_data;
   720     dtn_bundle_payload_t            response_payload;
   869     dtn_bundle_payload_t            response_payload;
   721     u_int offsets[1];
       
   722     u_int lengths[1];
       
   723 
   870 
   724     memset(buf,                      0, PATH_MAX);
   871     memset(buf,                      0, PATH_MAX);
   725     memset(&response_bundle_spec,    0, sizeof(dtn_bundle_spec_t));
   872     memset(&response_bundle_spec,    0, sizeof(dtn_bundle_spec_t));
   726     memset(&response_bpq_block,      0, sizeof(dtn_extension_block_t));
   873     memset(&response_bpq_block,      0, sizeof(dtn_extension_block_t));
   727     memset(&response_bpq_block_data, 0, sizeof(dtn_bpq_extension_block_data_t));
   874     memset(&response_bpq_block_data, 0, sizeof(dtn_bpq_extension_block_data_t));
   729 
   876 
   730     // set the payload
   877     // set the payload
   731     dtn_set_payload(&response_payload, DTN_PAYLOAD_FILE, pathname, strlen(pathname)); 
   878     dtn_set_payload(&response_payload, DTN_PAYLOAD_FILE, pathname, strlen(pathname)); 
   732 
   879 
   733     // set the bpq block data
   880     // set the bpq block data
   734     response_bpq_block_data.kind = BPQ_BLOCK_KIND_RESPONSE;
   881     response_bpq_block_data.kind = response_kind;
   735     response_bpq_block_data.matching_rule = query_bpq_block_data->matching_rule;
   882     response_bpq_block_data.matching_rule = query_bpq_block_data->matching_rule;
   736     response_bpq_block_data.query.query_len = query_bpq_block_data->query.query_len;
   883     response_bpq_block_data.query.query_len = query_bpq_block_data->query.query_len;
   737     response_bpq_block_data.query.query_val = query_bpq_block_data->query.query_val;
   884     response_bpq_block_data.query.query_val = query_bpq_block_data->query.query_val;
   738 
   885 
   739     offsets[0] = 0;
       
   740     lengths[0] = 100;   //todo: add payload length here
       
   741 
       
   742 /*  REMOVING TODO - CHECK THE RFC TO MAKE SURE THIS IS OK
       
   743     response_bpq_block_data.fragments.num_frag_returned = 1;
       
   744     response_bpq_block_data.fragments.frag_offsets = offsets;
       
   745     response_bpq_block_data.fragments.frag_lenghts = lengths; 
       
   746 */
       
   747     if ( (buf_len = bpq_to_char_array(&response_bpq_block_data, buf, PATH_MAX, verbose)) == -1 ) {
   886     if ( (buf_len = bpq_to_char_array(&response_bpq_block_data, buf, PATH_MAX, verbose)) == -1 ) {
   748         fprintf (stderr, "error encoding bpq: %d", buf_len);
   887         fprintf (stderr, "error encoding bpq: %d", buf_len);
   749         return -1;
   888         return -1;
   750     }
   889     }
   751 
   890 
   802     dtn_bundle_priority_t  priority,
   941     dtn_bundle_priority_t  priority,
   803     int delivery_options,
   942     int delivery_options,
   804     int verbose)
   943     int verbose)
   805 {
   944 {
   806     int i, j, num_blocks, found, ret = 0;
   945     int i, j, num_blocks, found, ret = 0;
       
   946     u_int response_kind;
   807     char pathname[PATH_MAX];
   947     char pathname[PATH_MAX];
   808     dtn_bundle_spec_t              bundle_spec;
   948     dtn_bundle_spec_t              bundle_spec;
   809     dtn_extension_block_t          * bpq_blocks;
   949     dtn_extension_block_t          * bpq_blocks;
   810     dtn_bpq_extension_block_data_t bpq_block_data;
   950     dtn_bpq_extension_block_data_t bpq_block_data;
   811     dtn_bundle_payload_t           payload;
   951     dtn_bundle_payload_t           payload;
   812 
   952 
   813     // start listening for bpq bundles
   953     // start listening for bpq bundles
   814     for (i = 0; count == -1 || i < count; ++i) {
   954     for (i = 0; count == 0 || i < count; ++i) {
   815         found = 0;
   955         found = 0;
   816         memset(&bundle_spec,    0, sizeof(dtn_bundle_spec_t));
   956         memset(&bundle_spec,    0, sizeof(dtn_bundle_spec_t));
   817         memset(&bpq_block_data, 0, sizeof(dtn_bpq_extension_block_data_t));
   957         memset(&bpq_block_data, 0, sizeof(dtn_bpq_extension_block_data_t));
   818         memset(&payload,        0, sizeof(dtn_bundle_payload_t));
   958         memset(&payload,        0, sizeof(dtn_bundle_payload_t));
   819         memset(pathname,        0, PATH_MAX);
   959         memset(pathname,        0, PATH_MAX);
   854                 if (ret != DTN_SUCCESS) {
   994                 if (ret != DTN_SUCCESS) {
   855                     fprintf(stderr, "error decoding query bundle: %d\n", ret);
   995                     fprintf(stderr, "error decoding query bundle: %d\n", ret);
   856                     return ret;
   996                     return ret;
   857                 }
   997                 }
   858 
   998 
   859                 match_bpq(&bpq_block_data, matching_filename, pathname, &found);
   999                 match_bpq( 	&bpq_block_data,
       
  1000                 			matching_filename,
       
  1001                 			&response_kind,
       
  1002                 			pathname,
       
  1003                 			PATH_MAX,
       
  1004                 			&bundle_expiry,
       
  1005                 			&found);
       
  1006 
   860                 break;
  1007                 break;
   861             }                
  1008             }                
   862         }
  1009         }
   863 
  1010 
   864         // if found respond and continue listening
  1011         // if found respond and continue listening
   866             if (verbose) fprintf(stdout, "BPQ match found for query: %s\n",
  1013             if (verbose) fprintf(stdout, "BPQ match found for query: %s\n",
   867                                          bpq_block_data.query.query_val);
  1014                                          bpq_block_data.query.query_val);
   868 
  1015 
   869             ret = send_response_bpq(handle,
  1016             ret = send_response_bpq(handle,
   870                                     regid,
  1017                                     regid,
       
  1018                                     response_kind,
   871                                     &bundle_spec,
  1019                                     &bundle_spec,
   872                                     reply_eid,
  1020                                     reply_eid,
   873                                     &bpq_block_data,
  1021                                     &bpq_block_data,
   874                                     pathname,
  1022                                     pathname,
   875                                     bundle_expiry,
  1023                                     bundle_expiry,
   898     dtn_endpoint_id_t local_eid;
  1046     dtn_endpoint_id_t local_eid;
   899     dtn_endpoint_id_t reply_eid;
  1047     dtn_endpoint_id_t reply_eid;
   900     char local_eid_name[PATH_MAX];
  1048     char local_eid_name[PATH_MAX];
   901     char reply_eid_name[PATH_MAX];
  1049     char reply_eid_name[PATH_MAX];
   902     char matching_filename[PATH_MAX];
  1050     char matching_filename[PATH_MAX];
   903     int count = -1;                                     //forever
  1051     int count = 0;                                      //forever
   904     dtn_timeval_t bundle_expiry = 3600;                 //one hour
  1052     dtn_timeval_t bundle_expiry = 3600;                 //one hour
   905     dtn_reg_id_t regid = DTN_REGID_NONE;
  1053     dtn_reg_id_t regid = DTN_REGID_NONE;
   906     dtn_timeval_t reg_expiry = 30;
  1054     dtn_timeval_t reg_expiry = 30;
   907     int reg_fail_action = DTN_REG_DEFER;
  1055     int reg_fail_action = DTN_REG_DEFER;
   908     char reg_fail_script[PATH_MAX]; 
  1056     char reg_fail_script[PATH_MAX]; 
   963         bundle_expiry,
  1111         bundle_expiry,
   964         priority,
  1112         priority,
   965         delivery_options,
  1113         delivery_options,
   966         verbose);
  1114         verbose);
   967 
  1115 
   968 // UNREACHABLE CODE if count = -1 //////////////////////////////////////////////
  1116 // UNREACHABLE CODE if count = 0 //////////////////////////////////////////////
   969 
  1117 
   970     // close the ipc handle
  1118     // close the ipc handle
   971     if (verbose) fprintf(stdout, "closing connection to dtn router...\n");
  1119     if (verbose) fprintf(stdout, "closing connection to dtn router...\n");
   972     dtn_close(handle);
  1120     dtn_close(handle);
   973     if (verbose) fprintf(stdout, "closed connection to dtn router...\n");
  1121     if (verbose) fprintf(stdout, "closed connection to dtn router...\n");
   974 
  1122 
   975     return 0;
  1123     return 0;
   976 
  1124 
   977 // UNREACHABLE CODE if count = -1 //////////////////////////////////////////////
  1125 // UNREACHABLE CODE if count = 0 //////////////////////////////////////////////
   978 }
  1126 }
   979 
  1127