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