• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
_socket(int type)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 
_close(int fd)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 
_bind(int fd,int type)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 
_listen(int fd,int type)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 
_accept(int fd,int type)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 
_shutdown(int fd,int how)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 
thread_accept(struct thread_args * args)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 
do_accept_shutdown(int type)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 
usage()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 
main(int argc,char ** argv)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