source: mainline/uspace/app/nettest2/nettest2.c@ 1ab8539

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1ab8539 was 1ab8539, checked in by Martin Decky <martin@…>, 11 years ago

remove system.uptime sysinfo entry since it is redundant
cleanup the time handling routines

  • still more cleanup is needed here, the code is a wild combination of quasi-POSIX API (with all the brain-dead types, etc.) and HelenOS API
  • Property mode set to 100644
File size: 9.8 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
[26de91a]40#include <assert.h>
[21580dd]41#include <malloc.h>
42#include <stdio.h>
[d4d74dc]43#include <unistd.h>
[19f857a]44#include <str.h>
[21580dd]45#include <task.h>
46#include <time.h>
[2721a75]47#include <arg_parse.h>
[3e6a98c5]48#include <stdbool.h>
[21580dd]49
[287d729]50#include <inet/dnsr.h>
[e4554d4]51#include <net/in.h>
52#include <net/in6.h>
53#include <net/inet.h>
[d9e2e0e]54#include <net/socket.h>
55#include <net/socket_parse.h>
[21580dd]56
[b445803]57/** Echo module name. */
[b5cf742a]58#define NAME "nettest2"
[21580dd]59
[b445803]60/** Packet data pattern. */
[b5cf742a]61#define NETTEST2_TEXT "Networking test 2 - transfer"
[21580dd]62
[e948fde]63static uint16_t family = AF_NONE;
[02a09ed]64static size_t size = 28;
65static bool verbose = false;
66static sock_type_t type = SOCK_DGRAM;
67static int sockets = 10;
68static int messages = 10;
69static uint16_t port = 7;
[987930f]70
[b445803]71static void nettest2_print_help(void)
72{
73 printf(
[987930f]74 "Network Networking test 2 aplication - UDP transfer\n"
[287d729]75 "Usage: nettest2 [options] host\n"
[987930f]76 "Where options are:\n"
77 "-f protocol_family | --family=protocol_family\n"
78 "\tThe listenning socket protocol family. Only the PF_INET and "
79 "PF_INET6 are supported.\n"
80 "\n"
81 "-h | --help\n"
82 "\tShow this application help.\n"
83 "\n"
84 "-m count | --messages=count\n"
85 "\tThe number of messages to send and receive per socket. The "
86 "default is 10.\n"
87 "\n"
88 "-n sockets | --sockets=count\n"
89 "\tThe number of sockets to use. The default is 10.\n"
90 "\n"
91 "-p port_number | --port=port_number\n"
92 "\tThe port number the application should send messages to. The "
93 "default is 7.\n"
94 "\n"
95 "-s packet_size | --size=packet_size\n"
96 "\tThe packet data size the application sends. The default is 29 "
97 "bytes.\n"
98 "\n"
99 "-v | --verbose\n"
100 "\tShow all output messages.\n");
[b445803]101}
[21580dd]102
[69e0d6d]103/** Fill buffer with the NETTEST2_TEXT pattern.
[b445803]104 *
[987930f]105 * @param buffer Data buffer.
106 * @param size Buffer size in bytes.
[21580dd]107 */
[987930f]108static void nettest2_fill_buffer(char *buffer, size_t size)
[b445803]109{
[b5cf742a]110 size_t length = 0;
[b445803]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 }
[b5cf742a]116
[987930f]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;
[b5cf742a]131
[987930f]132 switch (argv[*index][1]) {
133 /*
134 * Short options with only one letter
135 */
136 case 'f':
[b5cf742a]137 rc = arg_parse_name_int(argc, argv, index, &value, 0,
[987930f]138 socket_parse_protocol_family);
139 if (rc != EOK)
140 return rc;
[b5cf742a]141
142 family = (uint16_t) value;
[987930f]143 break;
144 case 'h':
145 nettest2_print_help();
146 return EOK;
147 case 'm':
148 rc = arg_parse_int(argc, argv, index, &messages, 0);
149 if (rc != EOK)
150 return rc;
[b5cf742a]151
[987930f]152 break;
153 case 'n':
154 rc = arg_parse_int(argc, argv, index, &sockets, 0);
155 if (rc != EOK)
156 return rc;
[b5cf742a]157
[987930f]158 break;
159 case 'p':
160 rc = arg_parse_int(argc, argv, index, &value, 0);
161 if (rc != EOK)
162 return rc;
[b5cf742a]163
[987930f]164 port = (uint16_t) value;
165 break;
166 case 's':
167 rc = arg_parse_int(argc, argv, index, &value, 0);
168 if (rc != EOK)
169 return rc;
[b5cf742a]170
[987930f]171 size = (value >= 0) ? (size_t) value : 0;
172 break;
173 case 't':
174 rc = arg_parse_name_int(argc, argv, index, &value, 0,
175 socket_parse_socket_type);
176 if (rc != EOK)
177 return rc;
[b5cf742a]178
[987930f]179 type = (sock_type_t) value;
180 break;
181 case 'v':
182 verbose = true;
183 break;
[b5cf742a]184
[987930f]185 /*
186 * Long options with double dash ('-')
187 */
188 case '-':
189 if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) {
[b5cf742a]190 rc = arg_parse_name_int(argc, argv, index, &value, 9,
[987930f]191 socket_parse_protocol_family);
192 if (rc != EOK)
193 return rc;
[b5cf742a]194
195 family = (uint16_t) value;
[987930f]196 } else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) {
197 nettest2_print_help();
198 return EOK;
199 } else if (str_lcmp(argv[*index] + 2, "messages=", 6) == 0) {
200 rc = arg_parse_int(argc, argv, index, &messages, 8);
201 if (rc != EOK)
202 return rc;
203 } else if (str_lcmp(argv[*index] + 2, "sockets=", 6) == 0) {
204 rc = arg_parse_int(argc, argv, index, &sockets, 8);
205 if (rc != EOK)
206 return rc;
207 } else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) {
208 rc = arg_parse_int(argc, argv, index, &value, 7);
209 if (rc != EOK)
210 return rc;
[b5cf742a]211
[987930f]212 port = (uint16_t) value;
213 } else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) {
214 rc = arg_parse_name_int(argc, argv, index, &value, 7,
215 socket_parse_socket_type);
216 if (rc != EOK)
217 return rc;
[b5cf742a]218
[987930f]219 type = (sock_type_t) value;
220 } else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) {
221 verbose = 1;
222 } else {
223 nettest2_print_help();
224 return EINVAL;
225 }
226 break;
227 default:
228 nettest2_print_help();
229 return EINVAL;
230 }
[b5cf742a]231
[987930f]232 return EOK;
233}
[21580dd]234
[b445803]235int main(int argc, char *argv[])
236{
[aadf01e]237 int index;
[5f69504]238 int rc;
[02a09ed]239
[987930f]240 /*
241 * Parse the command line arguments.
242 *
243 * Stop before the last argument if it does not start with dash ('-')
244 */
245 for (index = 1; (index < argc - 1) || ((index == argc - 1) &&
246 (argv[index][0] == '-')); ++index) {
247 /* Options should start with dash ('-') */
[b445803]248 if (argv[index][0] == '-') {
[987930f]249 rc = nettest2_parse_opt(argc, argv, &index);
250 if (rc != EOK)
251 return rc;
[b445803]252 } else {
[3be62bc]253 nettest2_print_help();
[21580dd]254 return EINVAL;
255 }
256 }
[b5cf742a]257
[02a09ed]258 /* The last argument containing the host */
[b445803]259 if (index >= argc) {
[02a09ed]260 printf("Host name missing.\n");
[3be62bc]261 nettest2_print_help();
262 return EINVAL;
263 }
[02a09ed]264
265 char *addr_s = argv[argc - 1];
266
267 /* Interpret as address */
268 inet_addr_t addr_addr;
269 rc = inet_addr_parse(addr_s, &addr_addr);
270
271 if (rc != EOK) {
272 /* Interpret as a host name */
273 dnsr_hostinfo_t *hinfo = NULL;
[e948fde]274 rc = dnsr_name2host(addr_s, &hinfo, ipver_from_af(family));
[02a09ed]275
276 if (rc != EOK) {
277 printf("Error resolving host '%s'.\n", addr_s);
278 return EINVAL;
279 }
280
281 addr_addr = hinfo->addr;
282 }
283
[26de91a]284 struct sockaddr *address;
285 socklen_t addrlen;
286 rc = inet_addr_sockaddr(&addr_addr, port, &address, &addrlen);
287 if (rc != EOK) {
288 assert(rc == ENOMEM);
289 printf("Out of memory.\n");
290 return ENOMEM;
291 }
[02a09ed]292
[e948fde]293 if (family == AF_NONE)
[26de91a]294 family = address->sa_family;
[e948fde]295
[26de91a]296 if (address->sa_family != family) {
[02a09ed]297 printf("Address family does not match explicitly set family.\n");
298 return EINVAL;
299 }
300
[987930f]301 /* Check data buffer size. */
[b445803]302 if (size <= 0) {
[7e752b2]303 fprintf(stderr, "Data buffer size too small (%zu). Using 1024 "
[987930f]304 "bytes instead.\n", size);
[21580dd]305 size = 1024;
306 }
[b5cf742a]307
[987930f]308 /*
309 * Prepare the buffer. Allocate size bytes plus one for terminating
310 * null character.
311 */
[02a09ed]312 char *data = (char *) malloc(size + 1);
[b445803]313 if (!data) {
[aadf01e]314 fprintf(stderr, "Failed to allocate data buffer.\n");
[21580dd]315 return ENOMEM;
316 }
[b5cf742a]317
[987930f]318 /* Fill buffer with a pattern. */
319 nettest2_fill_buffer(data, size);
[b5cf742a]320
[987930f]321 /* Check socket count. */
[b445803]322 if (sockets <= 0) {
[987930f]323 fprintf(stderr, "Socket count too small (%d). Using "
324 "2 instead.\n", sockets);
[21580dd]325 sockets = 2;
326 }
[b5cf742a]327
[987930f]328 /*
329 * Prepare the socket buffer.
330 * Allocate count entries plus the terminating null (\0)
331 */
[02a09ed]332 int *socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
[b445803]333 if (!socket_ids) {
[aadf01e]334 fprintf(stderr, "Failed to allocate receive buffer.\n");
[21580dd]335 return ENOMEM;
336 }
[02a09ed]337
[0b4a67a]338 socket_ids[sockets] = 0;
[b5cf742a]339
[b445803]340 if (verbose)
[aadf01e]341 printf("Starting tests\n");
[b5cf742a]342
[5f69504]343 rc = sockets_create(verbose, socket_ids, sockets, family, type);
344 if (rc != EOK)
345 return rc;
[b5cf742a]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 }
[b5cf742a]353
[b445803]354 if (verbose)
[aadf01e]355 printf("\n");
[b5cf742a]356
[02a09ed]357 struct timeval time_before;
[1ab8539]358 gettimeofday(&time_before, NULL);
[b5cf742a]359
[987930f]360 rc = sockets_sendto_recvfrom(verbose, socket_ids, sockets, address,
[c442f63]361 &addrlen, data, size, messages, type);
[5f69504]362 if (rc != EOK)
363 return rc;
[b5cf742a]364
[02a09ed]365 struct timeval time_after;
[1ab8539]366 gettimeofday(&time_after, NULL);
[b5cf742a]367
[b445803]368 if (verbose)
[aadf01e]369 printf("\tOK\n");
[b5cf742a]370
[7e752b2]371 printf("sendto + recvfrom tested in %ld microseconds\n",
[987930f]372 tv_sub(&time_after, &time_before));
[b5cf742a]373
[1ab8539]374 gettimeofday(&time_before, NULL);
[b5cf742a]375
[987930f]376 rc = sockets_sendto(verbose, socket_ids, sockets, address, addrlen,
[c442f63]377 data, size, messages, type);
[5f69504]378 if (rc != EOK)
379 return rc;
[b5cf742a]380
[987930f]381 rc = sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen,
382 data, size, messages);
[5f69504]383 if (rc != EOK)
384 return rc;
[b5cf742a]385
[1ab8539]386 gettimeofday(&time_after, NULL);
[b5cf742a]387
[b445803]388 if (verbose)
[aadf01e]389 printf("\tOK\n");
[b5cf742a]390
[7e752b2]391 printf("sendto, recvfrom tested in %ld microseconds\n",
[987930f]392 tv_sub(&time_after, &time_before));
[b5cf742a]393
[5f69504]394 rc = sockets_close(verbose, socket_ids, sockets);
395 if (rc != EOK)
396 return rc;
[b5cf742a]397
[26de91a]398 free(address);
399
[b445803]400 if (verbose)
[aadf01e]401 printf("\nExiting\n");
[b5cf742a]402
[21580dd]403 return EOK;
404}
405
406/** @}
407 */
Note: See TracBrowser for help on using the repository browser.