source: mainline/uspace/app/nettest2/nettest2.c@ fae4d30

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fae4d30 was d4d74dc, checked in by Vojtech Horky <vojtechhorky@…>, 13 years ago

Less includes in library headers

There is no need for errno.h to include fibril.h.
Similarly, tinput.h does not need list.h or async.h.

Unfortunately, many programs depended on the fact that including
errno.h would (recursively) include unistd.h and NULL would be
defined. Most of the fixes remedy this problem.

  • Property mode set to 100644
File size: 10.3 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup nettest
30 * @{
31 */
32
33/** @file
34 * Networking test 2 application - transfer.
35 */
36
37#include "nettest.h"
38#include "print_error.h"
39
40#include <malloc.h>
41#include <stdio.h>
42#include <unistd.h>
43#include <str.h>
44#include <task.h>
45#include <time.h>
46#include <arg_parse.h>
47#include <bool.h>
48
49#include <net/in.h>
50#include <net/in6.h>
51#include <net/inet.h>
52#include <net/socket.h>
53#include <net/socket_parse.h>
54
55/** Echo module name. */
56#define NAME "Nettest2"
57
58/** Packet data pattern. */
59#define NETTEST2_TEXT "Networking test 2 - transfer"
60
61static size_t size;
62static bool verbose;
63static sock_type_t type;
64static int sockets;
65static int messages;
66static int family;
67static uint16_t port;
68
69static void nettest2_print_help(void)
70{
71 printf(
72 "Network Networking test 2 aplication - UDP transfer\n"
73 "Usage: echo [options] address\n"
74 "Where options are:\n"
75 "-f protocol_family | --family=protocol_family\n"
76 "\tThe listenning socket protocol family. Only the PF_INET and "
77 "PF_INET6 are supported.\n"
78 "\n"
79 "-h | --help\n"
80 "\tShow this application help.\n"
81 "\n"
82 "-m count | --messages=count\n"
83 "\tThe number of messages to send and receive per socket. The "
84 "default is 10.\n"
85 "\n"
86 "-n sockets | --sockets=count\n"
87 "\tThe number of sockets to use. The default is 10.\n"
88 "\n"
89 "-p port_number | --port=port_number\n"
90 "\tThe port number the application should send messages to. The "
91 "default is 7.\n"
92 "\n"
93 "-s packet_size | --size=packet_size\n"
94 "\tThe packet data size the application sends. The default is 29 "
95 "bytes.\n"
96 "\n"
97 "-v | --verbose\n"
98 "\tShow all output messages.\n");
99}
100
101/** Fill buffer with the NETTEST2_TEXT pattern.
102 *
103 * @param buffer Data buffer.
104 * @param size Buffer size in bytes.
105 */
106static void nettest2_fill_buffer(char *buffer, size_t size)
107{
108 size_t length;
109
110 length = 0;
111 while (size > length + sizeof(NETTEST2_TEXT) - 1) {
112 memcpy(buffer + length, NETTEST2_TEXT,
113 sizeof(NETTEST2_TEXT) - 1);
114 length += sizeof(NETTEST2_TEXT) - 1;
115 }
116
117 memcpy(buffer + length, NETTEST2_TEXT, size - length);
118 buffer[size] = '\0';
119}
120
121/** Parse one command-line option.
122 *
123 * @param argc Number of all command-line arguments.
124 * @param argv All command-line arguments.
125 * @param index Current argument index (in, out).
126 */
127static int nettest2_parse_opt(int argc, char *argv[], int *index)
128{
129 int value;
130 int rc;
131
132 switch (argv[*index][1]) {
133 /*
134 * Short options with only one letter
135 */
136 case 'f':
137 rc = arg_parse_name_int(argc, argv, index, &family, 0,
138 socket_parse_protocol_family);
139 if (rc != EOK)
140 return rc;
141 break;
142 case 'h':
143 nettest2_print_help();
144 return EOK;
145 break;
146 case 'm':
147 rc = arg_parse_int(argc, argv, index, &messages, 0);
148 if (rc != EOK)
149 return rc;
150 break;
151 case 'n':
152 rc = arg_parse_int(argc, argv, index, &sockets, 0);
153 if (rc != EOK)
154 return rc;
155 break;
156 case 'p':
157 rc = arg_parse_int(argc, argv, index, &value, 0);
158 if (rc != EOK)
159 return rc;
160 port = (uint16_t) value;
161 break;
162 case 's':
163 rc = arg_parse_int(argc, argv, index, &value, 0);
164 if (rc != EOK)
165 return rc;
166 size = (value >= 0) ? (size_t) value : 0;
167 break;
168 case 't':
169 rc = arg_parse_name_int(argc, argv, index, &value, 0,
170 socket_parse_socket_type);
171 if (rc != EOK)
172 return rc;
173 type = (sock_type_t) value;
174 break;
175 case 'v':
176 verbose = true;
177 break;
178 /*
179 * Long options with double dash ('-')
180 */
181 case '-':
182 if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) {
183 rc = arg_parse_name_int(argc, argv, index, &family, 9,
184 socket_parse_protocol_family);
185 if (rc != EOK)
186 return rc;
187 } else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) {
188 nettest2_print_help();
189 return EOK;
190 } else if (str_lcmp(argv[*index] + 2, "messages=", 6) == 0) {
191 rc = arg_parse_int(argc, argv, index, &messages, 8);
192 if (rc != EOK)
193 return rc;
194 } else if (str_lcmp(argv[*index] + 2, "sockets=", 6) == 0) {
195 rc = arg_parse_int(argc, argv, index, &sockets, 8);
196 if (rc != EOK)
197 return rc;
198 } else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) {
199 rc = arg_parse_int(argc, argv, index, &value, 7);
200 if (rc != EOK)
201 return rc;
202 port = (uint16_t) value;
203 } else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) {
204 rc = arg_parse_name_int(argc, argv, index, &value, 7,
205 socket_parse_socket_type);
206 if (rc != EOK)
207 return rc;
208 type = (sock_type_t) value;
209 } else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) {
210 verbose = 1;
211 } else {
212 nettest2_print_help();
213 return EINVAL;
214 }
215 break;
216 default:
217 nettest2_print_help();
218 return EINVAL;
219 }
220
221 return EOK;
222}
223
224int main(int argc, char *argv[])
225{
226 struct sockaddr *address;
227 struct sockaddr_in address_in;
228 struct sockaddr_in6 address_in6;
229 socklen_t addrlen;
230 uint8_t *address_start;
231
232 int *socket_ids;
233 char *data;
234 int index;
235 struct timeval time_before;
236 struct timeval time_after;
237
238 int rc;
239
240 size = 28;
241 verbose = false;
242 type = SOCK_DGRAM;
243 sockets = 10;
244 messages = 10;
245 family = PF_INET;
246 port = 7;
247
248 /*
249 * Parse the command line arguments.
250 *
251 * Stop before the last argument if it does not start with dash ('-')
252 */
253 for (index = 1; (index < argc - 1) || ((index == argc - 1) &&
254 (argv[index][0] == '-')); ++index) {
255
256 /* Options should start with dash ('-') */
257 if (argv[index][0] == '-') {
258 rc = nettest2_parse_opt(argc, argv, &index);
259 if (rc != EOK)
260 return rc;
261 } else {
262 nettest2_print_help();
263 return EINVAL;
264 }
265 }
266
267 /* If not before the last argument containing the address */
268 if (index >= argc) {
269 printf("Command line error: missing address\n");
270 nettest2_print_help();
271 return EINVAL;
272 }
273
274 /* Prepare the address buffer */
275
276 switch (family) {
277 case PF_INET:
278 address_in.sin_family = AF_INET;
279 address_in.sin_port = htons(port);
280 address = (struct sockaddr *) &address_in;
281 addrlen = sizeof(address_in);
282 address_start = (uint8_t *) &address_in.sin_addr.s_addr;
283 break;
284 case PF_INET6:
285 address_in6.sin6_family = AF_INET6;
286 address_in6.sin6_port = htons(port);
287 address = (struct sockaddr *) &address_in6;
288 addrlen = sizeof(address_in6);
289 address_start = (uint8_t *) &address_in6.sin6_addr.s6_addr;
290 break;
291 default:
292 fprintf(stderr, "Address family is not supported\n");
293 return EAFNOSUPPORT;
294 }
295
296 /* Parse the last argument which should contain the address. */
297 rc = inet_pton(family, argv[argc - 1], address_start);
298 if (rc != EOK) {
299 fprintf(stderr, "Address parse error %d\n", rc);
300 return rc;
301 }
302
303 /* Check data buffer size. */
304 if (size <= 0) {
305 fprintf(stderr, "Data buffer size too small (%zu). Using 1024 "
306 "bytes instead.\n", size);
307 size = 1024;
308 }
309
310 /*
311 * Prepare the buffer. Allocate size bytes plus one for terminating
312 * null character.
313 */
314 data = (char *) malloc(size + 1);
315 if (!data) {
316 fprintf(stderr, "Failed to allocate data buffer.\n");
317 return ENOMEM;
318 }
319
320 /* Fill buffer with a pattern. */
321 nettest2_fill_buffer(data, size);
322
323 /* Check socket count. */
324 if (sockets <= 0) {
325 fprintf(stderr, "Socket count too small (%d). Using "
326 "2 instead.\n", sockets);
327 sockets = 2;
328 }
329
330 /*
331 * Prepare the socket buffer.
332 * Allocate count entries plus the terminating null (\0)
333 */
334 socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
335 if (!socket_ids) {
336 fprintf(stderr, "Failed to allocate receive buffer.\n");
337 return ENOMEM;
338 }
339 socket_ids[sockets] = 0;
340
341 if (verbose)
342 printf("Starting tests\n");
343
344 rc = sockets_create(verbose, socket_ids, sockets, family, type);
345 if (rc != EOK)
346 return rc;
347
348 if (type == SOCK_STREAM) {
349 rc = sockets_connect(verbose, socket_ids, sockets,
350 address, addrlen);
351 if (rc != EOK)
352 return rc;
353 }
354
355 if (verbose)
356 printf("\n");
357
358 rc = gettimeofday(&time_before, NULL);
359 if (rc != EOK) {
360 fprintf(stderr, "Get time of day error %d\n", rc);
361 return rc;
362 }
363
364 rc = sockets_sendto_recvfrom(verbose, socket_ids, sockets, address,
365 &addrlen, data, size, messages);
366 if (rc != EOK)
367 return rc;
368
369 rc = gettimeofday(&time_after, NULL);
370 if (rc != EOK) {
371 fprintf(stderr, "Get time of day error %d\n", rc);
372 return rc;
373 }
374
375 if (verbose)
376 printf("\tOK\n");
377
378 printf("sendto + recvfrom tested in %ld microseconds\n",
379 tv_sub(&time_after, &time_before));
380
381 rc = gettimeofday(&time_before, NULL);
382 if (rc != EOK) {
383 fprintf(stderr, "Get time of day error %d\n", rc);
384 return rc;
385 }
386
387 rc = sockets_sendto(verbose, socket_ids, sockets, address, addrlen,
388 data, size, messages);
389 if (rc != EOK)
390 return rc;
391
392 rc = sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen,
393 data, size, messages);
394 if (rc != EOK)
395 return rc;
396
397 rc = gettimeofday(&time_after, NULL);
398 if (rc != EOK) {
399 fprintf(stderr, "Get time of day error %d\n", rc);
400 return rc;
401 }
402
403 if (verbose)
404 printf("\tOK\n");
405
406 printf("sendto, recvfrom tested in %ld microseconds\n",
407 tv_sub(&time_after, &time_before));
408
409 rc = sockets_close(verbose, socket_ids, sockets);
410 if (rc != EOK)
411 return rc;
412
413 if (verbose)
414 printf("\nExiting\n");
415
416 return EOK;
417}
418
419/** @}
420 */
Note: See TracBrowser for help on using the repository browser.