00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #include <stdio.h>
00022 #include <unistd.h>
00023 #include <errno.h>
00024 #include <strings.h>
00025 #include <string.h>
00026 #include <stdlib.h>
00027 #include <time.h>
00028 #include <sys/time.h>
00029
00030 #include "dtn_api.h"
00031 #include "dtnping.h"
00032
00033 const char *progname;
00034
00035 void
00036 usage()
00037 {
00038 fprintf(stderr, "usage: %s [-c count] [-i interval] [-e expiration] [-w waittime] eid\n",
00039 progname);
00040 exit(1);
00041 }
00042
00043 void doOptions(int argc, const char **argv);
00044
00045 int expiration = 30;
00046 int wait_after_done = 0;
00047 char dest_eid_str[DTN_MAX_ENDPOINT_ID] = "";
00048 char source_eid_str[DTN_MAX_ENDPOINT_ID] = "";
00049 char replyto_eid_str[DTN_MAX_ENDPOINT_ID] = "";
00050
00051
00052 int
00053 main(int argc, const char** argv)
00054 {
00055 int ret;
00056 dtn_handle_t handle;
00057 dtn_endpoint_id_t source_eid;
00058 dtn_endpoint_id_t replyto_eid;
00059 dtn_reg_info_t reginfo;
00060 dtn_reg_id_t regid;
00061 dtn_bundle_spec_t ping_spec;
00062 dtn_bundle_spec_t reply_spec;
00063 dtn_bundle_payload_t ping_payload;
00064 ping_payload_t payload_contents;
00065 ping_payload_t recv_contents;
00066 dtn_bundle_payload_t reply_payload;
00067 dtn_bundle_status_report_t* sr_data;
00068 dtn_bundle_id_t bundle_id;
00069 int debug = 1;
00070 char demux[64];
00071 int dest_len = 0;
00072 struct timeval send_time, now;
00073 u_int32_t nonce;
00074 int done;
00075 time_t clock;
00076 struct tm* tm_buf;
00077
00078
00079
00080 setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00081
00082 doOptions(argc, argv);
00083
00084 memset(&ping_spec, 0, sizeof(ping_spec));
00085
00086 gettimeofday(&now, 0);
00087 srand(now.tv_sec);
00088 nonce = rand();
00089
00090
00091 int err = dtn_open(&handle);
00092 if (err != DTN_SUCCESS) {
00093 fprintf(stderr, "fatal error opening dtn handle: %s\n",
00094 dtn_strerror(err));
00095 exit(1);
00096 }
00097
00098
00099
00100 if (strcmp(dest_eid_str, "localhost") == 0) {
00101 dtn_build_local_eid(handle, &ping_spec.dest, "ping");
00102
00103 } else {
00104 if (dtn_parse_eid_string(&ping_spec.dest, dest_eid_str)) {
00105 fprintf(stderr, "invalid destination eid string '%s'\n",
00106 dest_eid_str);
00107 exit(1);
00108 }
00109 }
00110
00111 dest_len = strlen(ping_spec.dest.uri);
00112 if ((dest_len < 4) ||
00113 (strcmp(ping_spec.dest.uri + dest_len - 4, "ping") != 0))
00114 {
00115 fprintf(stderr, "\nWARNING: ping destination does not end in \"ping\"\n\n");
00116 }
00117
00118
00119
00120
00121 snprintf(demux, sizeof(demux), "/traceroute.%d", getpid());
00122 if (source_eid_str[0] != '\0') {
00123 if (dtn_parse_eid_string(&source_eid, source_eid_str)) {
00124 fprintf(stderr, "invalid source eid string '%s'\n",
00125 source_eid_str);
00126 exit(1);
00127 }
00128 } else {
00129 dtn_build_local_eid(handle, &source_eid, demux);
00130 }
00131
00132 if (debug) printf("source_eid [%s]\n", source_eid.uri);
00133 dtn_copy_eid(&ping_spec.source, &source_eid);
00134
00135
00136 if ( replyto_eid_str[0]!=0 ) {
00137 if (dtn_parse_eid_string(&replyto_eid, replyto_eid_str)) {
00138 fprintf(stderr, "invalid replyto eid string '%s'\n",
00139 replyto_eid_str);
00140 exit(1);
00141 }
00142 dtn_copy_eid(&ping_spec.replyto, &replyto_eid);
00143 printf("using user-supplied replyto\n");
00144 } else {
00145 dtn_copy_eid(&ping_spec.replyto, &source_eid);
00146 printf("using default replyto\n");
00147 }
00148
00149
00150
00151
00152
00153 memset(®info, 0, sizeof(reginfo));
00154 dtn_copy_eid(®info.endpoint, &source_eid);
00155 reginfo.flags = DTN_REG_DROP;
00156 reginfo.regid = DTN_REGID_NONE;
00157 reginfo.expiration = 0;
00158 if ((ret = dtn_register(handle, ®info, ®id)) != 0) {
00159 fprintf(stderr, "error creating registration: %d (%s)\n",
00160 ret, dtn_strerror(dtn_errno(handle)));
00161 exit(1);
00162 }
00163 if (debug) printf("dtn_register succeeded, regid %d\n", regid);
00164
00165
00166 ping_spec.expiration = expiration;
00167 ping_spec.dopts = DOPTS_DELETE_RCPT |
00168 DOPTS_RECEIVE_RCPT |
00169 DOPTS_FORWARD_RCPT |
00170 DOPTS_DELIVERY_RCPT;
00171
00172
00173 gettimeofday(&send_time, NULL);
00174
00175
00176
00177
00178 memcpy(&payload_contents.ping, PING_STR, 8);
00179 payload_contents.seqno = 0;
00180 payload_contents.nonce = nonce;
00181 payload_contents.time = send_time.tv_sec;
00182
00183 memset(&ping_payload, 0, sizeof(ping_payload));
00184 dtn_set_payload(&ping_payload, DTN_PAYLOAD_MEM,
00185 (char*)&payload_contents, sizeof(payload_contents));
00186
00187 memset(&bundle_id, 0, sizeof(bundle_id));
00188 if ((ret = dtn_send(handle, regid, &ping_spec, &ping_payload, &bundle_id)) != 0) {
00189 fprintf(stderr, "error sending bundle: %d (%s)\n",
00190 ret, dtn_strerror(dtn_errno(handle)));
00191 exit(1);
00192 }
00193
00194 memset(&reply_spec, 0, sizeof(reply_spec));
00195 memset(&reply_payload, 0, sizeof(reply_payload));
00196
00197 clock = time(&clock);
00198 tm_buf = gmtime(&clock);
00199 printf("%s: sent at %.*s UTC\n",
00200 ping_spec.source.uri, 24, asctime(tm_buf));
00201
00202
00203 done = 0;
00204 while (1) {
00205 int timeout = done ? wait_after_done * 1000 : -1;
00206 if ((ret = dtn_recv(handle, &reply_spec,
00207 DTN_PAYLOAD_MEM, &reply_payload, timeout)) < 0)
00208 {
00209 if (done && dtn_errno(handle) == DTN_ETIMEOUT) {
00210 break;
00211 }
00212 fprintf(stderr, "error getting ping reply: %d (%s)\n",
00213 ret, dtn_strerror(dtn_errno(handle)));
00214 exit(1);
00215 }
00216
00217 gettimeofday(&now, 0);
00218
00219 if (reply_payload.status_report != NULL)
00220 {
00221 sr_data = reply_payload.status_report;
00222 if (sr_data->flags & STATUS_RECEIVED)
00223 {
00224 clock = sr_data->receipt_ts.secs + DTNTIME_OFFSET;
00225 tm_buf = gmtime(&clock);
00226 printf("%s: received at %.*s UTC (%ld ms rtt)\n",
00227 reply_spec.source.uri, 24, asctime(tm_buf),
00228 TIMEVAL_DIFF_MSEC(now, send_time));
00229 }
00230 if (sr_data->flags & STATUS_FORWARDED)
00231 {
00232 clock = sr_data->forwarding_ts.secs + DTNTIME_OFFSET;
00233 tm_buf = gmtime(&clock);
00234 printf("%s: forwarded at %.*s UTC (%ld ms rtt)\n",
00235 reply_spec.source.uri, 24, asctime(tm_buf),
00236 TIMEVAL_DIFF_MSEC(now, send_time));
00237 }
00238 if (sr_data->flags & STATUS_DELIVERED)
00239 {
00240 clock = sr_data->delivery_ts.secs + DTNTIME_OFFSET;
00241 tm_buf = gmtime(&clock);
00242 printf("%s: delivered at %.*s UTC (%ld ms rtt)\n",
00243 reply_spec.source.uri, 24, asctime(tm_buf),
00244 TIMEVAL_DIFF_MSEC(now, send_time));
00245 }
00246 if (sr_data->flags & STATUS_DELETED)
00247 {
00248 clock = sr_data->deletion_ts.secs + DTNTIME_OFFSET;
00249 tm_buf = gmtime(&clock);
00250 printf("%s: deleted at %.*s UTC (%s) (%ld ms rtt)\n",
00251 reply_spec.source.uri, 24, asctime(tm_buf),
00252 dtn_status_report_reason_to_str(sr_data->reason),
00253 TIMEVAL_DIFF_MSEC(now, send_time));
00254 break;
00255 }
00256 }
00257 else {
00258 if (reply_payload.buf.buf_len != sizeof(ping_payload_t))
00259 {
00260 printf("%d bytes from [%s]: ERROR: length != %zu\n",
00261 reply_payload.buf.buf_len,
00262 reply_spec.source.uri,
00263 sizeof(ping_payload_t));
00264 break;
00265 }
00266
00267 memcpy(&recv_contents, reply_payload.buf.buf_val,
00268 sizeof(recv_contents));
00269
00270 if (recv_contents.seqno != 0)
00271 {
00272 printf("%d bytes from [%s]: ERROR: invalid seqno %d\n",
00273 reply_payload.buf.buf_len,
00274 reply_spec.source.uri,
00275 recv_contents.seqno);
00276 break;
00277 }
00278
00279 if (recv_contents.nonce != nonce)
00280 {
00281 printf("%d bytes from [%s]: ERROR: invalid nonce %u != %u\n",
00282 reply_payload.buf.buf_len,
00283 reply_spec.source.uri,
00284 recv_contents.nonce, nonce);
00285 break;
00286 }
00287
00288 if ((int)recv_contents.time != (int)send_time.tv_sec)
00289 {
00290 printf("%d bytes from [%s]: ERROR: time mismatch %u != %lu\n",
00291 reply_payload.buf.buf_len,
00292 reply_spec.source.uri,
00293 recv_contents.time,
00294 (long unsigned int)send_time.tv_sec);
00295 }
00296
00297 clock = reply_spec.creation_ts.secs + DTNTIME_OFFSET;
00298 tm_buf = gmtime(&clock);
00299 printf("%s: echo reply at %.*s UTC (%ld ms rtt)\n",
00300 reply_spec.source.uri, 24, asctime(tm_buf),
00301 TIMEVAL_DIFF_MSEC(now, send_time));
00302 done = 1;
00303 }
00304
00305 dtn_free_payload(&reply_payload);
00306 }
00307
00308 dtn_close(handle);
00309
00310 return 0;
00311 }
00312
00313 void
00314 doOptions(int argc, const char **argv)
00315 {
00316 int c;
00317
00318 progname = argv[0];
00319
00320 while ( (c=getopt(argc, (char **) argv, "he:d:s:r:w:")) !=EOF ) {
00321 switch (c) {
00322 case 'e':
00323 expiration = atoi(optarg);
00324 break;
00325 case 'r':
00326 strcpy(replyto_eid_str, optarg);
00327 printf("Setting replyto_eid_str to: %s\n", replyto_eid_str);
00328 break;
00329 case 'd':
00330 strcpy(dest_eid_str, optarg);
00331 break;
00332 case 's':
00333 strcpy(source_eid_str, optarg);
00334 break;
00335 case 'h':
00336 usage();
00337 break;
00338 case 'w':
00339 wait_after_done = atoi(optarg);
00340 break;
00341 default:
00342 break;
00343 }
00344 }
00345
00346 if ((optind < argc) && (strlen(dest_eid_str) == 0)) {
00347 strcpy(dest_eid_str, argv[optind++]);
00348 }
00349
00350 if (optind < argc) {
00351 fprintf(stderr, "unsupported argument '%s'\n", argv[optind]);
00352 exit(1);
00353 }
00354
00355 if (dest_eid_str[0] == '\0') {
00356 fprintf(stderr, "must supply a destination eid (or 'localhost')\n");
00357 exit(1);
00358 }
00359 }
00360