00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00040 #include <assert.h>
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <str.h>
00044 #include <task.h>
00045 #include <arg_parse.h>
00046
00047 #include <net/in.h>
00048 #include <net/in6.h>
00049 #include <net/inet.h>
00050 #include <net/socket.h>
00051 #include <net/socket_parse.h>
00052
00053 #include "print_error.h"
00054
00055 #define NAME "netecho"
00056
00057 static int count = -1;
00058 static int family = PF_INET;
00059 static sock_type_t type = SOCK_DGRAM;
00060 static uint16_t port = 7;
00061 static int backlog = 3;
00062 static size_t size = 1024;
00063 static int verbose = 0;
00064
00065 static char *reply = NULL;
00066 static size_t reply_length;
00067
00068 static char *data;
00069
00070 static void echo_print_help(void)
00071 {
00072 printf(
00073 "Network echo server\n"
00074 "Usage: " NAME " [options]\n"
00075 "Where options are:\n"
00076 "-b backlog | --backlog=size\n"
00077 "\tThe size of the accepted sockets queue. Only for SOCK_STREAM. "
00078 "The default is 3.\n"
00079 "\n"
00080 "-c count | --count=count\n"
00081 "\tThe number of received messages to handle. A negative number "
00082 "means infinity. The default is infinity.\n"
00083 "\n"
00084 "-f protocol_family | --family=protocol_family\n"
00085 "\tThe listenning socket protocol family. Only the PF_INET and "
00086 "PF_INET6 are supported.\n"
00087 "\n"
00088 "-h | --help\n"
00089 "\tShow this application help.\n"
00090 "\n"
00091 "-p port_number | --port=port_number\n"
00092 "\tThe port number the application should listen at. The default "
00093 "is 7.\n"
00094 "\n"
00095 "-r reply_string | --reply=reply_string\n"
00096 "\tThe constant reply string. The default is the original data "
00097 "received.\n"
00098 "\n"
00099 "-s receive_size | --size=receive_size\n"
00100 "\tThe maximum receive data size the application should accept. "
00101 "The default is 1024 bytes.\n"
00102 "\n"
00103 "-t socket_type | --type=socket_type\n"
00104 "\tThe listenning socket type. Only the SOCK_DGRAM and the "
00105 "SOCK_STREAM are supported.\n"
00106 "\n"
00107 "-v | --verbose\n"
00108 "\tShow all output messages.\n"
00109 );
00110 }
00111
00112 static int netecho_parse_option(int argc, char *argv[], int *index)
00113 {
00114 int value;
00115 int rc;
00116
00117 switch (argv[*index][1]) {
00118 case 'b':
00119 rc = arg_parse_int(argc, argv, index, &backlog, 0);
00120 if (rc != EOK)
00121 return rc;
00122 break;
00123 case 'c':
00124 rc = arg_parse_int(argc, argv, index, &count, 0);
00125 if (rc != EOK)
00126 return rc;
00127 break;
00128 case 'f':
00129 rc = arg_parse_name_int(argc, argv, index, &family, 0,
00130 socket_parse_protocol_family);
00131 if (rc != EOK)
00132 return rc;
00133 break;
00134 case 'h':
00135 echo_print_help();
00136 exit(0);
00137 break;
00138 case 'p':
00139 rc = arg_parse_int(argc, argv, index, &value, 0);
00140 if (rc != EOK)
00141 return rc;
00142 port = (uint16_t) value;
00143 break;
00144 case 'r':
00145 rc = arg_parse_string(argc, argv, index, &reply, 0);
00146 if (rc != EOK)
00147 return rc;
00148 break;
00149 case 's':
00150 rc = arg_parse_int(argc, argv, index, &value, 0);
00151 if (rc != EOK)
00152 return rc;
00153 size = (value >= 0) ? (size_t) value : 0;
00154 break;
00155 case 't':
00156 rc = arg_parse_name_int(argc, argv, index, &value, 0,
00157 socket_parse_socket_type);
00158 if (rc != EOK)
00159 return rc;
00160 type = (sock_type_t) value;
00161 break;
00162 case 'v':
00163 verbose = 1;
00164 break;
00165
00166 case '-':
00167 if (str_lcmp(argv[*index] + 2, "backlog=", 6) == 0) {
00168 rc = arg_parse_int(argc, argv, index, &backlog, 8);
00169 if (rc != EOK)
00170 return rc;
00171 } else if (str_lcmp(argv[*index] + 2, "count=", 6) == 0) {
00172 rc = arg_parse_int(argc, argv, index, &count, 8);
00173 if (rc != EOK)
00174 return rc;
00175 } else if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) {
00176 rc = arg_parse_name_int(argc, argv, index, &family, 9,
00177 socket_parse_protocol_family);
00178 if (rc != EOK)
00179 return rc;
00180 } else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) {
00181 echo_print_help();
00182 exit(0);
00183 } else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) {
00184 rc = arg_parse_int(argc, argv, index, &value, 7);
00185 if (rc != EOK)
00186 return rc;
00187 port = (uint16_t) value;
00188 } else if (str_lcmp(argv[*index] + 2, "reply=", 6) == 0) {
00189 rc = arg_parse_string(argc, argv, index, &reply, 8);
00190 if (rc != EOK)
00191 return rc;
00192 } else if (str_lcmp(argv[*index] + 2, "size=", 5) == 0) {
00193 rc = arg_parse_int(argc, argv, index, &value, 7);
00194 if (rc != EOK)
00195 return rc;
00196 size = (value >= 0) ? (size_t) value : 0;
00197 } else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) {
00198 rc = arg_parse_name_int(argc, argv, index, &value, 7,
00199 socket_parse_socket_type);
00200 if (rc != EOK)
00201 return rc;
00202 type = (sock_type_t) value;
00203 } else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) {
00204 verbose = 1;
00205 } else {
00206 echo_print_help();
00207 return EINVAL;
00208 }
00209 break;
00210 default:
00211 echo_print_help();
00212 return EINVAL;
00213 }
00214
00215 return EOK;
00216 }
00217
00223 static int netecho_socket_process_message(int listening_id)
00224 {
00225 uint8_t address_buf[sizeof(struct sockaddr_in6)];
00226
00227 socklen_t addrlen;
00228 int socket_id;
00229 ssize_t rcv_size;
00230 size_t length;
00231 uint8_t *address_start;
00232
00233 char address_string[INET6_ADDRSTRLEN];
00234 struct sockaddr_in *address_in = (struct sockaddr_in *) address_buf;
00235 struct sockaddr_in6 *address_in6 = (struct sockaddr_in6 *) address_buf;
00236 struct sockaddr *address = (struct sockaddr *) address_buf;
00237
00238 int rc;
00239
00240 if (type == SOCK_STREAM) {
00241
00242 addrlen = sizeof(address_buf);
00243 socket_id = accept(listening_id, (void *) address_buf, &addrlen);
00244 if (socket_id <= 0) {
00245 socket_print_error(stderr, socket_id, "Socket accept: ", "\n");
00246 } else {
00247 if (verbose)
00248 printf("Socket %d accepted\n", socket_id);
00249 }
00250
00251 assert((size_t) addrlen <= sizeof(address_buf));
00252 } else {
00253 socket_id = listening_id;
00254 }
00255
00256
00257 if (socket_id > 0) {
00258
00259
00260 rcv_size = recvfrom(socket_id, data, size, 0, address,
00261 &addrlen);
00262 if (rcv_size < 0) {
00263 socket_print_error(stderr, rcv_size, "Socket receive: ", "\n");
00264 } else {
00265 length = (size_t) rcv_size;
00266 if (verbose) {
00267
00268
00269
00270 address_start = NULL;
00271 switch (address->sa_family) {
00272 case AF_INET:
00273 port = ntohs(address_in->sin_port);
00274 address_start = (uint8_t *) &address_in->sin_addr.s_addr;
00275 break;
00276 case AF_INET6:
00277 port = ntohs(address_in6->sin6_port);
00278 address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr;
00279 break;
00280 default:
00281 fprintf(stderr, "Address family %u (%#x) is not supported.\n",
00282 address->sa_family, address->sa_family);
00283 }
00284
00285
00286 if (address_start) {
00287 rc = inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string));
00288 if (rc != EOK) {
00289 fprintf(stderr, "Received address error %d\n", rc);
00290 } else {
00291 data[length] = '\0';
00292 printf("Socket %d received %zu bytes from %s:%d\n%s\n",
00293 socket_id, length, address_string, port, data);
00294 }
00295 }
00296 }
00297
00298
00299 rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen);
00300 if (rc != EOK)
00301 socket_print_error(stderr, rc, "Socket send: ", "\n");
00302 }
00303
00304
00305 if (type == SOCK_STREAM) {
00306 rc = closesocket(socket_id);
00307 if (rc != EOK)
00308 socket_print_error(stderr, rc, "Close socket: ", "\n");
00309 }
00310
00311 }
00312
00313 return EOK;
00314 }
00315
00316
00317 int main(int argc, char *argv[])
00318 {
00319 struct sockaddr *address;;
00320 struct sockaddr_in address_in;
00321 struct sockaddr_in6 address_in6;
00322 socklen_t addrlen;
00323
00324 int listening_id;
00325 int index;
00326 int rc;
00327
00328
00329 for (index = 1; index < argc; ++index) {
00330 if (argv[index][0] == '-') {
00331 rc = netecho_parse_option(argc, argv, &index);
00332 if (rc != EOK)
00333 return rc;
00334 } else {
00335 echo_print_help();
00336 return EINVAL;
00337 }
00338 }
00339
00340
00341 if (size <= 0) {
00342 fprintf(stderr, "Receive size too small (%zu). Using 1024 bytes instead.\n", size);
00343 size = 1024;
00344 }
00345
00346
00347 data = (char *) malloc(size + 1);
00348 if (!data) {
00349 fprintf(stderr, "Failed to allocate receive buffer.\n");
00350 return ENOMEM;
00351 }
00352
00353
00354 reply_length = reply ? str_length(reply) : 0;
00355
00356
00357 switch (family) {
00358 case PF_INET:
00359 address_in.sin_family = AF_INET;
00360 address_in.sin_port = htons(port);
00361 address = (struct sockaddr *) &address_in;
00362 addrlen = sizeof(address_in);
00363 break;
00364 case PF_INET6:
00365 address_in6.sin6_family = AF_INET6;
00366 address_in6.sin6_port = htons(port);
00367 address = (struct sockaddr *) &address_in6;
00368 addrlen = sizeof(address_in6);
00369 break;
00370 default:
00371 fprintf(stderr, "Protocol family is not supported\n");
00372 return EAFNOSUPPORT;
00373 }
00374
00375
00376 listening_id = socket(family, type, 0);
00377 if (listening_id < 0) {
00378 socket_print_error(stderr, listening_id, "Socket create: ", "\n");
00379 return listening_id;
00380 }
00381
00382
00383 if (type == SOCK_STREAM) {
00384
00385 if (backlog <= 0) {
00386 fprintf(stderr, "Accepted sockets queue size too small (%zu). Using 3 instead.\n", size);
00387 backlog = 3;
00388 }
00389
00390
00391 rc = listen(listening_id, backlog);
00392 if (rc != EOK) {
00393 socket_print_error(stderr, rc, "Socket listen: ", "\n");
00394 return rc;
00395 }
00396 }
00397
00398
00399 rc = bind(listening_id, address, addrlen);
00400 if (rc != EOK) {
00401 socket_print_error(stderr, rc, "Socket bind: ", "\n");
00402 return rc;
00403 }
00404
00405 if (verbose)
00406 printf("Socket %d listenning at %d\n", listening_id, port);
00407
00408
00409
00410
00411
00412 while (count) {
00413 rc = netecho_socket_process_message(listening_id);
00414 if (rc != EOK)
00415 break;
00416
00417
00418 if (count > 0) {
00419 count--;
00420 if (verbose)
00421 printf("Waiting for next %d message(s)\n", count);
00422 }
00423 }
00424
00425 if (verbose)
00426 printf("Closing the socket\n");
00427
00428
00429 rc = closesocket(listening_id);
00430 if (rc != EOK) {
00431 socket_print_error(stderr, rc, "Close socket: ", "\n");
00432 return rc;
00433 }
00434
00435 if (verbose)
00436 printf("Exiting\n");
00437
00438 return EOK;
00439 }
00440