summaryrefslogtreecommitdiffstats
path: root/tools/iproxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/iproxy.c')
-rw-r--r--tools/iproxy.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/tools/iproxy.c b/tools/iproxy.c
new file mode 100644
index 0000000..3cb2894
--- /dev/null
+++ b/tools/iproxy.c
@@ -0,0 +1,241 @@
1/*
2 * iproxy -- proxy that enables tcp service access to iPhone/iPod
3 * via USB cable
4 * TODO: improve code...
5 *
6 * Copyright (c) 2009 Nikias Bassen. All Rights Reserved.
7 * Based upon iTunnel source code, Copyright (c) 2008 Jing Su.
8 * http://www.cs.toronto.edu/~jingsu/itunnel/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24#include <stdio.h>
25#include <stdlib.h>
26#include <fcntl.h>
27#include <stddef.h>
28#include <sys/socket.h>
29#include <sys/un.h>
30#include <unistd.h>
31#include <errno.h>
32#include <arpa/inet.h>
33#include <pthread.h>
34#include "sock_stuff.h"
35#include "usbmuxd.h"
36
37static uint16_t listen_port = 0;
38static uint16_t device_port = 0;
39
40pthread_mutex_t smutex = PTHREAD_MUTEX_INITIALIZER;
41
42struct client_data {
43 int fd;
44 int sfd;
45 volatile int stop_ctos;
46 volatile int stop_stoc;
47};
48
49void *run_stoc_loop(void *arg)
50{
51 struct client_data *cdata = (struct client_data*)arg;
52 int recv_len;
53 int sent;
54 char buffer[131072];
55
56 printf("%s: fd = %d\n", __func__, cdata->fd);
57
58 while (!cdata->stop_stoc && cdata->fd>0 && cdata->sfd>0) {
59 recv_len = recv_buf_timeout(cdata->sfd, buffer, sizeof(buffer), 0, 5000);
60 if (recv_len <= 0) {
61 if (recv_len == 0) {
62 // try again
63 continue;
64 } else {
65 fprintf(stderr, "recv failed: %s\n", strerror(errno));
66 break;
67 }
68 } else {
69// printf("received %d bytes from server\n", recv_len);
70 // send to socket
71 sent = send_buf(cdata->fd, buffer, recv_len);
72 if (sent < recv_len) {
73 if (sent <= 0) {
74 fprintf(stderr, "send failed: %s\n", strerror(errno));
75 break;
76 } else {
77 fprintf(stderr, "only sent %d from %d bytes\n", sent, recv_len);
78 }
79 } else {
80 // sending succeeded, receive from device
81// printf("pushed %d bytes to client\n", sent);
82 }
83 }
84 }
85 close(cdata->fd);
86 cdata->fd = -1;
87 cdata->stop_ctos = 1;
88
89 return NULL;
90}
91
92void *run_ctos_loop(void *arg)
93{
94 struct client_data *cdata = (struct client_data*)arg;
95 int recv_len;
96 int sent;
97 char buffer[131072];
98 pthread_t stoc = 0;
99
100 printf("%s: fd = %d\n", __func__, cdata->fd);
101
102 cdata->stop_stoc = 0;
103 pthread_create(&stoc, NULL, run_stoc_loop, cdata);
104
105 while (!cdata->stop_ctos && cdata->fd>0 && cdata->sfd>0) {
106 recv_len = recv_buf_timeout(cdata->fd, buffer, sizeof(buffer), 0, 5000);
107 if (recv_len <= 0) {
108 if (recv_len == 0) {
109 // try again
110 continue;
111 } else {
112 fprintf(stderr, "recv failed: %s\n", strerror(errno));
113 break;
114 }
115 } else {
116// printf("pulled %d bytes from client\n", recv_len);
117 // send to local socket
118 sent = send_buf(cdata->sfd, buffer, recv_len);
119 if (sent < recv_len) {
120 if (sent <= 0) {
121 fprintf(stderr, "send failed: %s\n", strerror(errno));
122 break;
123 } else {
124 fprintf(stderr, "only sent %d from %d bytes\n", sent, recv_len);
125 }
126 } else {
127 // sending succeeded, receive from device
128// printf("sent %d bytes to server\n", sent);
129 }
130 }
131 }
132 close(cdata->fd);
133 cdata->fd = -1;
134 cdata->stop_stoc = 1;
135
136 pthread_join(stoc, NULL);
137
138 return NULL;
139}
140
141void *acceptor_thread(void *arg)
142{
143 struct client_data *cdata;
144 usbmuxd_scan_result *dev_list = NULL;
145 pthread_t ctos;
146 int count;
147
148 if (!arg) {
149 fprintf(stderr, "invalid client_data provided!\n");
150 return NULL;
151 }
152
153 cdata = (struct client_data*)arg;
154
155 if ((count = usbmuxd_scan(&dev_list)) < 0) {
156 printf("Connecting to usbmuxd failed, terminating.\n");
157 free(dev_list);
158 return NULL;
159 }
160
161 fprintf(stdout, "Number of available devices == %d\n", count);
162
163 if (dev_list == NULL || dev_list[0].handle == 0) {
164 printf("No connected device found, terminating.\n");
165 free(dev_list);
166 return NULL;
167 }
168
169 fprintf(stdout, "Requesting connecion to device handle == %d (serial: %s), port %d\n", dev_list[0].handle, dev_list[0].serial_number, device_port);
170
171 cdata->sfd = usbmuxd_connect(dev_list[0].handle, device_port);
172 free(dev_list);
173 if (cdata->sfd < 0) {
174 fprintf(stderr, "Error connecting to device!\n");
175 } else {
176 cdata->stop_ctos = 0;
177 pthread_create(&ctos, NULL, run_ctos_loop, cdata);
178 pthread_join(ctos, NULL);
179 }
180
181 if (cdata->fd > 0) {
182 close(cdata->fd);
183 }
184 if (cdata->sfd > 0) {
185 close(cdata->sfd);
186 }
187
188 return NULL;
189}
190
191int main(int argc, char **argv)
192{
193 int mysock = -1;
194
195 if (argc != 3) {
196 printf("usage: %s LOCAL_TCP_PORT DEVICE_TCP_PORT\n", argv[0]);
197 return 0;
198 }
199
200 listen_port = atoi(argv[1]);
201 device_port = atoi(argv[2]);
202
203 if (!listen_port) {
204 fprintf(stderr, "Invalid listen_port specified!\n");
205 return -EINVAL;
206 }
207
208 if (!device_port) {
209 fprintf(stderr, "Invalid device_port specified!\n");
210 return -EINVAL;
211 }
212
213 // first create the listening socket endpoint waiting for connections.
214 mysock = create_socket(listen_port);
215 if (mysock < 0) {
216 fprintf(stderr, "Error creating socket: %s\n", strerror(errno));
217 return -errno;
218 } else {
219 pthread_t acceptor;
220 struct sockaddr_in c_addr;
221 socklen_t len = sizeof(struct sockaddr_in);
222 struct client_data cdata;
223 int c_sock;
224 while (1) {
225 printf("waiting for connection\n");
226 c_sock = accept(mysock, (struct sockaddr*)&c_addr, &len);
227 if (c_sock) {
228 printf("accepted connection, fd = %d\n", c_sock);
229 cdata.fd = c_sock;
230 pthread_create(&acceptor, NULL, acceptor_thread, &cdata);
231 pthread_join(acceptor, NULL);
232 } else {
233 break;
234 }
235 }
236 close(c_sock);
237 close(mysock);
238 }
239
240 return 0;
241}