Changes in uspace/app/netecho/netecho.c [cd22764:7e752b2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/netecho/netecho.c
rcd22764 r7e752b2 32 32 33 33 /** @file 34 * Network echo server. 35 * 36 * Sockets-based server that echoes incomming messages. If stream mode 37 * is selected, accepts incoming connections. 34 * Network echo application. 35 * Answers received packets. 38 36 */ 39 37 40 #include < assert.h>38 #include <malloc.h> 41 39 #include <stdio.h> 42 #include <stdlib.h>43 40 #include <str.h> 44 41 #include <task.h> … … 53 50 #include "print_error.h" 54 51 55 #define NAME "netecho" 56 57 static int count = -1; 58 static int family = PF_INET; 59 static sock_type_t type = SOCK_DGRAM; 60 static uint16_t port = 7; 61 static int backlog = 3; 62 static size_t size = 1024; 63 static int verbose = 0; 64 65 static char *reply = NULL; 66 static size_t reply_length; 67 68 static char *data; 52 /** Network echo module name. */ 53 #define NAME "Network Echo" 69 54 70 55 static void echo_print_help(void) 71 56 { 72 57 printf( 73 "Network echo server\n" 74 "Usage: " NAME " [options]\n" 75 "Where options are:\n" 76 "-b backlog | --backlog=size\n" 77 "\tThe size of the accepted sockets queue. Only for SOCK_STREAM. " 78 "The default is 3.\n" 79 "\n" 80 "-c count | --count=count\n" 81 "\tThe number of received messages to handle. A negative number " 82 "means infinity. The default is infinity.\n" 83 "\n" 84 "-f protocol_family | --family=protocol_family\n" 85 "\tThe listenning socket protocol family. Only the PF_INET and " 86 "PF_INET6 are supported.\n" 87 "\n" 88 "-h | --help\n" 89 "\tShow this application help.\n" 90 "\n" 91 "-p port_number | --port=port_number\n" 92 "\tThe port number the application should listen at. The default " 93 "is 7.\n" 94 "\n" 95 "-r reply_string | --reply=reply_string\n" 96 "\tThe constant reply string. The default is the original data " 97 "received.\n" 98 "\n" 99 "-s receive_size | --size=receive_size\n" 100 "\tThe maximum receive data size the application should accept. " 101 "The default is 1024 bytes.\n" 102 "\n" 103 "-t socket_type | --type=socket_type\n" 104 "\tThe listenning socket type. Only the SOCK_DGRAM and the " 105 "SOCK_STREAM are supported.\n" 106 "\n" 107 "-v | --verbose\n" 108 "\tShow all output messages.\n" 58 "Network Echo aplication\n" \ 59 "Usage: echo [options]\n" \ 60 "Where options are:\n" \ 61 "-b backlog | --backlog=size\n" \ 62 "\tThe size of the accepted sockets queue. Only for SOCK_STREAM. The default is 3.\n" \ 63 "\n" \ 64 "-c count | --count=count\n" \ 65 "\tThe number of received messages to handle. A negative number means infinity. The default is infinity.\n" \ 66 "\n" \ 67 "-f protocol_family | --family=protocol_family\n" \ 68 "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n" 69 "\n" \ 70 "-h | --help\n" \ 71 "\tShow this application help.\n" 72 "\n" \ 73 "-p port_number | --port=port_number\n" \ 74 "\tThe port number the application should listen at. The default is 7.\n" \ 75 "\n" \ 76 "-r reply_string | --reply=reply_string\n" \ 77 "\tThe constant reply string. The default is the original data received.\n" \ 78 "\n" \ 79 "-s receive_size | --size=receive_size\n" \ 80 "\tThe maximum receive data size the application should accept. The default is 1024 bytes.\n" \ 81 "\n" \ 82 "-t socket_type | --type=socket_type\n" \ 83 "\tThe listenning socket type. Only the SOCK_DGRAM and the SOCK_STREAM are supported.\n" \ 84 "\n" \ 85 "-v | --verbose\n" \ 86 "\tShow all output messages.\n" 109 87 ); 110 88 } 111 89 112 static int netecho_parse_option(int argc, char *argv[], int *index)90 int main(int argc, char *argv[]) 113 91 { 92 size_t size = 1024; 93 int verbose = 0; 94 char *reply = NULL; 95 sock_type_t type = SOCK_DGRAM; 96 int count = -1; 97 int family = PF_INET; 98 uint16_t port = 7; 99 int backlog = 3; 100 101 socklen_t max_length = sizeof(struct sockaddr_in6); 102 uint8_t address_data[max_length]; 103 struct sockaddr *address = (struct sockaddr *) address_data; 104 struct sockaddr_in *address_in = (struct sockaddr_in *) address; 105 struct sockaddr_in6 *address_in6 = (struct sockaddr_in6 *) address; 106 socklen_t addrlen; 107 char address_string[INET6_ADDRSTRLEN]; 108 uint8_t *address_start; 109 int socket_id; 110 int listening_id; 111 char *data; 112 size_t length; 113 int index; 114 size_t reply_length; 114 115 int value; 115 116 int rc; 116 117 117 switch (argv[*index][1]) { 118 case 'b': 119 rc = arg_parse_int(argc, argv, index, &backlog, 0); 120 if (rc != EOK) 121 return rc; 122 break; 123 case 'c': 124 rc = arg_parse_int(argc, argv, index, &count, 0); 125 if (rc != EOK) 126 return rc; 127 break; 128 case 'f': 129 rc = arg_parse_name_int(argc, argv, index, &family, 0, 130 socket_parse_protocol_family); 131 if (rc != EOK) 132 return rc; 133 break; 134 case 'h': 135 echo_print_help(); 136 exit(0); 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 'r': 145 rc = arg_parse_string(argc, argv, index, &reply, 0); 146 if (rc != EOK) 147 return rc; 148 break; 149 case 's': 150 rc = arg_parse_int(argc, argv, index, &value, 0); 151 if (rc != EOK) 152 return rc; 153 size = (value >= 0) ? (size_t) value : 0; 154 break; 155 case 't': 156 rc = arg_parse_name_int(argc, argv, index, &value, 0, 157 socket_parse_socket_type); 158 if (rc != EOK) 159 return rc; 160 type = (sock_type_t) value; 161 break; 162 case 'v': 163 verbose = 1; 164 break; 165 /* Long options with double dash */ 166 case '-': 167 if (str_lcmp(argv[*index] + 2, "backlog=", 6) == 0) { 168 rc = arg_parse_int(argc, argv, index, &backlog, 8); 169 if (rc != EOK) 170 return rc; 171 } else if (str_lcmp(argv[*index] + 2, "count=", 6) == 0) { 172 rc = arg_parse_int(argc, argv, index, &count, 8); 173 if (rc != EOK) 174 return rc; 175 } else if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) { 176 rc = arg_parse_name_int(argc, argv, index, &family, 9, 177 socket_parse_protocol_family); 178 if (rc != EOK) 179 return rc; 180 } else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) { 181 echo_print_help(); 182 exit(0); 183 } else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) { 184 rc = arg_parse_int(argc, argv, index, &value, 7); 185 if (rc != EOK) 186 return rc; 187 port = (uint16_t) value; 188 } else if (str_lcmp(argv[*index] + 2, "reply=", 6) == 0) { 189 rc = arg_parse_string(argc, argv, index, &reply, 8); 190 if (rc != EOK) 191 return rc; 192 } else if (str_lcmp(argv[*index] + 2, "size=", 5) == 0) { 193 rc = arg_parse_int(argc, argv, index, &value, 7); 194 if (rc != EOK) 195 return rc; 196 size = (value >= 0) ? (size_t) value : 0; 197 } else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) { 198 rc = arg_parse_name_int(argc, argv, index, &value, 7, 199 socket_parse_socket_type); 200 if (rc != EOK) 201 return rc; 202 type = (sock_type_t) value; 203 } else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) { 204 verbose = 1; 118 // parse the command line arguments 119 for (index = 1; index < argc; ++ index) { 120 if (argv[index][0] == '-') { 121 switch (argv[index][1]) { 122 case 'b': 123 rc = arg_parse_int(argc, argv, &index, &backlog, 0); 124 if (rc != EOK) 125 return rc; 126 break; 127 case 'c': 128 rc = arg_parse_int(argc, argv, &index, &count, 0); 129 if (rc != EOK) 130 return rc; 131 break; 132 case 'f': 133 rc = arg_parse_name_int(argc, argv, &index, &family, 0, socket_parse_protocol_family); 134 if (rc != EOK) 135 return rc; 136 break; 137 case 'h': 138 echo_print_help(); 139 return EOK; 140 break; 141 case 'p': 142 rc = arg_parse_int(argc, argv, &index, &value, 0); 143 if (rc != EOK) 144 return rc; 145 port = (uint16_t) value; 146 break; 147 case 'r': 148 rc = arg_parse_string(argc, argv, &index, &reply, 0); 149 if (rc != EOK) 150 return rc; 151 break; 152 case 's': 153 rc = arg_parse_int(argc, argv, &index, &value, 0); 154 if (rc != EOK) 155 return rc; 156 size = (value >= 0) ? (size_t) value : 0; 157 break; 158 case 't': 159 rc = arg_parse_name_int(argc, argv, &index, &value, 0, socket_parse_socket_type); 160 if (rc != EOK) 161 return rc; 162 type = (sock_type_t) value; 163 break; 164 case 'v': 165 verbose = 1; 166 break; 167 // long options with the double minus sign ('-') 168 case '-': 169 if (str_lcmp(argv[index] + 2, "backlog=", 6) == 0) { 170 rc = arg_parse_int(argc, argv, &index, &backlog, 8); 171 if (rc != EOK) 172 return rc; 173 } else if (str_lcmp(argv[index] + 2, "count=", 6) == 0) { 174 rc = arg_parse_int(argc, argv, &index, &count, 8); 175 if (rc != EOK) 176 return rc; 177 } else if (str_lcmp(argv[index] + 2, "family=", 7) == 0) { 178 rc = arg_parse_name_int(argc, argv, &index, &family, 9, socket_parse_protocol_family); 179 if (rc != EOK) 180 return rc; 181 } else if (str_lcmp(argv[index] + 2, "help", 5) == 0) { 182 echo_print_help(); 183 return EOK; 184 } else if (str_lcmp(argv[index] + 2, "port=", 5) == 0) { 185 rc = arg_parse_int(argc, argv, &index, &value, 7); 186 if (rc != EOK) 187 return rc; 188 port = (uint16_t) value; 189 } else if (str_lcmp(argv[index] + 2, "reply=", 6) == 0) { 190 rc = arg_parse_string(argc, argv, &index, &reply, 8); 191 if (rc != EOK) 192 return rc; 193 } else if (str_lcmp(argv[index] + 2, "size=", 5) == 0) { 194 rc = arg_parse_int(argc, argv, &index, &value, 7); 195 if (rc != EOK) 196 return rc; 197 size = (value >= 0) ? (size_t) value : 0; 198 } else if (str_lcmp(argv[index] + 2, "type=", 5) == 0) { 199 rc = arg_parse_name_int(argc, argv, &index, &value, 7, socket_parse_socket_type); 200 if (rc != EOK) 201 return rc; 202 type = (sock_type_t) value; 203 } else if (str_lcmp(argv[index] + 2, "verbose", 8) == 0) { 204 verbose = 1; 205 } else { 206 echo_print_help(); 207 return EINVAL; 208 } 209 break; 210 default: 211 echo_print_help(); 212 return EINVAL; 213 } 205 214 } else { 206 215 echo_print_help(); 207 216 return EINVAL; 208 217 } 209 break; 210 default: 211 echo_print_help(); 212 return EINVAL; 213 } 214 215 return EOK; 216 } 217 218 /** Echo one message (accept one connection and echo message). 219 * 220 * @param listening_id Listening socket. 221 * @return EOK on success or negative error code. 222 */ 223 static int netecho_socket_process_message(int listening_id) 224 { 225 uint8_t address_buf[sizeof(struct sockaddr_in6)]; 226 227 socklen_t addrlen; 228 int socket_id; 229 ssize_t rcv_size; 230 size_t length; 231 uint8_t *address_start; 232 233 char address_string[INET6_ADDRSTRLEN]; 234 struct sockaddr_in *address_in = (struct sockaddr_in *) address_buf; 235 struct sockaddr_in6 *address_in6 = (struct sockaddr_in6 *) address_buf; 236 struct sockaddr *address = (struct sockaddr *) address_buf; 237 238 int rc; 239 240 if (type == SOCK_STREAM) { 241 /* Accept a socket if a stream socket is used */ 242 addrlen = sizeof(address_buf); 243 socket_id = accept(listening_id, (void *) address_buf, &addrlen); 244 if (socket_id <= 0) { 245 socket_print_error(stderr, socket_id, "Socket accept: ", "\n"); 246 } else { 247 if (verbose) 248 printf("Socket %d accepted\n", socket_id); 249 } 250 251 assert((size_t) addrlen <= sizeof(address_buf)); 252 } else { 253 socket_id = listening_id; 254 } 255 256 /* if the datagram socket is used or the stream socked was accepted */ 257 if (socket_id > 0) { 258 259 /* Receive a message to echo */ 260 rcv_size = recvfrom(socket_id, data, size, 0, address, 261 &addrlen); 262 if (rcv_size < 0) { 263 socket_print_error(stderr, rcv_size, "Socket receive: ", "\n"); 264 } else { 265 length = (size_t) rcv_size; 266 if (verbose) { 267 /* Print the header */ 268 269 /* Get the source port and prepare the address buffer */ 270 address_start = NULL; 271 switch (address->sa_family) { 272 case AF_INET: 273 port = ntohs(address_in->sin_port); 274 address_start = (uint8_t *) &address_in->sin_addr.s_addr; 275 break; 276 case AF_INET6: 277 port = ntohs(address_in6->sin6_port); 278 address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr; 279 break; 280 default: 281 fprintf(stderr, "Address family %u (%#x) is not supported.\n", 282 address->sa_family, address->sa_family); 283 } 284 285 /* Parse source address */ 286 if (address_start) { 287 rc = inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string)); 288 if (rc != EOK) { 289 fprintf(stderr, "Received address error %d\n", rc); 290 } else { 291 data[length] = '\0'; 292 printf("Socket %d received %zu bytes from %s:%d\n%s\n", 293 socket_id, length, address_string, port, data); 294 } 295 } 296 } 297 298 /* Answer the request either with the static reply or the original data */ 299 rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen); 300 if (rc != EOK) 301 socket_print_error(stderr, rc, "Socket send: ", "\n"); 302 } 303 304 /* Close accepted stream socket */ 305 if (type == SOCK_STREAM) { 306 rc = closesocket(socket_id); 307 if (rc != EOK) 308 socket_print_error(stderr, rc, "Close socket: ", "\n"); 309 } 310 311 } 312 313 return EOK; 314 } 315 316 317 int main(int argc, char *argv[]) 318 { 319 struct sockaddr *address;; 320 struct sockaddr_in address_in; 321 struct sockaddr_in6 address_in6; 322 socklen_t addrlen; 323 324 int listening_id; 325 int index; 326 int rc; 327 328 /* Parse command line arguments */ 329 for (index = 1; index < argc; ++index) { 330 if (argv[index][0] == '-') { 331 rc = netecho_parse_option(argc, argv, &index); 332 if (rc != EOK) 333 return rc; 334 } else { 335 echo_print_help(); 336 return EINVAL; 337 } 338 } 339 340 /* Check buffer size */ 218 } 219 220 // check the buffer size 341 221 if (size <= 0) { 342 222 fprintf(stderr, "Receive size too small (%zu). Using 1024 bytes instead.\n", size); 343 223 size = 1024; 344 224 } 345 346 /* size plus the terminating null character. */ 225 // size plus the terminating null (\0) 347 226 data = (char *) malloc(size + 1); 348 227 if (!data) { … … 351 230 } 352 231 353 / * Set the reply size if set */232 // set the reply size if set 354 233 reply_length = reply ? str_length(reply) : 0; 355 234 356 /* Prepare the address buffer */ 235 // prepare the address buffer 236 bzero(address_data, max_length); 357 237 switch (family) { 358 238 case PF_INET: 359 address_in.sin_family = AF_INET; 360 address_in.sin_port = htons(port); 361 address = (struct sockaddr *) &address_in; 362 addrlen = sizeof(address_in); 239 address_in->sin_family = AF_INET; 240 address_in->sin_port = htons(port); 241 addrlen = sizeof(struct sockaddr_in); 363 242 break; 364 243 case PF_INET6: 365 address_in6.sin6_family = AF_INET6; 366 address_in6.sin6_port = htons(port); 367 address = (struct sockaddr *) &address_in6; 368 addrlen = sizeof(address_in6); 244 address_in6->sin6_family = AF_INET6; 245 address_in6->sin6_port = htons(port); 246 addrlen = sizeof(struct sockaddr_in6); 369 247 break; 370 248 default: … … 373 251 } 374 252 375 / * Get a listening socket */253 // get a listening socket 376 254 listening_id = socket(family, type, 0); 377 255 if (listening_id < 0) { … … 380 258 } 381 259 382 / * if the stream socket is used */260 // if the stream socket is used 383 261 if (type == SOCK_STREAM) { 384 / * Check backlog size */262 // check the backlog 385 263 if (backlog <= 0) { 386 264 fprintf(stderr, "Accepted sockets queue size too small (%zu). Using 3 instead.\n", size); 387 265 backlog = 3; 388 266 } 389 390 /* Set the backlog */ 267 // set the backlog 391 268 rc = listen(listening_id, backlog); 392 269 if (rc != EOK) { … … 396 273 } 397 274 398 / * Bind the listening socket */275 // bind the listenning socket 399 276 rc = bind(listening_id, address, addrlen); 400 277 if (rc != EOK) { … … 406 283 printf("Socket %d listenning at %d\n", listening_id, port); 407 284 408 /*409 * do count times 410 * or indefinitely if set to a negative value411 */285 socket_id = listening_id; 286 287 // do count times 288 // or indefinitely if set to a negative value 412 289 while (count) { 413 rc = netecho_socket_process_message(listening_id); 414 if (rc != EOK) 415 break; 416 417 /* Decrease count if positive */ 290 291 addrlen = max_length; 292 if (type == SOCK_STREAM) { 293 // acceept a socket if the stream socket is used 294 socket_id = accept(listening_id, address, &addrlen); 295 if (socket_id <= 0) { 296 socket_print_error(stderr, socket_id, "Socket accept: ", "\n"); 297 } else { 298 if (verbose) 299 printf("Socket %d accepted\n", socket_id); 300 } 301 } 302 303 // if the datagram socket is used or the stream socked was accepted 304 if (socket_id > 0) { 305 306 // receive an echo request 307 value = recvfrom(socket_id, data, size, 0, address, &addrlen); 308 if (value < 0) { 309 socket_print_error(stderr, value, "Socket receive: ", "\n"); 310 } else { 311 length = (size_t) value; 312 if (verbose) { 313 // print the header 314 315 // get the source port and prepare the address buffer 316 address_start = NULL; 317 switch (address->sa_family) { 318 case AF_INET: 319 port = ntohs(address_in->sin_port); 320 address_start = (uint8_t *) &address_in->sin_addr.s_addr; 321 break; 322 case AF_INET6: 323 port = ntohs(address_in6->sin6_port); 324 address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr; 325 break; 326 default: 327 fprintf(stderr, "Address family %u (%#x) is not supported.\n", 328 address->sa_family, address->sa_family); 329 } 330 // parse the source address 331 if (address_start) { 332 rc = inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string)); 333 if (rc != EOK) { 334 fprintf(stderr, "Received address error %d\n", rc); 335 } else { 336 data[length] = '\0'; 337 printf("Socket %d received %zu bytes from %s:%d\n%s\n", 338 socket_id, length, address_string, port, data); 339 } 340 } 341 } 342 343 // answer the request either with the static reply or the original data 344 rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen); 345 if (rc != EOK) 346 socket_print_error(stderr, rc, "Socket send: ", "\n"); 347 } 348 349 // close the accepted stream socket 350 if (type == SOCK_STREAM) { 351 rc = closesocket(socket_id); 352 if (rc != EOK) 353 socket_print_error(stderr, rc, "Close socket: ", "\n"); 354 } 355 356 } 357 358 // decrease the count if positive 418 359 if (count > 0) { 419 360 count--; 420 361 if (verbose) 421 printf("Waiting for next %d message(s)\n", count);362 printf("Waiting for next %d packet(s)\n", count); 422 363 } 423 364 } … … 426 367 printf("Closing the socket\n"); 427 368 428 / * Close listenning socket */369 // close the listenning socket 429 370 rc = closesocket(listening_id); 430 371 if (rc != EOK) {
Note:
See TracChangeset
for help on using the changeset viewer.