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