diff options
author | Nick Pelly <npelly@google.com> | 2009-06-22 18:05:20 -0700 |
---|---|---|
committer | Nick Pelly <npelly@google.com> | 2009-06-22 18:05:20 -0700 |
commit | 9baad993d9788e544c3a30fcc5dae23fe8b1d074 (patch) | |
tree | f0f24c97f44af3e053bd14b55b1a363812ab1792 | |
parent | e9e80e66c601bbe1e4d8b1039f37f08683f65211 (diff) | |
download | bluetooth-9baad993d9788e544c3a30fcc5dae23fe8b1d074.tar.gz |
Checkpoint some debug tools. Not built by default.
-rw-r--r-- | tools/Android.mk | 23 | ||||
-rw-r--r-- | tools/asocket_test.c | 742 | ||||
-rw-r--r-- | tools/sock_shutdown_test.c | 226 | ||||
-rw-r--r-- | tools/socktest.c | 156 |
4 files changed, 1024 insertions, 123 deletions
diff --git a/tools/Android.mk b/tools/Android.mk index bed6f5b..4d2cf10 100644 --- a/tools/Android.mk +++ b/tools/Android.mk @@ -1,3 +1,5 @@ +BUILD_EXTRA_BT_TOOLS:=false + LOCAL_PATH:= $(call my-dir) # @@ -18,8 +20,6 @@ LOCAL_MODULE := bttest include $(BUILD_EXECUTABLE) -BUILD_EXTRA_BT_TOOLS:=false - ifeq ($(BUILD_EXTRA_BT_TOOLS),true) # @@ -43,6 +43,25 @@ LOCAL_MODULE := socktest include $(BUILD_EXECUTABLE) # +# asocket_test +# + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := asocket_test.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../bluez-clean-headers + +LOCAL_SHARED_LIBRARIES := libcutils + +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE := asocket_test + +include $(BUILD_EXECUTABLE) + +# # sock_shutdown_test # diff --git a/tools/asocket_test.c b/tools/asocket_test.c new file mode 100644 index 0000000..0c00526 --- /dev/null +++ b/tools/asocket_test.c @@ -0,0 +1,742 @@ +/* +** Copyright 2009 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/** socket testing */ + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <sys/uio.h> +#include <unistd.h> + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/poll.h> +#include <sys/un.h> +#include <netinet/in.h> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/rfcomm.h> +#include <bluetooth/sco.h> +#include <bluetooth/l2cap.h> + +#include "cutils/abort_socket.h" + +enum sock_type { + UNIX = 0, + RFCOMM, + SCO, + L2CAP, + TCP, +}; + +struct thread_args { + int fd; + int type; + int delay; +}; + +struct sockaddr_un local_addr_un = {AF_UNIX, "/data/foo"}; +struct sockaddr_rc local_addr_rc = {AF_BLUETOOTH, *BDADDR_ANY, 4}; +struct sockaddr_sco local_addr_sco = {AF_BLUETOOTH, *BDADDR_LOCAL}; +struct sockaddr_l2 local_addr_l2 = {AF_BLUETOOTH, htobs(0x1001), *BDADDR_ANY, 0}; +struct sockaddr_in local_addr_in = {AF_INET, 9999, {0}, {0}}; + +struct sockaddr_un remote_addr_un ; +struct sockaddr_rc remote_addr_rc ; +struct sockaddr_sco remote_addr_sco ; +struct sockaddr_l2 remote_addr_l2 ; +struct sockaddr_in remote_addr_in ; + +static void print_events(int events) { + if (events & POLLIN) printf("POLLIN "); + if (events & POLLPRI) printf("POLLPRI "); + if (events & POLLOUT) printf("POLLOUT "); + if (events & POLLERR) printf("POLLERR "); + if (events & POLLHUP) printf("POLLHUP "); + if (events & POLLNVAL) printf("POLLNVAL "); + printf("\n"); +} + +static void print_fds(struct pollfd *ufds, nfds_t nfds) { + unsigned int i; + for (i=0; i<nfds; i++) + printf("%d ", ufds[i].fd); +} + +static int _socket(int type) { + int ret; + int family = -1; + int typ = -1; + int protocol = -1; + + switch (type) { + case UNIX: + family = PF_UNIX; + typ = SOCK_STREAM; + protocol = 0; + break; + case RFCOMM: + family = PF_BLUETOOTH; + typ = SOCK_STREAM; + protocol = BTPROTO_RFCOMM; + break; + case SCO: + family = PF_BLUETOOTH; + typ = SOCK_SEQPACKET; + protocol = BTPROTO_SCO; + break; + case L2CAP: + family = PF_BLUETOOTH; + typ = SOCK_SEQPACKET; + protocol = BTPROTO_L2CAP; + break; + case TCP: + family = PF_INET; + typ = SOCK_STREAM; + protocol = 0; + break; + } + + printf("%d: socket()\n", gettid()); + ret = socket(family, typ, protocol); + printf("%d: socket() = %d\n", gettid(), ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + + return ret; +} + +static int _close(int fd, int type) { + int ret; + + printf("%d: close(%d)\n", gettid(), fd); + ret = close(fd); + printf("%d: close(%d) = %d\n", gettid(), fd, ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + + return ret; +} + +static int _bind(int fd, int type) { + int len = 0; + int ret; + struct sockaddr *addr = NULL; + + switch (type) { + case UNIX: + unlink(local_addr_un.sun_path); + addr = (struct sockaddr *) &local_addr_un; + len = sizeof(local_addr_un); + break; + case RFCOMM: + addr = (struct sockaddr *) &local_addr_rc; + len = sizeof(local_addr_rc); + break; + case SCO: + addr = (struct sockaddr *) &local_addr_sco; + len = sizeof(local_addr_sco); + break; + case L2CAP: + addr = (struct sockaddr *) &local_addr_l2; + len = sizeof(local_addr_l2); + break; + case TCP: + addr = (struct sockaddr *) &local_addr_in; + len = sizeof(local_addr_in); + break; + } + + printf("%d: bind(%d)\n", gettid(), fd); + ret = bind(fd, addr, len); + printf("%d: bind(%d) = %d\n", gettid(), fd, ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + + return ret; +} + +static int _listen(int fd, int type) { + int ret; + + printf("%d: listen(%d)\n", gettid(), fd); + ret = listen(fd, 1); + printf("%d: listen(%d) = %d\n", gettid(), fd, ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + + return ret; +} + +static int _read(int fd) { + int ret; + char buf; + + printf("%d: read(%d)\n", gettid(), fd); + ret = read(fd, &buf, 1); + printf("%d: read(%d) = %d [%d]\n", gettid(), fd, ret, (int)buf); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + + return ret; +} + + +static int _accept(int fd, int type) { + int ret; + int len; + struct sockaddr *addr = NULL; + + switch (type) { + case UNIX: + addr = (struct sockaddr *) &remote_addr_un; + len = sizeof(remote_addr_un); + break; + case RFCOMM: + addr = (struct sockaddr *) &remote_addr_rc; + len = sizeof(remote_addr_rc); + break; + case SCO: + addr = (struct sockaddr *) &remote_addr_sco; + len = sizeof(remote_addr_sco); + break; + case L2CAP: + addr = (struct sockaddr *) &remote_addr_l2; + len = sizeof(remote_addr_l2); + break; + case TCP: + addr = (struct sockaddr *) &remote_addr_in; + len = sizeof(remote_addr_in); + break; + } + + printf("%d: accept(%d)\n", gettid(), fd); + ret = accept(fd, addr, &len); + printf("%d: accept(%d) = %d\n", gettid(), fd, ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + else { + printf("\tlen = %d\n", len); + } + + return ret; +} + +static int _connect(int fd, int type) { + int ret; + int len = 0; + struct sockaddr *addr = NULL; + + switch (type) { + case UNIX: + addr = (struct sockaddr *) &local_addr_un; + len = sizeof(local_addr_un); + break; + case RFCOMM: + addr = (struct sockaddr *) &local_addr_rc; + len = sizeof(local_addr_rc); + break; + case SCO: + addr = (struct sockaddr *) &local_addr_sco; + len = sizeof(local_addr_sco); + break; + case L2CAP: + addr = (struct sockaddr *) &local_addr_l2; + len = sizeof(local_addr_l2); + break; + case TCP: + addr = (struct sockaddr *) &local_addr_in; + len = sizeof(local_addr_in); + break; + } + + printf("%d: connect(%d)\n", gettid(), fd); + ret = connect(fd, addr, len); + printf("%d: connect(%d) = %d\n", gettid(), fd, ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + + return ret; +} + +static int _write(int fd, int type) { + int ret; + char buf = 69; + + printf("%d: write(%d)\n", gettid(), fd); + ret = write(fd, &buf, 1); + printf("%d: write(%d) = %d\n", gettid(), fd, ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + + return ret; +} + +static int _shutdown(int fd, int how) { + int ret; + + printf("%d: shutdown(%d)\n", gettid(), fd); + ret = shutdown(fd, how); + printf("%d: shutdown(%d) = %d\n", gettid(), fd, ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + + return ret; +} + +static int _poll(struct pollfd *ufds, nfds_t nfds, int timeout) { + int ret; + unsigned int i; + + printf("%d: poll(", gettid()); + print_fds(ufds, nfds); + printf(")\n"); + ret = poll(ufds, nfds, timeout); + printf("%d: poll() = %d\n", gettid(), ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + if (ret > 0) { + for (i=0; i<nfds; i++) { + if (ufds[i].revents) { + printf("\tfd %d ", ufds[i].fd); print_events(ufds[i].revents); + } + } + } + return ret; +} + +static void thread_delay_close(struct thread_args *args) { + printf("%d: START\n", gettid()); + sleep(args->delay); + _close(args->fd, args->type); + printf("%d: END\n", gettid()); +} + +static void thread_poll(void *args) { + int fd = (int)args; + struct pollfd pfd; + printf("%d: START\n", gettid()); + pfd.fd = fd; + pfd.events = 0; + _poll(&pfd, 1, -1); + printf("%d: END\n", gettid()); +} + +static void thread_read(void *args) { + int fd = (int)args; + printf("%d: START\n", gettid()); + _read(fd); + printf("%d: END\n", gettid()); +} + +static void thread_pollin(void *args) { + int fd = (int)args; + struct pollfd pfd; + printf("%d: START\n", gettid()); + pfd.fd = fd; + pfd.events = POLLIN; + _poll(&pfd, 1, -1); + printf("%d: END\n", gettid()); +} + +static void thread_shutdown(int fd) { + printf("%d: START\n", gettid()); + sleep(4); + _shutdown(fd, SHUT_RDWR); + printf("%d: END\n", gettid()); +} + +static void thread_accept(struct thread_args *args) { + printf("%d: START\n", gettid()); + sleep(args->delay); + _accept(args->fd, args->type); + printf("%d: END\n", gettid()); +} + +static void thread_connect(struct thread_args *args) { + printf("%d: START\n", gettid()); + sleep(args->delay); + _connect(args->fd, args->type); + printf("%d: END\n", gettid()); +} + +static void thread_delay_close_write(struct thread_args *args) { + printf("%d: START\n", gettid()); + sleep(args->delay); + _close(args->fd, args->type); + sleep(args->delay); + _write(args->fd, args->type); + printf("%d: END\n", gettid()); +} + +static void thread_accept_write(struct thread_args *args) { + printf("%d: START\n", gettid()); + sleep(args->delay); + _accept(args->fd, args->type); + sleep(args->delay); + _write(args->fd, args->type); + printf("%d: END\n", gettid()); +} + +static void thread_delay_connect(struct thread_args *args) { + printf("%d: START\n", gettid()); + sleep(args->delay); + args->fd = _socket(args->type); + _connect(args->fd, args->type); + printf("%d: END\n", gettid()); +} + +static int do_accept_accept_accept(int type) { + int fd; + + fd = _socket(type); + if (fd < 0) goto error; + + if (_bind(fd, type) < 0) goto error; + + if (_listen(fd, type) < 0) goto error; + + while (1) { + _accept(fd, type); + } + + return 0; + +error: + return -1; +} + +static int do_accept_and_close(int type) { + int fd; + pthread_t thread; + struct thread_args args = {-1, type, 1}; + + fd = _socket(type); + if (fd < 0) goto error; + + if (_bind(fd, type) < 0) goto error; + + if (_listen(fd, type) < 0) goto error; + + args.fd = fd; + pthread_create(&thread, NULL, (void *)thread_delay_close, (void *)&args); + + _accept(fd, type); + + pthread_join(thread, NULL); + + return 0; + +error: + return -1; +} + +static int do_accept_shutdown(int type) { + int fd; + pthread_t thread; + struct thread_args args = {-1, type, 0}; + + fd = _socket(type); + if (fd < 0) goto error; + + if (_bind(fd, type) < 0) goto error; + + if (_listen(fd, type) < 0) goto error; + + args.fd = fd; + pthread_create(&thread, NULL, (void *)thread_accept, (void *)&args); + + sleep(4); + _shutdown(fd, SHUT_RDWR); + + pthread_join(thread, NULL); + + _close(fd, type); + + return 0; + +error: + return -1; +} + +static int do_connect_shutdown(int type) { + int fd; + pthread_t thread; + struct thread_args args = {-1, type, 0}; + + fd = _socket(type); + if (fd < 0) goto error; + + args.fd = fd; + pthread_create(&thread, NULL, (void *)thread_connect, (void *)&args); + + sleep(4); + _shutdown(fd, SHUT_RDWR); + + pthread_join(thread, NULL); + + _close(fd, type); + + return 0; + +error: + return -1; +} + +// accept in one thread. close then write in another +static int do_accept_close_write(int type) { + int fd; + pthread_t thread; + struct thread_args args = {-1, type, 1}; + + fd = _socket(type); + if (fd < 0) goto error; + + if (_bind(fd, type) < 0) goto error; + + if (_listen(fd, type) < 0) goto error; + + args.fd = fd; + pthread_create(&thread, NULL, (void *)thread_delay_close_write, (void *)&args); + + _accept(fd, type); + + pthread_join(thread, NULL); + + return 0; + +error: + return -1; +} + +static int do_poll_poll_poll_shutdown(int type) { + const int MAX_T = 32; + int fd; + pthread_t t[MAX_T]; + int i; + + fd = _socket(type); + + for (i=0; i<MAX_T; i++) + pthread_create(&t[i], NULL, (void *)thread_poll, (void *)fd); + + sleep(1); + + _shutdown(fd, SHUT_RDWR); + + for (i=0; i<MAX_T; i++) + pthread_join(t[i], NULL); + + _close(fd, type); + + return 0; +} + +static int do_poll_poll_poll_close(int type) { + const int MAX_T = 32; + int fd; + pthread_t t[MAX_T]; + int i; + + fd = _socket(type); + + for (i=0; i<MAX_T; i++) + pthread_create(&t[i], NULL, (void *)thread_poll, (void *)fd); + + sleep(1); + + _close(fd, type); + + for (i=0; i<MAX_T; i++) + pthread_join(t[i], NULL); + + return 0; +} + +static int do_read_read_read_close(int type) { + const int MAX_T = 32; + int fd; + pthread_t t[MAX_T]; + int i; + + fd = _socket(type); + + for (i=0; i<MAX_T; i++) + pthread_create(&t[i], NULL, (void *)thread_read, (void *)fd); + + sleep(1); + + _close(fd, type); + + for (i=0; i<MAX_T; i++) + pthread_join(t[i], NULL); + + return 0; +} + +static int do_read_read_read_shutdown(int type) { + const int MAX_T = 32; + int fd; + pthread_t t[MAX_T]; + int i; + + fd = _socket(type); + + for (i=0; i<MAX_T; i++) + pthread_create(&t[i], NULL, (void *)thread_read, (void *)fd); + + sleep(1); + + _shutdown(fd, SHUT_RDWR); + + for (i=0; i<MAX_T; i++) + pthread_join(t[i], NULL); + + _close(fd, type); + + return 0; +} + +static int do_connected_read1_shutdown1(int type) { + int fd1, fd2; + pthread_t t1; + pthread_t t2; + struct thread_args a1 = {-1, type, 0}; + struct thread_args a2 = {-1, type, 2}; + + fd1 = _socket(type); + if (fd1 < 0) goto error; + + if (_bind(fd1, type) < 0) goto error; + + if (_listen(fd1, type) < 0) goto error; + + a1.fd = fd1; + pthread_create(&t1, NULL, (void *)thread_accept_write, (void *)&a1); + + fd2 = _socket(type); + if (_connect(fd2, type)) goto error; + + pthread_create(&t2, NULL, (void *)thread_shutdown, (void *)&fd2); + + while (1) if (_read(fd2)) break; + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; + +error: + return -1; +} + +// accept in one thread, connect from two different threads +static int do_accept_connect_connect(int type) { + int fd; + pthread_t t1; + pthread_t t2; + struct thread_args a1 = {-1, type, 1}; + struct thread_args a2 = {-1, type, 2}; + + fd = _socket(type); + if (fd < 0) goto error; + + if (_bind(fd, type) < 0) goto error; + + if (_listen(fd, type) < 0) goto error; + + pthread_create(&t1, NULL, (void *)thread_delay_connect, (void *)&a1); + pthread_create(&t2, NULL, (void *)thread_delay_connect, (void *)&a2); + + _accept(fd, type); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; + +error: + return -1; +} + +struct { + char *name; + int (*ptr)(int); +} action_table[] = { + {"accept_accept_accept", do_accept_accept_accept}, + {"accept_and_close", do_accept_and_close}, + {"accept_shutdown", do_accept_shutdown}, + {"connect_shutdown", do_connect_shutdown}, + {"accept_close_write", do_accept_close_write}, + {"accept_connect_connect", do_accept_connect_connect}, + {"poll_poll_poll_shutdown", do_poll_poll_poll_shutdown}, + {"poll_poll_poll_close", do_poll_poll_poll_close}, + {"read_read_read_shutdown", do_read_read_read_shutdown}, + {"read_read_read_close", do_read_read_read_close}, + {"connected_read1_shutdown1", do_connected_read1_shutdown1}, + {NULL, NULL}, +}; + +struct { + char *name; + enum sock_type type; +} type_table[] = { + {"unix", UNIX}, + {"rfcomm", RFCOMM}, + {"sco", SCO}, + {"l2cap", L2CAP}, + {"tcp", TCP}, + {NULL, -1}, +}; + +static void usage() { + int i; + + printf("socktest TYPE ACTION\n"); + printf("\nTYPE:\n"); + for (i = 0; type_table[i].name; i++) { + printf("\t%s\n", type_table[i].name); + } + printf("\nACTION:\n"); + for (i = 0; action_table[i].name; i++) { + printf("\t%s\n", action_table[i].name); + } +} + +int main(int argc, char **argv) { + int i; + int type = -1; + + if (argc != 3) { + usage(); + return -1; + } + for (i = 0; type_table[i].name; i++) { + if (!strcmp(argv[1], type_table[i].name)) { + type = type_table[i].type; + break; + } + } + if (type == -1) { + usage(); + return -1; + } + for (i = 0; action_table[i].name; i++) { + if (!strcmp(argv[2], action_table[i].name)) { + printf("TYPE = %s ACTION = %s\n", type_table[type].name, + action_table[i].name); + return (*action_table[i].ptr)(type); + } + } + usage(); + return -1; +} diff --git a/tools/sock_shutdown_test.c b/tools/sock_shutdown_test.c index 4febc46..fbf89bf 100644 --- a/tools/sock_shutdown_test.c +++ b/tools/sock_shutdown_test.c @@ -1,20 +1,4 @@ -/* -** Copyright 2009 The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -/** socket testing */ +/** testing behavior of shutdown() */ #include <stdlib.h> #include <stdio.h> @@ -44,24 +28,25 @@ enum sock_type { SCO, L2CAP, TCP, - SOCKETPAIR, }; -static void print_events(int events) { - if (events & POLLIN) printf("POLLIN "); - if (events & POLLPRI) printf("POLLPRI "); - if (events & POLLOUT) printf("POLLOUT "); - if (events & POLLERR) printf("POLLERR "); - if (events & POLLHUP) printf("POLLHUP "); - if (events & POLLNVAL) printf("POLLNVAL "); - printf("\n"); -} +struct thread_args { + int fd; + int type; + int delay; +}; -static void print_fds(struct pollfd *ufds, nfds_t nfds) { - unsigned int i; - for (i=0; i<nfds; i++) - printf("%d ", ufds[i].fd); -} +struct sockaddr_un local_addr_un = {AF_UNIX, "/tmp/foo"}; +struct sockaddr_rc local_addr_rc = {AF_BLUETOOTH, *BDADDR_ANY, 4}; +struct sockaddr_sco local_addr_sco = {AF_BLUETOOTH, *BDADDR_LOCAL}; +struct sockaddr_l2 local_addr_l2 = {AF_BLUETOOTH, htobs(0x1001), *BDADDR_ANY, 0}; +struct sockaddr_in local_addr_in = {AF_INET, 9999, {0}, {0}}; + +struct sockaddr_un remote_addr_un ; +struct sockaddr_rc remote_addr_rc ; +struct sockaddr_sco remote_addr_sco ; +struct sockaddr_l2 remote_addr_l2 ; +struct sockaddr_in remote_addr_in ; static int _socket(int type) { int ret; @@ -95,18 +80,6 @@ static int _socket(int type) { typ = SOCK_STREAM; protocol = 0; break; - case SOCKETPAIR: - { - int fd[2]; - printf("%d: socketpair()\n", gettid()); - ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); - printf("%d: socketpair() = %d\n", gettid(), ret); - if (ret) { - printf("\terr %d (%s)\n", errno, strerror(errno)); - return -1; - } - return fd[0]; - } } printf("%d: socket()\n", gettid()); @@ -128,71 +101,149 @@ static int _close(int fd) { return ret; } -static int _shutdown(int fd) { +static int _bind(int fd, int type) { + int len = 0; int ret; + struct sockaddr *addr = NULL; - printf("%d: shutdown(%d)\n", gettid(), fd); - ret = shutdown(fd, SHUT_RDWR); - printf("%d: shutdown(%d) = %d\n", gettid(), fd, ret); + switch (type) { + case UNIX: + unlink(local_addr_un.sun_path); + addr = (struct sockaddr *) &local_addr_un; + len = sizeof(local_addr_un); + break; + case RFCOMM: + addr = (struct sockaddr *) &local_addr_rc; + len = sizeof(local_addr_rc); + break; + case SCO: + addr = (struct sockaddr *) &local_addr_sco; + len = sizeof(local_addr_sco); + break; + case L2CAP: + addr = (struct sockaddr *) &local_addr_l2; + len = sizeof(local_addr_l2); + break; + case TCP: + addr = (struct sockaddr *) &local_addr_in; + len = sizeof(local_addr_in); + break; + } + + printf("%d: bind(%d)\n", gettid(), fd); + ret = bind(fd, addr, len); + printf("%d: bind(%d) = %d\n", gettid(), fd, ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); return ret; } -static int _poll(struct pollfd *ufds, nfds_t nfds, int timeout) { +static int _listen(int fd, int type) { int ret; - unsigned int i; - printf("%d: poll(", gettid()); - print_fds(ufds, nfds); - printf(")\n"); - ret = poll(ufds, nfds, timeout); - printf("%d: poll() = %d\n", gettid(), ret); + printf("%d: listen(%d)\n", gettid(), fd); + ret = listen(fd, 1); + printf("%d: listen(%d) = %d\n", gettid(), fd, ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); - if (ret > 0) { - for (i=0; i<nfds; i++) { - if (ufds[i].revents) { - printf("\tfd %d ", ufds[i].fd); print_events(ufds[i].revents); - } - } + + return ret; +} + +static int _accept(int fd, int type) { + int ret; + int len; + struct sockaddr *addr = NULL; + + switch (type) { + case UNIX: + addr = (struct sockaddr *) &remote_addr_un; + len = sizeof(remote_addr_un); + break; + case RFCOMM: + addr = (struct sockaddr *) &remote_addr_rc; + len = sizeof(remote_addr_rc); + break; + case SCO: + addr = (struct sockaddr *) &remote_addr_sco; + len = sizeof(remote_addr_sco); + break; + case L2CAP: + addr = (struct sockaddr *) &remote_addr_l2; + len = sizeof(remote_addr_l2); + break; + case TCP: + addr = (struct sockaddr *) &remote_addr_in; + len = sizeof(remote_addr_in); + break; + } + + printf("%d: accept(%d)\n", gettid(), fd); + ret = accept(fd, addr, &len); + printf("%d: accept(%d) = %d\n", gettid(), fd, ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + else { + printf("\tlen = %d\n", len); } + return ret; } -static void thread_poll(int fd) { - struct pollfd pfd; +static int _shutdown(int fd, int how) { + int ret; + + printf("%d: shutdown(%d)\n", gettid(), fd); + ret = shutdown(fd, how); + printf("%d: shutdown(%d) = %d\n", gettid(), fd, ret); + if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); + + return ret; +} + +static void thread_accept(struct thread_args *args) { printf("%d: START\n", gettid()); - pfd.fd = fd; - pfd.events = 0; - _poll(&pfd, 1, -1); + sleep(args->delay); + _accept(args->fd, args->type); printf("%d: END\n", gettid()); } -static int do_poll_shutdown(int type) { - const int MAX_T = 2; +static int do_accept_shutdown(int type) { int fd; - pthread_t t[MAX_T]; - int i; + pthread_t thread; + struct thread_args args = {-1, type, 0}; fd = _socket(type); + if (fd < 0) goto error; + + if (_bind(fd, type) < 0) goto error; - for (i=0; i<MAX_T; i++) - pthread_create(&t[i], NULL, (void *)thread_poll, (void *)fd); + if (_listen(fd, type) < 0) goto error; - sleep(1); + args.fd = fd; + pthread_create(&thread, NULL, (void *)thread_accept, (void *)&args); - _shutdown(fd); + sleep(2); + _shutdown(fd, SHUT_RDWR); - for (i=0; i<MAX_T; i++) - pthread_join(t[i], NULL); + pthread_join(thread, NULL); _close(fd); return 0; + +error: + return -1; } struct { char *name; + int (*ptr)(int); +} action_table[] = { + {"accept_shutdown", do_accept_shutdown}, + {NULL, NULL}, +}; + +struct { + char *name; enum sock_type type; } type_table[] = { {"unix", UNIX}, @@ -200,33 +251,46 @@ struct { {"sco", SCO}, {"l2cap", L2CAP}, {"tcp", TCP}, - {"socketpair", SOCKETPAIR}, {NULL, -1}, }; static void usage() { int i; - printf("sock_shutdown_test TYPE\n"); + printf("sock_shutdown_test TYPE ACTION\n"); printf("\nTYPE:\n"); for (i = 0; type_table[i].name; i++) { printf("\t%s\n", type_table[i].name); } + printf("\nACTION:\n"); + for (i = 0; action_table[i].name; i++) { + printf("\t%s\n", action_table[i].name); + } } int main(int argc, char **argv) { int i; int type = -1; - if (argc != 2) { + if (argc != 3) { usage(); return -1; } for (i = 0; type_table[i].name; i++) { if (!strcmp(argv[1], type_table[i].name)) { type = type_table[i].type; - printf("TYPE = %s\n", type_table[type].name); - return do_poll_shutdown(type); + break; + } + } + if (type == -1) { + usage(); + return -1; + } + for (i = 0; action_table[i].name; i++) { + if (!strcmp(argv[2], action_table[i].name)) { + printf("TYPE = %s ACTION = %s\n", type_table[type].name, + action_table[i].name); + return (*action_table[i].ptr)(type); } } usage(); diff --git a/tools/socktest.c b/tools/socktest.c index 7a4c272..b0c45c5 100644 --- a/tools/socktest.c +++ b/tools/socktest.c @@ -22,6 +22,7 @@ #include <sys/uio.h> #include <unistd.h> +#include <fcntl.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> @@ -114,9 +115,9 @@ static int _socket(int type) { break; } - printf("%d: socket()\n", gettid()); + printf("%ld: socket()\n", pthread_self()); ret = socket(family, typ, protocol); - printf("%d: socket() = %d\n", gettid(), ret); + printf("%ld: socket() = %d\n", pthread_self(), ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); return ret; @@ -125,9 +126,9 @@ static int _socket(int type) { static int _close(int fd, int type) { int ret; - printf("%d: close(%d)\n", gettid(), fd); + printf("%ld: close(%d)\n", pthread_self(), fd); ret = close(fd); - printf("%d: close(%d) = %d\n", gettid(), fd, ret); + printf("%ld: close(%d) = %d\n", pthread_self(), fd, ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); return ret; @@ -162,9 +163,9 @@ static int _bind(int fd, int type) { break; } - printf("%d: bind(%d)\n", gettid(), fd); + printf("%ld: bind(%d)\n", pthread_self(), fd); ret = bind(fd, addr, len); - printf("%d: bind(%d) = %d\n", gettid(), fd, ret); + printf("%ld: bind(%d) = %d\n", pthread_self(), fd, ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); return ret; @@ -173,9 +174,9 @@ static int _bind(int fd, int type) { static int _listen(int fd, int type) { int ret; - printf("%d: listen(%d)\n", gettid(), fd); + printf("%ld: listen(%d)\n", pthread_self(), fd); ret = listen(fd, 1); - printf("%d: listen(%d) = %d\n", gettid(), fd, ret); + printf("%ld: listen(%d) = %d\n", pthread_self(), fd, ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); return ret; @@ -185,9 +186,9 @@ static int _read(int fd) { int ret; char buf; - printf("%d: read(%d)\n", gettid(), fd); + printf("%ld: read(%d)\n", pthread_self(), fd); ret = read(fd, &buf, 1); - printf("%d: read(%d) = %d [%d]\n", gettid(), fd, ret, (int)buf); + printf("%ld: read(%d) = %d [%d]\n", pthread_self(), fd, ret, (int)buf); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); return ret; @@ -222,9 +223,9 @@ static int _accept(int fd, int type) { break; } - printf("%d: accept(%d)\n", gettid(), fd); + printf("%ld: accept(%d)\n", pthread_self(), fd); ret = accept(fd, addr, &len); - printf("%d: accept(%d) = %d\n", gettid(), fd, ret); + printf("%ld: accept(%d) = %d\n", pthread_self(), fd, ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); else { printf("\tlen = %d\n", len); @@ -233,6 +234,20 @@ static int _accept(int fd, int type) { return ret; } +int get_bdaddr(const char *str, bdaddr_t *ba) { + char *d = ((char *)ba) + 5, *endp; + int i; + for(i = 0; i < 6; i++) { + *d-- = strtol(str, &endp, 16); + if (*endp != ':' && i != 5) { + memset(ba, 0, sizeof(bdaddr_t)); + return -1; + } + str = endp + 1; + } + return 0; +} + static int _connect(int fd, int type) { int ret; int len = 0; @@ -244,6 +259,7 @@ static int _connect(int fd, int type) { len = sizeof(local_addr_un); break; case RFCOMM: + get_bdaddr("00:11:22:33:44:55", &local_addr_rc.rc_bdaddr); addr = (struct sockaddr *) &local_addr_rc; len = sizeof(local_addr_rc); break; @@ -261,9 +277,9 @@ static int _connect(int fd, int type) { break; } - printf("%d: connect(%d)\n", gettid(), fd); + printf("%ld: connect(%d)\n", pthread_self(), fd); ret = connect(fd, addr, len); - printf("%d: connect(%d) = %d\n", gettid(), fd, ret); + printf("%ld: connect(%d) = %d\n", pthread_self(), fd, ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); return ret; @@ -273,9 +289,9 @@ static int _write(int fd, int type) { int ret; char buf = 69; - printf("%d: write(%d)\n", gettid(), fd); + printf("%ld: write(%d)\n", pthread_self(), fd); ret = write(fd, &buf, 1); - printf("%d: write(%d) = %d\n", gettid(), fd, ret); + printf("%ld: write(%d) = %d\n", pthread_self(), fd, ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); return ret; @@ -284,9 +300,9 @@ static int _write(int fd, int type) { static int _shutdown(int fd, int how) { int ret; - printf("%d: shutdown(%d)\n", gettid(), fd); + printf("%ld: shutdown(%d)\n", pthread_self(), fd); ret = shutdown(fd, how); - printf("%d: shutdown(%d) = %d\n", gettid(), fd, ret); + printf("%ld: shutdown(%d) = %d\n", pthread_self(), fd, ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); return ret; @@ -296,11 +312,11 @@ static int _poll(struct pollfd *ufds, nfds_t nfds, int timeout) { int ret; unsigned int i; - printf("%d: poll(", gettid()); + printf("%ld: poll(", pthread_self()); print_fds(ufds, nfds); printf(")\n"); ret = poll(ufds, nfds, timeout); - printf("%d: poll() = %d\n", gettid(), ret); + printf("%ld: poll() = %d\n", pthread_self(), ret); if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); if (ret > 0) { for (i=0; i<nfds; i++) { @@ -313,84 +329,84 @@ static int _poll(struct pollfd *ufds, nfds_t nfds, int timeout) { } static void thread_delay_close(struct thread_args *args) { - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); sleep(args->delay); _close(args->fd, args->type); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static void thread_poll(void *args) { int fd = (int)args; struct pollfd pfd; - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); pfd.fd = fd; pfd.events = 0; _poll(&pfd, 1, -1); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static void thread_read(void *args) { int fd = (int)args; - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); _read(fd); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static void thread_pollin(void *args) { int fd = (int)args; struct pollfd pfd; - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); pfd.fd = fd; pfd.events = POLLIN; _poll(&pfd, 1, -1); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static void thread_shutdown(int fd) { - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); sleep(4); _shutdown(fd, SHUT_RDWR); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static void thread_accept(struct thread_args *args) { - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); sleep(args->delay); _accept(args->fd, args->type); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static void thread_connect(struct thread_args *args) { - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); sleep(args->delay); _connect(args->fd, args->type); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static void thread_delay_close_write(struct thread_args *args) { - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); sleep(args->delay); _close(args->fd, args->type); sleep(args->delay); _write(args->fd, args->type); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static void thread_accept_write(struct thread_args *args) { - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); sleep(args->delay); _accept(args->fd, args->type); sleep(args->delay); _write(args->fd, args->type); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static void thread_delay_connect(struct thread_args *args) { - printf("%d: START\n", gettid()); + printf("%ld: START\n", pthread_self()); sleep(args->delay); args->fd = _socket(args->type); _connect(args->fd, args->type); - printf("%d: END\n", gettid()); + printf("%ld: END\n", pthread_self()); } static int do_accept_accept_accept(int type) { @@ -490,6 +506,64 @@ error: return -1; } +static int do_connectnb_shutdown(int type) { + int fd; + int flags; + pthread_t thread; + struct thread_args args = {-1, type, 0}; + + + fd = _socket(type); + if (fd < 0) goto error; + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + return -1; + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) + return -1; + + _connect(fd, type); + + sleep(1); + _shutdown(fd, SHUT_RDWR); + + sleep(2); + + _close(fd, type); + + return 0; + +error: + return -1; +} + +static int do_connectnb_close(int type) { + int fd; + pthread_t thread; + struct thread_args args = {-1, type, 0}; + int flags; + + fd = _socket(type); + if (fd < 0) goto error; + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + return -1; + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) + return -1; + + _connect(fd, type); + + sleep(2); + + _close(fd, type); + + return 0; + +error: + return -1; +} + // accept in one thread. close then write in another static int do_accept_close_write(int type) { int fd; @@ -674,6 +748,8 @@ struct { {"accept_and_close", do_accept_and_close}, {"accept_shutdown", do_accept_shutdown}, {"connect_shutdown", do_connect_shutdown}, + {"connectnb_shutdown", do_connectnb_shutdown}, + {"connectnb_close", do_connectnb_close}, {"accept_close_write", do_accept_close_write}, {"accept_connect_connect", do_accept_connect_connect}, {"poll_poll_poll_shutdown", do_poll_poll_poll_shutdown}, |