source: mainline/uspace/app/nettest2/nettest2.c@ 48fa501

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 48fa501 was 3e6a98c5, checked in by Jiri Svoboda <jiri@…>, 13 years ago

Standards-compliant boolean type.

  • Property mode set to 100644
File size: 10.3 KB
RevLine 
[21580dd]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
[b445803]30 * @{
[21580dd]31 */
32
33/** @file
[b445803]34 * Networking test 2 application - transfer.
[21580dd]35 */
36
[b445803]37#include "nettest.h"
38#include "print_error.h"
39
[21580dd]40#include <malloc.h>
41#include <stdio.h>
[d4d74dc]42#include <unistd.h>
[19f857a]43#include <str.h>
[21580dd]44#include <task.h>
45#include <time.h>
[2721a75]46#include <arg_parse.h>
[3e6a98c5]47#include <stdbool.h>
[21580dd]48
[e4554d4]49#include <net/in.h>
50#include <net/in6.h>
51#include <net/inet.h>
[d9e2e0e]52#include <net/socket.h>
53#include <net/socket_parse.h>
[21580dd]54
[b445803]55/** Echo module name. */
[21580dd]56#define NAME "Nettest2"
57
[b445803]58/** Packet data pattern. */
[21580dd]59#define NETTEST2_TEXT "Networking test 2 - transfer"
60
[987930f]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
[b445803]69static void nettest2_print_help(void)
70{
71 printf(
[987930f]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");
[b445803]99}
[21580dd]100
[69e0d6d]101/** Fill buffer with the NETTEST2_TEXT pattern.
[b445803]102 *
[987930f]103 * @param buffer Data buffer.
104 * @param size Buffer size in bytes.
[21580dd]105 */
[987930f]106static void nettest2_fill_buffer(char *buffer, size_t size)
[b445803]107{
108 size_t length;
109
110 length = 0;
111 while (size > length + sizeof(NETTEST2_TEXT) - 1) {
[987930f]112 memcpy(buffer + length, NETTEST2_TEXT,
113 sizeof(NETTEST2_TEXT) - 1);
[b445803]114 length += sizeof(NETTEST2_TEXT) - 1;
115 }
[987930f]116
117 memcpy(buffer + length, NETTEST2_TEXT, size - length);
118 buffer[size] = '\0';
[b445803]119}
120
[987930f]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}
[21580dd]223
[b445803]224int main(int argc, char *argv[])
225{
[987930f]226 struct sockaddr *address;
[c9ebbe71]227 struct sockaddr_in address_in;
228 struct sockaddr_in6 address_in6;
[aadf01e]229 socklen_t addrlen;
[b445803]230 uint8_t *address_start;
[aadf01e]231
[b445803]232 int *socket_ids;
233 char *data;
[aadf01e]234 int index;
235 struct timeval time_before;
236 struct timeval time_after;
[21580dd]237
[5f69504]238 int rc;
239
[987930f]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 ('-') */
[b445803]257 if (argv[index][0] == '-') {
[987930f]258 rc = nettest2_parse_opt(argc, argv, &index);
259 if (rc != EOK)
260 return rc;
[b445803]261 } else {
[3be62bc]262 nettest2_print_help();
[21580dd]263 return EINVAL;
264 }
265 }
266
[987930f]267 /* If not before the last argument containing the address */
[b445803]268 if (index >= argc) {
[3be62bc]269 printf("Command line error: missing address\n");
270 nettest2_print_help();
271 return EINVAL;
272 }
273
[987930f]274 /* Prepare the address buffer */
275
[b445803]276 switch (family) {
277 case PF_INET:
[c9ebbe71]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;
[b445803]283 break;
284 case PF_INET6:
[c9ebbe71]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;
[b445803]290 break;
291 default:
292 fprintf(stderr, "Address family is not supported\n");
293 return EAFNOSUPPORT;
[21580dd]294 }
295
[987930f]296 /* Parse the last argument which should contain the address. */
[5f69504]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;
[21580dd]301 }
302
[987930f]303 /* Check data buffer size. */
[b445803]304 if (size <= 0) {
[7e752b2]305 fprintf(stderr, "Data buffer size too small (%zu). Using 1024 "
[987930f]306 "bytes instead.\n", size);
[21580dd]307 size = 1024;
308 }
[3be62bc]309
[987930f]310 /*
311 * Prepare the buffer. Allocate size bytes plus one for terminating
312 * null character.
313 */
[aadf01e]314 data = (char *) malloc(size + 1);
[b445803]315 if (!data) {
[aadf01e]316 fprintf(stderr, "Failed to allocate data buffer.\n");
[21580dd]317 return ENOMEM;
318 }
319
[987930f]320 /* Fill buffer with a pattern. */
321 nettest2_fill_buffer(data, size);
322
323 /* Check socket count. */
[b445803]324 if (sockets <= 0) {
[987930f]325 fprintf(stderr, "Socket count too small (%d). Using "
326 "2 instead.\n", sockets);
[21580dd]327 sockets = 2;
328 }
[3be62bc]329
[987930f]330 /*
331 * Prepare the socket buffer.
332 * Allocate count entries plus the terminating null (\0)
333 */
[aadf01e]334 socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
[b445803]335 if (!socket_ids) {
[aadf01e]336 fprintf(stderr, "Failed to allocate receive buffer.\n");
[21580dd]337 return ENOMEM;
338 }
[0b4a67a]339 socket_ids[sockets] = 0;
[21580dd]340
[b445803]341 if (verbose)
[aadf01e]342 printf("Starting tests\n");
[21580dd]343
[5f69504]344 rc = sockets_create(verbose, socket_ids, sockets, family, type);
345 if (rc != EOK)
346 return rc;
[9d28b9c]347
[5f69504]348 if (type == SOCK_STREAM) {
[987930f]349 rc = sockets_connect(verbose, socket_ids, sockets,
350 address, addrlen);
[5f69504]351 if (rc != EOK)
352 return rc;
353 }
[21580dd]354
[b445803]355 if (verbose)
[aadf01e]356 printf("\n");
[9d28b9c]357
[5f69504]358 rc = gettimeofday(&time_before, NULL);
359 if (rc != EOK) {
360 fprintf(stderr, "Get time of day error %d\n", rc);
361 return rc;
[21580dd]362 }
363
[987930f]364 rc = sockets_sendto_recvfrom(verbose, socket_ids, sockets, address,
365 &addrlen, data, size, messages);
[5f69504]366 if (rc != EOK)
367 return rc;
[21580dd]368
[5f69504]369 rc = gettimeofday(&time_after, NULL);
370 if (rc != EOK) {
371 fprintf(stderr, "Get time of day error %d\n", rc);
372 return rc;
[21580dd]373 }
374
[b445803]375 if (verbose)
[aadf01e]376 printf("\tOK\n");
[21580dd]377
[7e752b2]378 printf("sendto + recvfrom tested in %ld microseconds\n",
[987930f]379 tv_sub(&time_after, &time_before));
[21580dd]380
[5f69504]381 rc = gettimeofday(&time_before, NULL);
382 if (rc != EOK) {
383 fprintf(stderr, "Get time of day error %d\n", rc);
384 return rc;
[21580dd]385 }
386
[987930f]387 rc = sockets_sendto(verbose, socket_ids, sockets, address, addrlen,
388 data, size, messages);
[5f69504]389 if (rc != EOK)
390 return rc;
391
[987930f]392 rc = sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen,
393 data, size, messages);
[5f69504]394 if (rc != EOK)
395 return rc;
[21580dd]396
[5f69504]397 rc = gettimeofday(&time_after, NULL);
398 if (rc != EOK) {
399 fprintf(stderr, "Get time of day error %d\n", rc);
400 return rc;
[21580dd]401 }
402
[b445803]403 if (verbose)
[aadf01e]404 printf("\tOK\n");
[21580dd]405
[7e752b2]406 printf("sendto, recvfrom tested in %ld microseconds\n",
[987930f]407 tv_sub(&time_after, &time_before));
[21580dd]408
[5f69504]409 rc = sockets_close(verbose, socket_ids, sockets);
410 if (rc != EOK)
411 return rc;
[21580dd]412
[b445803]413 if (verbose)
[aadf01e]414 printf("\nExiting\n");
[21580dd]415
416 return EOK;
417}
418
419/** @}
420 */
Note: See TracBrowser for help on using the repository browser.