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

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

dnsr_name2host should use ip_ver_t instead of AF.

  • 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. */
[b5cf742a]57#define NAME "nettest2"
[21580dd]58
[b445803]59/** Packet data pattern. */
[b5cf742a]60#define NETTEST2_TEXT "Networking test 2 - transfer"
[21580dd]61
[e948fde]62static uint16_t family = AF_NONE;
[02a09ed]63static size_t size = 28;
64static bool verbose = false;
65static sock_type_t type = SOCK_DGRAM;
66static int sockets = 10;
67static int messages = 10;
68static uint16_t port = 7;
[987930f]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{
[b5cf742a]109 size_t length = 0;
[b445803]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 }
[b5cf742a]115
[987930f]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;
[b5cf742a]130
[987930f]131 switch (argv[*index][1]) {
132 /*
133 * Short options with only one letter
134 */
135 case 'f':
[b5cf742a]136 rc = arg_parse_name_int(argc, argv, index, &value, 0,
[987930f]137 socket_parse_protocol_family);
138 if (rc != EOK)
139 return rc;
[b5cf742a]140
141 family = (uint16_t) value;
[987930f]142 break;
143 case 'h':
144 nettest2_print_help();
145 return EOK;
146 case 'm':
147 rc = arg_parse_int(argc, argv, index, &messages, 0);
148 if (rc != EOK)
149 return rc;
[b5cf742a]150
[987930f]151 break;
152 case 'n':
153 rc = arg_parse_int(argc, argv, index, &sockets, 0);
154 if (rc != EOK)
155 return rc;
[b5cf742a]156
[987930f]157 break;
158 case 'p':
159 rc = arg_parse_int(argc, argv, index, &value, 0);
160 if (rc != EOK)
161 return rc;
[b5cf742a]162
[987930f]163 port = (uint16_t) value;
164 break;
165 case 's':
166 rc = arg_parse_int(argc, argv, index, &value, 0);
167 if (rc != EOK)
168 return rc;
[b5cf742a]169
[987930f]170 size = (value >= 0) ? (size_t) value : 0;
171 break;
172 case 't':
173 rc = arg_parse_name_int(argc, argv, index, &value, 0,
174 socket_parse_socket_type);
175 if (rc != EOK)
176 return rc;
[b5cf742a]177
[987930f]178 type = (sock_type_t) value;
179 break;
180 case 'v':
181 verbose = true;
182 break;
[b5cf742a]183
[987930f]184 /*
185 * Long options with double dash ('-')
186 */
187 case '-':
188 if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) {
[b5cf742a]189 rc = arg_parse_name_int(argc, argv, index, &value, 9,
[987930f]190 socket_parse_protocol_family);
191 if (rc != EOK)
192 return rc;
[b5cf742a]193
194 family = (uint16_t) value;
[987930f]195 } else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) {
196 nettest2_print_help();
197 return EOK;
198 } else if (str_lcmp(argv[*index] + 2, "messages=", 6) == 0) {
199 rc = arg_parse_int(argc, argv, index, &messages, 8);
200 if (rc != EOK)
201 return rc;
202 } else if (str_lcmp(argv[*index] + 2, "sockets=", 6) == 0) {
203 rc = arg_parse_int(argc, argv, index, &sockets, 8);
204 if (rc != EOK)
205 return rc;
206 } else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) {
207 rc = arg_parse_int(argc, argv, index, &value, 7);
208 if (rc != EOK)
209 return rc;
[b5cf742a]210
[987930f]211 port = (uint16_t) value;
212 } else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) {
213 rc = arg_parse_name_int(argc, argv, index, &value, 7,
214 socket_parse_socket_type);
215 if (rc != EOK)
216 return rc;
[b5cf742a]217
[987930f]218 type = (sock_type_t) value;
219 } else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) {
220 verbose = 1;
221 } else {
222 nettest2_print_help();
223 return EINVAL;
224 }
225 break;
226 default:
227 nettest2_print_help();
228 return EINVAL;
229 }
[b5cf742a]230
[987930f]231 return EOK;
232}
[21580dd]233
[b445803]234int main(int argc, char *argv[])
235{
[aadf01e]236 int index;
[5f69504]237 int rc;
[02a09ed]238
[987930f]239 /*
240 * Parse the command line arguments.
241 *
242 * Stop before the last argument if it does not start with dash ('-')
243 */
244 for (index = 1; (index < argc - 1) || ((index == argc - 1) &&
245 (argv[index][0] == '-')); ++index) {
246 /* Options should start with dash ('-') */
[b445803]247 if (argv[index][0] == '-') {
[987930f]248 rc = nettest2_parse_opt(argc, argv, &index);
249 if (rc != EOK)
250 return rc;
[b445803]251 } else {
[3be62bc]252 nettest2_print_help();
[21580dd]253 return EINVAL;
254 }
255 }
[b5cf742a]256
[02a09ed]257 /* The last argument containing the host */
[b445803]258 if (index >= argc) {
[02a09ed]259 printf("Host name missing.\n");
[3be62bc]260 nettest2_print_help();
261 return EINVAL;
262 }
[02a09ed]263
264 char *addr_s = argv[argc - 1];
265
266 /* Interpret as address */
267 inet_addr_t addr_addr;
268 rc = inet_addr_parse(addr_s, &addr_addr);
269
270 if (rc != EOK) {
271 /* Interpret as a host name */
272 dnsr_hostinfo_t *hinfo = NULL;
[e948fde]273 rc = dnsr_name2host(addr_s, &hinfo, ipver_from_af(family));
[02a09ed]274
275 if (rc != EOK) {
276 printf("Error resolving host '%s'.\n", addr_s);
277 return EINVAL;
278 }
279
280 addr_addr = hinfo->addr;
281 }
282
283 struct sockaddr_in addr;
284 struct sockaddr_in6 addr6;
285 uint16_t af = inet_addr_sockaddr_in(&addr_addr, &addr, &addr6);
286
[e948fde]287 if (family == AF_NONE)
288 family = af;
289
[02a09ed]290 if (af != family) {
291 printf("Address family does not match explicitly set family.\n");
292 return EINVAL;
293 }
294
[987930f]295 /* Prepare the address buffer */
[02a09ed]296
297 struct sockaddr *address;
298 socklen_t addrlen;
299
300 switch (af) {
301 case AF_INET:
302 addr.sin_port = htons(port);
303 address = (struct sockaddr *) &addr;
304 addrlen = sizeof(addr);
[b445803]305 break;
[02a09ed]306 case AF_INET6:
307 addr6.sin6_port = htons(port);
308 address = (struct sockaddr *) &addr6;
309 addrlen = sizeof(addr6);
[b445803]310 break;
311 default:
312 fprintf(stderr, "Address family is not supported\n");
313 return EAFNOSUPPORT;
[21580dd]314 }
[b5cf742a]315
[987930f]316 /* Check data buffer size. */
[b445803]317 if (size <= 0) {
[7e752b2]318 fprintf(stderr, "Data buffer size too small (%zu). Using 1024 "
[987930f]319 "bytes instead.\n", size);
[21580dd]320 size = 1024;
321 }
[b5cf742a]322
[987930f]323 /*
324 * Prepare the buffer. Allocate size bytes plus one for terminating
325 * null character.
326 */
[02a09ed]327 char *data = (char *) malloc(size + 1);
[b445803]328 if (!data) {
[aadf01e]329 fprintf(stderr, "Failed to allocate data buffer.\n");
[21580dd]330 return ENOMEM;
331 }
[b5cf742a]332
[987930f]333 /* Fill buffer with a pattern. */
334 nettest2_fill_buffer(data, size);
[b5cf742a]335
[987930f]336 /* Check socket count. */
[b445803]337 if (sockets <= 0) {
[987930f]338 fprintf(stderr, "Socket count too small (%d). Using "
339 "2 instead.\n", sockets);
[21580dd]340 sockets = 2;
341 }
[b5cf742a]342
[987930f]343 /*
344 * Prepare the socket buffer.
345 * Allocate count entries plus the terminating null (\0)
346 */
[02a09ed]347 int *socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
[b445803]348 if (!socket_ids) {
[aadf01e]349 fprintf(stderr, "Failed to allocate receive buffer.\n");
[21580dd]350 return ENOMEM;
351 }
[02a09ed]352
[0b4a67a]353 socket_ids[sockets] = 0;
[b5cf742a]354
[b445803]355 if (verbose)
[aadf01e]356 printf("Starting tests\n");
[b5cf742a]357
[5f69504]358 rc = sockets_create(verbose, socket_ids, sockets, family, type);
359 if (rc != EOK)
360 return rc;
[b5cf742a]361
[5f69504]362 if (type == SOCK_STREAM) {
[987930f]363 rc = sockets_connect(verbose, socket_ids, sockets,
364 address, addrlen);
[5f69504]365 if (rc != EOK)
366 return rc;
367 }
[b5cf742a]368
[b445803]369 if (verbose)
[aadf01e]370 printf("\n");
[b5cf742a]371
[02a09ed]372 struct timeval time_before;
[5f69504]373 rc = gettimeofday(&time_before, NULL);
374 if (rc != EOK) {
375 fprintf(stderr, "Get time of day error %d\n", rc);
376 return rc;
[21580dd]377 }
[b5cf742a]378
[987930f]379 rc = sockets_sendto_recvfrom(verbose, socket_ids, sockets, address,
[c442f63]380 &addrlen, data, size, messages, type);
[5f69504]381 if (rc != EOK)
382 return rc;
[b5cf742a]383
[02a09ed]384 struct timeval time_after;
[5f69504]385 rc = gettimeofday(&time_after, NULL);
386 if (rc != EOK) {
387 fprintf(stderr, "Get time of day error %d\n", rc);
388 return rc;
[21580dd]389 }
[b5cf742a]390
[b445803]391 if (verbose)
[aadf01e]392 printf("\tOK\n");
[b5cf742a]393
[7e752b2]394 printf("sendto + recvfrom tested in %ld microseconds\n",
[987930f]395 tv_sub(&time_after, &time_before));
[b5cf742a]396
[5f69504]397 rc = gettimeofday(&time_before, NULL);
398 if (rc != EOK) {
399 fprintf(stderr, "Get time of day error %d\n", rc);
400 return rc;
[21580dd]401 }
[b5cf742a]402
[987930f]403 rc = sockets_sendto(verbose, socket_ids, sockets, address, addrlen,
[c442f63]404 data, size, messages, type);
[5f69504]405 if (rc != EOK)
406 return rc;
[b5cf742a]407
[987930f]408 rc = sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen,
409 data, size, messages);
[5f69504]410 if (rc != EOK)
411 return rc;
[b5cf742a]412
[5f69504]413 rc = gettimeofday(&time_after, NULL);
414 if (rc != EOK) {
415 fprintf(stderr, "Get time of day error %d\n", rc);
416 return rc;
[21580dd]417 }
[b5cf742a]418
[b445803]419 if (verbose)
[aadf01e]420 printf("\tOK\n");
[b5cf742a]421
[7e752b2]422 printf("sendto, recvfrom tested in %ld microseconds\n",
[987930f]423 tv_sub(&time_after, &time_before));
[b5cf742a]424
[5f69504]425 rc = sockets_close(verbose, socket_ids, sockets);
426 if (rc != EOK)
427 return rc;
[b5cf742a]428
[b445803]429 if (verbose)
[aadf01e]430 printf("\nExiting\n");
[b5cf742a]431
[21580dd]432 return EOK;
433}
434
435/** @}
436 */
Note: See TracBrowser for help on using the repository browser.