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