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

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

Make dnsr client initialization implicit (to allow for multiple consumers in the same program).

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