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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c6a7b3a was d4d74dc, checked in by Vojtech Horky <vojtechhorky@…>, 13 years ago

Less includes in library headers

There is no need for errno.h to include fibril.h.
Similarly, tinput.h does not need list.h or async.h.

Unfortunately, many programs depended on the fact that including
errno.h would (recursively) include unistd.h and NULL would be
defined. Most of the fixes remedy this problem.

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