network_cmds-511.tar.gz
[apple/network_cmds.git] / spray.tproj / spray.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1993 Winning Strategies, Inc.
26 * All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by Winning Strategies, Inc.
39 * 4. The name of the author may not be used to endorse or promote products
40 * derived from this software without specific prior written permission
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 *
53 * $Id: spray.c,v 1.2 2006/02/07 06:22:44 lindak Exp $
54 */
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <unistd.h>
59
60 #include <rpc/rpc.h>
61 #include <rpcsvc/spray.h>
62
63 #ifndef SPRAYOVERHEAD
64 #define SPRAYOVERHEAD 86
65 #endif
66
67 void usage ();
68 void print_xferstats ();
69
70 /* spray buffer */
71 char spray_buffer[SPRAYMAX];
72
73 /* RPC timeouts */
74 struct timeval NO_DEFAULT = { -1, -1 };
75 struct timeval ONE_WAY = { 0, 0 };
76 struct timeval TIMEOUT = { 25, 0 };
77
78 int
79 main(argc, argv)
80 int argc;
81 char **argv;
82 {
83 char *progname;
84 spraycumul host_stats;
85 sprayarr host_array;
86 CLIENT *cl;
87 int c;
88 int i;
89 int count = 0;
90 int delay = 0;
91 int length = 0;
92 double xmit_time; /* time to receive data */
93
94 progname = *argv;
95 while ((c = getopt(argc, argv, "c:d:l:")) != -1) {
96 switch (c) {
97 case 'c':
98 count = atoi(optarg);
99 break;
100 case 'd':
101 delay = atoi(optarg);
102 break;
103 case 'l':
104 length = atoi(optarg);
105 break;
106 default:
107 usage();
108 /* NOTREACHED */
109 }
110 }
111 argc -= optind;
112 argv += optind;
113
114 if (argc != 1) {
115 usage();
116 /* NOTREACHED */
117 }
118
119
120 /* Correct packet length. */
121 if (length > SPRAYMAX) {
122 length = SPRAYMAX;
123 } else if (length < SPRAYOVERHEAD) {
124 length = SPRAYOVERHEAD;
125 } else {
126 /* The RPC portion of the packet is a multiple of 32 bits. */
127 length -= SPRAYOVERHEAD - 3;
128 length &= ~3;
129 length += SPRAYOVERHEAD;
130 }
131
132
133 /*
134 * The default value of count is the number of packets required
135 * to make the total stream size 100000 bytes.
136 */
137 if (!count) {
138 count = 100000 / length;
139 }
140
141 /* Initialize spray argument */
142 host_array.sprayarr_len = length - SPRAYOVERHEAD;
143 host_array.sprayarr_val = spray_buffer;
144
145
146 /* create connection with server */
147 cl = clnt_create(*argv, SPRAYPROG, SPRAYVERS, "udp");
148 if (cl == NULL) {
149 clnt_pcreateerror(progname);
150 exit(1);
151 }
152
153
154 /*
155 * For some strange reason, RPC 4.0 sets the default timeout,
156 * thus timeouts specified in clnt_call() are always ignored.
157 *
158 * The following (undocumented) hack resets the internal state
159 * of the client handle.
160 */
161 clnt_control(cl, CLSET_TIMEOUT, (char *)&NO_DEFAULT);
162
163
164 /* Clear server statistics */
165 if (clnt_call(cl, SPRAYPROC_CLEAR, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
166 clnt_perror(cl, progname);
167 exit(1);
168 }
169
170
171 /* Spray server with packets */
172 printf ("sending %d packets of lnth %d to %s ...", count, length, *argv);
173 fflush (stdout);
174
175 for (i = 0; i < count; i++) {
176 clnt_call(cl, SPRAYPROC_SPRAY, (xdrproc_t)xdr_sprayarr, &host_array, (xdrproc_t)xdr_void, NULL, ONE_WAY);
177
178 if (delay) {
179 usleep(delay);
180 }
181 }
182
183
184 /* Collect statistics from server */
185 if (clnt_call(cl, SPRAYPROC_GET, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_spraycumul, &host_stats, TIMEOUT) != RPC_SUCCESS) {
186 clnt_perror(cl, progname);
187 exit(1);
188 }
189
190 xmit_time = host_stats.clock.sec +
191 (host_stats.clock.usec / 1000000.0);
192
193 printf ("\n\tin %.2f seconds elapsed time\n", xmit_time);
194
195
196 /* report dropped packets */
197 if (host_stats.counter != count) {
198 int packets_dropped = count - host_stats.counter;
199
200 printf("\t%d packets (%.2f%%) dropped\n",
201 packets_dropped,
202 100.0 * packets_dropped / count );
203 } else {
204 printf("\tno packets dropped\n");
205 }
206
207 printf("Sent:");
208 print_xferstats(count, length, xmit_time);
209
210 printf("Rcvd:");
211 print_xferstats(host_stats.counter, length, xmit_time);
212
213 exit (0);
214 }
215
216
217 void
218 print_xferstats(packets, packetlen, xfertime)
219 int packets;
220 int packetlen;
221 double xfertime;
222 {
223 int datalen;
224 double pps; /* packets per second */
225 double bps; /* bytes per second */
226
227 datalen = packets * packetlen;
228 pps = packets / xfertime;
229 bps = datalen / xfertime;
230
231 printf("\t%.0f packets/sec, ", pps);
232
233 if (bps >= 1024)
234 printf ("%.1fK ", bps / 1024);
235 else
236 printf ("%.0f ", bps);
237
238 printf("bytes/sec\n");
239 }
240
241
242 void
243 usage ()
244 {
245 fprintf(stderr, "usage: spray [-c count] [-l length] [-d delay] host\n");
246 exit(1);
247 }