source: mainline/uspace/app/nettest1/nettest1.c@ 0bbef9b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0bbef9b was 0bbef9b, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Remove use of ERROR_ macros from nettest1.

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