summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/device.c115
1 files changed, 66 insertions, 49 deletions
diff --git a/src/device.c b/src/device.c
index 15f829b..1297a85 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2,6 +2,7 @@
2 usbmuxd - iPhone/iPod Touch USB multiplex server daemon 2 usbmuxd - iPhone/iPod Touch USB multiplex server daemon
3 3
4Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com> 4Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
5Copyright (C) 2014 Mikkel Kamstrup Erlandsen <mikkel.kamstrup@xamarin.com>
5 6
6This program is free software; you can redistribute it and/or modify 7This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by 8it under the terms of the GNU General Public License as published by
@@ -126,6 +127,41 @@ static uint64_t mstime64(void)
126 return tv.tv_sec * 1000 + tv.tv_usec / 1000; 127 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
127} 128}
128 129
130static struct mux_device* get_mux_device_for_id(int device_id)
131{
132 struct mux_device *dev = NULL;
133 pthread_mutex_lock(&device_list_mutex);
134 FOREACH(struct mux_device *cdev, &device_list) {
135 if(cdev->id == device_id) {
136 dev = cdev;
137 break;
138 }
139 } ENDFOREACH
140 pthread_mutex_unlock(&device_list_mutex);
141
142 return dev;
143}
144
145static struct mux_connection* get_mux_connection(int device_id, struct mux_client *client)
146{
147 struct mux_connection *conn = NULL;
148 pthread_mutex_lock(&device_list_mutex);
149 FOREACH(struct mux_device *dev, &device_list) {
150 if(dev->id == device_id) {
151 FOREACH(struct mux_connection *lconn, &dev->connections) {
152 if(lconn->client == client) {
153 conn = lconn;
154 break;
155 }
156 } ENDFOREACH
157 break;
158 }
159 } ENDFOREACH
160 pthread_mutex_unlock(&device_list_mutex);
161
162 return conn;
163}
164
129static int get_next_device_id(void) 165static int get_next_device_id(void)
130{ 166{
131 while(1) { 167 while(1) {
@@ -274,15 +310,7 @@ static void connection_teardown(struct mux_connection *conn)
274 310
275int device_start_connect(int device_id, uint16_t dport, struct mux_client *client) 311int device_start_connect(int device_id, uint16_t dport, struct mux_client *client)
276{ 312{
277 struct mux_device *dev = NULL; 313 struct mux_device *dev = get_mux_device_for_id(device_id);
278 pthread_mutex_lock(&device_list_mutex);
279 FOREACH(struct mux_device *cdev, &device_list) {
280 if(cdev->id == device_id) {
281 dev = cdev;
282 break;
283 }
284 } ENDFOREACH
285 pthread_mutex_unlock(&device_list_mutex);
286 if(!dev) { 314 if(!dev) {
287 usbmuxd_log(LL_WARNING, "Attempted to connect to nonexistent device %d", device_id); 315 usbmuxd_log(LL_WARNING, "Attempted to connect to nonexistent device %d", device_id);
288 return -RESULT_BADDEV; 316 return -RESULT_BADDEV;
@@ -369,6 +397,19 @@ static void update_connection(struct mux_connection *conn)
369 client_set_events(conn->client, conn->events); 397 client_set_events(conn->client, conn->events);
370} 398}
371 399
400static int send_tcp_ack(struct mux_connection *conn)
401{
402 if(send_tcp(conn, TH_ACK, NULL, 0) < 0) {
403 usbmuxd_log(LL_ERROR, "Error sending TCP ACK (%d->%d)", conn->sport, conn->dport);
404 connection_teardown(conn);
405 return -1;
406 }
407
408 update_connection(conn);
409
410 return 0;
411}
412
372/** 413/**
373 * Flush input and output buffers for a client connection. 414 * Flush input and output buffers for a client connection.
374 * 415 *
@@ -380,21 +421,7 @@ static void update_connection(struct mux_connection *conn)
380 */ 421 */
381void device_client_process(int device_id, struct mux_client *client, short events) 422void device_client_process(int device_id, struct mux_client *client, short events)
382{ 423{
383 // Find the connection for the given device_id 424 struct mux_connection *conn = get_mux_connection(device_id, client);
384 struct mux_connection *conn = NULL;
385 pthread_mutex_lock(&device_list_mutex);
386 FOREACH(struct mux_device *dev, &device_list) {
387 if(dev->id == device_id) {
388 FOREACH(struct mux_connection *lconn, &dev->connections) {
389 if(lconn->client == client) {
390 conn = lconn;
391 break;
392 }
393 } ENDFOREACH
394 break;
395 }
396 } ENDFOREACH
397 pthread_mutex_unlock(&device_list_mutex);
398 425
399 if(!conn) { 426 if(!conn) {
400 usbmuxd_log(LL_WARNING, "Could not find connection for device %d client %p", device_id, client); 427 usbmuxd_log(LL_WARNING, "Could not find connection for device %d client %p", device_id, client);
@@ -405,8 +432,8 @@ void device_client_process(int device_id, struct mux_client *client, short event
405 int res; 432 int res;
406 int size; 433 int size;
407 if(events & POLLOUT) { 434 if(events & POLLOUT) {
408 // Client is ready to receive data, send what we have 435 // Client is ready to receive data, send what we have
409 // in the client's connection buffer 436 // in the client's connection buffer
410 size = client_write(conn->client, conn->ib_buf, conn->ib_size); 437 size = client_write(conn->client, conn->ib_buf, conn->ib_size);
411 if(size <= 0) { 438 if(size <= 0) {
412 usbmuxd_log(LL_DEBUG, "error writing to client (%d)", size); 439 usbmuxd_log(LL_DEBUG, "error writing to client (%d)", size);
@@ -422,8 +449,8 @@ void device_client_process(int device_id, struct mux_client *client, short event
422 } 449 }
423 } 450 }
424 if(events & POLLIN) { 451 if(events & POLLIN) {
425 // There is inbound trafic on the client socket, 452 // There is inbound trafic on the client socket,
426 // convert it to tcp and send to the device 453 // convert it to tcp and send to the device
427 size = client_read(conn->client, conn->ob_buf, conn->sendable); 454 size = client_read(conn->client, conn->ob_buf, conn->sendable);
428 if(size <= 0) { 455 if(size <= 0) {
429 if (size < 0) { 456 if (size < 0) {
@@ -475,23 +502,12 @@ static void connection_device_input(struct mux_connection *conn, unsigned char *
475 502
476void device_abort_connect(int device_id, struct mux_client *client) 503void device_abort_connect(int device_id, struct mux_client *client)
477{ 504{
478 pthread_mutex_lock(&device_list_mutex); 505 struct mux_connection *conn = get_mux_connection(device_id, client);
479 FOREACH(struct mux_device *dev, &device_list) { 506 if (conn) {
480 if(dev->id == device_id) { 507 connection_teardown(conn);
481 FOREACH(struct mux_connection *conn, &dev->connections) { 508 } else {
482 if(conn->client == client) { 509 usbmuxd_log(LL_WARNING, "Attempted to abort for nonexistent connection for device %d", device_id);
483 connection_teardown(conn); 510 }
484 pthread_mutex_unlock(&device_list_mutex);
485 return;
486 }
487 } ENDFOREACH
488 pthread_mutex_unlock(&device_list_mutex);
489 usbmuxd_log(LL_WARNING, "Attempted to abort for nonexistent connection for device %d", device_id);
490 return;
491 }
492 } ENDFOREACH
493 pthread_mutex_unlock(&device_list_mutex);
494 usbmuxd_log(LL_WARNING, "Attempted to abort connection for nonexistent device %d", device_id);
495} 511}
496 512
497static void device_version_input(struct mux_device *dev, struct version_header *vh) 513static void device_version_input(struct mux_device *dev, struct version_header *vh)
@@ -543,6 +559,7 @@ static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned
543 return; 559 return;
544 } 560 }
545 561
562 // Find the connection on this device that has the right sport and dport
546 FOREACH(struct mux_connection *lconn, &dev->connections) { 563 FOREACH(struct mux_connection *lconn, &dev->connections) {
547 if(lconn->sport == sport && lconn->dport == dport) { 564 if(lconn->sport == sport && lconn->dport == dport) {
548 conn = lconn; 565 conn = lconn;
@@ -603,6 +620,9 @@ static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned
603 connection_teardown(conn); 620 connection_teardown(conn);
604 } else { 621 } else {
605 connection_device_input(conn, payload, payload_length); 622 connection_device_input(conn, payload, payload_length);
623
624 // Device likes it best when we are prompty ACKing data
625 send_tcp_ack(conn);
606 } 626 }
607 } 627 }
608} 628}
@@ -866,10 +886,7 @@ void device_check_timeouts(void)
866 (conn->flags & CONN_ACK_PENDING) && 886 (conn->flags & CONN_ACK_PENDING) &&
867 (ct - conn->last_ack_time) > ACK_TIMEOUT) { 887 (ct - conn->last_ack_time) > ACK_TIMEOUT) {
868 usbmuxd_log(LL_DEBUG, "Sending ACK due to expired timeout (%" PRIu64 " -> %" PRIu64 ")", conn->last_ack_time, ct); 888 usbmuxd_log(LL_DEBUG, "Sending ACK due to expired timeout (%" PRIu64 " -> %" PRIu64 ")", conn->last_ack_time, ct);
869 if(send_tcp(conn, TH_ACK, NULL, 0) < 0) { 889 send_tcp_ack(conn);
870 usbmuxd_log(LL_ERROR, "Error sending TCP ACK to device %d (%d->%d)", dev->id, conn->sport, conn->dport);
871 connection_teardown(conn);
872 }
873 } 890 }
874 } ENDFOREACH 891 } ENDFOREACH
875 } 892 }