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