asocket_test.c revision 9baad993d9788e544c3a30fcc5dae23fe8b1d074
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
43enum sock_type {
44    UNIX = 0,
45    RFCOMM,
46    SCO,
47    L2CAP,
48    TCP,
49};
50
51struct thread_args {
52    int fd;
53    int type;
54    int delay;
55};
56
57struct sockaddr_un  local_addr_un  = {AF_UNIX, "/data/foo"};
58struct sockaddr_rc  local_addr_rc  = {AF_BLUETOOTH, *BDADDR_ANY, 4};
59struct sockaddr_sco local_addr_sco = {AF_BLUETOOTH, *BDADDR_LOCAL};
60struct sockaddr_l2  local_addr_l2  = {AF_BLUETOOTH, htobs(0x1001), *BDADDR_ANY, 0};
61struct sockaddr_in  local_addr_in  = {AF_INET, 9999, {0}, {0}};
62
63struct sockaddr_un  remote_addr_un  ;
64struct sockaddr_rc  remote_addr_rc  ;
65struct sockaddr_sco remote_addr_sco ;
66struct sockaddr_l2  remote_addr_l2  ;
67struct sockaddr_in  remote_addr_in  ;
68
69static 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
79static 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
85static 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
127static 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
138static 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
175static 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
186static 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
199static 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
238static 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
274static 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
286static 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
297static 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
317static 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
324static 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
334static 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
341static 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
351static 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
358static 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
365static 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
372static 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
381static 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
390static 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
398static 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
414error:
415    return -1;
416}
417
418static 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
439error:
440    return -1;
441}
442
443static 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
467error:
468    return -1;
469}
470
471static 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
491error:
492    return -1;
493}
494
495// accept in one thread. close then write in another
496static 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
517error:
518    return -1;
519}
520
521static 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
544static 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
565static 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
586static 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
609static 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
638error:
639    return -1;
640}
641
642// accept in one thread, connect from two different threads
643static 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
667error:
668    return -1;
669}
670
671struct {
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
689struct {
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
701static 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
715int 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