diff options
| -rw-r--r-- | tools/idevicedebugserverproxy.c | 120 |
1 files changed, 75 insertions, 45 deletions
diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c index 2209abc..fc1ead9 100644 --- a/tools/idevicedebugserverproxy.c +++ b/tools/idevicedebugserverproxy.c | |||
| @@ -38,33 +38,25 @@ static int debug_mode = 0; | |||
| 38 | static int quit_flag = 0; | 38 | static int quit_flag = 0; |
| 39 | 39 | ||
| 40 | typedef struct { | 40 | typedef struct { |
| 41 | int server_fd; | ||
| 42 | int client_fd; | 41 | int client_fd; |
| 43 | uint16_t local_port; | ||
| 44 | idevice_t device; | 42 | idevice_t device; |
| 45 | debugserver_client_t debugserver_client; | 43 | debugserver_client_t debugserver_client; |
| 46 | volatile int stop_ctod; | 44 | volatile int stop_ctod; |
| 47 | volatile int stop_dtoc; | 45 | volatile int stop_dtoc; |
| 48 | } socket_info_t; | 46 | } socket_info_t; |
| 49 | 47 | ||
| 50 | static socket_info_t global_socket_info; | 48 | struct thread_info { |
| 49 | thread_t th; | ||
| 50 | struct thread_info *next; | ||
| 51 | }; | ||
| 52 | |||
| 53 | typedef struct thread_info thread_info_t; | ||
| 54 | |||
| 51 | 55 | ||
| 52 | static void clean_exit(int sig) | 56 | static void clean_exit(int sig) |
| 53 | { | 57 | { |
| 54 | if (quit_flag == 0) | 58 | fprintf(stderr, "Exiting...\n"); |
| 55 | fprintf(stderr, "Setting quit status. Cancel again to quit server.\n"); | ||
| 56 | else | ||
| 57 | fprintf(stderr, "Exiting...\n"); | ||
| 58 | |||
| 59 | quit_flag++; | 59 | quit_flag++; |
| 60 | |||
| 61 | /* shutdown server socket if we have to terminate to unblock the server loop */ | ||
| 62 | if (quit_flag > 1) { | ||
| 63 | if (global_socket_info.server_fd > 0) { | ||
| 64 | socket_shutdown(global_socket_info.server_fd, SHUT_RDWR); | ||
| 65 | socket_close(global_socket_info.server_fd); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | } | 60 | } |
| 69 | 61 | ||
| 70 | static void print_usage(int argc, char **argv) | 62 | static void print_usage(int argc, char **argv) |
| @@ -83,7 +75,7 @@ static void print_usage(int argc, char **argv) | |||
| 83 | static void *thread_device_to_client(void *data) | 75 | static void *thread_device_to_client(void *data) |
| 84 | { | 76 | { |
| 85 | socket_info_t* socket_info = (socket_info_t*)data; | 77 | socket_info_t* socket_info = (socket_info_t*)data; |
| 86 | idevice_error_t res = IDEVICE_E_UNKNOWN_ERROR; | 78 | debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR; |
| 87 | 79 | ||
| 88 | int recv_len; | 80 | int recv_len; |
| 89 | int sent; | 81 | int sent; |
| @@ -92,15 +84,14 @@ static void *thread_device_to_client(void *data) | |||
| 92 | debug("%s: started thread...\n", __func__); | 84 | debug("%s: started thread...\n", __func__); |
| 93 | 85 | ||
| 94 | debug("%s: client_fd = %d\n", __func__, socket_info->client_fd); | 86 | debug("%s: client_fd = %d\n", __func__, socket_info->client_fd); |
| 95 | debug("%s: server fd = %d\n", __func__, socket_info->server_fd); | ||
| 96 | 87 | ||
| 97 | while (!quit_flag && !socket_info->stop_dtoc && socket_info->client_fd > 0 && socket_info->server_fd > 0) { | 88 | while (!quit_flag && !socket_info->stop_dtoc && socket_info->client_fd > 0) { |
| 98 | debug("%s: receiving data from device...\n", __func__); | 89 | debug("%s: receiving data from device...\n", __func__); |
| 99 | 90 | ||
| 100 | res = debugserver_client_receive_with_timeout(socket_info->debugserver_client, buffer, sizeof(buffer), (uint32_t*)&recv_len, 5000); | 91 | res = debugserver_client_receive_with_timeout(socket_info->debugserver_client, buffer, sizeof(buffer), (uint32_t*)&recv_len, 5000); |
| 101 | 92 | ||
| 102 | if (recv_len <= 0) { | 93 | if (recv_len <= 0) { |
| 103 | if (recv_len == 0 && res == IDEVICE_E_SUCCESS) { | 94 | if (recv_len == 0 && res == DEBUGSERVER_E_SUCCESS) { |
| 104 | // try again | 95 | // try again |
| 105 | continue; | 96 | continue; |
| 106 | } else { | 97 | } else { |
| @@ -139,7 +130,7 @@ static void *thread_device_to_client(void *data) | |||
| 139 | static void *thread_client_to_device(void *data) | 130 | static void *thread_client_to_device(void *data) |
| 140 | { | 131 | { |
| 141 | socket_info_t* socket_info = (socket_info_t*)data; | 132 | socket_info_t* socket_info = (socket_info_t*)data; |
| 142 | idevice_error_t res = IDEVICE_E_UNKNOWN_ERROR; | 133 | debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR; |
| 143 | 134 | ||
| 144 | int recv_len; | 135 | int recv_len; |
| 145 | int sent; | 136 | int sent; |
| @@ -149,7 +140,6 @@ static void *thread_client_to_device(void *data) | |||
| 149 | debug("%s: started thread...\n", __func__); | 140 | debug("%s: started thread...\n", __func__); |
| 150 | 141 | ||
| 151 | debug("%s: client_fd = %d\n", __func__, socket_info->client_fd); | 142 | debug("%s: client_fd = %d\n", __func__, socket_info->client_fd); |
| 152 | debug("%s: server_fd = %d\n", __func__, socket_info->server_fd); | ||
| 153 | 143 | ||
| 154 | /* spawn server to client thread */ | 144 | /* spawn server to client thread */ |
| 155 | socket_info->stop_dtoc = 0; | 145 | socket_info->stop_dtoc = 0; |
| @@ -157,7 +147,7 @@ static void *thread_client_to_device(void *data) | |||
| 157 | fprintf(stderr, "Failed to start device to client thread...\n"); | 147 | fprintf(stderr, "Failed to start device to client thread...\n"); |
| 158 | } | 148 | } |
| 159 | 149 | ||
| 160 | while (!quit_flag && !socket_info->stop_ctod && socket_info->client_fd > 0 && socket_info->server_fd > 0) { | 150 | while (!quit_flag && !socket_info->stop_ctod && socket_info->client_fd > 0) { |
| 161 | debug("%s: receiving data from client...\n", __func__); | 151 | debug("%s: receiving data from client...\n", __func__); |
| 162 | 152 | ||
| 163 | /* attempt to read incoming data from client */ | 153 | /* attempt to read incoming data from client */ |
| @@ -177,7 +167,7 @@ static void *thread_client_to_device(void *data) | |||
| 177 | debug("%s: sending data to device...\n", __func__); | 167 | debug("%s: sending data to device...\n", __func__); |
| 178 | res = debugserver_client_send(socket_info->debugserver_client, buffer, recv_len, (uint32_t*)&sent); | 168 | res = debugserver_client_send(socket_info->debugserver_client, buffer, recv_len, (uint32_t*)&sent); |
| 179 | 169 | ||
| 180 | if (sent < recv_len || res != IDEVICE_E_SUCCESS) { | 170 | if (sent < recv_len || res != DEBUGSERVER_E_SUCCESS) { |
| 181 | if (sent <= 0) { | 171 | if (sent <= 0) { |
| 182 | fprintf(stderr, "send failed: %s\n", strerror(errno)); | 172 | fprintf(stderr, "send failed: %s\n", strerror(errno)); |
| 183 | break; | 173 | break; |
| @@ -245,18 +235,34 @@ static void* connection_handler(void* data) | |||
| 245 | int main(int argc, char *argv[]) | 235 | int main(int argc, char *argv[]) |
| 246 | { | 236 | { |
| 247 | idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; | 237 | idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; |
| 248 | thread_t th; | 238 | idevice_t device = NULL; |
| 239 | thread_info_t *thread_list = NULL; | ||
| 249 | const char* udid = NULL; | 240 | const char* udid = NULL; |
| 250 | uint16_t local_port = 0; | 241 | uint16_t local_port = 0; |
| 242 | int server_fd; | ||
| 251 | int result = EXIT_SUCCESS; | 243 | int result = EXIT_SUCCESS; |
| 252 | int i; | 244 | int i; |
| 253 | 245 | ||
| 246 | #ifndef WIN32 | ||
| 247 | struct sigaction sa; | ||
| 248 | struct sigaction si; | ||
| 249 | memset(&sa, '\0', sizeof(struct sigaction)); | ||
| 250 | memset(&si, '\0', sizeof(struct sigaction)); | ||
| 251 | |||
| 252 | sa.sa_handler = clean_exit; | ||
| 253 | sigemptyset(&sa.sa_mask); | ||
| 254 | |||
| 255 | si.sa_handler = SIG_IGN; | ||
| 256 | sigemptyset(&si.sa_mask); | ||
| 257 | |||
| 258 | sigaction(SIGINT, &sa, NULL); | ||
| 259 | sigaction(SIGTERM, &sa, NULL); | ||
| 260 | sigaction(SIGQUIT, &sa, NULL); | ||
| 261 | sigaction(SIGPIPE, &si, NULL); | ||
| 262 | #else | ||
| 254 | /* bind signals */ | 263 | /* bind signals */ |
| 255 | signal(SIGINT, clean_exit); | 264 | signal(SIGINT, clean_exit); |
| 256 | signal(SIGTERM, clean_exit); | 265 | signal(SIGTERM, clean_exit); |
| 257 | #ifndef WIN32 | ||
| 258 | signal(SIGQUIT, clean_exit); | ||
| 259 | signal(SIGPIPE, SIG_IGN); | ||
| 260 | #endif | 266 | #endif |
| 261 | 267 | ||
| 262 | /* parse cmdline arguments */ | 268 | /* parse cmdline arguments */ |
| @@ -297,11 +303,8 @@ int main(int argc, char *argv[]) | |||
| 297 | goto leave_cleanup; | 303 | goto leave_cleanup; |
| 298 | } | 304 | } |
| 299 | 305 | ||
| 300 | /* setup and create socket endpoint */ | ||
| 301 | global_socket_info.local_port = local_port; | ||
| 302 | |||
| 303 | /* start services and connect to device */ | 306 | /* start services and connect to device */ |
| 304 | ret = idevice_new(&global_socket_info.device, udid); | 307 | ret = idevice_new(&device, udid); |
| 305 | if (ret != IDEVICE_E_SUCCESS) { | 308 | if (ret != IDEVICE_E_SUCCESS) { |
| 306 | if (udid) { | 309 | if (udid) { |
| 307 | fprintf(stderr, "No device found with udid %s, is it plugged in?\n", udid); | 310 | fprintf(stderr, "No device found with udid %s, is it plugged in?\n", udid); |
| @@ -313,40 +316,67 @@ int main(int argc, char *argv[]) | |||
| 313 | } | 316 | } |
| 314 | 317 | ||
| 315 | /* create local socket */ | 318 | /* create local socket */ |
| 316 | global_socket_info.server_fd = socket_create(global_socket_info.local_port); | 319 | server_fd = socket_create(local_port); |
| 317 | if (global_socket_info.server_fd < 0) { | 320 | if (server_fd < 0) { |
| 318 | fprintf(stderr, "Could not create socket\n"); | 321 | fprintf(stderr, "Could not create socket\n"); |
| 319 | result = EXIT_FAILURE; | 322 | result = EXIT_FAILURE; |
| 320 | goto leave_cleanup; | 323 | goto leave_cleanup; |
| 321 | } | 324 | } |
| 322 | 325 | ||
| 323 | while (!quit_flag) { | 326 | while (!quit_flag) { |
| 324 | debug("%s: Waiting for connection on local port %d\n", __func__, global_socket_info.local_port); | 327 | debug("%s: Waiting for connection on local port %d\n", __func__, local_port); |
| 325 | 328 | ||
| 326 | /* wait for client */ | 329 | /* wait for client */ |
| 327 | global_socket_info.client_fd = socket_accept(global_socket_info.server_fd, global_socket_info.local_port); | 330 | int client_fd = socket_accept(server_fd, local_port); |
| 328 | if (global_socket_info.client_fd < 0) { | 331 | if (client_fd < 0) { |
| 329 | continue; | 332 | continue; |
| 330 | } | 333 | } |
| 331 | 334 | ||
| 332 | debug("%s: Handling new client connection...\n", __func__); | 335 | debug("%s: Handling new client connection...\n", __func__); |
| 333 | 336 | ||
| 334 | if (thread_new(&th, connection_handler, (void*)&global_socket_info) != 0) { | 337 | thread_info_t *el = (thread_info_t*)malloc(sizeof(thread_info_t)); |
| 338 | if (!el) { | ||
| 339 | fprintf(stderr, "Out of memory\n"); | ||
| 340 | exit(EXIT_FAILURE); | ||
| 341 | } | ||
| 342 | el->next = NULL; | ||
| 343 | |||
| 344 | if (thread_list) { | ||
| 345 | thread_list->next = el; | ||
| 346 | } else { | ||
| 347 | thread_list = el; | ||
| 348 | } | ||
| 349 | |||
| 350 | socket_info_t *sinfo = (socket_info_t*)malloc(sizeof(socket_info_t)); | ||
| 351 | if (!sinfo) { | ||
| 352 | fprintf(stderr, "Out of memory\n"); | ||
| 353 | exit(EXIT_FAILURE); | ||
| 354 | } | ||
| 355 | sinfo->client_fd = client_fd; | ||
| 356 | sinfo->device = device; | ||
| 357 | |||
| 358 | if (thread_new(&(el->th), connection_handler, (void*)sinfo) != 0) { | ||
| 335 | fprintf(stderr, "Could not start connection handler.\n"); | 359 | fprintf(stderr, "Could not start connection handler.\n"); |
| 336 | socket_shutdown(global_socket_info.server_fd, SHUT_RDWR); | 360 | socket_shutdown(server_fd, SHUT_RDWR); |
| 337 | socket_close(global_socket_info.server_fd); | 361 | socket_close(server_fd); |
| 338 | continue; | 362 | continue; |
| 339 | } | 363 | } |
| 340 | |||
| 341 | /* we do not need it anymore */ | ||
| 342 | thread_free(th); | ||
| 343 | } | 364 | } |
| 344 | 365 | ||
| 345 | debug("%s: Shutting down debugserver proxy...\n", __func__); | 366 | debug("%s: Shutting down debugserver proxy...\n", __func__); |
| 346 | 367 | ||
| 368 | /* join and clean up threads */ | ||
| 369 | while (thread_list) { | ||
| 370 | thread_info_t *el = thread_list; | ||
| 371 | thread_join(el->th); | ||
| 372 | thread_free(el->th); | ||
| 373 | thread_list = el->next; | ||
| 374 | free(el); | ||
| 375 | } | ||
| 376 | |||
| 347 | leave_cleanup: | 377 | leave_cleanup: |
| 348 | if (global_socket_info.device) { | 378 | if (device) { |
| 349 | idevice_free(global_socket_info.device); | 379 | idevice_free(device); |
| 350 | } | 380 | } |
| 351 | 381 | ||
| 352 | return result; | 382 | return result; |
