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