source: mainline/uspace/app/nettest1/nettest1.c@ ad34feb

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