|
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(®info, 0, sizeof(reginfo)); |
|
228 dtn_copy_eid(®info.endpoint, &bundle_spec.replyto); |
|
229 reginfo.flags = DTN_REG_DEFER; |
|
230 reginfo.regid = regid; |
|
231 reginfo.expiration = 0; |
|
232 if ((ret = dtn_register(handle, ®info, ®id)) != 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 |