From 782ceb2428e5522e61cdf55aed8a278d161273a1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 30 Oct 2012 18:57:16 -0700 Subject: [PATCH] monitor: Add support for server channels --- monitor/control.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ monitor/control.h | 1 + monitor/main.c | 7 +++- 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/monitor/control.c b/monitor/control.c index da2eb69d6..1448c4c8a 100644 --- a/monitor/control.c +++ b/monitor/control.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include @@ -648,8 +650,106 @@ static int open_channel(uint16_t channel) return 0; } +static void client_callback(int fd, uint32_t events, void *user_data) +{ + struct control_data *data = user_data; + unsigned char buf[HCI_MAX_FRAME_SIZE]; + ssize_t len; + + if (events & (EPOLLERR | EPOLLHUP)) { + mainloop_remove_fd(data->fd); + return; + } + + len = recv(fd, buf, sizeof(buf), 0); + if (len < 0) + return; +} + +static void server_accept_callback(int fd, uint32_t events, void *user_data) +{ + struct control_data *data; + struct sockaddr_un addr; + socklen_t len; + int nfd; + + if (events & (EPOLLERR | EPOLLHUP)) { + mainloop_remove_fd(fd); + return; + } + + memset(&addr, 0, sizeof(addr)); + len = sizeof(addr); + + nfd = accept(fd, (struct sockaddr *) &addr, &len); + if (nfd < 0) { + perror("Failed to accept client socket"); + return; + } + + printf("--- New monitor connection ---\n"); + + data = malloc(sizeof(*data)); + if (!data) { + close(nfd); + return; + } + + memset(data, 0, sizeof(*data)); + data->channel = HCI_CHANNEL_MONITOR; + data->fd = nfd; + + mainloop_add_fd(data->fd, EPOLLIN, client_callback, data, free_data); +} + +static int server_fd = -1; + +void control_server(const char *path) +{ + struct sockaddr_un addr; + int fd; + + if (server_fd >= 0) + return; + + unlink(path); + + fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + perror("Failed to open server socket"); + return; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, path); + + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("Failed to bind server socket"); + close(fd); + return; + } + + if (listen(fd, 5) < 0) { + perror("Failed to listen server socket"); + close(fd); + return; + } + + if (mainloop_add_fd(fd, EPOLLIN, server_accept_callback, + NULL, NULL) < 0) { + close(fd); + return; + } + + server_fd = fd; +} + int control_tracing(void) { + if (server_fd >= 0) + return 0; + if (open_channel(HCI_CHANNEL_MONITOR) < 0) return -1; diff --git a/monitor/control.h b/monitor/control.h index 961f66ce8..105684017 100644 --- a/monitor/control.h +++ b/monitor/control.h @@ -24,6 +24,7 @@ #include +void control_server(const char *path); int control_tracing(void); void control_message(uint16_t opcode, const void *data, uint16_t size); diff --git a/monitor/main.c b/monitor/main.c index 0b8ae30a8..87e5342e1 100644 --- a/monitor/main.c +++ b/monitor/main.c @@ -53,11 +53,13 @@ static void usage(void) printf("\tbtmon [options]\n"); printf("options:\n" "\t-b, --btsnoop Save dump in btsnoop format\n" + "\t-s, --server Start monitor server socket\n" "\t-h, --help Show help options\n"); } static const struct option main_options[] = { { "btsnoop", required_argument, NULL, 'b' }, + { "server", required_argument, NULL, 'r' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { } @@ -73,7 +75,7 @@ int main(int argc, char *argv[]) for (;;) { int opt; - opt = getopt_long(argc, argv, "b:vh", main_options, NULL); + opt = getopt_long(argc, argv, "b:s:vh", main_options, NULL); if (opt < 0) break; @@ -81,6 +83,9 @@ int main(int argc, char *argv[]) case 'b': btsnoop_open(optarg); break; + case 's': + control_server(optarg); + break; case 'v': printf("%s\n", VERSION); return EXIT_SUCCESS; -- 2.47.3