• 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