socktest.c revision 47653588a022190d4b3e20194ef643dfb7b90632
1/* 2** Copyright 2009 The Android Open Source Project 3** 4** Licensed under the Apache License, Version 2.0 (the "License"); 5** you may not use this file except in compliance with the License. 6** You may obtain a copy of the License at 7** 8** http://www.apache.org/licenses/LICENSE-2.0 9** 10** Unless required by applicable law or agreed to in writing, software 11** distributed under the License is distributed on an "AS IS" BASIS, 12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13** See the License for the specific language governing permissions and 14** limitations under the License. 15*/ 16 17/** socket testing */ 18 19#include <stdlib.h> 20#include <stdio.h> 21#include <errno.h> 22#include <sys/uio.h> 23#include <unistd.h> 24 25#include <pthread.h> 26#include <stdio.h> 27#include <stdlib.h> 28#include <errno.h> 29#include <unistd.h> 30#include <sys/socket.h> 31#include <sys/ioctl.h> 32#include <sys/poll.h> 33#include <sys/un.h> 34#include <netinet/in.h> 35 36#include <bluetooth/bluetooth.h> 37#include <bluetooth/rfcomm.h> 38#include <bluetooth/sco.h> 39#include <bluetooth/l2cap.h> 40 41enum sock_type { 42 UNIX = 0, 43 RFCOMM, 44 SCO, 45 L2CAP, 46 TCP, 47}; 48 49struct thread_args { 50 int fd; 51 int type; 52 int delay; 53}; 54 55struct sockaddr_un local_addr_un = {AF_UNIX, "/data/foo"}; 56struct sockaddr_rc local_addr_rc = {AF_BLUETOOTH, *BDADDR_ANY, 4}; 57struct sockaddr_sco local_addr_sco = {AF_BLUETOOTH, *BDADDR_LOCAL}; 58struct sockaddr_l2 local_addr_l2 = {AF_BLUETOOTH, htobs(0x1001), *BDADDR_ANY, 0}; 59struct sockaddr_in local_addr_in = {AF_INET, 9999, {0}, {0}}; 60 61struct sockaddr_un remote_addr_un ; 62struct sockaddr_rc remote_addr_rc ; 63struct sockaddr_sco remote_addr_sco ; 64struct sockaddr_l2 remote_addr_l2 ; 65struct sockaddr_in remote_addr_in ; 66 67static void print_events(int events) { 68 if (events & POLLIN) printf("POLLIN "); 69 if (events & POLLPRI) printf("POLLPRI "); 70 if (events & POLLOUT) printf("POLLOUT "); 71 if (events & POLLERR) printf("POLLERR "); 72 if (events & POLLHUP) printf("POLLHUP "); 73 if (events & POLLNVAL) printf("POLLNVAL "); 74 printf("\n"); 75} 76 77static void print_fds(struct pollfd *ufds, nfds_t nfds) { 78 unsigned int i; 79 for (i=0; i<nfds; i++) 80 printf("%d ", ufds[i].fd); 81} 82 83static int _socket(int type) { 84 int ret; 85 int family = -1; 86 int typ = -1; 87 int protocol = -1; 88 89 switch (type) { 90 case UNIX: 91 family = PF_UNIX; 92 typ = SOCK_STREAM; 93 protocol = 0; 94 break; 95 case RFCOMM: 96 family = PF_BLUETOOTH; 97 typ = SOCK_STREAM; 98 protocol = BTPROTO_RFCOMM; 99 break; 100 case SCO: 101 family = PF_BLUETOOTH; 102 typ = SOCK_SEQPACKET; 103 protocol = BTPROTO_SCO; 104 break; 105 case L2CAP: 106 family = PF_BLUETOOTH; 107 typ = SOCK_SEQPACKET; 108 protocol = BTPROTO_L2CAP; 109 break; 110 case TCP: 111 family = PF_INET; 112 typ = SOCK_STREAM; 113 protocol = 0; 114 break; 115 } 116 117 printf("%d: socket()\n", gettid()); 118 ret = socket(family, typ, protocol); 119 printf("%d: socket() = %d\n", gettid(), ret); 120 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 121 122 return ret; 123} 124 125static int _close(int fd, int type) { 126 int ret; 127 128 printf("%d: close(%d)\n", gettid(), fd); 129 ret = close(fd); 130 printf("%d: close(%d) = %d\n", gettid(), fd, ret); 131 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 132 133 return ret; 134} 135 136static int _bind(int fd, int type) { 137 int len = 0; 138 int ret; 139 struct sockaddr *addr = NULL; 140 141 switch (type) { 142 case UNIX: 143 unlink(local_addr_un.sun_path); 144 addr = (struct sockaddr *) &local_addr_un; 145 len = sizeof(local_addr_un); 146 break; 147 case RFCOMM: 148 addr = (struct sockaddr *) &local_addr_rc; 149 len = sizeof(local_addr_rc); 150 break; 151 case SCO: 152 addr = (struct sockaddr *) &local_addr_sco; 153 len = sizeof(local_addr_sco); 154 break; 155 case L2CAP: 156 addr = (struct sockaddr *) &local_addr_l2; 157 len = sizeof(local_addr_l2); 158 break; 159 case TCP: 160 addr = (struct sockaddr *) &local_addr_in; 161 len = sizeof(local_addr_in); 162 break; 163 } 164 165 printf("%d: bind(%d)\n", gettid(), fd); 166 ret = bind(fd, addr, len); 167 printf("%d: bind(%d) = %d\n", gettid(), fd, ret); 168 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 169 170 return ret; 171} 172 173static int _listen(int fd, int type) { 174 int ret; 175 176 printf("%d: listen(%d)\n", gettid(), fd); 177 ret = listen(fd, 1); 178 printf("%d: listen(%d) = %d\n", gettid(), fd, ret); 179 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 180 181 return ret; 182} 183 184static int _read(int fd) { 185 int ret; 186 char buf; 187 188 printf("%d: read(%d)\n", gettid(), fd); 189 ret = read(fd, &buf, 1); 190 printf("%d: read(%d) = %d [%d]\n", gettid(), fd, ret, (int)buf); 191 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 192 193 return ret; 194} 195 196 197static int _accept(int fd, int type) { 198 int ret; 199 int len; 200 struct sockaddr *addr = NULL; 201 202 switch (type) { 203 case UNIX: 204 addr = (struct sockaddr *) &remote_addr_un; 205 len = sizeof(remote_addr_un); 206 break; 207 case RFCOMM: 208 addr = (struct sockaddr *) &remote_addr_rc; 209 len = sizeof(remote_addr_rc); 210 break; 211 case SCO: 212 addr = (struct sockaddr *) &remote_addr_sco; 213 len = sizeof(remote_addr_sco); 214 break; 215 case L2CAP: 216 addr = (struct sockaddr *) &remote_addr_l2; 217 len = sizeof(remote_addr_l2); 218 break; 219 case TCP: 220 addr = (struct sockaddr *) &remote_addr_in; 221 len = sizeof(remote_addr_in); 222 break; 223 } 224 225 printf("%d: accept(%d)\n", gettid(), fd); 226 ret = accept(fd, addr, &len); 227 printf("%d: accept(%d) = %d\n", gettid(), fd, ret); 228 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 229 else { 230 printf("\tlen = %d\n", len); 231 } 232 233 return ret; 234} 235 236static int _connect(int fd, int type) { 237 int ret; 238 int len = 0; 239 struct sockaddr *addr = NULL; 240 241 switch (type) { 242 case UNIX: 243 addr = (struct sockaddr *) &local_addr_un; 244 len = sizeof(local_addr_un); 245 break; 246 case RFCOMM: 247 addr = (struct sockaddr *) &local_addr_rc; 248 len = sizeof(local_addr_rc); 249 break; 250 case SCO: 251 addr = (struct sockaddr *) &local_addr_sco; 252 len = sizeof(local_addr_sco); 253 break; 254 case L2CAP: 255 addr = (struct sockaddr *) &local_addr_l2; 256 len = sizeof(local_addr_l2); 257 break; 258 case TCP: 259 addr = (struct sockaddr *) &local_addr_in; 260 len = sizeof(local_addr_in); 261 break; 262 } 263 264 printf("%d: connect(%d)\n", gettid(), fd); 265 ret = connect(fd, addr, len); 266 printf("%d: connect(%d) = %d\n", gettid(), fd, ret); 267 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 268 269 return ret; 270} 271 272static int _write(int fd, int type) { 273 int ret; 274 char buf = 69; 275 276 printf("%d: write(%d)\n", gettid(), fd); 277 ret = write(fd, &buf, 1); 278 printf("%d: write(%d) = %d\n", gettid(), fd, ret); 279 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 280 281 return ret; 282} 283 284static int _shutdown(int fd, int how) { 285 int ret; 286 287 printf("%d: shutdown(%d)\n", gettid(), fd); 288 ret = shutdown(fd, how); 289 printf("%d: shutdown(%d) = %d\n", gettid(), fd, ret); 290 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 291 292 return ret; 293} 294 295static int _poll(struct pollfd *ufds, nfds_t nfds, int timeout) { 296 int ret; 297 unsigned int i; 298 299 printf("%d: poll(", gettid()); 300 print_fds(ufds, nfds); 301 printf(")\n"); 302 ret = poll(ufds, nfds, timeout); 303 printf("%d: poll() = %d\n", gettid(), ret); 304 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 305 if (ret > 0) { 306 for (i=0; i<nfds; i++) { 307 if (ufds[i].revents) { 308 printf("\tfd %d ", ufds[i].fd); print_events(ufds[i].revents); 309 } 310 } 311 } 312 return ret; 313} 314 315static void thread_delay_close(struct thread_args *args) { 316 printf("%d: START\n", gettid()); 317 sleep(args->delay); 318 _close(args->fd, args->type); 319 printf("%d: END\n", gettid()); 320} 321 322static void thread_poll(void *args) { 323 int fd = (int)args; 324 struct pollfd pfd; 325 printf("%d: START\n", gettid()); 326 pfd.fd = fd; 327 pfd.events = 0; 328 _poll(&pfd, 1, -1); 329 printf("%d: END\n", gettid()); 330} 331 332static void thread_read(void *args) { 333 int fd = (int)args; 334 printf("%d: START\n", gettid()); 335 _read(fd); 336 printf("%d: END\n", gettid()); 337} 338 339static void thread_pollin(void *args) { 340 int fd = (int)args; 341 struct pollfd pfd; 342 printf("%d: START\n", gettid()); 343 pfd.fd = fd; 344 pfd.events = POLLIN; 345 _poll(&pfd, 1, -1); 346 printf("%d: END\n", gettid()); 347} 348 349static void thread_shutdown(int fd) { 350 printf("%d: START\n", gettid()); 351 sleep(4); 352 _shutdown(fd, SHUT_RDWR); 353 printf("%d: END\n", gettid()); 354} 355 356static void thread_accept(struct thread_args *args) { 357 printf("%d: START\n", gettid()); 358 sleep(args->delay); 359 _accept(args->fd, args->type); 360 printf("%d: END\n", gettid()); 361} 362 363static void thread_connect(struct thread_args *args) { 364 printf("%d: START\n", gettid()); 365 sleep(args->delay); 366 _connect(args->fd, args->type); 367 printf("%d: END\n", gettid()); 368} 369 370static void thread_delay_close_write(struct thread_args *args) { 371 printf("%d: START\n", gettid()); 372 sleep(args->delay); 373 _close(args->fd, args->type); 374 sleep(args->delay); 375 _write(args->fd, args->type); 376 printf("%d: END\n", gettid()); 377} 378 379static void thread_accept_write(struct thread_args *args) { 380 printf("%d: START\n", gettid()); 381 sleep(args->delay); 382 _accept(args->fd, args->type); 383 sleep(args->delay); 384 _write(args->fd, args->type); 385 printf("%d: END\n", gettid()); 386} 387 388static void thread_delay_connect(struct thread_args *args) { 389 printf("%d: START\n", gettid()); 390 sleep(args->delay); 391 args->fd = _socket(args->type); 392 _connect(args->fd, args->type); 393 printf("%d: END\n", gettid()); 394} 395 396static int do_accept_accept_accept(int type) { 397 int fd; 398 399 fd = _socket(type); 400 if (fd < 0) goto error; 401 402 if (_bind(fd, type) < 0) goto error; 403 404 if (_listen(fd, type) < 0) goto error; 405 406 while (1) { 407 _accept(fd, type); 408 } 409 410 return 0; 411 412error: 413 return -1; 414} 415 416static int do_accept_and_close(int type) { 417 int fd; 418 pthread_t thread; 419 struct thread_args args = {-1, type, 1}; 420 421 fd = _socket(type); 422 if (fd < 0) goto error; 423 424 if (_bind(fd, type) < 0) goto error; 425 426 if (_listen(fd, type) < 0) goto error; 427 428 args.fd = fd; 429 pthread_create(&thread, NULL, (void *)thread_delay_close, (void *)&args); 430 431 _accept(fd, type); 432 433 pthread_join(thread, NULL); 434 435 return 0; 436 437error: 438 return -1; 439} 440 441static int do_accept_shutdown(int type) { 442 int fd; 443 pthread_t thread; 444 struct thread_args args = {-1, type, 0}; 445 446 fd = _socket(type); 447 if (fd < 0) goto error; 448 449 if (_bind(fd, type) < 0) goto error; 450 451 if (_listen(fd, type) < 0) goto error; 452 453 args.fd = fd; 454 pthread_create(&thread, NULL, (void *)thread_accept, (void *)&args); 455 456 sleep(4); 457 _shutdown(fd, SHUT_RDWR); 458 459 pthread_join(thread, NULL); 460 461 _close(fd, type); 462 463 return 0; 464 465error: 466 return -1; 467} 468 469static int do_connect_shutdown(int type) { 470 int fd; 471 pthread_t thread; 472 struct thread_args args = {-1, type, 0}; 473 474 fd = _socket(type); 475 if (fd < 0) goto error; 476 477 args.fd = fd; 478 pthread_create(&thread, NULL, (void *)thread_connect, (void *)&args); 479 480 sleep(4); 481 _shutdown(fd, SHUT_RDWR); 482 483 pthread_join(thread, NULL); 484 485 _close(fd, type); 486 487 return 0; 488 489error: 490 return -1; 491} 492 493// accept in one thread. close then write in another 494static int do_accept_close_write(int type) { 495 int fd; 496 pthread_t thread; 497 struct thread_args args = {-1, type, 1}; 498 499 fd = _socket(type); 500 if (fd < 0) goto error; 501 502 if (_bind(fd, type) < 0) goto error; 503 504 if (_listen(fd, type) < 0) goto error; 505 506 args.fd = fd; 507 pthread_create(&thread, NULL, (void *)thread_delay_close_write, (void *)&args); 508 509 _accept(fd, type); 510 511 pthread_join(thread, NULL); 512 513 return 0; 514 515error: 516 return -1; 517} 518 519static int do_poll_poll_poll_shutdown(int type) { 520 const int MAX_T = 32; 521 int fd; 522 pthread_t t[MAX_T]; 523 int i; 524 525 fd = _socket(type); 526 527 for (i=0; i<MAX_T; i++) 528 pthread_create(&t[i], NULL, (void *)thread_poll, (void *)fd); 529 530 sleep(1); 531 532 _shutdown(fd, SHUT_RDWR); 533 534 for (i=0; i<MAX_T; i++) 535 pthread_join(t[i], NULL); 536 537 _close(fd, type); 538 539 return 0; 540} 541 542static int do_poll_poll_poll_close(int type) { 543 const int MAX_T = 32; 544 int fd; 545 pthread_t t[MAX_T]; 546 int i; 547 548 fd = _socket(type); 549 550 for (i=0; i<MAX_T; i++) 551 pthread_create(&t[i], NULL, (void *)thread_poll, (void *)fd); 552 553 sleep(1); 554 555 _close(fd, type); 556 557 for (i=0; i<MAX_T; i++) 558 pthread_join(t[i], NULL); 559 560 return 0; 561} 562 563static int do_read_read_read_close(int type) { 564 const int MAX_T = 32; 565 int fd; 566 pthread_t t[MAX_T]; 567 int i; 568 569 fd = _socket(type); 570 571 for (i=0; i<MAX_T; i++) 572 pthread_create(&t[i], NULL, (void *)thread_read, (void *)fd); 573 574 sleep(1); 575 576 _close(fd, type); 577 578 for (i=0; i<MAX_T; i++) 579 pthread_join(t[i], NULL); 580 581 return 0; 582} 583 584static int do_read_read_read_shutdown(int type) { 585 const int MAX_T = 32; 586 int fd; 587 pthread_t t[MAX_T]; 588 int i; 589 590 fd = _socket(type); 591 592 for (i=0; i<MAX_T; i++) 593 pthread_create(&t[i], NULL, (void *)thread_read, (void *)fd); 594 595 sleep(1); 596 597 _shutdown(fd, SHUT_RDWR); 598 599 for (i=0; i<MAX_T; i++) 600 pthread_join(t[i], NULL); 601 602 _close(fd, type); 603 604 return 0; 605} 606 607static int do_connected_read1_shutdown1(int type) { 608 int fd1, fd2; 609 pthread_t t1; 610 pthread_t t2; 611 struct thread_args a1 = {-1, type, 0}; 612 struct thread_args a2 = {-1, type, 2}; 613 614 fd1 = _socket(type); 615 if (fd1 < 0) goto error; 616 617 if (_bind(fd1, type) < 0) goto error; 618 619 if (_listen(fd1, type) < 0) goto error; 620 621 a1.fd = fd1; 622 pthread_create(&t1, NULL, (void *)thread_accept_write, (void *)&a1); 623 624 fd2 = _socket(type); 625 if (_connect(fd2, type)) goto error; 626 627 pthread_create(&t2, NULL, (void *)thread_shutdown, (void *)&fd2); 628 629 while (1) if (_read(fd2)) break; 630 631 pthread_join(t1, NULL); 632 pthread_join(t2, NULL); 633 634 return 0; 635 636error: 637 return -1; 638} 639 640// accept in one thread, connect from two different threads 641static int do_accept_connect_connect(int type) { 642 int fd; 643 pthread_t t1; 644 pthread_t t2; 645 struct thread_args a1 = {-1, type, 1}; 646 struct thread_args a2 = {-1, type, 2}; 647 648 fd = _socket(type); 649 if (fd < 0) goto error; 650 651 if (_bind(fd, type) < 0) goto error; 652 653 if (_listen(fd, type) < 0) goto error; 654 655 pthread_create(&t1, NULL, (void *)thread_delay_connect, (void *)&a1); 656 pthread_create(&t2, NULL, (void *)thread_delay_connect, (void *)&a2); 657 658 _accept(fd, type); 659 660 pthread_join(t1, NULL); 661 pthread_join(t2, NULL); 662 663 return 0; 664 665error: 666 return -1; 667} 668 669struct { 670 char *name; 671 int (*ptr)(int); 672} action_table[] = { 673 {"accept_accept_accept", do_accept_accept_accept}, 674 {"accept_and_close", do_accept_and_close}, 675 {"accept_shutdown", do_accept_shutdown}, 676 {"connect_shutdown", do_connect_shutdown}, 677 {"accept_close_write", do_accept_close_write}, 678 {"accept_connect_connect", do_accept_connect_connect}, 679 {"poll_poll_poll_shutdown", do_poll_poll_poll_shutdown}, 680 {"poll_poll_poll_close", do_poll_poll_poll_close}, 681 {"read_read_read_shutdown", do_read_read_read_shutdown}, 682 {"read_read_read_close", do_read_read_read_close}, 683 {"connected_read1_shutdown1", do_connected_read1_shutdown1}, 684 {NULL, NULL}, 685}; 686 687struct { 688 char *name; 689 enum sock_type type; 690} type_table[] = { 691 {"unix", UNIX}, 692 {"rfcomm", RFCOMM}, 693 {"sco", SCO}, 694 {"l2cap", L2CAP}, 695 {"tcp", TCP}, 696 {NULL, -1}, 697}; 698 699static void usage() { 700 int i; 701 702 printf("socktest TYPE ACTION\n"); 703 printf("\nTYPE:\n"); 704 for (i = 0; type_table[i].name; i++) { 705 printf("\t%s\n", type_table[i].name); 706 } 707 printf("\nACTION:\n"); 708 for (i = 0; action_table[i].name; i++) { 709 printf("\t%s\n", action_table[i].name); 710 } 711} 712 713int main(int argc, char **argv) { 714 int i; 715 int type = -1; 716 717 if (argc != 3) { 718 usage(); 719 return -1; 720 } 721 for (i = 0; type_table[i].name; i++) { 722 if (!strcmp(argv[1], type_table[i].name)) { 723 type = type_table[i].type; 724 break; 725 } 726 } 727 if (type == -1) { 728 usage(); 729 return -1; 730 } 731 for (i = 0; action_table[i].name; i++) { 732 if (!strcmp(argv[2], action_table[i].name)) { 733 printf("TYPE = %s ACTION = %s\n", type_table[type].name, 734 action_table[i].name); 735 return (*action_table[i].ptr)(type); 736 } 737 } 738 usage(); 739 return -1; 740} 741