dtnping.c

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037  */
00038 
00039 #include <stdio.h>
00040 #include <unistd.h>
00041 #include <errno.h>
00042 #include <strings.h>
00043 #include <string.h>
00044 #include <stdlib.h>
00045 #include <sys/time.h>
00046 
00047 #include "dtn_api.h"
00048 
00049 const char *progname;
00050 
00051 void
00052 usage()
00053 {
00054     fprintf(stderr, "usage: %s [-c count] [-i interval] [-e expiration] eid\n",
00055             progname);
00056     exit(1);
00057 }
00058 
00059 void doOptions(int argc, const char **argv);
00060 
00061 int sleepVal = 1;
00062 int count = 0;
00063 int expiration = 30;
00064 char dest_eid_str[DTN_MAX_ENDPOINT_ID] = "";
00065 char source_eid_str[DTN_MAX_ENDPOINT_ID] = "";
00066 char replyto_eid_str[DTN_MAX_ENDPOINT_ID] = "";
00067 char* payload_str = "dtn_ping!";
00068 
00069 int
00070 main(int argc, const char** argv)
00071 {
00072     int i;
00073     int ret;
00074     dtn_handle_t handle;
00075     dtn_endpoint_id_t source_eid;
00076     dtn_reg_info_t reginfo;
00077     dtn_reg_id_t regid;
00078     dtn_bundle_spec_t ping_spec;
00079     dtn_bundle_spec_t reply_spec;
00080     dtn_bundle_payload_t ping_payload;
00081     dtn_bundle_payload_t reply_payload;
00082     dtn_bundle_id_t bundle_id;
00083     int debug = 1;
00084     char demux[64];
00085     char payload_buf[1024];
00086 
00087     struct timeval start, end;
00088     
00089     // force stdout to always be line buffered, even if output is
00090     // redirected to a pipe or file
00091     setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00092     
00093     doOptions(argc, argv);
00094 
00095     memset(&ping_spec, 0, sizeof(ping_spec));
00096 
00097     // open the ipc handle
00098     int err = dtn_open(&handle);
00099     if (err != DTN_SUCCESS) {
00100         fprintf(stderr, "fatal error opening dtn handle: %s\n",
00101                 dtn_strerror(err));
00102         exit(1);
00103     }
00104 
00105     // make sure they supplied a valid destination eid or
00106     // "localhost", in which case we just use the local daemon
00107     if (strcmp(dest_eid_str, "localhost") == 0) {
00108         dtn_build_local_eid(handle, &ping_spec.dest, "");
00109         
00110     } else {
00111         if (dtn_parse_eid_string(&ping_spec.dest, dest_eid_str)) {
00112             fprintf(stderr, "invalid destination eid string '%s'\n",
00113                     dest_eid_str);
00114             exit(1);
00115         }
00116     }
00117     
00118     // if the user specified a source eid, register on it.
00119     // otherwise, build a local eid based on the configuration of
00120     // our dtn router plus the demux string
00121     snprintf(demux, sizeof(demux), "/ping.%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     // set the source eid in the bundle spec
00133     if (debug) printf("source_eid [%s]\n", source_eid.uri);
00134     dtn_copy_eid(&ping_spec.source, &source_eid);
00135     
00136     // now parse the replyto eid, if specified. otherwise just use
00137     // the source eid
00138     if (replyto_eid_str[0] != '\0') {
00139         if (dtn_parse_eid_string(&ping_spec.replyto, replyto_eid_str)) {
00140             fprintf(stderr, "invalid replyto eid string '%s'\n",
00141                     replyto_eid_str);
00142             exit(1);
00143         }
00144         
00145     } else {
00146         dtn_copy_eid(&ping_spec.replyto, &source_eid);
00147     }
00148 
00149     if (debug) printf("replyto_eid [%s]\n", ping_spec.replyto.uri);
00150     
00151     // now create a new registration based on the source
00152     memset(&reginfo, 0, sizeof(reginfo));
00153     dtn_copy_eid(&reginfo.endpoint, &source_eid);
00154     reginfo.failure_action = DTN_REG_DEFER;
00155     reginfo.regid = DTN_REGID_NONE;
00156     reginfo.expiration = 0;
00157     if ((ret = dtn_register(handle, &reginfo, &regid)) != 0) {
00158         fprintf(stderr, "error creating registration: %d (%s)\n",
00159                 ret, dtn_strerror(dtn_errno(handle)));
00160         exit(1);
00161     }    
00162     if (debug) printf("dtn_register succeeded, regid %d\n", regid);
00163 
00164     // check for any bundles queued for the registration
00165     if (debug) printf("checking for bundles already queued...\n");
00166     do {
00167         memset(&reply_spec, 0, sizeof(reply_spec));
00168         memset(&reply_payload, 0, sizeof(reply_payload));
00169         
00170         ret = dtn_recv(handle, &reply_spec,
00171                        DTN_PAYLOAD_MEM, &reply_payload, 0);
00172 
00173         if (ret == 0) {
00174             fprintf(stderr, "error: unexpected ping already queued... "
00175                     "discarding\n");
00176         } else if (dtn_errno(handle) != DTN_ETIMEOUT) {
00177             fprintf(stderr, "error: "
00178                     "unexpected error checking for queued bundles: %s\n",
00179                     dtn_strerror(dtn_errno(handle)));
00180             exit(1);
00181         }
00182 
00183         dtn_free_payload(&reply_payload);
00184     } while (ret == 0);
00185     
00186     // set the expiration time
00187     ping_spec.expiration = expiration;
00188 
00189     // fill in a payload of a single type code of 0x3 (echo request)
00190     // and no flags, followed by a short payload string to verify the
00191     // echo feature
00192     payload_buf[0] = 0x3 << 4;
00193     strcpy(&payload_buf[1], payload_str);
00194 
00195     memset(&ping_payload, 0, sizeof(ping_payload));
00196     dtn_set_payload(&ping_payload, DTN_PAYLOAD_MEM, payload_buf, 1 + strlen(payload_str));
00197     
00198     printf("PING [%s]...\n", ping_spec.dest.uri);
00199     
00200     // loop, sending pings and getting replies.
00201     for (i = 0; count == 0 || i < count; ++i) {
00202         gettimeofday(&start, NULL);
00203         
00204         memset(&bundle_id, 0, sizeof(bundle_id));
00205                     
00206         if ((ret = dtn_send(handle, &ping_spec, &ping_payload,
00207                             &bundle_id)) != 0) {
00208             fprintf(stderr, "error sending bundle: %d (%s)\n",
00209                     ret, dtn_strerror(dtn_errno(handle)));
00210             exit(1);
00211         }
00212 
00213         memset(&reply_spec, 0, sizeof(reply_spec));
00214         memset(&reply_payload, 0, sizeof(reply_payload));
00215         
00216         // now we block waiting for the echo reply
00217         if ((ret = dtn_recv(handle, &reply_spec,
00218                             DTN_PAYLOAD_MEM, &reply_payload, -1)) < 0)
00219         {
00220             fprintf(stderr, "error getting ping reply: %d (%s)\n",
00221                     ret, dtn_strerror(dtn_errno(handle)));
00222             exit(1);
00223         }
00224         gettimeofday(&end, NULL);
00225 
00226         printf("%d bytes from [%s]: '%.*s' time=%0.2f ms\n",
00227                reply_payload.dtn_bundle_payload_t_u.buf.buf_len,
00228                reply_spec.source.uri,
00229                reply_payload.dtn_bundle_payload_t_u.buf.buf_len - 1,
00230                reply_payload.dtn_bundle_payload_t_u.buf.buf_val + 1,
00231                ((double)(end.tv_sec - start.tv_sec) * 1000.0 + 
00232                 (double)(end.tv_usec - start.tv_usec)/1000.0));
00233         fflush(stdout);
00234         dtn_free_payload(&reply_payload);
00235         
00236         sleep(sleepVal);
00237     }
00238 
00239     dtn_close(handle);
00240     
00241     return 0;
00242 }
00243 
00244 void
00245 doOptions(int argc, const char **argv)
00246 {
00247     int c;
00248 
00249     progname = argv[0];
00250 
00251     while ( (c=getopt(argc, (char **) argv, "hc:i:e:d:s:r:")) !=EOF ) {
00252         switch (c) {
00253         case 'c':
00254             count = atoi(optarg);
00255             break;
00256         case 'i':
00257             sleepVal = atoi(optarg);
00258             break;
00259         case 'e':
00260             expiration = atoi(optarg);
00261             break;
00262         case 'd':
00263             strcpy(dest_eid_str, optarg);
00264             break;
00265         case 's':
00266             strcpy(source_eid_str, optarg);
00267             break;
00268         case 'r':
00269             strcpy(replyto_eid_str, optarg);
00270             break;
00271         case 'h':
00272             usage();
00273             break;
00274         default:
00275             break;
00276         }
00277     }
00278 
00279     if ((optind < argc) && (strlen(dest_eid_str) == 0)) {
00280         strcpy(dest_eid_str, argv[optind++]);
00281     }
00282 
00283     if (optind < argc) {
00284         fprintf(stderr, "unsupported argument '%s'\n", argv[optind]);
00285         exit(1);
00286     }
00287 
00288     if (dest_eid_str[0] == '\0') {
00289         fprintf(stderr, "must supply a destination eid (or 'localhost')\n");
00290         exit(1);
00291     }
00292 }
00293 

Generated on Fri Dec 22 14:47:58 2006 for DTN Reference Implementation by  doxygen 1.5.1