[insert project logo here (125x200px max)]

Navigator

Mailinglists

Please report any errors or ommissions you find to our `Help' mailinglist, or post a message in the Forums.

Copyright and Licensing Information

Snap is (c) Jonathan T. Moore, 1999-2002 and licensed under the GNU General Public License (GPL).

All other parts of Splash are (c) Willem de Bruijn, 2002-2003 and licensed under the BSD Open Source License.

All sourcecode is made publicly available.

Acknowledgement

Splash and the Splash website are hosted by SourceForge.net

SourceForge.net Logo

osi-open source certified logo

Splash - Documentation

SNMP Plus a Lightweight API for SNAP Handling

Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

snap-1.1-wjdb/src/snap_sendandreceive.c

Go to the documentation of this file.
00001  /*
00002  * snap_sendandreceive.c : SNAP user-space node daemon.
00003  * Sends a package and waits for a return packet
00004  * It prints the stack output of the return packet
00005  *
00006  * $Id: snap_sendandreceive.c,v 1.7 2003/01/11 13:15:00 wdebruij Exp $
00007  */
00008 
00009 #include <time.h>
00010 #include <sys/time.h>
00011 #include "../lib/libsnap.h"
00012 #include <arpa/inet.h>
00013 #include <assert.h>
00014 #include <fcntl.h>
00015 #include <netinet/ip.h>
00016 #include <netdb.h>
00017 #include <netinet/in.h>
00018 #include <unistd.h>
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <sys/socket.h>
00022 #include <sys/un.h>
00023 #include <sys/stat.h>
00024 #include <sys/types.h>
00025 #include "../lib/snap.h"
00026 #include "../lib/bytecode.h"
00027 #include "../lib/packet.h"
00028 #include "../lib/d_printf.h"
00029 #include "../lib/memalloc.h"
00030 #include "../lib/io.h"
00031 #include <pthread.h>
00032 
00033 #include "snap_demux_handler.h"
00034 
00035 #define NIPQUAD(addr) \
00036         ((unsigned char *)&addr)[0], \
00037         ((unsigned char *)&addr)[1], \
00038         ((unsigned char *)&addr)[2], \
00039         ((unsigned char *)&addr)[3]
00040 
00041 #define IPPROTO_SNAP 130
00042 #define NO_RUNS 101
00043 
00044 /* settable options */
00045 unsigned char out_ttl = 32;
00046 short int receiveport = 7777;
00047 struct sockaddr_in destaddr;
00048 struct sockaddr_in srcaddr;
00049 struct sockaddr_in localaddr;
00050 
00051 extern char *basename(const char *);
00052 void parse_cmdline(int argc,char **argv);
00053 
00054 int infd;
00055 buffer_t inbuf;
00056 int sd;
00057 
00058 int compare_longints(const void* a, const void* b){
00059   const long int *da = (const long int *) a;
00060   const long int *db = (const long int *) b;
00061 
00062   return (*da > *db) - (*da < *db);
00063 }
00064 
00065 int init_request(int argc,char **argv) {
00066   int packet_lenb;
00067   struct snaphdr *hdr;
00068   char ra_space[4];
00069 
00070   parse_cmdline(argc,argv);
00071 
00072   /* first suck in the binary packet */
00073   packet_lenb = file_to_str(infd,&inbuf);
00074   if (packet_lenb < inbuf.lenb)
00075     inbuf.lenb = packet_lenb;
00076   d_printf(50,"read in %d bytes\n",inbuf.lenb);
00077 
00078   /* touch up certain SNAP header entries */
00079   hdr = (struct snaphdr *)inbuf.s;
00080   hdr->saddr = srcaddr.sin_addr.s_addr;
00081   hdr->daddr = destaddr.sin_addr.s_addr;
00082   hdr->version = 1;
00083   hdr->flags = 0;
00084   hdr->sport = htons(receiveport);
00085 
00086   /* open up raw socket */
00087   if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_SNAP)) < 0) {
00088     perror("inject: socket");
00089     exit(1);
00090   }
00091 
00092   /* set socket options : first, router alert */
00093   bzero(ra_space,4);
00094   ra_space[IPOPT_OPTVAL] = IPOPT_RA;
00095   ra_space[IPOPT_OLEN] = 4;
00096   if (setsockopt(sd, IPPROTO_IP, IP_OPTIONS, ra_space,
00097          sizeof(ra_space)) < 0) {
00098     perror("inject: setsockopt: router alert");
00099     exit(1);
00100   }
00101 
00102   /* now set resource bound as requested */
00103   if (setsockopt(sd, IPPROTO_IP, IP_TTL,
00104          (char *)&out_ttl, sizeof(out_ttl)) < 0) {
00105     perror("inject: setsockopt: ttl");
00106     exit(1);
00107   }
00108 
00109   return(0);
00110 }
00111 
00112 void sendpkt(){
00113   /* send to the local interpreter */
00114   /* replace localaddr with destaddr in the sendto(..) to send directly */
00115   localaddr.sin_addr.s_addr = htonl( (127 << 24) + 1 ); /* == 127.0.0.1 */
00116   localaddr.sin_family = AF_INET;
00117 
00118   if (sendto(sd, inbuf.s, inbuf.lenb, 0, (struct sockaddr *)&localaddr,
00119          sizeof(localaddr)) < 0) {
00120     perror("snap_sendandreceive : sendto");
00121   }
00122 }
00123 
00124 void usage(int argc, char **argv) {
00125   printf("usage: %s [-?] [-t ttl] [-p receiveport] src dest infile\n",basename(argv[0]));
00126   printf("\t-t : set the outgoing TTL (resource bound) (default=16)\n");
00127   printf("\t-p : set the source port number (default=7777)\n");
00128   printf("\t-? : print this help\n");
00129 }
00130 
00131 void parse_cmdline(int argc, char **argv) {
00132   char *opts = "?t:p:";
00133   char c;
00134   int args_expected = 3;
00135   int args_processed = 0;
00136   int argidx;
00137   char *infilename;
00138 
00139   while((c = getopt(argc,argv,opts)) != EOF) {
00140     switch(c) {
00141     case '?':
00142       usage(argc,argv);
00143       exit(1);
00144     case 't':
00145       out_ttl = atoi(optarg);
00146       if (out_ttl <= 0) {
00147     fprintf(stderr,"%s: invalid TTL: %d\n",basename(argv[0]),out_ttl);
00148     fflush(stderr);
00149     usage(argc,argv);
00150     exit(1);
00151       }
00152       fprintf(stderr,"%s: setting TTL to %d\n",basename(argv[0]),out_ttl);
00153       break;
00154     case 'p':
00155       receiveport = atoi(optarg);
00156       if (receiveport <= 0) {
00157     fprintf(stderr,"%s: invalid source port: %d\n",
00158         basename(argv[0]),receiveport);
00159     fflush(stderr);
00160     usage(argc,argv);
00161     exit(1);
00162       }
00163       break;
00164     default:
00165       fprintf(stderr,"%s: unrecognized option -%c\n",
00166           basename(argv[0]),c);
00167       fflush(stderr);
00168       usage(argc,argv);
00169       exit(1);
00170     }
00171   }
00172   argidx = optind;
00173 
00174   bzero(&destaddr,sizeof(destaddr));
00175 
00176   while(args_processed < args_expected) {
00177     if (argidx >= argc) {
00178       /* missing arguments */
00179       printf("%s: missing argument(s)\n",basename(argv[0]));
00180       usage(argc,argv);
00181       exit(1);
00182     }
00183     switch(args_processed) {
00184     case 0: {           /* source address */
00185       struct hostent *srchostp = NULL;
00186       srchostp = gethostbyname(argv[argidx]);
00187       if (srchostp == NULL) {
00188     fprintf(stderr,"%s: unknown dest host %s\n",
00189         basename(argv[0]),argv[argidx]);
00190     fflush(stderr);
00191     usage(argc,argv);
00192     exit(1);
00193       }
00194       assert(srchostp->h_addrtype == AF_INET);
00195       assert(srchostp->h_length == sizeof(unsigned int));
00196       memcpy(&srcaddr.sin_addr.s_addr,srchostp->h_addr,srchostp->h_length);
00197       srcaddr.sin_family = AF_INET;
00198       break;
00199     }
00200     case 1: {           /* destination address */
00201       struct hostent *desthostp = NULL;
00202       desthostp = gethostbyname(argv[argidx]);
00203       if (desthostp == NULL) {
00204     fprintf(stderr,"%s: unknown dest host %s\n",
00205         basename(argv[0]),argv[argidx]);
00206     fflush(stderr);
00207     usage(argc,argv);
00208     exit(1);
00209       }
00210       assert(desthostp->h_addrtype == AF_INET);
00211       assert(desthostp->h_length == sizeof(unsigned int));
00212       memcpy(&destaddr.sin_addr.s_addr,desthostp->h_addr,desthostp->h_length);
00213       destaddr.sin_family = AF_INET;
00214       break;
00215     }
00216     case 2:         /* packet file name */
00217       infilename = argv[argidx];
00218       if (strcmp(infilename,"-") == 0) {
00219     infd = 0;       /* stdin */
00220       } else {
00221     infd = open(infilename,O_RDONLY);
00222     if (infd == -1) {
00223       fprintf(stderr,"%s: unable to open file \"%s\" for input\n",
00224           basename(argv[0]),infilename);
00225       fflush(stderr);
00226       exit(1);
00227     }
00228       }
00229       break;
00230     }
00231     argidx++;
00232     args_processed++;
00233   }
00234   if (argidx < argc) {
00235     /* extra arguments */
00236     printf("%s: extra argument(s)\n",basename(argv[0]));
00237     usage(argc,argv);
00238     exit(1);
00239   }
00240   return;
00241 }
00242 
00243 int main(int argc, char** argv){
00244     struct timeval tStart;
00245     struct timeval tEnd;
00246     long int tDiff, tAvg;
00247     int received=0, received_prev=-1;
00248     int timeouts=0, sent=0;
00249     char* env_val;
00250     int protocols;
00251     /*pthread_t snap_thread;*/
00252 
00253     struct timeval tSaves[NO_RUNS][2];
00254     long int tDiffs[NO_RUNS];
00255     int runCount = 0;
00256 
00257     /* get starting time */
00258     gettimeofday(&tStart,NULL);
00259 
00260     /* initialize the request */
00261     init_request (argc, argv);
00262 
00263     /* initialize the recv protocol(s) */
00264     env_val = getenv("SNAP_DEMUX_HANDLER");
00265     if (env_val != NULL)
00266         protocols = atoi(env_val);
00267     else
00268         protocols = SNAP_UNIX;
00269     snap_demux_init(protocols);
00270 
00271     /* execute the requests */
00272     while (received < NO_RUNS){
00273         if (received_prev == received)
00274             timeouts++;
00275         gettimeofday(&tSaves[received][0], NULL);
00276         received_prev = received;
00277         sendpkt();
00278         sent++;
00279         if (snap_demux_handler((buffer_handler) &snap_demux_buffer_print_unsafe))
00280             received++;
00281 
00282         gettimeofday(&tSaves[received_prev][1], NULL);
00283     }
00284 
00285     snap_demux_close();
00286 
00287     /* get the end time*/
00288     gettimeofday(&tEnd, NULL);
00289 
00290     /* write out the processing time per run */
00291     tAvg = 0;
00292 
00293     printf("\n");
00294     for (runCount = 0; runCount < NO_RUNS; runCount++){
00295             tDiff = ((tSaves[runCount][1].tv_sec - tSaves[runCount][0].tv_sec) * 1000000) + (tSaves[runCount][1].tv_usec - tSaves[runCount][0].tv_usec);
00296             tDiffs[runCount] = tDiff;
00297             printf("%.05ld : time to complete run %d \n",tDiff,runCount);
00298             tAvg += tDiff;
00299     }
00300 
00301     printf("\n");
00302     /* write out the total processing time */
00303     tDiff = ((tEnd.tv_sec - tStart.tv_sec) * 1000000) + (tEnd.tv_usec - tStart.tv_usec);
00304     printf("the total execution took %ld milliseconds for %d runs.\n",tDiff,NO_RUNS);
00305 
00306     /* write out the preprocessing time */
00307     tDiff = ((tSaves[0][0].tv_sec - tStart.tv_sec) * 1000000) + (tSaves[0][0].tv_usec - tStart.tv_usec);
00308     printf("preprocessing took %ld microseconds.\n",tDiff);
00309 
00310     /* write out the average processing time per run*/
00311     printf("On average, a communication run took %ld microseconds\n",  tAvg / NO_RUNS );
00312 
00313     /* write out the median of the processing time */
00314     qsort(tDiffs, NO_RUNS, sizeof (long int), compare_longints);
00315     printf("the median of a communication run is %ld microseconds\n", tDiffs[(NO_RUNS / 2) + 1]);
00316 
00317     /* write out the postprocessing time */
00318     tDiff = ((tEnd.tv_sec - tSaves[NO_RUNS - 1][1].tv_sec) * 1000000) + (tEnd.tv_usec - tSaves[NO_RUNS - 1][1].tv_usec);
00319     printf("postprocessing took %ld microseconds.\n",tDiff);
00320 
00321     /* write out the number of timeouts */
00322     printf("there were %d TIMEOUT errors on %d sends. This gives and errorpercentage of %.2g\n",timeouts,sent,(double) (timeouts*100) / (double) sent);
00323 
00324     /* write out the average processing time including pre and postprocessing */
00325     tDiff = ((tEnd.tv_sec - tStart.tv_sec) * 1000000) + (tEnd.tv_usec - tStart.tv_usec);
00326     printf("On average, a complete request took %ld microseconds\n", tDiff / NO_RUNS );
00327 
00328   return 0;
00329 }