sock_shutdown_test.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 SOCKETPAIR, 48}; 49 50static void print_events(int events) { 51 if (events & POLLIN) printf("POLLIN "); 52 if (events & POLLPRI) printf("POLLPRI "); 53 if (events & POLLOUT) printf("POLLOUT "); 54 if (events & POLLERR) printf("POLLERR "); 55 if (events & POLLHUP) printf("POLLHUP "); 56 if (events & POLLNVAL) printf("POLLNVAL "); 57 printf("\n"); 58} 59 60static void print_fds(struct pollfd *ufds, nfds_t nfds) { 61 unsigned int i; 62 for (i=0; i<nfds; i++) 63 printf("%d ", ufds[i].fd); 64} 65 66static int _socket(int type) { 67 int ret; 68 int family = -1; 69 int typ = -1; 70 int protocol = -1; 71 72 switch (type) { 73 case UNIX: 74 family = PF_UNIX; 75 typ = SOCK_STREAM; 76 protocol = 0; 77 break; 78 case RFCOMM: 79 family = PF_BLUETOOTH; 80 typ = SOCK_STREAM; 81 protocol = BTPROTO_RFCOMM; 82 break; 83 case SCO: 84 family = PF_BLUETOOTH; 85 typ = SOCK_SEQPACKET; 86 protocol = BTPROTO_SCO; 87 break; 88 case L2CAP: 89 family = PF_BLUETOOTH; 90 typ = SOCK_SEQPACKET; 91 protocol = BTPROTO_L2CAP; 92 break; 93 case TCP: 94 family = PF_INET; 95 typ = SOCK_STREAM; 96 protocol = 0; 97 break; 98 case SOCKETPAIR: 99 { 100 int fd[2]; 101 printf("%d: socketpair()\n", gettid()); 102 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); 103 printf("%d: socketpair() = %d\n", gettid(), ret); 104 if (ret) { 105 printf("\terr %d (%s)\n", errno, strerror(errno)); 106 return -1; 107 } 108 return fd[0]; 109 } 110 } 111 112 printf("%d: socket()\n", gettid()); 113 ret = socket(family, typ, protocol); 114 printf("%d: socket() = %d\n", gettid(), ret); 115 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 116 117 return ret; 118} 119 120static int _close(int fd) { 121 int ret; 122 123 printf("%d: close(%d)\n", gettid(), fd); 124 ret = close(fd); 125 printf("%d: close(%d) = %d\n", gettid(), fd, ret); 126 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 127 128 return ret; 129} 130 131static int _shutdown(int fd) { 132 int ret; 133 134 printf("%d: shutdown(%d)\n", gettid(), fd); 135 ret = shutdown(fd, SHUT_RDWR); 136 printf("%d: shutdown(%d) = %d\n", gettid(), fd, ret); 137 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 138 139 return ret; 140} 141 142static int _poll(struct pollfd *ufds, nfds_t nfds, int timeout) { 143 int ret; 144 unsigned int i; 145 146 printf("%d: poll(", gettid()); 147 print_fds(ufds, nfds); 148 printf(")\n"); 149 ret = poll(ufds, nfds, timeout); 150 printf("%d: poll() = %d\n", gettid(), ret); 151 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 152 if (ret > 0) { 153 for (i=0; i<nfds; i++) { 154 if (ufds[i].revents) { 155 printf("\tfd %d ", ufds[i].fd); print_events(ufds[i].revents); 156 } 157 } 158 } 159 return ret; 160} 161 162static void thread_poll(int fd) { 163 struct pollfd pfd; 164 printf("%d: START\n", gettid()); 165 pfd.fd = fd; 166 pfd.events = 0; 167 _poll(&pfd, 1, -1); 168 printf("%d: END\n", gettid()); 169} 170 171static int do_poll_shutdown(int type) { 172 const int MAX_T = 2; 173 int fd; 174 pthread_t t[MAX_T]; 175 int i; 176 177 fd = _socket(type); 178 179 for (i=0; i<MAX_T; i++) 180 pthread_create(&t[i], NULL, (void *)thread_poll, (void *)fd); 181 182 sleep(1); 183 184 _shutdown(fd); 185 186 for (i=0; i<MAX_T; i++) 187 pthread_join(t[i], NULL); 188 189 _close(fd); 190 191 return 0; 192} 193 194struct { 195 char *name; 196 enum sock_type type; 197} type_table[] = { 198 {"unix", UNIX}, 199 {"rfcomm", RFCOMM}, 200 {"sco", SCO}, 201 {"l2cap", L2CAP}, 202 {"tcp", TCP}, 203 {"socketpair", SOCKETPAIR}, 204 {NULL, -1}, 205}; 206 207static void usage() { 208 int i; 209 210 printf("sock_shutdown_test TYPE\n"); 211 printf("\nTYPE:\n"); 212 for (i = 0; type_table[i].name; i++) { 213 printf("\t%s\n", type_table[i].name); 214 } 215} 216 217int main(int argc, char **argv) { 218 int i; 219 int type = -1; 220 221 if (argc != 2) { 222 usage(); 223 return -1; 224 } 225 for (i = 0; type_table[i].name; i++) { 226 if (!strcmp(argv[1], type_table[i].name)) { 227 type = type_table[i].type; 228 printf("TYPE = %s\n", type_table[type].name); 229 return do_poll_shutdown(type); 230 } 231 } 232 usage(); 233 return -1; 234} 235