Diff between 6716e680f4aa5a0901c55be75c1a68e3512bf2e1 and 782ceb2428e5522e61cdf55aed8a278d161273a1

Changed Files

File Additions Deletions Status
monitor/control.c +100 -0 modified
monitor/control.h +1 -0 modified
monitor/main.c +6 -1 modified

Full Patch

diff --git a/monitor/control.c b/monitor/control.c
index da2eb69..1448c4c 100644
--- a/monitor/control.c
+++ b/monitor/control.c
@@ -32,6 +32,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
@@ -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 961f66c..1056840 100644
--- a/monitor/control.h
+++ b/monitor/control.h
@@ -24,6 +24,7 @@
 
 #include <stdint.h>
 
+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 0b8ae30..87e5342 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 <file>  Save dump in btsnoop format\n"
+		"\t-s, --server <path>   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;