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 /** testing behavior of shutdown() */
     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 enum sock_type {
     42     UNIX = 0,
     43     RFCOMM,
     44     SCO,
     45     L2CAP,
     46     TCP,
     47 };
     48 
     49 struct thread_args {
     50     int fd;
     51     int type;
     52     int delay;
     53 };
     54 
     55 struct sockaddr_un  local_addr_un  = {AF_UNIX, "/tmp/foo"};
     56 struct sockaddr_rc  local_addr_rc  = {AF_BLUETOOTH, *BDADDR_ANY, 4};
     57 struct sockaddr_sco local_addr_sco = {AF_BLUETOOTH, *BDADDR_LOCAL};
     58 struct sockaddr_l2  local_addr_l2  = {AF_BLUETOOTH, htobs(0x1001), *BDADDR_ANY, 0};
     59 struct sockaddr_in  local_addr_in  = {AF_INET, 9999, {0}, {0}};
     60 
     61 struct sockaddr_un  remote_addr_un  ;
     62 struct sockaddr_rc  remote_addr_rc  ;
     63 struct sockaddr_sco remote_addr_sco ;
     64 struct sockaddr_l2  remote_addr_l2  ;
     65 struct sockaddr_in  remote_addr_in  ;
     66 
     67 static int _socket(int type) {
     68     int ret;
     69     int family = -1;
     70     int typ = -1;
     71     int protocol = -1;
     72 
     73     switch (type) {
     74     case UNIX:
     75         family = PF_UNIX;
     76         typ = SOCK_STREAM;
     77         protocol = 0;
     78         break;
     79     case RFCOMM:
     80         family = PF_BLUETOOTH;
     81         typ = SOCK_STREAM;
     82         protocol = BTPROTO_RFCOMM;
     83         break;
     84     case SCO:
     85         family = PF_BLUETOOTH;
     86         typ = SOCK_SEQPACKET;
     87         protocol = BTPROTO_SCO;
     88         break;
     89     case L2CAP:
     90         family = PF_BLUETOOTH;
     91         typ = SOCK_SEQPACKET;
     92         protocol = BTPROTO_L2CAP;
     93         break;
     94     case TCP:
     95         family = PF_INET;
     96         typ = SOCK_STREAM;
     97         protocol = 0;
     98         break;
     99     }
    100 
    101     printf("%d: socket()\n", gettid());
    102     ret = socket(family, typ, protocol);
    103     printf("%d: socket() = %d\n", gettid(), ret);
    104     if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
    105 
    106     return ret;
    107 }
    108 
    109 static int _close(int fd) {
    110     int ret;
    111 
    112     printf("%d: close(%d)\n", gettid(), fd);
    113     ret = close(fd);
    114     printf("%d: close(%d) = %d\n", gettid(), fd, ret);
    115     if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
    116 
    117     return ret;
    118 }
    119 
    120 static int _bind(int fd, int type) {
    121     int len = 0;
    122     int ret;
    123     struct sockaddr *addr = NULL;
    124 
    125     switch (type) {
    126     case UNIX:
    127         unlink(local_addr_un.sun_path);
    128         addr = (struct sockaddr *) &local_addr_un;
    129         len = sizeof(local_addr_un);
    130         break;
    131     case RFCOMM:
    132         addr = (struct sockaddr *) &local_addr_rc;
    133         len = sizeof(local_addr_rc);
    134         break;
    135     case SCO:
    136         addr = (struct sockaddr *) &local_addr_sco;
    137         len = sizeof(local_addr_sco);
    138         break;
    139     case L2CAP:
    140         addr = (struct sockaddr *) &local_addr_l2;
    141         len = sizeof(local_addr_l2);
    142         break;
    143     case TCP:
    144         addr = (struct sockaddr *) &local_addr_in;
    145         len = sizeof(local_addr_in);
    146         break;
    147     }
    148 
    149     printf("%d: bind(%d)\n", gettid(), fd);
    150     ret = bind(fd, addr, len);
    151     printf("%d: bind(%d) = %d\n", gettid(), fd, ret);
    152     if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
    153 
    154     return ret;
    155 }
    156 
    157 static int _listen(int fd, int type) {
    158     int ret;
    159 
    160     printf("%d: listen(%d)\n", gettid(), fd);
    161     ret = listen(fd, 1);
    162     printf("%d: listen(%d) = %d\n", gettid(), fd, ret);
    163     if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
    164 
    165     return ret;
    166 }
    167 
    168 static int _accept(int fd, int type) {
    169     int ret;
    170     int len;
    171     struct sockaddr *addr = NULL;
    172 
    173     switch (type) {
    174     case UNIX:
    175         addr = (struct sockaddr *) &remote_addr_un;
    176         len = sizeof(remote_addr_un);
    177         break;
    178     case RFCOMM:
    179         addr = (struct sockaddr *) &remote_addr_rc;
    180         len = sizeof(remote_addr_rc);
    181         break;
    182     case SCO:
    183         addr = (struct sockaddr *) &remote_addr_sco;
    184         len = sizeof(remote_addr_sco);
    185         break;
    186     case L2CAP:
    187         addr = (struct sockaddr *) &remote_addr_l2;
    188         len = sizeof(remote_addr_l2);
    189         break;
    190     case TCP:
    191         addr = (struct sockaddr *) &remote_addr_in;
    192         len = sizeof(remote_addr_in);
    193         break;
    194     }
    195 
    196     printf("%d: accept(%d)\n", gettid(), fd);
    197     ret = accept(fd, addr, &len);
    198     printf("%d: accept(%d) = %d\n", gettid(), fd, ret);
    199     if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
    200     else {
    201         printf("\tlen = %d\n", len);
    202     }
    203 
    204     return ret;
    205 }
    206 
    207 static int _shutdown(int fd, int how) {
    208     int ret;
    209 
    210     printf("%d: shutdown(%d)\n", gettid(), fd);
    211     ret = shutdown(fd, how);
    212     printf("%d: shutdown(%d) = %d\n", gettid(), fd, ret);
    213     if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
    214 
    215     return ret;
    216 }
    217 
    218 static void thread_accept(struct thread_args *args) {
    219     printf("%d: START\n", gettid());
    220     sleep(args->delay);
    221     _accept(args->fd, args->type);
    222     printf("%d: END\n", gettid());
    223 }
    224 
    225 static int do_accept_shutdown(int type) {
    226     int fd;
    227     pthread_t thread;
    228     struct thread_args args = {-1, type, 0};
    229 
    230     fd = _socket(type);
    231     if (fd < 0) goto error;
    232 
    233     if (_bind(fd, type) < 0) goto error;
    234 
    235     if (_listen(fd, type) < 0) goto error;
    236 
    237     args.fd = fd;
    238     pthread_create(&thread, NULL, (void *)thread_accept, (void *)&args);
    239 
    240     sleep(2);
    241     _shutdown(fd, SHUT_RDWR);
    242 
    243     pthread_join(thread, NULL);
    244 
    245     _close(fd);
    246 
    247     return 0;
    248 
    249 error:
    250     return -1;
    251 }
    252 
    253 struct {
    254     char *name;
    255     int (*ptr)(int);
    256 } action_table[]  = {
    257     {"accept_shutdown", do_accept_shutdown},
    258     {NULL, NULL},
    259 };
    260 
    261 struct {
    262     char *name;
    263     enum sock_type type;
    264 } type_table[]  = {
    265     {"unix", UNIX},
    266     {"rfcomm", RFCOMM},
    267     {"sco", SCO},
    268     {"l2cap", L2CAP},
    269     {"tcp", TCP},
    270     {NULL, -1},
    271 };
    272 
    273 static void usage() {
    274     int i;
    275 
    276     printf("sock_shutdown_test TYPE ACTION\n");
    277     printf("\nTYPE:\n");
    278     for (i = 0; type_table[i].name; i++) {
    279         printf("\t%s\n", type_table[i].name);
    280     }
    281     printf("\nACTION:\n");
    282     for (i = 0; action_table[i].name; i++) {
    283         printf("\t%s\n", action_table[i].name);
    284     }
    285 }
    286 
    287 int main(int argc, char **argv) {
    288     int i;
    289     int type = -1;
    290 
    291     if (argc != 3) {
    292         usage();
    293         return -1;
    294     }
    295     for (i = 0; type_table[i].name; i++) {
    296         if (!strcmp(argv[1], type_table[i].name)) {
    297             type = type_table[i].type;
    298             break;
    299         }
    300     }
    301     if (type == -1) {
    302         usage();
    303         return -1;
    304     }
    305     for (i = 0; action_table[i].name; i++) {
    306         if (!strcmp(argv[2], action_table[i].name)) {
    307             printf("TYPE = %s ACTION = %s\n", type_table[type].name,
    308                     action_table[i].name);
    309             return (*action_table[i].ptr)(type);
    310         }
    311     }
    312     usage();
    313     return -1;
    314 }
    315