source: mainline/uspace/app/nettest1/nettest1.c@ 848e3d15

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

Move the client socket code to the standard library.

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