summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/idevicedebugserverproxy.c196
1 files changed, 61 insertions, 135 deletions
diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c
index 5b42473..c094c30 100644
--- a/tools/idevicedebugserverproxy.c
+++ b/tools/idevicedebugserverproxy.c
@@ -2,6 +2,7 @@
2 * idevicedebugserverproxy.c 2 * idevicedebugserverproxy.c
3 * Proxy a debugserver connection from device for remote debugging 3 * Proxy a debugserver connection from device for remote debugging
4 * 4 *
5 * Copyright (c) 2021 Nikias Bassen, All Rights Reserved.
5 * Copyright (c) 2012 Martin Szulecki All Rights Reserved. 6 * Copyright (c) 2012 Martin Szulecki All Rights Reserved.
6 * 7 *
7 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
@@ -30,6 +31,7 @@
30#include <string.h> 31#include <string.h>
31#include <errno.h> 32#include <errno.h>
32#include <signal.h> 33#include <signal.h>
34#include <sys/select.h>
33 35
34#include <libimobiledevice/libimobiledevice.h> 36#include <libimobiledevice/libimobiledevice.h>
35#include <libimobiledevice/debugserver.h> 37#include <libimobiledevice/debugserver.h>
@@ -47,12 +49,11 @@ typedef struct {
47 int client_fd; 49 int client_fd;
48 idevice_t device; 50 idevice_t device;
49 debugserver_client_t debugserver_client; 51 debugserver_client_t debugserver_client;
50 volatile int stop_ctod;
51 volatile int stop_dtoc;
52} socket_info_t; 52} socket_info_t;
53 53
54struct thread_info { 54struct thread_info {
55 THREAD_T th; 55 THREAD_T th;
56 int client_fd;
56 struct thread_info *next; 57 struct thread_info *next;
57}; 58};
58 59
@@ -85,153 +86,75 @@ static void print_usage(int argc, char **argv)
85 printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n"); 86 printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n");
86} 87}
87 88
88static void *thread_device_to_client(void *data) 89struct service_client_private {
89{ 90 idevice_connection_t connection;
90 socket_info_t* socket_info = (socket_info_t*)data; 91};
91 debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR; 92struct debugserver_client_private {
92 93 struct service_client_private* parent;
93 int recv_len; 94 int noack_mode;
94 int sent; 95};
95 char buffer[131072];
96
97 debug("%s: started thread...\n", __func__);
98
99 debug("%s: client_fd = %d\n", __func__, socket_info->client_fd);
100
101 while (!quit_flag && !socket_info->stop_dtoc && socket_info->client_fd > 0) {
102 debug("%s: receiving data from device...\n", __func__);
103
104 res = debugserver_client_receive_with_timeout(socket_info->debugserver_client, buffer, sizeof(buffer), (uint32_t*)&recv_len, 5000);
105
106 if (recv_len <= 0) {
107 if (recv_len == 0 && res == DEBUGSERVER_E_SUCCESS) {
108 // try again
109 continue;
110 } else {
111 fprintf(stderr, "recv failed: %s\n", strerror(errno));
112 break;
113 }
114 } else {
115 /* send to device */
116 debug("%s: sending data to client...\n", __func__);
117 sent = socket_send(socket_info->client_fd, buffer, recv_len);
118 if (sent < recv_len) {
119 if (sent <= 0) {
120 fprintf(stderr, "send failed: %s\n", strerror(errno));
121 break;
122 } else {
123 fprintf(stderr, "only sent %d from %d bytes\n", sent, recv_len);
124 }
125 } else {
126 // sending succeeded, receive from device
127 debug("%s: pushed %d bytes to client\n", __func__, sent);
128 }
129 }
130 }
131
132 debug("%s: shutting down...\n", __func__);
133
134 socket_shutdown(socket_info->client_fd, SHUT_RDWR);
135 socket_close(socket_info->client_fd);
136
137 socket_info->client_fd = -1;
138 socket_info->stop_ctod = 1;
139
140 return NULL;
141}
142
143static void *thread_client_to_device(void *data)
144{
145 socket_info_t* socket_info = (socket_info_t*)data;
146 debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR;
147
148 int recv_len;
149 int sent;
150 char buffer[131072];
151 THREAD_T dtoc;
152
153 debug("%s: started thread...\n", __func__);
154
155 debug("%s: client_fd = %d\n", __func__, socket_info->client_fd);
156
157 /* spawn server to client thread */
158 socket_info->stop_dtoc = 0;
159 if (thread_new(&dtoc, thread_device_to_client, data) != 0) {
160 fprintf(stderr, "Failed to start device to client thread...\n");
161 }
162
163 while (!quit_flag && !socket_info->stop_ctod && socket_info->client_fd > 0) {
164 debug("%s: receiving data from client...\n", __func__);
165
166 /* attempt to read incoming data from client */
167 recv_len = socket_receive_timeout(socket_info->client_fd, buffer, sizeof(buffer), 0, 5000);
168
169 /* any data received? */
170 if (recv_len <= 0) {
171 if (recv_len == 0) {
172 /* try again */
173 continue;
174 } else {
175 fprintf(stderr, "Receive failed: %s\n", strerror(errno));
176 break;
177 }
178 } else {
179 /* forward data to device */
180 debug("%s: sending data to device...\n", __func__);
181 res = debugserver_client_send(socket_info->debugserver_client, buffer, recv_len, (uint32_t*)&sent);
182
183 if (sent < recv_len || res != DEBUGSERVER_E_SUCCESS) {
184 if (sent <= 0) {
185 fprintf(stderr, "send failed: %s\n", strerror(errno));
186 break;
187 } else {
188 fprintf(stderr, "only sent %d from %d bytes\n", sent, recv_len);
189 }
190 } else {
191 // sending succeeded, receive from device
192 debug("%s: sent %d bytes to device\n", __func__, sent);
193 }
194 }
195 }
196
197 debug("%s: shutting down...\n", __func__);
198
199 socket_shutdown(socket_info->client_fd, SHUT_RDWR);
200 socket_close(socket_info->client_fd);
201
202 socket_info->client_fd = -1;
203 socket_info->stop_dtoc = 1;
204
205 /* join other thread to allow it to stop */
206 thread_join(dtoc);
207 thread_free(dtoc);
208
209 return NULL;
210}
211 96
212static void* connection_handler(void* data) 97static void* connection_handler(void* data)
213{ 98{
214 debugserver_error_t derr = DEBUGSERVER_E_SUCCESS; 99 debugserver_error_t derr = DEBUGSERVER_E_SUCCESS;
215 socket_info_t* socket_info = (socket_info_t*)data; 100 socket_info_t* socket_info = (socket_info_t*)data;
216 THREAD_T ctod; 101 char buf[4096];
102
103 int client_fd = socket_info->client_fd;
217 104
218 debug("%s: client_fd = %d\n", __func__, socket_info->client_fd); 105 debug("%s: client_fd = %d\n", __func__, client_fd);
219 106
220 derr = debugserver_client_start_service(socket_info->device, &socket_info->debugserver_client, TOOL_NAME); 107 derr = debugserver_client_start_service(socket_info->device, &socket_info->debugserver_client, TOOL_NAME);
221 if (derr != DEBUGSERVER_E_SUCCESS) { 108 if (derr != DEBUGSERVER_E_SUCCESS) {
222 fprintf(stderr, "Could not start debugserver on device!\nPlease make sure to mount a developer disk image first.\n"); 109 fprintf(stderr, "Could not start debugserver on device!\nPlease make sure to mount a developer disk image first.\n");
223 return NULL; 110 return NULL;
224 } 111 }
225 112 int dbgsvr_fd = -1;
226 /* spawn client to device thread */ 113 idevice_connection_get_fd(socket_info->debugserver_client->parent->connection, &dbgsvr_fd);
227 socket_info->stop_ctod = 0; 114 if (dbgsvr_fd == -1) {
228 if (thread_new(&ctod, thread_client_to_device, data) != 0) { 115 fprintf(stderr, "Could not get debugserver connection fd.\n");
229 fprintf(stderr, "Failed to start client to device thread...\n"); 116 return NULL;
230 } 117 }
231 118
232 /* join the fun */ 119 fd_set fds;
233 thread_join(ctod); 120 int maxfd = 0;
234 thread_free(ctod); 121 FD_ZERO(&fds);
122 FD_SET(client_fd, &fds);
123 if (client_fd > maxfd) maxfd = client_fd;
124 FD_SET(dbgsvr_fd, &fds);
125 if (dbgsvr_fd > maxfd) maxfd = dbgsvr_fd;
126
127 while (!quit_flag) {
128 fd_set read_fds = fds;
129 int ret_sel = select(maxfd+1, &read_fds, NULL, NULL, NULL);
130 if (ret_sel < 0) {
131 perror("select");
132 break;
133 }
134 if (FD_ISSET(client_fd, &read_fds)) {
135 ssize_t n = socket_receive(client_fd, buf, sizeof(buf));
136 if (n < 0) {
137 fprintf(stderr, "Failed to read from client fd: %s\n", strerror(-n));
138 break;
139 } else if (n == 0) {
140 fprintf(stderr, "connection closed\n");
141 break;
142 }
143
144 uint32_t sent = 0;
145 debugserver_client_send(socket_info->debugserver_client, buf, n, &sent);
146 }
147 if (FD_ISSET(dbgsvr_fd, &read_fds)) {
148 uint32_t r = 0;
149 derr = debugserver_client_receive_with_timeout(socket_info->debugserver_client, buf, sizeof(buf), &r, 1);
150 if (r > 0) {
151 socket_send(client_fd, buf, r);
152 } else if (derr != DEBUGSERVER_E_TIMEOUT) {
153 fprintf(stderr, "Failed to read from debugserver (%d)\n", derr);
154 break;
155 }
156 }
157 }
235 158
236 debug("%s: shutting down...\n", __func__); 159 debug("%s: shutting down...\n", __func__);
237 160
@@ -361,6 +284,7 @@ int main(int argc, char *argv[])
361 fprintf(stderr, "Out of memory\n"); 284 fprintf(stderr, "Out of memory\n");
362 exit(EXIT_FAILURE); 285 exit(EXIT_FAILURE);
363 } 286 }
287 el->client_fd = client_fd;
364 el->next = NULL; 288 el->next = NULL;
365 289
366 if (thread_list) { 290 if (thread_list) {
@@ -390,6 +314,8 @@ int main(int argc, char *argv[])
390 /* join and clean up threads */ 314 /* join and clean up threads */
391 while (thread_list) { 315 while (thread_list) {
392 thread_info_t *el = thread_list; 316 thread_info_t *el = thread_list;
317 socket_shutdown(el->client_fd, SHUT_RDWR);
318 socket_close(el->client_fd);
393 thread_join(el->th); 319 thread_join(el->th);
394 thread_free(el->th); 320 thread_free(el->th);
395 thread_list = el->next; 321 thread_list = el->next;