source: mainline/uspace/srv/net/app/nettest2/nettest2.c@ 3be62bc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3be62bc was 3be62bc, checked in by Lukas Mejdrech <lukasmejdrech@…>, 15 years ago
  • net app command line argument checks, * code reorganization
  • 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
30 * @{
31 */
32
33/** @file
34 * Networking test 2 application - transfer.
35 */
36
37#include <malloc.h>
38#include <stdio.h>
39#include <string.h>
40#include <task.h>
41#include <time.h>
42
43#include "../../include/in.h"
44#include "../../include/in6.h"
45#include "../../include/inet.h"
46#include "../../include/socket.h"
47
48#include "../../err.h"
49
[3be62bc]50#include "../nettest.h"
[21580dd]51#include "../parse.h"
52#include "../print_error.h"
53
54/** Echo module name.
55 */
56#define NAME "Nettest2"
57
58/** Packet data pattern.
59 */
60#define NETTEST2_TEXT "Networking test 2 - transfer"
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 nettest2_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 nettest2_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 = 28;
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
[aadf01e]108 printf("Task %d - ", task_get_id());
109 printf("%s\n", NAME);
[21580dd]110
[3be62bc]111 // parse the command line arguments
112 // stop before the last argument if it does not start with the minus sign ('-')
113 for(index = 1; (index < argc - 1) || ((index == argc - 1) && (argv[index][0] == '-')); ++ index){
114 // options should start with the minus sign ('-')
[aadf01e]115 if(argv[index][0] == '-'){
116 switch(argv[index][1]){
[3be62bc]117 // short options with only one letter
[aadf01e]118 case 'f':
119 ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, parse_protocol_family));
120 break;
121 case 'h':
[3be62bc]122 nettest2_print_help();
[aadf01e]123 return EOK;
124 break;
125 case 'm':
126 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &messages, "message count", 0));
127 break;
128 case 'n':
129 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &sockets, "socket count", 0));
130 break;
131 case 'p':
132 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "port number", 0));
133 port = (uint16_t) value;
134 break;
135 case 's':
136 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "packet size", 0));
137 size = (value >= 0) ? (size_t) value : 0;
138 break;
139 case 't':
140 ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 0, parse_socket_type));
141 type = (sock_type_t) value;
142 break;
143 case 'v':
144 verbose = 1;
145 break;
[3be62bc]146 // long options with the double minus sign ('-')
[aadf01e]147 case '-':
148 if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
149 ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, parse_protocol_family));
150 }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
[3be62bc]151 nettest2_print_help();
[aadf01e]152 return EOK;
153 }else if(str_lcmp(argv[index] + 2, "messages=", 6) == 0){
154 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &messages, "message count", 8));
155 }else if(str_lcmp(argv[index] + 2, "sockets=", 6) == 0){
156 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &sockets, "socket count", 8));
157 }else if(str_lcmp(argv[index] + 2, "port=", 5) == 0){
158 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "port number", 7));
159 port = (uint16_t) value;
160 }else if(str_lcmp(argv[index] + 2, "type=", 5) == 0){
161 ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 7, parse_socket_type));
162 type = (sock_type_t) value;
163 }else if(str_lcmp(argv[index] + 2, "verbose", 8) == 0){
164 verbose = 1;
165 }else{
166 print_unrecognized(index, argv[index] + 2);
[3be62bc]167 nettest2_print_help();
[aadf01e]168 return EINVAL;
169 }
170 break;
[21580dd]171 default:
[aadf01e]172 print_unrecognized(index, argv[index] + 1);
[3be62bc]173 nettest2_print_help();
[21580dd]174 return EINVAL;
175 }
176 }else{
[aadf01e]177 print_unrecognized(index, argv[index]);
[3be62bc]178 nettest2_print_help();
[21580dd]179 return EINVAL;
180 }
181 }
182
[3be62bc]183 // if not before the last argument containing the address
184 if(index >= argc){
185 printf("Command line error: missing address\n");
186 nettest2_print_help();
187 return EINVAL;
188 }
189
190 // prepare the address buffer
[aadf01e]191 bzero(address_data, max_length);
192 switch(family){
[21580dd]193 case PF_INET:
194 address_in->sin_family = AF_INET;
[aadf01e]195 address_in->sin_port = htons(port);
196 address_start = (uint8_t *) &address_in->sin_addr.s_addr;
197 addrlen = sizeof(struct sockaddr_in);
[21580dd]198 break;
199 case PF_INET6:
200 address_in6->sin6_family = AF_INET6;
[aadf01e]201 address_in6->sin6_port = htons(port);
202 address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr;
203 addrlen = sizeof(struct sockaddr_in6);
[21580dd]204 break;
205 default:
[aadf01e]206 fprintf(stderr, "Address family is not supported\n");
[21580dd]207 return EAFNOSUPPORT;
208 }
209
[3be62bc]210 // parse the last argument which should contain the address
[aadf01e]211 if(ERROR_OCCURRED(inet_pton(family, argv[argc - 1], address_start))){
212 fprintf(stderr, "Address parse error %d\n", ERROR_CODE);
[21580dd]213 return ERROR_CODE;
214 }
215
[3be62bc]216 // check the buffer size
[aadf01e]217 if(size <= 0){
218 fprintf(stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size);
[21580dd]219 size = 1024;
220 }
[3be62bc]221
222 // prepare the buffer
[21580dd]223 // size plus terminating null (\0)
[aadf01e]224 data = (char *) malloc(size + 1);
225 if(! data){
226 fprintf(stderr, "Failed to allocate data buffer.\n");
[21580dd]227 return ENOMEM;
228 }
[3be62bc]229 nettest2_refresh_data(data, size);
[21580dd]230
[3be62bc]231 // check the socket count
[aadf01e]232 if(sockets <= 0){
233 fprintf(stderr, "Socket count too small (%d). Using 2 instead.\n", sockets);
[21580dd]234 sockets = 2;
235 }
[3be62bc]236
237 // prepare the socket buffer
238 // count plus the terminating null (\0)
[aadf01e]239 socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
240 if(! socket_ids){
241 fprintf(stderr, "Failed to allocate receive buffer.\n");
[21580dd]242 return ENOMEM;
243 }
[aadf01e]244 socket_ids[sockets] = NULL;
[21580dd]245
[aadf01e]246 if(verbose){
247 printf("Starting tests\n");
248 }
[21580dd]249
[aadf01e]250 ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
[9d28b9c]251
[aadf01e]252 if(type == SOCK_STREAM){
253 ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, sockets, address, addrlen));
[21580dd]254 }
255
[aadf01e]256 if(verbose){
257 printf("\n");
258 }
[9d28b9c]259
[aadf01e]260 if(ERROR_OCCURRED(gettimeofday(&time_before, NULL))){
261 fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
[21580dd]262 return ERROR_CODE;
263 }
264
[aadf01e]265 ERROR_PROPAGATE(sockets_sendto_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, messages));
[21580dd]266
[aadf01e]267 if(ERROR_OCCURRED(gettimeofday(&time_after, NULL))){
268 fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
[21580dd]269 return ERROR_CODE;
270 }
271
[aadf01e]272 if(verbose){
273 printf("\tOK\n");
274 }
[21580dd]275
[aadf01e]276 printf("sendto + recvfrom tested in %d microseconds\n", tv_sub(&time_after, &time_before));
[21580dd]277
[aadf01e]278 if(ERROR_OCCURRED(gettimeofday(&time_before, NULL))){
279 fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
[21580dd]280 return ERROR_CODE;
281 }
282
[aadf01e]283 ERROR_PROPAGATE(sockets_sendto(verbose, socket_ids, sockets, address, addrlen, data, size, messages));
284 ERROR_PROPAGATE(sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, messages));
[21580dd]285
[aadf01e]286 if(ERROR_OCCURRED(gettimeofday(&time_after, NULL))){
287 fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
[21580dd]288 return ERROR_CODE;
289 }
290
[aadf01e]291 if(verbose){
292 printf("\tOK\n");
293 }
[21580dd]294
[aadf01e]295 printf("sendto, recvfrom tested in %d microseconds\n", tv_sub(&time_after, &time_before));
[21580dd]296
[aadf01e]297 ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
[21580dd]298
[aadf01e]299 if(verbose){
300 printf("\nExiting\n");
301 }
[21580dd]302
303 return EOK;
304}
305
[3be62bc]306void nettest2_print_help(void){
307 printf(
308 "Network Networking test 2 aplication - UDP transfer\n" \
309 "Usage: echo [options] numeric_address\n" \
310 "Where options are:\n" \
311 "-f protocol_family | --family=protocol_family\n" \
312 "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
313 "\n" \
314 "-h | --help\n" \
315 "\tShow this application help.\n"
316 "\n" \
317 "-m count | --messages=count\n" \
318 "\tThe number of messages to send and receive per socket. The default is 10.\n" \
319 "\n" \
320 "-n sockets | --sockets=count\n" \
321 "\tThe number of sockets to use. The default is 10.\n" \
322 "\n" \
323 "-p port_number | --port=port_number\n" \
324 "\tThe port number the application should send messages to. The default is 7.\n" \
325 "\n" \
326 "-s packet_size | --size=packet_size\n" \
327 "\tThe packet data size the application sends. The default is 29 bytes.\n" \
328 "\n" \
329 "-v | --verbose\n" \
330 "\tShow all output messages.\n"
331 );
332}
333
334void nettest2_refresh_data(char * data, size_t size){
335 size_t length;
336
337 // fill the data
338 length = 0;
339 while(size > length + sizeof(NETTEST2_TEXT) - 1){
340 memcpy(data + length, NETTEST2_TEXT, sizeof(NETTEST2_TEXT) - 1);
341 length += sizeof(NETTEST2_TEXT) - 1;
342 }
343 memcpy(data + length, NETTEST2_TEXT, size - length);
344 data[size] = '\0';
345}
346
[21580dd]347/** @}
348 */
Note: See TracBrowser for help on using the repository browser.