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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d017cea was 7e752b2, checked in by Martin Decky <martin@…>, 15 years ago
  • correct printf() formatting strings and corresponding arguments
  • minor cstyle changes and other small fixes
  • 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>
[19f857a]42#include <str.h>
[21580dd]43#include <task.h>
44#include <time.h>
[2721a75]45#include <arg_parse.h>
[987930f]46#include <bool.h>
[21580dd]47
[e4554d4]48#include <net/in.h>
49#include <net/in6.h>
50#include <net/inet.h>
[d9e2e0e]51#include <net/socket.h>
52#include <net/socket_parse.h>
[21580dd]53
[b445803]54/** Echo module name. */
[21580dd]55#define NAME "Nettest2"
56
[b445803]57/** Packet data pattern. */
[21580dd]58#define NETTEST2_TEXT "Networking test 2 - transfer"
59
[987930f]60static size_t size;
61static bool verbose;
62static sock_type_t type;
63static int sockets;
64static int messages;
65static int family;
66static uint16_t port;
67
[b445803]68static void nettest2_print_help(void)
69{
70 printf(
[987930f]71 "Network Networking test 2 aplication - UDP transfer\n"
72 "Usage: echo [options] address\n"
73 "Where options are:\n"
74 "-f protocol_family | --family=protocol_family\n"
75 "\tThe listenning socket protocol family. Only the PF_INET and "
76 "PF_INET6 are supported.\n"
77 "\n"
78 "-h | --help\n"
79 "\tShow this application help.\n"
80 "\n"
81 "-m count | --messages=count\n"
82 "\tThe number of messages to send and receive per socket. The "
83 "default is 10.\n"
84 "\n"
85 "-n sockets | --sockets=count\n"
86 "\tThe number of sockets to use. The default is 10.\n"
87 "\n"
88 "-p port_number | --port=port_number\n"
89 "\tThe port number the application should send messages to. The "
90 "default is 7.\n"
91 "\n"
92 "-s packet_size | --size=packet_size\n"
93 "\tThe packet data size the application sends. The default is 29 "
94 "bytes.\n"
95 "\n"
96 "-v | --verbose\n"
97 "\tShow all output messages.\n");
[b445803]98}
[21580dd]99
[69e0d6d]100/** Fill buffer with the NETTEST2_TEXT pattern.
[b445803]101 *
[987930f]102 * @param buffer Data buffer.
103 * @param size Buffer size in bytes.
[21580dd]104 */
[987930f]105static void nettest2_fill_buffer(char *buffer, size_t size)
[b445803]106{
107 size_t length;
108
109 length = 0;
110 while (size > length + sizeof(NETTEST2_TEXT) - 1) {
[987930f]111 memcpy(buffer + length, NETTEST2_TEXT,
112 sizeof(NETTEST2_TEXT) - 1);
[b445803]113 length += sizeof(NETTEST2_TEXT) - 1;
114 }
[987930f]115
116 memcpy(buffer + length, NETTEST2_TEXT, size - length);
117 buffer[size] = '\0';
[b445803]118}
119
[987930f]120/** Parse one command-line option.
121 *
122 * @param argc Number of all command-line arguments.
123 * @param argv All command-line arguments.
124 * @param index Current argument index (in, out).
125 */
126static int nettest2_parse_opt(int argc, char *argv[], int *index)
127{
128 int value;
129 int rc;
130
131 switch (argv[*index][1]) {
132 /*
133 * Short options with only one letter
134 */
135 case 'f':
136 rc = arg_parse_name_int(argc, argv, index, &family, 0,
137 socket_parse_protocol_family);
138 if (rc != EOK)
139 return rc;
140 break;
141 case 'h':
142 nettest2_print_help();
143 return EOK;
144 break;
145 case 'm':
146 rc = arg_parse_int(argc, argv, index, &messages, 0);
147 if (rc != EOK)
148 return rc;
149 break;
150 case 'n':
151 rc = arg_parse_int(argc, argv, index, &sockets, 0);
152 if (rc != EOK)
153 return rc;
154 break;
155 case 'p':
156 rc = arg_parse_int(argc, argv, index, &value, 0);
157 if (rc != EOK)
158 return rc;
159 port = (uint16_t) value;
160 break;
161 case 's':
162 rc = arg_parse_int(argc, argv, index, &value, 0);
163 if (rc != EOK)
164 return rc;
165 size = (value >= 0) ? (size_t) value : 0;
166 break;
167 case 't':
168 rc = arg_parse_name_int(argc, argv, index, &value, 0,
169 socket_parse_socket_type);
170 if (rc != EOK)
171 return rc;
172 type = (sock_type_t) value;
173 break;
174 case 'v':
175 verbose = true;
176 break;
177 /*
178 * Long options with double dash ('-')
179 */
180 case '-':
181 if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) {
182 rc = arg_parse_name_int(argc, argv, index, &family, 9,
183 socket_parse_protocol_family);
184 if (rc != EOK)
185 return rc;
186 } else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) {
187 nettest2_print_help();
188 return EOK;
189 } else if (str_lcmp(argv[*index] + 2, "messages=", 6) == 0) {
190 rc = arg_parse_int(argc, argv, index, &messages, 8);
191 if (rc != EOK)
192 return rc;
193 } else if (str_lcmp(argv[*index] + 2, "sockets=", 6) == 0) {
194 rc = arg_parse_int(argc, argv, index, &sockets, 8);
195 if (rc != EOK)
196 return rc;
197 } else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) {
198 rc = arg_parse_int(argc, argv, index, &value, 7);
199 if (rc != EOK)
200 return rc;
201 port = (uint16_t) value;
202 } else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) {
203 rc = arg_parse_name_int(argc, argv, index, &value, 7,
204 socket_parse_socket_type);
205 if (rc != EOK)
206 return rc;
207 type = (sock_type_t) value;
208 } else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) {
209 verbose = 1;
210 } else {
211 nettest2_print_help();
212 return EINVAL;
213 }
214 break;
215 default:
216 nettest2_print_help();
217 return EINVAL;
218 }
219
220 return EOK;
221}
[21580dd]222
[b445803]223int main(int argc, char *argv[])
224{
[987930f]225 struct sockaddr *address;
[c9ebbe71]226 struct sockaddr_in address_in;
227 struct sockaddr_in6 address_in6;
[aadf01e]228 socklen_t addrlen;
[b445803]229 uint8_t *address_start;
[aadf01e]230
[b445803]231 int *socket_ids;
232 char *data;
[aadf01e]233 int index;
234 struct timeval time_before;
235 struct timeval time_after;
[21580dd]236
[5f69504]237 int rc;
238
[987930f]239 size = 28;
240 verbose = false;
241 type = SOCK_DGRAM;
242 sockets = 10;
243 messages = 10;
244 family = PF_INET;
245 port = 7;
246
247 /*
248 * Parse the command line arguments.
249 *
250 * Stop before the last argument if it does not start with dash ('-')
251 */
252 for (index = 1; (index < argc - 1) || ((index == argc - 1) &&
253 (argv[index][0] == '-')); ++index) {
254
255 /* Options should start with dash ('-') */
[b445803]256 if (argv[index][0] == '-') {
[987930f]257 rc = nettest2_parse_opt(argc, argv, &index);
258 if (rc != EOK)
259 return rc;
[b445803]260 } else {
[3be62bc]261 nettest2_print_help();
[21580dd]262 return EINVAL;
263 }
264 }
265
[987930f]266 /* If not before the last argument containing the address */
[b445803]267 if (index >= argc) {
[3be62bc]268 printf("Command line error: missing address\n");
269 nettest2_print_help();
270 return EINVAL;
271 }
272
[987930f]273 /* Prepare the address buffer */
274
[b445803]275 switch (family) {
276 case PF_INET:
[c9ebbe71]277 address_in.sin_family = AF_INET;
278 address_in.sin_port = htons(port);
279 address = (struct sockaddr *) &address_in;
280 addrlen = sizeof(address_in);
281 address_start = (uint8_t *) &address_in.sin_addr.s_addr;
[b445803]282 break;
283 case PF_INET6:
[c9ebbe71]284 address_in6.sin6_family = AF_INET6;
285 address_in6.sin6_port = htons(port);
286 address = (struct sockaddr *) &address_in6;
287 addrlen = sizeof(address_in6);
288 address_start = (uint8_t *) &address_in6.sin6_addr.s6_addr;
[b445803]289 break;
290 default:
291 fprintf(stderr, "Address family is not supported\n");
292 return EAFNOSUPPORT;
[21580dd]293 }
294
[987930f]295 /* Parse the last argument which should contain the address. */
[5f69504]296 rc = inet_pton(family, argv[argc - 1], address_start);
297 if (rc != EOK) {
298 fprintf(stderr, "Address parse error %d\n", rc);
299 return rc;
[21580dd]300 }
301
[987930f]302 /* Check data buffer size. */
[b445803]303 if (size <= 0) {
[7e752b2]304 fprintf(stderr, "Data buffer size too small (%zu). Using 1024 "
[987930f]305 "bytes instead.\n", size);
[21580dd]306 size = 1024;
307 }
[3be62bc]308
[987930f]309 /*
310 * Prepare the buffer. Allocate size bytes plus one for terminating
311 * null character.
312 */
[aadf01e]313 data = (char *) malloc(size + 1);
[b445803]314 if (!data) {
[aadf01e]315 fprintf(stderr, "Failed to allocate data buffer.\n");
[21580dd]316 return ENOMEM;
317 }
318
[987930f]319 /* Fill buffer with a pattern. */
320 nettest2_fill_buffer(data, size);
321
322 /* Check socket count. */
[b445803]323 if (sockets <= 0) {
[987930f]324 fprintf(stderr, "Socket count too small (%d). Using "
325 "2 instead.\n", sockets);
[21580dd]326 sockets = 2;
327 }
[3be62bc]328
[987930f]329 /*
330 * Prepare the socket buffer.
331 * Allocate count entries plus the terminating null (\0)
332 */
[aadf01e]333 socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
[b445803]334 if (!socket_ids) {
[aadf01e]335 fprintf(stderr, "Failed to allocate receive buffer.\n");
[21580dd]336 return ENOMEM;
337 }
[0b4a67a]338 socket_ids[sockets] = 0;
[21580dd]339
[b445803]340 if (verbose)
[aadf01e]341 printf("Starting tests\n");
[21580dd]342
[5f69504]343 rc = sockets_create(verbose, socket_ids, sockets, family, type);
344 if (rc != EOK)
345 return rc;
[9d28b9c]346
[5f69504]347 if (type == SOCK_STREAM) {
[987930f]348 rc = sockets_connect(verbose, socket_ids, sockets,
349 address, addrlen);
[5f69504]350 if (rc != EOK)
351 return rc;
352 }
[21580dd]353
[b445803]354 if (verbose)
[aadf01e]355 printf("\n");
[9d28b9c]356
[5f69504]357 rc = gettimeofday(&time_before, NULL);
358 if (rc != EOK) {
359 fprintf(stderr, "Get time of day error %d\n", rc);
360 return rc;
[21580dd]361 }
362
[987930f]363 rc = sockets_sendto_recvfrom(verbose, socket_ids, sockets, address,
364 &addrlen, data, size, messages);
[5f69504]365 if (rc != EOK)
366 return rc;
[21580dd]367
[5f69504]368 rc = gettimeofday(&time_after, NULL);
369 if (rc != EOK) {
370 fprintf(stderr, "Get time of day error %d\n", rc);
371 return rc;
[21580dd]372 }
373
[b445803]374 if (verbose)
[aadf01e]375 printf("\tOK\n");
[21580dd]376
[7e752b2]377 printf("sendto + recvfrom tested in %ld microseconds\n",
[987930f]378 tv_sub(&time_after, &time_before));
[21580dd]379
[5f69504]380 rc = gettimeofday(&time_before, NULL);
381 if (rc != EOK) {
382 fprintf(stderr, "Get time of day error %d\n", rc);
383 return rc;
[21580dd]384 }
385
[987930f]386 rc = sockets_sendto(verbose, socket_ids, sockets, address, addrlen,
387 data, size, messages);
[5f69504]388 if (rc != EOK)
389 return rc;
390
[987930f]391 rc = sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen,
392 data, size, messages);
[5f69504]393 if (rc != EOK)
394 return rc;
[21580dd]395
[5f69504]396 rc = gettimeofday(&time_after, NULL);
397 if (rc != EOK) {
398 fprintf(stderr, "Get time of day error %d\n", rc);
399 return rc;
[21580dd]400 }
401
[b445803]402 if (verbose)
[aadf01e]403 printf("\tOK\n");
[21580dd]404
[7e752b2]405 printf("sendto, recvfrom tested in %ld microseconds\n",
[987930f]406 tv_sub(&time_after, &time_before));
[21580dd]407
[5f69504]408 rc = sockets_close(verbose, socket_ids, sockets);
409 if (rc != EOK)
410 return rc;
[21580dd]411
[b445803]412 if (verbose)
[aadf01e]413 printf("\nExiting\n");
[21580dd]414
415 return EOK;
416}
417
418/** @}
419 */
Note: See TracBrowser for help on using the repository browser.