source: mainline/uspace/app/nettest1/nettest1.c@ 2b5d966

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2b5d966 was 7f9d97f3, checked in by Jakub Jermar <jakub@…>, 11 years ago

Make gettimeofday() return the actual microseconds.

Enhance struct tm to also have a field to hold microseconds and make
sure that this information propagates from the RTC driver.

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