apps/dtnmoteproxy/dtnmoteproxy.c
changeset 0 2b3e5ec03512
equal deleted inserted replaced
-1:000000000000 0:2b3e5ec03512
       
     1 /*
       
     2  *    Copyright 1996-2006 Intel Corporation
       
     3  * 
       
     4  *    Licensed under the Apache License, Version 2.0 (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
       
     7  * 
       
     8  *        http://www.apache.org/licenses/LICENSE-2.0
       
     9  * 
       
    10  *    Unless required by applicable law or agreed to in writing, software
       
    11  *    distributed under the License is distributed on an "AS IS" BASIS,
       
    12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    13  *    See the License for the specific language governing permissions and
       
    14  *    limitations under the License.
       
    15  */
       
    16 
       
    17 
       
    18 /*
       
    19  * moteproxy: a DTN <-> mote proxying app, intended for use with GSK
       
    20  *   for MICA-2, use 57600 baud rate
       
    21  */
       
    22 
       
    23 /* Modified to recognize Mote-PC protocol -- Mark Thomas (23/06/04) 
       
    24  * Now uses serialsource.c to communicate with serial port 
       
    25  * Files: crc16.c, misc.c, mote_io.c and mote_io.h are not used anymore */
       
    26 
       
    27 #ifdef HAVE_CONFIG_H
       
    28 #  include <dtn-config.h>
       
    29 #endif
       
    30 
       
    31 #include <sys/types.h>
       
    32 #include <signal.h>
       
    33 #include <stdio.h>
       
    34 #include <stdlib.h>
       
    35 #include <unistd.h>
       
    36 #include <getopt.h>
       
    37 #include <fcntl.h>
       
    38 #include <string.h>
       
    39 #include "serialsource.h"
       
    40 
       
    41 #include <strings.h>
       
    42 #include <errno.h>
       
    43 #include <sys/stat.h>
       
    44 #include <sys/time.h>
       
    45 #include <time.h>
       
    46 
       
    47 #include <oasys/compat/inttypes.h>
       
    48 
       
    49 #include "dtn_api.h"
       
    50  
       
    51 #define	dout	stderr
       
    52 
       
    53 #include <ctype.h>
       
    54 
       
    55 char *progname;
       
    56 
       
    57 static char *msgs[] = {
       
    58   "unknown_packet_type",
       
    59   "ack_timeout"	,
       
    60   "sync"	,
       
    61   "too_long"	,
       
    62   "too_short"	,
       
    63   "bad_sync"	,
       
    64   "bad_crc"	,
       
    65   "closed"	,
       
    66   "no_memory"	,
       
    67   "unix_error"
       
    68 };
       
    69 
       
    70 typedef struct data_packet
       
    71 {
       
    72     // MultiHop Header 
       
    73     u_int16_t source_mote_id;
       
    74     u_int16_t origin_mote_id;
       
    75     u_int16_t seq_no;
       
    76     u_int8_t hop_cnt;
       
    77 
       
    78     // Surge Sensor Header 
       
    79     u_int8_t surge_pkt_type;
       
    80     u_int16_t surge_reading;
       
    81     u_int16_t surge_parent_addr;
       
    82     u_int32_t surge_seq_no;
       
    83     u_int8_t light;
       
    84     u_int8_t temp;
       
    85     u_int8_t magx;
       
    86     u_int8_t magy;
       
    87     u_int8_t accelx;
       
    88     u_int8_t accely;
       
    89 
       
    90 }DATAPACKET;
       
    91 
       
    92 #define DATAPACKET_SIZE 22
       
    93 #define SURGE_PKT	0x11
       
    94 #define DEBUG_PKT	0x03
       
    95 
       
    96 void parse_options(int, char**);
       
    97 dtn_endpoint_id_t * parse_eid(dtn_handle_t handle, dtn_endpoint_id_t * eid, 
       
    98                           char * str);
       
    99 void print_usage();
       
   100 void print_eid(char * label, dtn_endpoint_id_t * eid);
       
   101 void init_motes();
       
   102 void stderr_msg(serial_source_msg problem);
       
   103 void usage(char *str1, char *str2);
       
   104 void readCommandLineArgs(int argc, char **argv);
       
   105 void hexdump();
       
   106 void read_packet_file(char* filename);
       
   107 
       
   108 // specified options
       
   109 char arg_dest[128];
       
   110 char arg_target[128];
       
   111 
       
   112 char devicename[128] = "/dev/ttyS0";
       
   113 char baud[128] = "57600";
       
   114 char directory[128]="send";
       
   115 u_int32_t debug = 0;             // higher values cause more info to print
       
   116 serial_source src;
       
   117 
       
   118 int g_argc;
       
   119 char **g_argv;
       
   120 
       
   121 int
       
   122 main(int argc, char **argv)
       
   123 {
       
   124     /* save in case of crash */
       
   125     g_argc = argc;
       
   126     g_argv = argv;
       
   127 
       
   128     readCommandLineArgs(argc, argv);
       
   129     init_motes();
       
   130 
       
   131     // NOTREACHED 
       
   132     return (EXIT_FAILURE);      // should never get here 
       
   133 }
       
   134 
       
   135 void stderr_msg(serial_source_msg problem)
       
   136 {
       
   137   fprintf(stderr, "Note: %s\n", msgs[problem]);
       
   138 }
       
   139 
       
   140 int read_packet(char *buf, int *n)
       
   141 {
       
   142     const char *buff;
       
   143     int i;
       
   144     
       
   145     if (debug > 0) fprintf(stdout, "Reading packet:\n");
       
   146     
       
   147     if(!(buff = read_serial_packet(src, n)))
       
   148 	return 0;
       
   149 
       
   150     if (debug > 0) fprintf(stdout, " ==> : ");
       
   151     for (i = 0; i < buff[4]; i++)
       
   152         printf(" %02x", buff[i]);
       
   153     putchar('\n');
       
   154 
       
   155    
       
   156     // strip TOS header & copy to buf 
       
   157     memset(buf,0,BUFSIZ);
       
   158     memcpy(buf,buff,buff[4]+5);
       
   159     *n=buff[4] + 5;
       
   160     if(buff[2]==SURGE_PKT || buff[2]==DEBUG_PKT) return buff[2];
       
   161     return -1;
       
   162 }
       
   163 
       
   164 int
       
   165 reader_thread(void *p)
       
   166 {
       
   167 
       
   168     // loop reading from motes, writing to directory
       
   169 
       
   170     static int tcnt=0;
       
   171     DATAPACKET *dataPacket;
       
   172 
       
   173     // dtn api variables
       
   174     int ret;
       
   175     dtn_handle_t handle;
       
   176     dtn_reg_info_t reginfo;
       
   177     dtn_reg_id_t regid = DTN_REGID_NONE;
       
   178     dtn_bundle_spec_t bundle_spec;
       
   179     dtn_bundle_payload_t send_payload;
       
   180     dtn_bundle_id_t bundle_id;
       
   181     char demux[4096];
       
   182 
       
   183     p = NULL;
       
   184 
       
   185     // open the ipc handle
       
   186     if (debug > 0) fprintf(stdout, "Opening connection to local DTN daemon\n");
       
   187 
       
   188     int err = dtn_open(&handle);
       
   189     if (err != DTN_SUCCESS) {
       
   190         fprintf(stderr, "fatal error opening dtn handle: %s\n",
       
   191                 dtn_strerror(err));
       
   192         exit(1);
       
   193     }
       
   194 
       
   195     // ----------------------------------------------------
       
   196     // initialize bundle spec with src/dest/replyto
       
   197     // ----------------------------------------------------
       
   198 
       
   199     // initialize bundle spec
       
   200     memset(&bundle_spec, 0, sizeof(bundle_spec));
       
   201 
       
   202     // destination host is specified at run time, demux is hardcoded
       
   203     sprintf(demux, "%s/dtnmoteproxy/recv", arg_dest);
       
   204     parse_eid(handle, &bundle_spec.dest, demux);
       
   205 
       
   206     // source is local eid with file path as demux string
       
   207     sprintf(demux, "/dtnmoteproxy/send");
       
   208     parse_eid(handle, &bundle_spec.source, demux);
       
   209 
       
   210     // reply to is the same as the source
       
   211     dtn_copy_eid(&bundle_spec.replyto, &bundle_spec.source);
       
   212 
       
   213 
       
   214     if (debug > 2)
       
   215     {
       
   216         print_eid("source_eid", &bundle_spec.source);
       
   217         print_eid("replyto_eid", &bundle_spec.replyto);
       
   218         print_eid("dest_eid", &bundle_spec.dest);
       
   219     }
       
   220 
       
   221     // set the return receipt option
       
   222     bundle_spec.dopts |= DOPTS_DELIVERY_RCPT;
       
   223 
       
   224     // send file and wait for reply
       
   225 
       
   226     // create a new dtn registration to receive bundle status reports
       
   227     memset(&reginfo, 0, sizeof(reginfo));
       
   228     dtn_copy_eid(&reginfo.endpoint, &bundle_spec.replyto);
       
   229     reginfo.flags = DTN_REG_DEFER;
       
   230     reginfo.regid = regid;
       
   231     reginfo.expiration = 0;
       
   232     if ((ret = dtn_register(handle, &reginfo, &regid)) != 0) {
       
   233         fprintf(stderr, "error creating registration (id=%d): %d (%s)\n",
       
   234                 regid, ret, dtn_strerror(dtn_errno(handle)));
       
   235         exit(1);
       
   236     }
       
   237     
       
   238     if (debug > 3) printf("dtn_register succeeded, regid 0x%x\n", regid);
       
   239 
       
   240     while (1) {
       
   241         static unsigned char motedata[BUFSIZ];
       
   242 	int length;
       
   243 	int ret;
       
   244 
       
   245         if (debug > 1) fprintf(dout, "about to read from motes...\n");
       
   246 
       
   247 	while((ret=read_packet((char *) motedata, (int *) &length))){
       
   248 	    if(ret==DEBUG_PKT)
       
   249 		continue;
       
   250             if (debug > 0) {
       
   251                 fprintf(dout, "\nreader loop... got [%d] bytes from motes\n", 
       
   252                         length);
       
   253                 if (debug > 1) hexdump(motedata, length);
       
   254             }
       
   255 	   
       
   256             // the extra cast to void* is needed to circumvent gcc warnings
       
   257             // about unsafe casting 
       
   258 	    dataPacket=(DATAPACKET *)((void*)motedata);
       
   259 	    
       
   260 	    // skip packets from base mote 
       
   261 	    if(dataPacket->origin_mote_id == 0) continue;
       
   262 
       
   263             // set a default expiration time of one hour
       
   264             bundle_spec.expiration = 3600;
       
   265             
       
   266             // fill in a payload
       
   267             memset(&send_payload, 0, sizeof(send_payload));
       
   268 
       
   269             dtn_set_payload(&send_payload, DTN_PAYLOAD_MEM,
       
   270                             (char *) motedata, length);
       
   271  
       
   272             memset(&bundle_id, 0, sizeof(bundle_id));
       
   273                         
       
   274             if ((ret = dtn_send(handle, regid, &bundle_spec, &send_payload,
       
   275                                 &bundle_id)) != 0)
       
   276             {
       
   277                 fprintf(stderr, "error sending bundle: %d (%s)\n",
       
   278                         ret, dtn_strerror(dtn_errno(handle)));
       
   279             }   
       
   280             else fprintf(stderr, "motedata bundle sent");
       
   281 
       
   282 	    printf("Mote ID = %u\n",dataPacket->origin_mote_id);
       
   283 	    printf("Source Mote ID = %u\n",dataPacket->source_mote_id);
       
   284 	    printf("Hop Count = %u\n",dataPacket->hop_cnt);
       
   285 	    printf("Packet Type = %u\n",dataPacket->surge_pkt_type);
       
   286 	    printf("Parent Address = %u\n",dataPacket->surge_parent_addr);
       
   287 	    printf("Sequence Number = %u\n", (u_int)dataPacket->surge_seq_no);
       
   288 	    printf("Light = %u\n",dataPacket->light);
       
   289 	    printf("Temperature = %u\n\n",dataPacket->temp);	    
       
   290 
       
   291 	    tcnt=(tcnt+1)%10000;
       
   292 	  
       
   293         }
       
   294         if (debug > 0)
       
   295             fprintf(dout, "reader loop.... nothing to do? [shouldn't happen]\n");
       
   296     }
       
   297 
       
   298     // if this was ever changed to gracefully shutdown, it would be good to call:
       
   299     dtn_close(handle);
       
   300     
       
   301     return (1);
       
   302     // NOTREACHED 
       
   303 }
       
   304 
       
   305 
       
   306 void
       
   307 readCommandLineArgs(int argc, char **argv)
       
   308 {
       
   309     int c;
       
   310 
       
   311     while ((c = getopt(argc, argv, "hr:d:b:D:t:")) != EOF) {
       
   312         switch (c) {
       
   313         case 'h':
       
   314             usage("moteproxy", "");
       
   315             exit(0);
       
   316             break;
       
   317         case 'r':
       
   318             read_packet_file(optarg);
       
   319             exit(0);
       
   320         case 'd':
       
   321             debug = atoi(optarg);
       
   322             break;
       
   323         case 'b':
       
   324             strcpy(baud, optarg);
       
   325             break;
       
   326         case 't':
       
   327             strcpy(devicename, optarg);
       
   328             break;
       
   329 	case 'D':
       
   330 	    strcpy(arg_dest,optarg);
       
   331 	    break;		
       
   332         default:
       
   333             fprintf(stderr, "mfproxy: unknown option: '%c'\n", (char) c);
       
   334             usage("moteproxy", "");
       
   335             exit(EXIT_FAILURE);
       
   336         }
       
   337     }
       
   338 }
       
   339 
       
   340 void
       
   341 usage(char *str1, char *str2)
       
   342 {
       
   343     (void)str2;
       
   344     
       
   345     fprintf(stderr, "usage: %s\n", str1);
       
   346     fprintf(stderr, "  [-b baudrate]     - baud rate\n");
       
   347     fprintf(stderr, "  [-t devicename]      - name of mote network dev tty\n");
       
   348     fprintf(stderr, "  [-d debugValue]\n");
       
   349     fprintf(stderr, "  [-D directory]\n");
       
   350     fprintf(stderr, "  [-h]              - print this message.\n");
       
   351     fprintf(stderr, "\n");
       
   352 }
       
   353 
       
   354 
       
   355 // initialize the motes
       
   356 void
       
   357 init_motes()
       
   358 {
       
   359     src = open_serial_source(devicename, atoi(baud), 0, stderr_msg);
       
   360 
       
   361     if(reader_thread(NULL) == 1) {
       
   362         fprintf(stderr, "couldn't start reader on mote network\n");
       
   363         exit(EXIT_FAILURE);
       
   364     }
       
   365     return;
       
   366 }
       
   367 
       
   368 void read_packet_file(char* filename)
       
   369 {
       
   370     int fd = open(filename, O_RDONLY);
       
   371     static unsigned char buf[BUFSIZ];
       
   372     int n = read(fd, buf, BUFSIZ);
       
   373     hexdump(buf, n);
       
   374 }
       
   375 
       
   376 void
       
   377 hexdump(unsigned char *buf, int n)
       
   378 {
       
   379     int i;
       
   380     unsigned char *p = buf;
       
   381 
       
   382     fprintf(dout,"Packet contains %d:\n",n);
       
   383     for (i = 0; i < n; i++) {
       
   384         fprintf(dout,"%02x ", *p++);
       
   385         if ((i & 0x7) == 0x7)
       
   386             fprintf(dout,"\n");
       
   387     }
       
   388     printf("\n\n");
       
   389     fflush(stdout);
       
   390 }
       
   391 
       
   392 dtn_endpoint_id_t * parse_eid(dtn_handle_t handle, 
       
   393                           dtn_endpoint_id_t * eid, char * str)
       
   394 {
       
   395     
       
   396     // try the string as an actual dtn eid
       
   397     if (!dtn_parse_eid_string(eid, str)) 
       
   398     {
       
   399         return eid;
       
   400     }
       
   401     // build a local eid based on the configuration of our dtn
       
   402     // router plus the str as demux string
       
   403     else if (!dtn_build_local_eid(handle, eid, str))
       
   404     {
       
   405         return eid;
       
   406     }
       
   407     else
       
   408     {
       
   409         fprintf(stderr, "invalid eid string '%s'\n", str);
       
   410         exit(1);
       
   411     }
       
   412 }
       
   413 
       
   414 void print_eid(char* label, dtn_endpoint_id_t* eid)
       
   415 {
       
   416     printf("%s [%s]\n", label, eid->uri);
       
   417 }
       
   418