diff options
| -rw-r--r-- | src/device.c | 115 |
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 | ||
| 4 | Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com> | 4 | Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com> |
| 5 | Copyright (C) 2014 Mikkel Kamstrup Erlandsen <mikkel.kamstrup@xamarin.com> | ||
| 5 | 6 | ||
| 6 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by | 8 | it 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 | ||
| 130 | static 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 | |||
| 145 | static 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 | |||
| 129 | static int get_next_device_id(void) | 165 | static 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 | ||
| 275 | int device_start_connect(int device_id, uint16_t dport, struct mux_client *client) | 311 | int 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 | ||
| 400 | static 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 | */ |
| 381 | void device_client_process(int device_id, struct mux_client *client, short events) | 422 | void 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 | ||
| 476 | void device_abort_connect(int device_id, struct mux_client *client) | 503 | void 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 | ||
| 497 | static void device_version_input(struct mux_device *dev, struct version_header *vh) | 513 | static 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 | } |
