From 902aabdf8106338ae9022aef3dca6818da990403 Mon Sep 17 00:00:00 2001 From: artygus Date: Sun, 21 Apr 2019 11:33:07 +0100 Subject: [PATCH 1/3] sm_connect: hostname with port as a single argument --- .../ios_webkit_debug_proxy.h | 4 +-- .../ios-webkit-debug-proxy/socket_manager.h | 2 +- src/ios_webkit_debug_proxy.c | 26 ++++++++++++------- src/ios_webkit_debug_proxy_main.c | 4 +-- src/socket_manager.c | 23 +++++++++++++++- 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/include/ios-webkit-debug-proxy/ios_webkit_debug_proxy.h b/include/ios-webkit-debug-proxy/ios_webkit_debug_proxy.h index 297f398e..ab949c22 100644 --- a/include/ios-webkit-debug-proxy/ios_webkit_debug_proxy.h +++ b/include/ios-webkit-debug-proxy/ios_webkit_debug_proxy.h @@ -83,8 +83,8 @@ struct iwdp_struct { int (*listen)(iwdp_t self, int port); // Connect to a host:port for static data. - // @param hostname e.g. "chrome-devtools-frontend.appspot.com" - int (*connect)(iwdp_t self, const char *hostname, int port); + // @param hostname_with_port e.g. "chrome-devtools-frontend.appspot.com:8080" + int (*connect)(iwdp_t self, const char *hostname_with_port); // Send bytes to fd. iwdp_status (*send)(iwdp_t self, int fd, const char *data, size_t length); diff --git a/include/ios-webkit-debug-proxy/socket_manager.h b/include/ios-webkit-debug-proxy/socket_manager.h index 8a7d40fe..014c5268 100644 --- a/include/ios-webkit-debug-proxy/socket_manager.h +++ b/include/ios-webkit-debug-proxy/socket_manager.h @@ -19,7 +19,7 @@ extern "C" { int sm_listen(int port); // Connect to a server, return the file descriptor (or -1 for error). -int sm_connect(const char *hostname, int port); +int sm_connect(const char *socket_addr); typedef uint8_t sm_status; diff --git a/src/ios_webkit_debug_proxy.c b/src/ios_webkit_debug_proxy.c index 2e0cbfba..9399e35c 100644 --- a/src/ios_webkit_debug_proxy.c +++ b/src/ios_webkit_debug_proxy.c @@ -419,7 +419,7 @@ dl_status iwdp_on_attach(dl_t dl, const char *device_id, int device_num) { // com.apple.iPhoneSimulator:com.apple.webinspectord // so the launch is probably something like: // xpc_connection_create[_mach_service](...webinspectord, ...)? - wi_fd = self->connect(self, "localhost", 27753); + wi_fd = self->connect(self, "localhost:27753"); } else { wi_fd = self->attach(self, device_id, NULL, (device_name ? NULL : &device_name), &device_os_version); @@ -948,24 +948,28 @@ ws_status iwdp_on_static_request_for_http(ws_t ws, bool is_head, return iwdp_send_http(ws, is_head, "403 Forbidden", ".txt", "Invalid path"); } const char *fe_port = strchr(fe_host, ':'); - fe_port = (fe_port && fe_port <= fe_path ? fe_port + 1 : + fe_port = (fe_port && fe_port <= fe_path ? fe_port : NULL); // e.g. "http://foo.com/bar:x" - size_t fe_host_len = ((fe_port ? fe_port - 1 : fe_path) - fe_host); + size_t fe_host_len = ((fe_port ? fe_port : fe_path) - fe_host); char *host = strndup(fe_host, fe_host_len); - int port = 80; + + char *host_with_port; + char *port = NULL; if (fe_port) { - char *sport = strndup(fe_port, fe_path - fe_port); - int port2 = strtol(fe_port, NULL, 0); - free(sport); - port = (port2 > 0 ? port2 : port); + port = strndup(fe_port, fe_path - fe_port); } + if (asprintf(&host_with_port, "%s%s", host, port ? port : ":80") < 0) { + return self->on_error(self, "asprintf failed"); + }; + free(port); - int fs_fd = self->connect(self, host, port); + int fs_fd = self->connect(self, host_with_port); if (fs_fd < 0) { char *error; - if (asprintf(&error, "Unable to connect to %s:%d", host, port) < 0) { + if (asprintf(&error, "Unable to connect to %s", host_with_port) < 0) { return self->on_error(self, "asprintf failed"); } + free(host_with_port); free(host); free(path); ws_status ret = iwdp_send_http(ws, is_head, "500 Server Error", ".txt", @@ -978,6 +982,7 @@ ws_status iwdp_on_static_request_for_http(ws_t ws, bool is_head, ifs->fs_fd = fs_fd; iws->ifs = ifs; if (self->add_fd(self, fs_fd, ifs, false)) { + free(host_with_port); free(host); free(path); return self->on_error(self, "Unable to add fd %d", fs_fd); @@ -992,6 +997,7 @@ ws_status iwdp_on_static_request_for_http(ws_t ws, bool is_head, (is_head ? "HEAD" : "GET"), path, host) < 0) { return self->on_error(self, "asprintf failed"); } + free(host_with_port); free(host); free(path); size_t length = strlen(data); diff --git a/src/ios_webkit_debug_proxy_main.c b/src/ios_webkit_debug_proxy_main.c index e8dc5937..45272241 100644 --- a/src/ios_webkit_debug_proxy_main.c +++ b/src/ios_webkit_debug_proxy_main.c @@ -138,8 +138,8 @@ iwdp_status iwdpm_select_port(iwdp_t iwdp, const char *device_id, int iwdpm_listen(iwdp_t iwdp, int port) { return sm_listen(port); } -int iwdpm_connect(iwdp_t iwdp, const char *hostname, int port) { - return sm_connect(hostname, port); +int iwdpm_connect(iwdp_t iwdp, const char *socket_addr) { + return sm_connect(socket_addr); } iwdp_status iwdpm_send(iwdp_t iwdp, int fd, const char *data, size_t length) { sm_t sm = ((iwdpm_t)iwdp->state)->sm; diff --git a/src/socket_manager.c b/src/socket_manager.c index faf8b1ab..c0a70fbf 100644 --- a/src/socket_manager.c +++ b/src/socket_manager.c @@ -124,7 +124,7 @@ int sm_listen(int port) { return fd; } -int sm_connect(const char *hostname, int port) { +int sm_connect_tcp(const char *hostname, int port) { struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; @@ -222,6 +222,27 @@ int sm_connect(const char *hostname, int port) { return ret; } +int sm_connect(const char *socket_addr) { + const char *s_port = strrchr(socket_addr, ':'); + int port = 0; + + if (s_port) { + s_port += 1; + port = strtol(s_port, NULL, 0); + } + + if (port <= 0) { + return -1; + } + + size_t host_len = s_port - 1 - socket_addr; + char *host = strndup(socket_addr, host_len); + + int ret = sm_connect_tcp(host, port); + free(host); + return ret; +} + sm_status sm_on_debug(sm_t self, const char *format, ...) { if (self->is_debug && *self->is_debug) { From b92cde23a9c4ced3f10d5a493556fd387b842307 Mon Sep 17 00:00:00 2001 From: artygus Date: Sun, 21 Apr 2019 11:34:32 +0100 Subject: [PATCH 2/3] sm_connect: unix socket connection implementation --- src/socket_manager.c | 74 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 14 deletions(-) diff --git a/src/socket_manager.c b/src/socket_manager.c index c0a70fbf..cbf0031d 100644 --- a/src/socket_manager.c +++ b/src/socket_manager.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #endif #include "char_buffer.h" @@ -124,6 +126,42 @@ int sm_listen(int port) { return fd; } +#ifndef WIN32 +int sm_connect_unix(const char *filename) { + struct sockaddr_un name; + int sfd = -1; + struct stat fst; + + if (stat(filename, &fst) != 0 || !S_ISSOCK(fst.st_mode)) { + fprintf(stderr, "File '%s' is not a socket: %s\n", filename, + strerror(errno)); + return -1; + } + + if ((sfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { + perror("create socket failed"); + return -1; + } + + int opts = fcntl(sfd, F_GETFL); + if (fcntl(sfd, F_SETFL, (opts | O_NONBLOCK)) < 0) { + perror("failed to set socket to non-blocking"); + return -1; + } + + name.sun_family = AF_UNIX; + strncpy(name.sun_path, filename, sizeof(name.sun_path) - 1); + + if (connect(sfd, (struct sockaddr*)&name, sizeof(name)) < 0) { + close(sfd); + perror("connect failed"); + return -1; + } + + return sfd; +} +#endif + int sm_connect_tcp(const char *hostname, int port) { struct addrinfo hints; memset(&hints, 0, sizeof(hints)); @@ -223,24 +261,32 @@ int sm_connect_tcp(const char *hostname, int port) { } int sm_connect(const char *socket_addr) { - const char *s_port = strrchr(socket_addr, ':'); - int port = 0; + if (strncmp(socket_addr, "unix:", 5) == 0) { +#ifdef WIN32 + return -1; +#else + return sm_connect_unix(socket_addr + 5); +#endif + } else { + const char *s_port = strrchr(socket_addr, ':'); + int port = 0; - if (s_port) { - s_port += 1; - port = strtol(s_port, NULL, 0); - } + if (s_port) { + s_port += 1; + port = strtol(s_port, NULL, 0); + } - if (port <= 0) { - return -1; - } + if (port <= 0) { + return -1; + } - size_t host_len = s_port - 1 - socket_addr; - char *host = strndup(socket_addr, host_len); + size_t host_len = s_port - 1 - socket_addr; + char *host = strndup(socket_addr, host_len); - int ret = sm_connect_tcp(host, port); - free(host); - return ret; + int ret = sm_connect_tcp(host, port); + free(host); + return ret; + } } From 25b3663f157bf76df023876cc860ac3545d5543e Mon Sep 17 00:00:00 2001 From: artygus Date: Sun, 21 Apr 2019 12:57:50 +0100 Subject: [PATCH 3/3] added option to customize simulator webinspector socket address partly addresses #250 --- .../ios_webkit_debug_proxy.h | 2 +- src/ios_webkit_debug_proxy.c | 8 +++-- src/ios_webkit_debug_proxy_main.c | 31 ++++++++++++++++--- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/include/ios-webkit-debug-proxy/ios_webkit_debug_proxy.h b/include/ios-webkit-debug-proxy/ios_webkit_debug_proxy.h index ab949c22..50f93e5f 100644 --- a/include/ios-webkit-debug-proxy/ios_webkit_debug_proxy.h +++ b/include/ios-webkit-debug-proxy/ios_webkit_debug_proxy.h @@ -25,7 +25,7 @@ typedef struct iwdp_private *iwdp_private_t; struct iwdp_struct; typedef struct iwdp_struct *iwdp_t; -iwdp_t iwdp_new(const char* frontend); +iwdp_t iwdp_new(const char* frontend, const char* sim_wi_socket_addr); void iwdp_free(iwdp_t self); struct iwdp_struct { diff --git a/src/ios_webkit_debug_proxy.c b/src/ios_webkit_debug_proxy.c index 9399e35c..3909a795 100644 --- a/src/ios_webkit_debug_proxy.c +++ b/src/ios_webkit_debug_proxy.c @@ -39,6 +39,7 @@ struct iwdp_private { // frontend url, e.g. "http://bar.com/devtools.html" or "/foo/inspector.html" char *frontend; + char *sim_wi_socket_addr; }; @@ -413,13 +414,12 @@ dl_status iwdp_on_attach(dl_t dl, const char *device_id, int device_num) { if (is_sim) { // TODO launch webinspectord // For now we'll assume Safari starts it for us. - // The port 27753 is from `locate com.apple.webinspectord.plist`. // // `launchctl list` shows: // com.apple.iPhoneSimulator:com.apple.webinspectord // so the launch is probably something like: // xpc_connection_create[_mach_service](...webinspectord, ...)? - wi_fd = self->connect(self, "localhost:27753"); + wi_fd = self->connect(self, my->sim_wi_socket_addr); } else { wi_fd = self->attach(self, device_id, NULL, (device_name ? NULL : &device_name), &device_os_version); @@ -1441,6 +1441,7 @@ void iwdp_free(iwdp_t self) { if (my) { ht_free(my->device_id_to_iport); free(my->frontend); + free(my->sim_wi_socket_addr); memset(my, 0, sizeof(struct iwdp_private)); free(my); } @@ -1449,7 +1450,7 @@ void iwdp_free(iwdp_t self) { } } -iwdp_t iwdp_new(const char *frontend) { +iwdp_t iwdp_new(const char *frontend, const char *sim_wi_socket_addr) { iwdp_t self = (iwdp_t)malloc(sizeof(struct iwdp_struct)); iwdp_private_t my = (iwdp_private_t)malloc(sizeof(struct iwdp_private)); if (!self || !my) { @@ -1465,6 +1466,7 @@ iwdp_t iwdp_new(const char *frontend) { self->on_error = iwdp_on_error; self->private_state = my; my->frontend = (frontend ? strdup(frontend) : NULL); + my->sim_wi_socket_addr = strdup(sim_wi_socket_addr); my->device_id_to_iport = ht_new(HT_STRING_KEYS); if (!my->device_id_to_iport) { iwdp_free(self); diff --git a/src/ios_webkit_debug_proxy_main.c b/src/ios_webkit_debug_proxy_main.c index 45272241..b185d081 100644 --- a/src/ios_webkit_debug_proxy_main.c +++ b/src/ios_webkit_debug_proxy_main.c @@ -41,6 +41,7 @@ struct iwdpm_struct { char *config; char *frontend; + char *sim_wi_socket_addr; bool is_debug; pc_t pc; @@ -174,7 +175,7 @@ sm_status iwdpm_on_close(sm_t sm, int fd, void *value, bool is_server) { void iwdpm_create_bridge(iwdpm_t self) { sm_t sm = sm_new(4096); - iwdp_t iwdp = iwdp_new(self->frontend); + iwdp_t iwdp = iwdp_new(self->frontend, self->sim_wi_socket_addr); if (!sm || !iwdp) { sm_free(sm); return; @@ -207,6 +208,7 @@ void iwdpm_free(iwdpm_t self) { sm_free(self->sm); free(self->config); free(self->frontend); + free(self->sim_wi_socket_addr); memset(self, 0, sizeof(struct iwdpm_struct)); free(self); } @@ -228,6 +230,7 @@ int iwdpm_configure(iwdpm_t self, int argc, char **argv) { {"config", 1, NULL, 'c'}, {"frontend", 1, NULL, 'f'}, {"no-frontend", 0, NULL, 'F'}, + {"simulator-webinspector", 1, NULL, 's'}, {"debug", 0, NULL, 'd'}, {"help", 0, NULL, 'h'}, {"version", 0, NULL, 'V'}, @@ -236,13 +239,16 @@ int iwdpm_configure(iwdpm_t self, int argc, char **argv) { const char *DEFAULT_CONFIG = "null:9221,:9222-9322"; const char *DEFAULT_FRONTEND = "http://chrome-devtools-frontend.appspot.com/static/27.0.1453.93/devtools.html"; + // The port 27753 is from `locate com.apple.webinspectord.plist` + const char *DEFAULT_SIM_WI_SOCKET_ADDR = "localhost:27753"; self->config = strdup(DEFAULT_CONFIG); self->frontend = strdup(DEFAULT_FRONTEND); + self->sim_wi_socket_addr = strdup(DEFAULT_SIM_WI_SOCKET_ADDR); int ret = 0; while (!ret) { - int c = getopt_long(argc, argv, "hVu:c:f:Fd", longopts, (int *)0); + int c = getopt_long(argc, argv, "hVu:c:f:Fs:d", longopts, (int *)0); if (c == -1) { break; } @@ -284,6 +290,10 @@ int iwdpm_configure(iwdpm_t self, int argc, char **argv) { free(self->config); self->config = strdup(optarg); break; + case 's': + free(self->sim_wi_socket_addr); + self->sim_wi_socket_addr = strdup(optarg); + break; case 'f': case 'F': free(self->frontend); @@ -327,7 +337,7 @@ int iwdpm_configure(iwdpm_t self, int argc, char **argv) { "OPTIONS:\n" "\n" " -u UDID[:minPort-[maxPort]]\tTarget a specific device by its" - " 40-digit ID.\n" + " digital ID.\n" " minPort defaults to 9222. maxPort defaults to minPort.\n" " This is shorthand for the following \"-c\" option.\n" "\n" @@ -362,10 +372,23 @@ int iwdpm_configure(iwdpm_t self, int argc, char **argv) { "\n" " -F, --no-frontend\tDisable the DevTools frontend.\n" "\n" + " -s, --simulator-webinspector\tSimulator web inspector socket\n" + " address. Provided value value needs to be in format\n" + " HOSTNAME:PORT or UNIX:PATH\n" + " Defaults to:\n" + " %s\n" + " Examples:\n" + " * TCP socket:\n" + " 192.168.0.20:27753\n" + " * Unix domain socket:\n" + " unix:/private/tmp/com.apple.launchd.2j5k1TMh6i/" + "com.apple.webinspectord_sim.socket\n" + "\n" " -d, --debug\t\tEnable debug output.\n" " -h, --help\t\tPrint this usage information.\n" " -V, --version\t\tPrint version information and exit.\n" - "\n", (name ? name + 1 : argv[0]), PACKAGE_VERSION, DEFAULT_CONFIG, DEFAULT_FRONTEND); + "\n", (name ? name + 1 : argv[0]), PACKAGE_VERSION, DEFAULT_CONFIG, + DEFAULT_FRONTEND, DEFAULT_SIM_WI_SOCKET_ADDR); } return ret; }