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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a873201 was 3d459fc, checked in by Jakub Jermar <jakub@…>, 15 years ago

Gently cleanup nettest1.

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