summaryrefslogtreecommitdiffstats
path: root/src/usbmux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usbmux.c')
-rw-r--r--src/usbmux.c1259
1 files changed, 1259 insertions, 0 deletions
diff --git a/src/usbmux.c b/src/usbmux.c
new file mode 100644
index 0000000..e86e3bc
--- /dev/null
+++ b/src/usbmux.c
@@ -0,0 +1,1259 @@
1/*
2 * Copyright (c) 2008 Jing Su. All Rights Reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#include <stdint.h>
19#include <stdarg.h>
20#include <stdlib.h>
21#include <string.h>
22#include <usb.h>
23#include <stdio.h>
24#include <arpa/inet.h>
25#include <errno.h>
26#include <pthread.h>
27#include "usbmux.h"
28
29#define BULKIN 0x85
30#define BULKOUT 0x04
31#define HEADERLEN 28
32
33static const uint8_t TCP_FIN = 1;
34static const uint8_t TCP_SYN = 1 << 1;
35static const uint8_t TCP_RST = 1 << 2;
36static const uint8_t TCP_PSH = 1 << 3;
37static const uint8_t TCP_ACK = 1 << 4;
38static const uint8_t TCP_URG = 1 << 5;
39
40// I have trouble figuring out how to properly manage the windowing to
41// the device. It keeps sending back 512 and seems to drop off a cliff
42// when the device gets overwhelmed. In addition, the device likes to
43// panic and send out RESETS before the window hits zero. Also, waiting
44// for responses seems to not be a winning strategy.
45//
46// Since I'm not sure how in the hell to interpret the window sizes that
47// the device is sending back to us, I've figured out some magic number
48// constants which seem to work okay.
49static const uint32_t WINDOW_MAX = 5 * 1024;
50static const uint32_t WINDOW_INCREMENT = 512;
51
52typedef struct {
53 char *buffer;
54 int leftover;
55 int capacity;
56} receivebuf_t;
57
58struct usbmux_device_int {
59 struct usb_dev_handle *usbdev;
60 struct usb_device *__device;
61 receivebuf_t usbReceive;
62};
63
64typedef struct {
65 uint32_t type, length, major, minor, allnull;
66} usbmux_version_header;
67
68typedef struct {
69 uint32_t type, length;
70 uint16_t sport, dport;
71 uint32_t scnt, ocnt;
72 uint8_t offset, tcp_flags;
73 uint16_t window, nullnull, length16;
74} usbmux_tcp_header;
75
76struct usbmux_client_int {
77 usbmux_tcp_header *header;
78 usbmux_device_t device;
79
80 char *recv_buffer;
81 int r_len;
82 pthread_cond_t wait;
83
84 // this contains a conditional variable which usb-writers can wait
85 // on while waiting for window updates from the device.
86 pthread_cond_t wr_wait;
87 // I'm going to do something really cheesy here. We are going to
88 // just record the most recent scnt that we are expecting to hear
89 // back on. We will actually halt progress by limiting the number
90 // of outstanding un-acked bulk sends that we have beamed out.
91 uint32_t wr_pending_scnt;
92 long wr_window;
93
94 pthread_mutex_t mutex;
95
96 // this variable is not protected by the mutex. This will always
97 // be E_SUCCESS, unless an error of some kind breaks this stream.
98 // this will then be set to the error that caused the broken stream.
99 // no further operations other than free_client will be allowed.
100 int error;
101
102 int cleanup;
103};
104
105
106static pthread_mutex_t usbmuxmutex = PTHREAD_MUTEX_INITIALIZER;
107static usbmux_client_t *connlist = NULL;
108static int clients = 0;
109
110
111/**
112 */
113int toto_debug = 0;
114
115void usbmux_set_debug(int e)
116{
117 toto_debug = e;
118}
119
120void log_debug_msg(const char *format, ...)
121{
122#ifndef STRIP_DEBUG_CODE
123 va_list args;
124 /* run the real fprintf */
125 va_start(args, format);
126
127 if (toto_debug)
128 vfprintf(stderr, format, args);
129
130 va_end(args);
131#endif
132}
133
134#ifdef DEBUG
135/**
136 * for debugging purposes.
137 */
138static void print_buffer(const char *data, const int length)
139{
140 if (toto_debug <= 0) {
141 return;
142 }
143 int i;
144 int j;
145 unsigned char c;
146
147 for (i = 0; i < length; i += 16) {
148 printf("%04x: ", i);
149 for (j = 0; j < 16; j++) {
150 if (i + j >= length) {
151 printf(" ");
152 continue;
153 }
154 printf("%02hhx ", *(data + i + j));
155 }
156 printf(" | ");
157 for (j = 0; j < 16; j++) {
158 if (i + j >= length)
159 break;
160 c = *(data + i + j);
161 if ((c < 32) || (c > 127)) {
162 printf(".");
163 continue;
164 }
165 printf("%c", c);
166 }
167 printf("\n");
168 }
169 printf("\n");
170}
171#endif
172
173void hton_header(usbmux_tcp_header * hdr)
174{
175 if (hdr) {
176 hdr->length = htonl(hdr->length);
177 hdr->scnt = htonl(hdr->scnt);
178 hdr->ocnt = htonl(hdr->ocnt);
179 hdr->length16 = htons(hdr->length16);
180 }
181}
182
183void ntoh_header(usbmux_tcp_header * hdr)
184{
185 if (hdr) {
186 hdr->length = ntohl(hdr->length);
187 hdr->scnt = ntohl(hdr->scnt);
188 hdr->ocnt = ntohl(hdr->ocnt);
189 hdr->length16 = ntohs(hdr->length16);
190 }
191}
192
193/** Creates a USBMux header containing version information
194 *
195 * @return A USBMux header
196 */
197usbmux_version_header *version_header()
198{
199 usbmux_version_header *version =
200 (usbmux_version_header *) malloc(sizeof(usbmux_version_header));
201 version->type = 0;
202 version->length = htonl(20);
203 version->major = htonl(1);
204 version->minor = 0;
205 version->allnull = 0;
206 return version;
207}
208
209/**
210 * This function sets the configuration of the given device to 3
211 * and claims the interface 1. If usb_set_configuration fails, it detaches
212 * the kernel driver that blocks the device, and retries configuration.
213 *
214 * @param device which device to configure
215 */
216static int usbmux_config_usb_device(usbmux_device_t device)
217{
218 int ret;
219 int bytes;
220 char buf[512];
221
222#if 0
223 log_debug_msg("checking configuration...\n");
224 if (device->__device->config->bConfigurationValue != 3) {
225 log_debug_msg
226 ("WARNING: usb device configuration is not 3 as expected!\n");
227 }
228
229 log_debug_msg("setting configuration...\n");
230 ret = usb_set_configuration(device->device, 3);
231 if (ret != 0) {
232 log_debug_msg("Hm, usb_set_configuration returned %d: %s\n", ret,
233 strerror(-ret));
234#if LIBUSB_HAS_GET_DRIVER_NP
235 log_debug_msg("trying to fix:\n");
236 log_debug_msg("-> detaching kernel driver... ");
237 ret =
238 usb_detach_kernel_driver_np(device->device,
239 device->__device->config->
240 interface->altsetting->
241 bInterfaceNumber);
242 if (ret != 0) {
243 log_debug_msg("usb_detach_kernel_driver_np returned %d: %s\n",
244 ret, strerror(-ret));
245 } else {
246 log_debug_msg("done.\n");
247 log_debug_msg("setting configuration again... ");
248 ret = usb_set_configuration(device->device, 3);
249 if (ret != 0) {
250 log_debug_msg
251 ("Error: usb_set_configuration returned %d: %s\n", ret,
252 strerror(-ret));
253 log_debug_msg("--> trying to continue anyway...\n");
254 } else {
255 log_debug_msg("done.\n");
256 }
257 }
258#else
259 log_debug_msg("--> trying to continue anyway...\n");
260#endif
261 } else {
262 log_debug_msg("done.\n");
263 }
264#endif
265
266 log_debug_msg("claiming interface... ");
267 ret = usb_claim_interface(device->usbdev, 1);
268 if (ret != 0) {
269 log_debug_msg("Error: usb_claim_interface returned %d: %s\n", ret,
270 strerror(-ret));
271 return -ENODEV;
272 } else {
273 log_debug_msg("done.\n");
274 }
275
276 do {
277 bytes = usb_bulk_read(device->usbdev, BULKIN, buf, 512, 800);
278 } while (bytes > 0);
279
280 return 0;
281}
282
283/**
284 * Given a USB bus and device number, returns a device handle to the device on
285 * that bus. To aid compatibility with future devices, this function does not
286 * check the vendor and device IDs! To do that, you should use
287 * usbmux_get_device() or a system-specific API (e.g. HAL).
288 *
289 * @param bus_n The USB bus number.
290 * @param dev_n The USB device number.
291 * @param device A pointer to a usbmux_device_t, which must be set to NULL upon
292 * calling usbmux_get_specific_device, which will be filled with a device
293 * descriptor on return.
294 * @return 0 if ok, otherwise a negative errno value.
295 */
296int usbmux_get_specific_device(int bus_n, int dev_n,
297 usbmux_device_t * device)
298{
299 struct usb_bus *bus;
300 struct usb_device *dev;
301 usbmux_version_header *version;
302 int bytes = 0;
303
304 //check we can actually write in device
305 if (!device || (device && *device))
306 return -EINVAL;
307
308 usbmux_device_t newdevice =
309 (usbmux_device_t) malloc(sizeof(struct usbmux_device_int));
310
311 // Initialize the struct
312 newdevice->usbdev = NULL;
313 newdevice->__device = NULL;
314
315 // don't forget these:
316 newdevice->usbReceive.buffer = NULL;
317 newdevice->usbReceive.leftover = 0;
318 newdevice->usbReceive.capacity = 0;
319
320 // Initialize libusb
321 usb_init();
322 usb_find_busses();
323 usb_find_devices();
324
325 // Set the device configuration
326 for (bus = usb_get_busses(); bus; bus = bus->next)
327 //if (bus->location == bus_n)
328 for (dev = bus->devices; dev != NULL; dev = dev->next)
329 if (dev->devnum == dev_n) {
330 newdevice->__device = dev;
331 newdevice->usbdev = usb_open(newdevice->__device);
332 if (usbmux_config_usb_device(newdevice) == 0) {
333 goto found;
334 }
335 }
336
337 usbmux_free_device(newdevice);
338
339 log_debug_msg("usbmux_get_specific_device: device not found\n");
340 return -ENODEV;
341
342 found:
343 // Send the version command to the device
344 version = version_header();
345 bytes =
346 usb_bulk_write(newdevice->usbdev, BULKOUT, (char *) version,
347 sizeof(*version), 800);
348 if (bytes < 20) {
349 log_debug_msg("%s: libusb did NOT send enough!\n", __func__);
350 if (bytes < 0) {
351 log_debug_msg("%s: libusb gave me the error %d: %s (%s)\n",
352 __func__, bytes, usb_strerror(),
353 strerror(-bytes));
354 }
355 }
356 // Read the device's response
357 bytes =
358 usb_bulk_read(newdevice->usbdev, BULKIN, (char *) version,
359 sizeof(*version), 800);
360
361 // Check for bad response
362 if (bytes < 20) {
363 free(version);
364 usbmux_free_device(newdevice);
365 log_debug_msg("%s: Invalid version message -- header too short.\n",
366 __func__);
367 if (bytes < 0) {
368 log_debug_msg("%s: libusb error message %d: %s (%s)\n",
369 __func__, bytes, usb_strerror(),
370 strerror(-bytes));
371 return bytes;
372 }
373 return -EBADMSG;
374 }
375 // Check for correct version
376 if (ntohl(version->major) == 1 && ntohl(version->minor) == 0) {
377 // We're all ready to roll.
378 log_debug_msg("%s: success\n", __func__);
379 free(version);
380 *device = newdevice;
381 return 0;
382 } else {
383 // Bad header
384 usbmux_free_device(newdevice);
385 free(version);
386 log_debug_msg("%s: Received a bad header/invalid version number.",
387 __func__);
388 return -EBADMSG;
389 }
390
391 // If it got to this point it's gotta be bad
392 log_debug_msg("%s: Unknown error.\n", __func__);
393 usbmux_free_device(newdevice);
394 free(version);
395 return -EBADMSG; // if it got to this point it's gotta be bad
396}
397
398/** Cleans up an usbmux_device_t structure, then frees the structure itself.
399 * This is a library-level function; deals directly with the device to tear
400 * down relations, but otherwise is mostly internal.
401 *
402 * @param device A pointer to an usbmux_device_t structure.
403 */
404int usbmux_free_device(usbmux_device_t device)
405{
406 char buf[512];
407 int bytes;
408
409 if (!device)
410 return -EINVAL;
411 int ret = 0;
412
413 if (device->usbdev) {
414 do {
415 bytes = usb_bulk_read(device->usbdev, BULKIN, buf, 512, 800);
416 } while (bytes > 0);
417 }
418
419 if (bytes < 0) {
420 ret = bytes;
421 }
422
423 if (device->usbReceive.buffer) {
424 free(device->usbReceive.buffer);
425 }
426 if (device->usbdev) {
427 usb_release_interface(device->usbdev, 1);
428 usb_close(device->usbdev);
429 ret = 0;
430 }
431 free(device);
432
433 return ret;
434}
435
436
437
438/** Sends data to the device
439 * This is a low-level (i.e. directly to device) function.
440 *
441 * @param device The device to send data to
442 * @param data The data to send
443 * @param datalen The length of the data
444 * @return The number of bytes sent, or -ERRNO on error
445 */
446int send_to_device(usbmux_device_t device, char *data, int datalen)
447{
448 if (!device)
449 return -EINVAL;
450
451 int timeout = 1000;
452 int retrycount = 0;
453 int bytes = 0;
454
455#ifdef DEBUG
456#ifdef DEBUG_MORE
457 printf("===============================\n%s: trying to send\n",
458 __func__);
459 print_buffer(data, datalen);
460 printf("===============================\n");
461#endif
462#endif
463 do {
464 if (retrycount > 3) {
465 log_debug_msg
466 ("EPIC FAIL! aborting on retry count overload.\n");
467 return -ECOMM;
468 }
469
470 bytes =
471 usb_bulk_write(device->usbdev, BULKOUT, data, datalen,
472 timeout);
473 if (bytes == -ETIMEDOUT) {
474 // timed out waiting for write.
475 log_debug_msg("usb_bulk_write timeout error.\n");
476 return bytes;
477 } else if (bytes < 0) {
478 log_debug_msg
479 ("usb_bulk_write failed with error. err:%d (%s)(%s)\n",
480 bytes, usb_strerror(), strerror(-bytes));
481 return bytes;
482 } else if (bytes == 0) {
483 log_debug_msg("usb_bulk_write sent nothing. retrying.\n");
484 timeout = timeout * 4;
485 retrycount++;
486 continue;
487 } else if (bytes < datalen) {
488 log_debug_msg
489 ("usb_bulk_write failed to send full dataload. %d of %d\n",
490 bytes, datalen);
491 timeout = timeout * 4;
492 retrycount++;
493 data += bytes;
494 datalen -= bytes;
495 continue;
496 }
497 } while (0); // fall out
498
499#ifdef DEBUG
500 if (bytes > 0) {
501 if (toto_debug > 0) {
502 printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
503 printf("%s: sent to device\n", __func__);
504 print_buffer(data, bytes);
505 printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
506 }
507 }
508#endif
509 return bytes;
510}
511
512/** Receives data from the device
513 * This function is a low-level (i.e. direct from device) function.
514 *
515 * @param device The device to receive data from
516 * @param data Where to put data read
517 * @param datalen How much data to read in
518 * @param timeout How many milliseconds to wait for data
519 *
520 * @return How many bytes were read in, or -1 on error.
521 */
522int recv_from_device_timeout(usbmux_device_t device, char *data,
523 int datalen, int timeoutmillis)
524{
525 if (!device)
526 return -EINVAL;
527 //log_debug_msg("%s: attempting to receive %i bytes\n", __func__, datalen);
528
529 int bytes =
530 usb_bulk_read(device->usbdev, BULKIN, data, datalen,
531 timeoutmillis);
532 // There are some things which are errors, others which are no problem.
533 // It's not documented in libUSB, but it seems that the error values
534 // returned are just negated ERRNO values.
535 if (bytes < 0) {
536 if (bytes == -ETIMEDOUT) {
537 // ignore this. it just means timeout reached before we
538 // picked up any data. no problem.
539 return 0;
540 } else {
541 fprintf(stderr, "%s: libusb gave me the error %d: %s (%s)\n",
542 __func__, bytes, usb_strerror(), strerror(-bytes));
543 log_debug_msg("%s: libusb gave me the error %d: %s (%s)\n",
544 __func__, bytes, usb_strerror(),
545 strerror(-bytes));
546 }
547 return bytes;
548 }
549#ifdef DEBUG
550 if (bytes > 0) {
551 if (toto_debug > 0) {
552 printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
553 printf("%s: received from device:\n", __func__);
554 print_buffer(data, bytes);
555 printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
556 }
557 }
558#endif
559
560 return bytes;
561}
562
563/** Creates a USBMux packet for the given set of ports.
564 *
565 * @param s_port The source port for the connection.
566 * @param d_port The destination port for the connection.
567 *
568 * @return A USBMux packet
569 */
570usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port)
571{
572 usbmux_tcp_header *conn =
573 (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header));
574 conn->type = htonl(6);
575 conn->length = HEADERLEN;
576 conn->sport = htons(s_port);
577 conn->dport = htons(d_port);
578 conn->scnt = 0;
579 conn->ocnt = 0;
580 conn->offset = 0x50;
581 conn->window = htons(0x0200);
582 conn->nullnull = 0x0000;
583 conn->length16 = HEADERLEN;
584 return conn;
585}
586
587
588/** Removes a connection from the list of connections made.
589 * The list of connections is necessary for buffering.
590 *
591 * @param connection The connection to delete from the tracking list.
592 */
593static void delete_connection(usbmux_client_t connection)
594{
595 usbmux_client_t *newlist = NULL;
596
597 pthread_mutex_lock(&usbmuxmutex);
598
599 // update the global list of connections
600 if (clients > 1) {
601 newlist =
602 (usbmux_client_t *) malloc(sizeof(usbmux_client_t) *
603 (clients - 1));
604 int i = 0, j = 0;
605 for (i = 0; i < clients; i++) {
606 if (connlist[i] == connection)
607 continue;
608 else {
609 newlist[j] = connlist[i];
610 j++;
611 }
612 }
613 }
614 if (connlist) {
615 free(connlist);
616 }
617 connlist = newlist;
618 clients--;
619
620 // free up this connection
621 pthread_mutex_lock(&connection->mutex);
622 if (connection->recv_buffer) {
623 free(connection->recv_buffer);
624 connection->recv_buffer = NULL;
625 }
626 if (connection->header) {
627 free(connection->header);
628 connection->header = NULL;
629 }
630 connection->r_len = 0;
631 pthread_mutex_unlock(&connection->mutex);
632 pthread_mutex_destroy(&connection->mutex);
633 free(connection);
634
635 pthread_mutex_unlock(&usbmuxmutex);
636}
637
638/** Adds a connection to the list of connections made.
639 * The connection list is necessary for buffering.
640 *
641 * @param connection The connection to add to the global list of connections.
642 */
643
644static void add_connection(usbmux_client_t connection)
645{
646 pthread_mutex_lock(&usbmuxmutex);
647 usbmux_client_t *newlist =
648 (usbmux_client_t *) realloc(connlist,
649 sizeof(usbmux_client_t) * (clients +
650 1));
651 newlist[clients] = connection;
652 connlist = newlist;
653 clients++;
654 pthread_mutex_unlock(&usbmuxmutex);
655}
656
657/**
658 * Get a source port number that is not used by one of our connections
659 * This is needed for us to make sure we are not sending on another
660 * connection.
661 */
662static uint16_t get_free_port()
663{
664 int i;
665 uint16_t newport = 30000;
666 int cnt = 0;
667
668 pthread_mutex_lock(&usbmuxmutex);
669 while (1) {
670 cnt = 0;
671 for (i = 0; i < clients; i++) {
672 if (ntohs(connlist[i]->header->sport) == newport) {
673 cnt++;
674 }
675 }
676 if (cnt == 0) {
677 // newport is not used in our list of connections!
678 break;
679 } else {
680 newport++;
681 if (newport < 30000) {
682 // if all ports from 30000 to 65535 are in use,
683 // the value wraps (16-bit overflow)
684 // return 0, no port is available.
685 // This should not happen, but just in case ;)
686 newport = 0;
687 break;
688 }
689 }
690 }
691 pthread_mutex_unlock(&usbmuxmutex);
692
693 return newport;
694}
695
696/** Initializes a connection to 'device' with source port s_port and destination port d_port
697 *
698 * @param device The device to initialize a connection on.
699 * @param src_port The source port
700 * @param dst_port The destination port -- 0xf27e for lockdownd.
701 * @param client A mux TCP header for the connection which is used for tracking and data transfer.
702 * @return 0 on success, a negative errno value otherwise.
703 */
704int usbmux_new_client(usbmux_device_t device, uint16_t src_port,
705 uint16_t dst_port, usbmux_client_t * client)
706{
707 if (!device || !dst_port)
708 return -EINVAL;
709
710 src_port = get_free_port();
711
712 if (!src_port) {
713 // this is a special case, if we get 0, this is not good, so
714 return -EISCONN; // TODO: error code suitable?
715 }
716 // Initialize connection stuff
717 usbmux_client_t new_connection =
718 (usbmux_client_t) malloc(sizeof(struct usbmux_client_int));
719 new_connection->header = new_mux_packet(src_port, dst_port);
720
721 // send TCP syn
722 if (new_connection && new_connection->header) {
723 int err = 0;
724 new_connection->header->tcp_flags = TCP_SYN;
725 new_connection->header->length = new_connection->header->length;
726 new_connection->header->length16 =
727 new_connection->header->length16;
728 new_connection->header->scnt = 0;
729 new_connection->header->ocnt = 0;
730 new_connection->device = device;
731 new_connection->recv_buffer = NULL;
732 new_connection->r_len = 0;
733 pthread_cond_init(&new_connection->wait, NULL);
734 pthread_mutex_init(&new_connection->mutex, NULL);
735 pthread_cond_init(&new_connection->wr_wait, NULL);
736 new_connection->wr_pending_scnt = 0;
737 new_connection->wr_window = 0;
738 add_connection(new_connection);
739 new_connection->error = 0;
740 new_connection->cleanup = 0;
741 hton_header(new_connection->header);
742 log_debug_msg("%s: send_to_device (%d --> %d)\n", __func__,
743 ntohs(new_connection->header->sport),
744 ntohs(new_connection->header->dport));
745 err =
746 send_to_device(device, (char *) new_connection->header,
747 sizeof(usbmux_tcp_header));
748 if (err >= 0) {
749 *client = new_connection;
750 return 0;
751 } else {
752 delete_connection(new_connection);
753 return err;
754 }
755 }
756 // if we get to this point it's probably bad
757 return -ENOMEM;
758}
759
760/** Cleans up the given USBMux connection.
761 * @note Once a connection is closed it may not be used again.
762 *
763 * @param connection The connection to close.
764 *
765 * @return 0 on success or a negative errno value on error.
766 */
767int usbmux_free_client(usbmux_client_t client)
768{
769 if (!client || !client->device)
770 return -EINVAL;
771
772 int err = 0;
773 int result = 0;
774 pthread_mutex_lock(&client->mutex);
775 client->header->tcp_flags = TCP_FIN;
776 client->header->length = 0x1C;
777 client->header->window = 0;
778 client->header->length16 = 0x1C;
779 hton_header(client->header);
780
781 err =
782 send_to_device(client->device, (char *) client->header,
783 sizeof(usbmux_tcp_header));
784 if (err < 0) {
785 log_debug_msg("%s: error sending TCP_FIN\n", __func__);
786 result = err;
787 }
788
789 client->cleanup = 1;
790
791 // make sure we don't have any last-minute laggards waiting on this.
792 // I put it after the mutex unlock because we have cases where the
793 // conditional wait is dependent on re-grabbing that mutex.
794 pthread_cond_broadcast(&client->wait);
795 pthread_cond_destroy(&client->wait);
796 pthread_cond_broadcast(&client->wr_wait);
797 pthread_cond_destroy(&client->wr_wait);
798
799 pthread_mutex_unlock(&client->mutex);
800
801 return result;
802}
803
804/** Sends the given data over the selected connection.
805 *
806 * @param client The client we're sending data on.
807 * @param data A pointer to the data to send.
808 * @param datalen How much data we're sending.
809 * @param sent_bytes The number of bytes sent, minus the header (28)
810 *
811 * @return 0 on success or a negative errno value on error.
812 */
813int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen,
814 uint32_t * sent_bytes)
815{
816 if (!client->device || !client || !sent_bytes)
817 return -EINVAL;
818
819 if (client->error < 0) {
820 return client->error;
821 }
822
823 *sent_bytes = 0;
824 pthread_mutex_lock(&client->mutex);
825
826 int sendresult = 0;
827 uint32_t blocksize = 0;
828 if (client->wr_window <= 0) {
829 struct timespec ts;
830 clock_gettime(CLOCK_REALTIME, &ts);
831 //ts.tv_sec += 1;
832 ts.tv_nsec += 750 * 1000;
833 if (pthread_cond_timedwait(&client->wait, &client->mutex, &ts) ==
834 ETIMEDOUT) {
835 // timed out. optimistically grow the window and try to make progress
836 client->wr_window += WINDOW_INCREMENT;
837 }
838 }
839
840 blocksize = sizeof(usbmux_tcp_header) + datalen;
841
842 // client->scnt and client->ocnt should already be in host notation...
843 // we don't need to change them juuuust yet.
844 char *buffer = (char *) malloc(blocksize + 2); // allow 2 bytes of safety padding
845 // Set the length
846 client->header->length = blocksize;
847 client->header->length16 = blocksize;
848
849 // Put header into big-endian notation
850 hton_header(client->header);
851 // Concatenation of stuff in the buffer.
852 memcpy(buffer, client->header, sizeof(usbmux_tcp_header));
853 memcpy(buffer + sizeof(usbmux_tcp_header), data, datalen);
854
855 log_debug_msg("%s: send_to_device(%d --> %d)\n", __func__,
856 ntohs(client->header->sport),
857 ntohs(client->header->dport));
858 sendresult = send_to_device(client->device, buffer, blocksize);
859 // Now that we've sent it off, we can clean up after our sloppy selves.
860 if (buffer)
861 free(buffer);
862
863 // revert header fields that have been swapped before trying to send
864 ntoh_header(client->header);
865
866 // update counts ONLY if the send succeeded.
867 if ((uint32_t) sendresult == blocksize) {
868 // Re-calculate scnt
869 client->header->scnt += datalen;
870 client->wr_window -= blocksize;
871 }
872
873 pthread_mutex_unlock(&client->mutex);
874
875 if (sendresult == -ETIMEDOUT || sendresult == 0) {
876 // no problem for now...
877 *sent_bytes = 0;
878 return -ETIMEDOUT;
879 } else if (sendresult < 0) {
880 return sendresult;
881 } else if ((uint32_t) sendresult == blocksize) {
882 // actual number of data bytes sent.
883 *sent_bytes = sendresult - HEADERLEN;
884 return 0;
885 } else {
886 fprintf(stderr,
887 "usbsend managed to dump a packet that is not full size. %d of %d\n",
888 sendresult, blocksize);
889 return -EBADMSG;
890 }
891}
892
893/** append the packet's DATA to the receive buffer for the client.
894 *
895 * this has a few other corner-case functions:
896 * 1. this will properly handle the handshake syn+ack.
897 * 2. for all receives, this will appropriately update the ocnt.
898 *
899 * @return number of bytes consumed (header + data)
900 */
901uint32_t append_receive_buffer(usbmux_client_t client, char *packet)
902{
903 if (client == NULL || packet == NULL)
904 return 0;
905
906 usbmux_tcp_header *header = (usbmux_tcp_header *) packet;
907 char *data = &packet[HEADERLEN];
908 uint32_t packetlen = ntohl(header->length);
909 uint32_t datalen = packetlen - HEADERLEN;
910
911 int dobroadcast = 0;
912
913 pthread_mutex_lock(&client->mutex);
914
915 // we need to handle a few corner case tasks and book-keeping which
916 // falls on our responsibility because we are the ones reading in
917 // feedback.
918 if (client->header->scnt == 0 && client->header->ocnt == 0) {
919 log_debug_msg("client is still waiting for handshake.\n");
920 if (header->tcp_flags == (TCP_SYN | TCP_ACK)) {
921 log_debug_msg("yes, got syn+ack ; replying with ack.\n");
922 client->header->tcp_flags = TCP_ACK;
923 client->header->length = sizeof(usbmux_tcp_header);
924 client->header->length16 = sizeof(usbmux_tcp_header);
925 client->header->scnt += 1;
926 client->header->ocnt = header->ocnt;
927 hton_header(client->header);
928 // push it to USB
929 // TODO: need to check for error in the send here.... :(
930 log_debug_msg("%s: send_to_device (%d --> %d)\n", __func__,
931 ntohs(client->header->sport),
932 ntohs(client->header->dport));
933 if (send_to_device
934 (client->device, (char *) client->header,
935 sizeof(usbmux_tcp_header)) <= 0) {
936 log_debug_msg("%s: error when pushing to usb...\n",
937 __func__);
938 }
939 // need to revert some of the fields back to host notation.
940 ntoh_header(client->header);
941 } else {
942 client->error = -ECONNABORTED;
943 // woah... this connection failed us.
944 // TODO: somehow signal that this stream is a no-go.
945 log_debug_msg("WOAH! client failed to get proper syn+ack.\n");
946 }
947 }
948 // update TCP counters and windows.
949 //
950 // save the window that we're getting from the USB device.
951 // apparently the window is bigger than just the 512 that's typically
952 // advertised. iTunes apparently shifts this value by 8 to get a much
953 // larger number.
954 if (header->tcp_flags & TCP_RST) {
955 client->error = -ECONNRESET;
956
957 if (datalen > 0) {
958 char e_msg[128];
959 e_msg[0] = 0;
960 if (datalen > 1) {
961 memcpy(e_msg, data + 1, datalen - 1);
962 e_msg[datalen - 1] = 0;
963 }
964 // fetch the message
965 switch (data[0]) {
966 case 0:
967 // this is not an error, it's just a status message.
968 log_debug_msg("received status message: %s\n", e_msg);
969 datalen = 0;
970 break;
971 case 1:
972 log_debug_msg("received error message: %s\n", e_msg);
973 datalen = 0;
974 break;
975 default:
976 log_debug_msg
977 ("received unknown message (type 0x%02x): %s\n",
978 data[0], e_msg);
979 //datalen = 0; // <-- we let this commented out for testing
980 break;
981 }
982 } else {
983 log_debug_msg
984 ("peer sent connection reset. setting error: %d\n",
985 client->error);
986 }
987 }
988 // the packet's ocnt tells us how much of our data the device has received.
989 if (header->tcp_flags & TCP_ACK) {
990 // this is a hacky magic number condition. it seems that once
991 // the window reported by the device starts to drop below this
992 // number, we quickly fall into connection reset problems.
993 // Once we see the reported window size start falling off,
994 // ut off and wait for solid acks to come back.
995 if (ntohs(header->window) < 256)
996 client->wr_window = 0;
997
998 // check what just got acked.
999 if (ntohl(header->ocnt) < client->header->scnt) {
1000 // we got some kind of ack, but it hasn't caught up
1001 // with the pending that have been sent.
1002 pthread_cond_broadcast(&client->wr_wait);
1003 } else if (ntohl(header->ocnt) >
1004 /*client->wr_pending_scnt */ client->header->scnt) {
1005 fprintf(stderr,
1006 "WTF?! acks overtook pending outstanding. %u,%u\n",
1007 ntohl(header->ocnt), client->wr_pending_scnt);
1008 } else {
1009 // reset the window
1010 client->wr_window = WINDOW_MAX;
1011 pthread_cond_broadcast(&client->wr_wait);
1012 }
1013 }
1014 // the packet's scnt will be our new ocnt.
1015 client->header->ocnt = ntohl(header->scnt);
1016
1017 // ensure there is enough space, either by first malloc or realloc
1018 if (datalen > 0) {
1019 log_debug_msg("%s: putting %d bytes into client's recv_buffer\n",
1020 __func__, datalen);
1021 if (client->r_len == 0)
1022 dobroadcast = 1;
1023
1024 if (client->recv_buffer == NULL) {
1025 client->recv_buffer = malloc(datalen);
1026 client->r_len = 0;
1027 } else {
1028 client->recv_buffer =
1029 realloc(client->recv_buffer, client->r_len + datalen);
1030 }
1031
1032 memcpy(&client->recv_buffer[client->r_len], data, datalen);
1033 client->r_len += datalen;
1034 }
1035
1036 pthread_mutex_unlock(&client->mutex);
1037
1038 // I put this outside the mutex unlock just so that when the threads
1039 // wake, we don't have to do another round of unlock+try to grab.
1040 if (dobroadcast)
1041 pthread_cond_broadcast(&client->wait);
1042
1043 return packetlen;
1044}
1045
1046/**
1047 * @note THERE IS NO MUTEX LOCK IN THIS FUNCTION!
1048 * because we're only called from one location, pullbulk, where the lock
1049 * is already held.
1050 */
1051usbmux_client_t find_client(usbmux_tcp_header * recv_header)
1052{
1053 // remember, as we're looking for the client, the receive header is
1054 // coming from the USB into our client. This means that when we check
1055 // the src/dst ports, we need to reverse them.
1056 usbmux_client_t retval = NULL;
1057
1058 // just for debugging check, I'm going to convert the numbers to host-endian.
1059 uint16_t hsport = ntohs(recv_header->sport);
1060 uint16_t hdport = ntohs(recv_header->dport);
1061
1062 pthread_mutex_lock(&usbmuxmutex);
1063 int i;
1064 for (i = 0; i < clients; i++) {
1065 uint16_t csport = ntohs(connlist[i]->header->sport);
1066 uint16_t cdport = ntohs(connlist[i]->header->dport);
1067
1068 if (hsport == cdport && hdport == csport) {
1069 retval = connlist[i];
1070 break;
1071 }
1072 }
1073 pthread_mutex_unlock(&usbmuxmutex);
1074
1075 return retval;
1076}
1077
1078/** pull in a big USB bulk packet and distribute it to queues appropriately.
1079 */
1080int usbmux_pullbulk(usbmux_device_t device)
1081{
1082 if (!device)
1083 return -EINVAL;
1084
1085 int res = 0;
1086 static const int DEFAULT_CAPACITY = 128 * 1024;
1087 if (device->usbReceive.buffer == NULL) {
1088 device->usbReceive.capacity = DEFAULT_CAPACITY;
1089 device->usbReceive.buffer = malloc(device->usbReceive.capacity);
1090 device->usbReceive.leftover = 0;
1091 }
1092 // start the cursor off just ahead of the leftover.
1093 char *cursor = &device->usbReceive.buffer[device->usbReceive.leftover];
1094 // pull in content, note that the amount we can pull is capacity minus leftover
1095 int readlen =
1096 recv_from_device_timeout(device, cursor,
1097 device->usbReceive.capacity -
1098 device->usbReceive.leftover, 3000);
1099 if (readlen < 0) {
1100 res = readlen;
1101 //fprintf(stderr, "recv_from_device_timeout gave us an error.\n");
1102 readlen = 0;
1103 }
1104 if (readlen > 0) {
1105 //fprintf(stdout, "recv_from_device_timeout pulled an extra %d bytes\n", readlen);
1106 }
1107 // the amount of content we have to work with is the remainder plus
1108 // what we managed to read
1109 device->usbReceive.leftover += readlen;
1110
1111 // reset the cursor to the front of that buffer and work through
1112 // trying to decode packets out of them.
1113 cursor = device->usbReceive.buffer;
1114 while (1) {
1115 // check if there's even sufficient data to decode a header
1116 if (device->usbReceive.leftover < HEADERLEN)
1117 break;
1118 usbmux_tcp_header *header = (usbmux_tcp_header *) cursor;
1119
1120 log_debug_msg("%s: recv_from_device_timeout (%d --> %d)\n",
1121 __func__, ntohs(header->sport),
1122 ntohs(header->dport));
1123
1124 // now that we have a header, check if there is sufficient data
1125 // to construct a full packet, including its data
1126 uint32_t packetlen = ntohl(header->length);
1127 if ((uint32_t) device->usbReceive.leftover < packetlen) {
1128 fprintf(stderr,
1129 "%s: not enough data to construct a full packet\n",
1130 __func__);
1131 break;
1132 }
1133 // ok... find the client this packet will get stuffed to.
1134 usbmux_client_t client = find_client(header);
1135 if (client == NULL) {
1136 log_debug_msg
1137 ("WARNING: client for packet cannot be found. dropping packet.\n");
1138 } else {
1139 // stuff the data
1140 log_debug_msg
1141 ("%s: found client, calling append_receive_buffer\n",
1142 __func__);
1143 append_receive_buffer(client, cursor);
1144
1145 // perhaps this is too general, == -ECONNRESET
1146 // might be a better check here
1147 if (client->error < 0) {
1148 pthread_mutex_lock(&client->mutex);
1149 if (client->cleanup) {
1150 pthread_mutex_unlock(&client->mutex);
1151 log_debug_msg("freeing up connection (%d->%d)\n",
1152 ntohs(client->header->sport),
1153 ntohs(client->header->dport));
1154 delete_connection(client);
1155 } else {
1156 pthread_mutex_unlock(&client->mutex);
1157 }
1158 }
1159 }
1160
1161 // move the cursor and account for the consumption
1162 cursor += packetlen;
1163 device->usbReceive.leftover -= packetlen;
1164 }
1165
1166 // now, we need to manage any leftovers.
1167 // I'm going to manage the leftovers by alloc'ing a new block and
1168 // copyingthe leftovers to it. This is just to prevent problems with
1169 // memory moves where there may be overlap. Besides, the leftovers
1170 // should be small enough that this copy is minimal in overhead.
1171 //
1172 // if there are no leftovers, we just leave the datastructure as is,
1173 // and re-use the block next time.
1174 if (device->usbReceive.leftover > 0
1175 && cursor != device->usbReceive.buffer) {
1176 log_debug_msg("%s: we got a leftover, so handle it\n", __func__);
1177 char *newbuff = malloc(DEFAULT_CAPACITY);
1178 memcpy(newbuff, cursor, device->usbReceive.leftover);
1179 free(device->usbReceive.buffer);
1180 device->usbReceive.buffer = newbuff;
1181 device->usbReceive.capacity = DEFAULT_CAPACITY;
1182 }
1183
1184 return res;
1185}
1186
1187/**
1188 * return the error code stored in usbmux_client_t structure,
1189 * e.g. non-zero when an usb read error occurs.
1190 *
1191 * @param client the usbmux client
1192 *
1193 * @return 0 or a negative errno value.
1194 */
1195int usbmux_get_error(usbmux_client_t client)
1196{
1197 if (!client) {
1198 return 0;
1199 }
1200 return client->error;
1201}
1202
1203/** This function reads from the client's recv_buffer.
1204 *
1205 * @param client The client to receive data from.
1206 * @param data Where to put the data we receive.
1207 * @param datalen How much data to read.
1208 * @param timeout How many milliseconds to wait for data
1209 *
1210 * @return 0 on success or a negative errno value on failure.
1211 */
1212int usbmux_recv_timeout(usbmux_client_t client, char *data,
1213 uint32_t datalen, uint32_t * recv_bytes,
1214 int timeout)
1215{
1216
1217 if (!client || !data || datalen == 0 || !recv_bytes)
1218 return -EINVAL;
1219
1220 if (client->error < 0)
1221 return client->error;
1222
1223 pthread_mutex_lock(&client->mutex);
1224
1225 if (timeout > 0 && (client->recv_buffer == NULL || client->r_len == 0)) {
1226 struct timespec ts;
1227 clock_gettime(CLOCK_REALTIME, &ts);
1228 ts.tv_sec += timeout / 1000;
1229 ts.tv_nsec += (timeout - ((int) (timeout / 1000)) * 1000) * 1000;
1230 pthread_cond_timedwait(&client->wait, &client->mutex, &ts);
1231 }
1232
1233 *recv_bytes = 0;
1234 if (client->recv_buffer != NULL && client->r_len > 0) {
1235 uint32_t foolen = datalen;
1236 if ((int) foolen > client->r_len)
1237 foolen = client->r_len;
1238 memcpy(data, client->recv_buffer, foolen);
1239 *recv_bytes = foolen;
1240
1241 // preserve any left-over unread amounts.
1242 int remainder = client->r_len - foolen;
1243 if (remainder > 0) {
1244 char *newbuf = malloc(remainder);
1245 memcpy(newbuf, client->recv_buffer + foolen, remainder);
1246 client->r_len = remainder;
1247 free(client->recv_buffer);
1248 client->recv_buffer = newbuf;
1249 } else {
1250 free(client->recv_buffer);
1251 client->recv_buffer = NULL;
1252 client->r_len = 0;
1253 }
1254 }
1255
1256 pthread_mutex_unlock(&client->mutex);
1257
1258 return 0;
1259}