diff options
-rw-r--r-- | libusbmuxd.c | 138 | ||||
-rw-r--r-- | main.c | 1875 | ||||
-rw-r--r-- | sock_stuff.c | 470 | ||||
-rw-r--r-- | sock_stuff.h | 15 | ||||
-rw-r--r-- | usbmux.c | 325 |
5 files changed, 1559 insertions, 1264 deletions
diff --git a/libusbmuxd.c b/libusbmuxd.c index edd585c..c8acbf8 100644 --- a/libusbmuxd.c +++ b/libusbmuxd.c @@ -14,37 +14,37 @@ // socket utility functions #include "sock_stuff.h" -static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t *result) +static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result) { - struct usbmuxd_result res; - int recv_len; - - if (!result) { - return -EINVAL; - } - - if ((recv_len = recv_buf(sfd, &res, sizeof(res))) <= 0) { - perror("recv"); - return -errno; - } else { - if ((recv_len == sizeof(res)) - && (res.header.length == (uint32_t)recv_len) - && (res.header.reserved == 0) - && (res.header.type == USBMUXD_RESULT) - ) { - *result = res.result; - if (res.header.tag == tag) { - return 1; - } else { - return 0; - } - } - } - - return -1; + struct usbmuxd_result res; + int recv_len; + + if (!result) { + return -EINVAL; + } + + if ((recv_len = recv_buf(sfd, &res, sizeof(res))) <= 0) { + perror("recv"); + return -errno; + } else { + if ((recv_len == sizeof(res)) + && (res.header.length == (uint32_t) recv_len) + && (res.header.reserved == 0) + && (res.header.type == USBMUXD_RESULT) + ) { + *result = res.result; + if (res.header.tag == tag) { + return 1; + } else { + return 0; + } + } + } + + return -1; } -int usbmuxd_scan(usbmuxd_scan_result **available_devices) +int usbmuxd_scan(usbmuxd_scan_result ** available_devices) { struct usbmuxd_scan_request s_req; int sfd; @@ -68,13 +68,16 @@ int usbmuxd_scan(usbmuxd_scan_result **available_devices) s_req.header.tag = 2; // send scan request packet - if (send_buf(sfd, &s_req, s_req.header.length) == (int)s_req.header.length) { + if (send_buf(sfd, &s_req, s_req.header.length) == + (int) s_req.header.length) { res = -1; // get response if (usbmuxd_get_result(sfd, s_req.header.tag, &res) && (res == 0)) { scan_success = 1; } else { - fprintf(stderr, "%s: Did not get response to scan request (with result=0)...\n", __func__); + fprintf(stderr, + "%s: Did not get response to scan request (with result=0)...\n", + __func__); close(sfd); return res; } @@ -91,29 +94,45 @@ int usbmuxd_scan(usbmuxd_scan_result **available_devices) if (recv_buf_timeout(sfd, &pktlen, 4, MSG_PEEK, 1000) == 4) { if (pktlen != sizeof(dev_info_pkt)) { // invalid packet size received! - fprintf(stderr, "%s: Invalid packet size (%d) received when expecting a device info record.\n", __func__, pktlen); + fprintf(stderr, + "%s: Invalid packet size (%d) received when expecting a device info record.\n", + __func__, pktlen); break; } recv_len = recv_buf(sfd, &dev_info_pkt, pktlen); if (recv_len <= 0) { - fprintf(stderr, "%s: Error when receiving device info record\n", __func__); + fprintf(stderr, + "%s: Error when receiving device info record\n", + __func__); break; - } else if ((uint32_t)recv_len < pktlen) { - fprintf(stderr, "%s: received less data than specified in header!\n", __func__); + } else if ((uint32_t) recv_len < pktlen) { + fprintf(stderr, + "%s: received less data than specified in header!\n", + __func__); } else { //fprintf(stderr, "%s: got device record with id %d, UUID=%s\n", __func__, dev_info_pkt.device_info.device_id, dev_info_pkt.device_info.serial_number); - newlist = (usbmuxd_scan_result *)realloc(*available_devices, sizeof(usbmuxd_scan_result) * (dev_cnt+1)); + newlist = + (usbmuxd_scan_result *) realloc(*available_devices, + sizeof + (usbmuxd_scan_result) * + (dev_cnt + 1)); if (newlist) { - newlist[dev_cnt].handle = (int)dev_info_pkt.device.device_id; - newlist[dev_cnt].product_id = dev_info_pkt.device.product_id; - memset(newlist[dev_cnt].serial_number, '\0', sizeof(newlist[dev_cnt].serial_number)); - memcpy(newlist[dev_cnt].serial_number, dev_info_pkt.device.serial_number, - sizeof(dev_info_pkt.device.serial_number)); + newlist[dev_cnt].handle = + (int) dev_info_pkt.device.device_id; + newlist[dev_cnt].product_id = + dev_info_pkt.device.product_id; + memset(newlist[dev_cnt].serial_number, '\0', + sizeof(newlist[dev_cnt].serial_number)); + memcpy(newlist[dev_cnt].serial_number, + dev_info_pkt.device.serial_number, + sizeof(dev_info_pkt.device.serial_number)); *available_devices = newlist; dev_cnt++; } else { - fprintf(stderr, "%s: ERROR: out of memory when trying to realloc!\n", __func__); + fprintf(stderr, + "%s: ERROR: out of memory when trying to realloc!\n", + __func__); break; } } @@ -125,8 +144,11 @@ int usbmuxd_scan(usbmuxd_scan_result **available_devices) } // terminating zero record - newlist = (usbmuxd_scan_result *)realloc(*available_devices, sizeof(usbmuxd_scan_result) * (dev_cnt+1)); - memset(newlist+dev_cnt, 0, sizeof(usbmuxd_scan_result)); + newlist = + (usbmuxd_scan_result *) realloc(*available_devices, + sizeof(usbmuxd_scan_result) * + (dev_cnt + 1)); + memset(newlist + dev_cnt, 0, sizeof(usbmuxd_scan_result)); *available_devices = newlist; return dev_cnt; @@ -141,31 +163,33 @@ int usbmuxd_connect(const int handle, const unsigned short tcp_port) sfd = connect_unix_socket(USBMUXD_SOCKET_FILE); if (sfd < 0) { - fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n", __func__, strerror(errno)); - return sfd; + fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n", + __func__, strerror(errno)); + return sfd; } c_req.header.length = sizeof(c_req); c_req.header.reserved = 0; c_req.header.type = USBMUXD_CONNECT; c_req.header.tag = 3; - c_req.device_id = (uint32_t)handle; + c_req.device_id = (uint32_t) handle; c_req.tcp_dport = htons(tcp_port); c_req.reserved = 0; if (send_buf(sfd, &c_req, sizeof(c_req)) < 0) { - perror("send"); + perror("send"); } else { - // read ACK - //fprintf(stderr, "%s: Reading connect result...\n", __func__); - if (usbmuxd_get_result(sfd, c_req.header.tag, &res)) { - if (res == 0) { - //fprintf(stderr, "%s: Connect success!\n", __func__); - connected = 1; - } else { - fprintf(stderr, "%s: Connect failed, Error code=%d\n", __func__, res); + // read ACK + //fprintf(stderr, "%s: Reading connect result...\n", __func__); + if (usbmuxd_get_result(sfd, c_req.header.tag, &res)) { + if (res == 0) { + //fprintf(stderr, "%s: Connect success!\n", __func__); + connected = 1; + } else { + fprintf(stderr, "%s: Connect failed, Error code=%d\n", + __func__, res); + } } - } } if (connected) { @@ -173,6 +197,6 @@ int usbmuxd_connect(const int handle, const unsigned short tcp_port) } close(sfd); - + return -1; } @@ -59,29 +59,29 @@ static int foreground = 0; static int exit_on_no_devices = 0; struct device_info { - uint32_t device_id; - usbmux_device_t phone; - int use_count; - pthread_t bulk_reader; - pthread_mutex_t mutex; - /* mutex for mutual exclusion of calling the usbmux_send function - * TODO: I don't know if we need really need this? */ - pthread_mutex_t writer_mutex; + uint32_t device_id; + usbmux_device_t phone; + int use_count; + pthread_t bulk_reader; + pthread_mutex_t mutex; + /* mutex for mutual exclusion of calling the usbmux_send function + * TODO: I don't know if we need really need this? */ + pthread_mutex_t writer_mutex; }; struct client_data { - volatile int dead; - int socket; - int tag; - pthread_t thread; - pthread_t handler; - pthread_t reader; - int reader_quit; - int reader_dead; - int handler_dead; - int connected; - usbmux_client_t muxclient; - struct device_info *dev; + volatile int dead; + int socket; + int tag; + pthread_t thread; + pthread_t handler; + pthread_t reader; + int reader_quit; + int reader_dead; + int handler_dead; + int connected; + usbmux_client_t muxclient; + struct device_info *dev; }; static struct device_info **devices = NULL; @@ -97,69 +97,77 @@ static pthread_mutex_t usb_mutex = PTHREAD_MUTEX_INITIALIZER; */ static void logmsg(int prio, const char *format, ...) { - va_list args; - va_start(args, format); - - if (!foreground) { - // daemon. log using syslog. - vsyslog(prio, format, args); - } else { - // running in foreground. log to stdout/stderr. - char msgbuf[256]; - FILE *lfp = stdout; - switch(prio) { - case LOG_EMERG: - case LOG_ALERT: - case LOG_CRIT: - case LOG_ERR: - case LOG_WARNING: - lfp = stderr; - break; - default: - lfp = stdout; + va_list args; + va_start(args, format); + + if (!foreground) { + // daemon. log using syslog. + vsyslog(prio, format, args); + } else { + // running in foreground. log to stdout/stderr. + char msgbuf[256]; + FILE *lfp = stdout; + switch (prio) { + case LOG_EMERG: + case LOG_ALERT: + case LOG_CRIT: + case LOG_ERR: + case LOG_WARNING: + lfp = stderr; + break; + default: + lfp = stdout; + } + strcpy(msgbuf, "usbmuxd: "); + vsnprintf(msgbuf + 9, 244, format, args); + strcat(msgbuf, "\n"); + fputs(msgbuf, lfp); } - strcpy(msgbuf, "usbmuxd: "); - vsnprintf(msgbuf+9, 244, format, args); - strcat(msgbuf, "\n"); - fputs(msgbuf, lfp); - } - va_end(args); + va_end(args); } #ifdef DEBUG /** * for debugging purposes. */ -static void print_buffer(FILE *fp, const char *data, const int length) +static void print_buffer(FILE * fp, const char *data, const int length) { - int i; + int i; int j; unsigned char c; - for(i=0; i<length; i+=16) { - if (verbose >= 4) fprintf(fp, "%04x: ", i); - for (j=0;j<16;j++) { - if (i+j >= length) { - if (verbose >= 4) fprintf(fp, " "); + for (i = 0; i < length; i += 16) { + if (verbose >= 4) + fprintf(fp, "%04x: ", i); + for (j = 0; j < 16; j++) { + if (i + j >= length) { + if (verbose >= 4) + fprintf(fp, " "); continue; } - if (verbose >= 4) fprintf(fp, "%02hhx ", *(data+i+j)); + if (verbose >= 4) + fprintf(fp, "%02hhx ", *(data + i + j)); } - if (verbose >= 4) fprintf(fp, " | "); - for(j=0;j<16;j++) { - if (i+j >= length) + if (verbose >= 4) + fprintf(fp, " | "); + for (j = 0; j < 16; j++) { + if (i + j >= length) break; - c = *(data+i+j); + c = *(data + i + j); if ((c < 32) || (c > 127)) { - if (verbose >= 4) fprintf(fp, "."); + if (verbose >= 4) + fprintf(fp, "."); continue; } - if (verbose >= 4) fprintf(fp, "%c", c); + if (verbose >= 4) + fprintf(fp, "%c", c); } - if (verbose >= 4) fprintf(fp, "\n"); + if (verbose >= 4) + fprintf(fp, "\n"); } - if (verbose >= 4) fprintf(fp, "\n"); + if (verbose >= 4) + fprintf(fp, "\n"); } #endif @@ -176,35 +184,40 @@ static void print_buffer(FILE *fp, const char *data, const int length) */ static int usbmuxd_get_request(int fd, void **data, size_t len) { - uint32_t pktlen; - int recv_len; - - if (peek_buf(fd, &pktlen, sizeof(pktlen)) < (int)sizeof(pktlen)) { - return -errno; - } - - if (len == 0) { - // allocate buffer space - *data = malloc(pktlen); - } else if (len < pktlen) { - // target buffer is to small to hold this packet! fix it! - if (verbose >= 2) logmsg(LOG_WARNING, "%s: WARNING -- packet (%d) is larger than target buffer (%d)! Truncating.", __func__, pktlen, len); - pktlen = len; - } - - recv_len = recv_buf(fd, *data, pktlen); - if ((recv_len > 0) && ((uint32_t)recv_len < pktlen)) { - if (verbose >= 2) logmsg(LOG_WARNING, "%s: Uh-oh, we got less than the packet's size, %d instead of %d...", __func__, recv_len, pktlen); - } + uint32_t pktlen; + int recv_len; + + if (peek_buf(fd, &pktlen, sizeof(pktlen)) < (int) sizeof(pktlen)) { + return -errno; + } + if (len == 0) { + // allocate buffer space + *data = malloc(pktlen); + } else if (len < pktlen) { + // target buffer is to small to hold this packet! fix it! + if (verbose >= 2) + logmsg(LOG_WARNING, + "%s: WARNING -- packet (%d) is larger than target buffer (%d)! Truncating.", + __func__, pktlen, len); + pktlen = len; + } + + recv_len = recv_buf(fd, *data, pktlen); + if ((recv_len > 0) && ((uint32_t) recv_len < pktlen)) { + if (verbose >= 2) + logmsg(LOG_WARNING, + "%s: Uh-oh, we got less than the packet's size, %d instead of %d...", + __func__, recv_len, pktlen); + } #ifdef DEBUG - if (*data && (recv_len > 0) && verbose >= 4) { - fprintf(stderr, "%s: received:\n", __func__); - print_buffer(stderr, *data, recv_len); - } + if (*data && (recv_len > 0) && verbose >= 4) { + fprintf(stderr, "%s: received:\n", __func__); + print_buffer(stderr, *data, recv_len); + } #endif - return recv_len; + return recv_len; } /** @@ -218,20 +231,22 @@ static int usbmuxd_get_request(int fd, void **data, size_t len) */ static int usbmuxd_send_result(int fd, uint32_t tag, uint32_t result_code) { - struct usbmuxd_result res; - int ret; - - res.header.length = sizeof(res); - res.header.reserved = 0; - res.header.type = USBMUXD_RESULT; - res.header.tag = tag; - res.result = result_code; - - if (verbose >= 4) logmsg(LOG_NOTICE, "%s: tag=%d result=%d", __func__, res.header.tag, res.result); - - ret = send_buf(fd, &res, sizeof(res)); - fsync(fd); // let's get it sent - return ret; + struct usbmuxd_result res; + int ret; + + res.header.length = sizeof(res); + res.header.reserved = 0; + res.header.type = USBMUXD_RESULT; + res.header.tag = tag; + res.result = result_code; + + if (verbose >= 4) + logmsg(LOG_NOTICE, "%s: tag=%d result=%d", __func__, + res.header.tag, res.result); + + ret = send_buf(fd, &res, sizeof(res)); + fsync(fd); // let's get it sent + return ret; } /** @@ -244,69 +259,84 @@ static int usbmuxd_send_result(int fd, uint32_t tag, uint32_t result_code) */ static void *usbmuxd_client_reader_thread(void *arg) { - struct client_data *cdata; - - char rbuffer[512]; - uint32_t rbuffersize = 512; - uint32_t rlen; - int err; - char *cursor; - ssize_t len; - int result; - - if (!arg) { - if (verbose >= 2) logmsg(LOG_ERR, "%s: invalid client_data supplied!", __func__); - cdata->reader_dead = 1; - return NULL; - } + struct client_data *cdata; + + char rbuffer[512]; + uint32_t rbuffersize = 512; + uint32_t rlen; + int err; + char *cursor; + ssize_t len; + int result; + + if (!arg) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s: invalid client_data supplied!", __func__); + cdata->reader_dead = 1; + return NULL; + } - cdata = (struct client_data*)arg; + cdata = (struct client_data *) arg; - cdata->reader_dead = 0; + cdata->reader_dead = 0; - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%d:%d]: started", __func__, cdata->dev->device_id, cdata->dev->use_count); + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%d:%d]: started", __func__, + cdata->dev->device_id, cdata->dev->use_count); - while (!quit_flag && !cdata->reader_quit) { - result = check_fd(cdata->socket, FD_WRITE, DEFAULT_TIMEOUT); - if (result <= 0) { - if (result < 0) { - if (verbose >= 2) logmsg(LOG_ERR, "%s: select error: %s", __func__, strerror(errno)); - } - continue; - } + while (!quit_flag && !cdata->reader_quit) { + result = check_fd(cdata->socket, FD_WRITE, DEFAULT_TIMEOUT); + if (result <= 0) { + if (result < 0) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s: select error: %s", __func__, + strerror(errno)); + } + continue; + } - rlen = 0; - err = usbmux_recv_timeout(cdata->muxclient, rbuffer, rbuffersize, &rlen, DEFAULT_TIMEOUT); - if (err != 0) { - if (verbose >= 2) logmsg(LOG_ERR, "%s[%d:%d]: encountered USB read error: %d", __func__, cdata->dev->device_id, cdata->dev->use_count, err); - break; - } + rlen = 0; + err = + usbmux_recv_timeout(cdata->muxclient, rbuffer, rbuffersize, + &rlen, DEFAULT_TIMEOUT); + if (err != 0) { + if (verbose >= 2) + logmsg(LOG_ERR, + "%s[%d:%d]: encountered USB read error: %d", + __func__, cdata->dev->device_id, + cdata->dev->use_count, err); + break; + } - cursor = rbuffer; - while (rlen > 0) { - len = send_buf(cdata->socket, cursor, rlen); - if (len <= 0) { - logmsg(LOG_ERR, "%s: Error: send returned %d", __func__, len); - err = 1; - break; - } - // calculate remainder - rlen -= len; - // advance cursor - cursor += len; - } - if (err != 0) { - logmsg(LOG_ERR, "%s: Error when writing to client...", __func__); - break; + cursor = rbuffer; + while (rlen > 0) { + len = send_buf(cdata->socket, cursor, rlen); + if (len <= 0) { + logmsg(LOG_ERR, "%s: Error: send returned %d", __func__, + len); + err = 1; + break; + } + // calculate remainder + rlen -= len; + // advance cursor + cursor += len; + } + if (err != 0) { + logmsg(LOG_ERR, "%s: Error when writing to client...", + __func__); + break; + } + fsync(cdata->socket); } - fsync(cdata->socket); - } - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%d:%d]: terminated", __func__, cdata->dev->device_id, cdata->dev->use_count); + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%d:%d]: terminated", __func__, + cdata->dev->device_id, cdata->dev->use_count); - cdata->reader_dead = 1; + cdata->reader_dead = 1; - return NULL; + return NULL; } /** @@ -321,60 +351,73 @@ static void *usbmuxd_client_reader_thread(void *arg) */ static int usbmuxd_handleConnectResult(struct client_data *cdata) { - int result; - char buffer[512]; - char err_type[64]; - int err_code; - ssize_t maxlen = 512; - uint32_t rlen; - int err; - - if (!cdata) { - if (verbose >= 2) logmsg(LOG_ERR, "%s: Invalid client_data provided!", __func__); - return -EINVAL; - } - - result = check_fd(cdata->socket, FD_WRITE, DEFAULT_TIMEOUT); - if (result <= 0) { - if (result < 0) { - if (verbose >= 2) logmsg(LOG_ERR, "%s: select error: %s", __func__, strerror(errno)); - return result; + int result; + char buffer[512]; + char err_type[64]; + int err_code; + ssize_t maxlen = 512; + uint32_t rlen; + int err; + + if (!cdata) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s: Invalid client_data provided!", __func__); + return -EINVAL; } - } else { - result = 0; - err = usbmux_recv_timeout(cdata->muxclient, buffer, maxlen, &rlen, 100); - if (err < 0) { - if (verbose >= 2) logmsg(LOG_ERR, "%s: encountered USB read error: %d", __func__, err); - usbmuxd_send_result(cdata->socket, cdata->tag, -err); - return err; + + result = check_fd(cdata->socket, FD_WRITE, DEFAULT_TIMEOUT); + if (result <= 0) { + if (result < 0) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s: select error: %s", __func__, + strerror(errno)); + return result; + } } else { - if (rlen > 0) { - if ((buffer[0] == 1) && (rlen > 20) && !memcmp(buffer+1, "handleConnectResult:", 20)) { - // hm... we got an error message! - buffer[rlen] = 0; - if (verbose >= 1) logmsg(LOG_ERR, "%s: %s\n", __func__, buffer+22); - - if (sscanf(buffer+22, "%s - %d\n", err_type, &err_code) == 2) { - usbmuxd_send_result(cdata->socket, cdata->tag, err_code); - return -err_code; - } else { - usbmuxd_send_result(cdata->socket, cdata->tag, ENODATA); - return -ENODATA; - } + result = 0; + err = + usbmux_recv_timeout(cdata->muxclient, buffer, maxlen, &rlen, + 100); + if (err < 0) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s: encountered USB read error: %d", + __func__, err); + usbmuxd_send_result(cdata->socket, cdata->tag, -err); + return err; } else { - // send success result - usbmuxd_send_result(cdata->socket, cdata->tag, 0); - // and the server greeting message - send_buf(cdata->socket, buffer, rlen); + if (rlen > 0) { + if ((buffer[0] == 1) && (rlen > 20) + && !memcmp(buffer + 1, "handleConnectResult:", 20)) { + // hm... we got an error message! + buffer[rlen] = 0; + if (verbose >= 1) + logmsg(LOG_ERR, "%s: %s\n", __func__, buffer + 22); + + if (sscanf + (buffer + 22, "%s - %d\n", err_type, &err_code) + == 2) { + usbmuxd_send_result(cdata->socket, cdata->tag, + err_code); + return -err_code; + } else { + usbmuxd_send_result(cdata->socket, cdata->tag, + ENODATA); + return -ENODATA; + } + } else { + // send success result + usbmuxd_send_result(cdata->socket, cdata->tag, 0); + // and the server greeting message + send_buf(cdata->socket, buffer, rlen); + } + } else { + // no server greeting? this seems to be ok. send success. + usbmuxd_send_result(cdata->socket, cdata->tag, 0); + } } - } else { - // no server greeting? this seems to be ok. send success. - usbmuxd_send_result(cdata->socket, cdata->tag, 0); - } + //fsync(cdata->socket); } - //fsync(cdata->socket); - } - return result; + return result; } /** @@ -383,96 +426,115 @@ static int usbmuxd_handleConnectResult(struct client_data *cdata) */ static void *usbmuxd_client_handler_thread(void *arg) { - struct client_data *cdata; - int result; - char *cursor; - char buffer[65536]; - ssize_t len; - ssize_t maxlen = sizeof(buffer); - uint32_t wlen; - int err; - - if (!arg) { - if (verbose >= 2) logmsg(LOG_ERR, "%s: invalid client_data provided!", __func__); - return NULL; - } - - cdata = (struct client_data*)arg; - - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%d:%d]: started", __func__, cdata->dev->device_id,cdata->dev->use_count); + struct client_data *cdata; + int result; + char *cursor; + char buffer[65536]; + ssize_t len; + ssize_t maxlen = sizeof(buffer); + uint32_t wlen; + int err; + + if (!arg) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s: invalid client_data provided!", __func__); + return NULL; + } - if (usbmuxd_handleConnectResult(cdata)) { - if (verbose >= 3) logmsg(LOG_ERR, "handleConnectResult: Error"); - goto leave; - } else { - if (verbose >= 3) logmsg(LOG_NOTICE, "handleConnectResult: Success"); - } + cdata = (struct client_data *) arg; - // starting mux reader thread - cdata->reader_quit = 0; - cdata->reader_dead = 0; - if (pthread_create(&cdata->reader, NULL, usbmuxd_client_reader_thread, cdata) != 0) { - if (verbose >= 2) logmsg(LOG_ERR, "%s: could not start client_reader thread", __func__); - cdata->reader = 0; - } + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%d:%d]: started", __func__, + cdata->dev->device_id, cdata->dev->use_count); - while (!quit_flag && !cdata->reader_dead) { - result = check_fd(cdata->socket, FD_READ, DEFAULT_TIMEOUT); - if (result <= 0) { - if (result < 0) { - if (verbose >= 3) logmsg(LOG_ERR, "%s: Error: checkfd: %s", __func__, strerror(errno)); - } - continue; + if (usbmuxd_handleConnectResult(cdata)) { + if (verbose >= 3) + logmsg(LOG_ERR, "handleConnectResult: Error"); + goto leave; + } else { + if (verbose >= 3) + logmsg(LOG_NOTICE, "handleConnectResult: Success"); } - // check_fd told us there's data available, so read from client - // and push to USB device. - len = recv(cdata->socket, buffer, maxlen, 0); - if (len == 0) { - break; - } - if (len < 0) { - if (verbose >= 2) logmsg(LOG_ERR, "%s[%d:%d]: Error: recv: %s", __func__, cdata->dev->device_id, cdata->dev->use_count, strerror(errno)); - break; + // starting mux reader thread + cdata->reader_quit = 0; + cdata->reader_dead = 0; + if (pthread_create + (&cdata->reader, NULL, usbmuxd_client_reader_thread, cdata) != 0) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s: could not start client_reader thread", + __func__); + cdata->reader = 0; } - cursor = buffer; - - pthread_mutex_lock(&cdata->dev->writer_mutex); - do { - wlen = 0; - err = usbmux_send(cdata->muxclient, cursor, len, &wlen); - if (err == -ETIMEDOUT) { - // some kind of timeout... just be patient and retry. - } else if (err < 0) { - if (verbose >= 2) logmsg(LOG_ERR, "%s[%d:%d]: USB write error: %d", __func__, cdata->dev->device_id, cdata->dev->use_count, err); - len = -1; - break; - } - - // calculate remainder. - len -= wlen; - // advance cursor appropiately. - cursor += wlen; - } while ((len > 0) && !quit_flag); - pthread_mutex_unlock(&cdata->dev->writer_mutex); - if (len < 0) { - break; + while (!quit_flag && !cdata->reader_dead) { + result = check_fd(cdata->socket, FD_READ, DEFAULT_TIMEOUT); + if (result <= 0) { + if (result < 0) { + if (verbose >= 3) + logmsg(LOG_ERR, "%s: Error: checkfd: %s", __func__, + strerror(errno)); + } + continue; + } + // check_fd told us there's data available, so read from client + // and push to USB device. + len = recv(cdata->socket, buffer, maxlen, 0); + if (len == 0) { + break; + } + if (len < 0) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s[%d:%d]: Error: recv: %s", __func__, + cdata->dev->device_id, cdata->dev->use_count, + strerror(errno)); + break; + } + + cursor = buffer; + + pthread_mutex_lock(&cdata->dev->writer_mutex); + do { + wlen = 0; + err = usbmux_send(cdata->muxclient, cursor, len, &wlen); + if (err == -ETIMEDOUT) { + // some kind of timeout... just be patient and retry. + } else if (err < 0) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s[%d:%d]: USB write error: %d", + __func__, cdata->dev->device_id, + cdata->dev->use_count, err); + len = -1; + break; + } + // calculate remainder. + len -= wlen; + // advance cursor appropiately. + cursor += wlen; + } + while ((len > 0) && !quit_flag); + pthread_mutex_unlock(&cdata->dev->writer_mutex); + if (len < 0) { + break; + } } - } -leave: - // cleanup - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%d:%d]: terminating", __func__, cdata->dev->device_id, cdata->dev->use_count); - if (cdata->reader != 0) { - cdata->reader_quit = 1; - pthread_join(cdata->reader, NULL); - } + leave: + // cleanup + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%d:%d]: terminating", __func__, + cdata->dev->device_id, cdata->dev->use_count); + if (cdata->reader != 0) { + cdata->reader_quit = 1; + pthread_join(cdata->reader, NULL); + } - cdata->handler_dead = 1; + cdata->handler_dead = 1; - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%d:%d]: terminated", __func__, cdata->dev->device_id, cdata->dev->use_count); - return NULL; + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%d:%d]: terminated", __func__, + cdata->dev->device_id, cdata->dev->use_count); + return NULL; } /** @@ -481,36 +543,41 @@ leave: */ static void *usbmuxd_bulk_reader_thread(void *arg) { - struct device_info *cur_dev; - int err; + struct device_info *cur_dev; + int err; - if (!arg) { - if (verbose >= 2) logmsg(LOG_ERR, "%s: Invalid client_data provided", __func__); - return NULL; - } + if (!arg) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s: Invalid client_data provided", __func__); + return NULL; + } - cur_dev = (struct device_info*)arg; + cur_dev = (struct device_info *) arg; - if (verbose >= 3) logmsg(LOG_NOTICE, "%s: started", __func__); + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s: started", __func__); - while (!quit_flag && cur_dev) { + while (!quit_flag && cur_dev) { - pthread_mutex_lock(&cur_dev->mutex); - if (cur_dev->use_count <= 0) { - pthread_mutex_unlock(&cur_dev->mutex); - break; - } - pthread_mutex_unlock(&cur_dev->mutex); + pthread_mutex_lock(&cur_dev->mutex); + if (cur_dev->use_count <= 0) { + pthread_mutex_unlock(&cur_dev->mutex); + break; + } + pthread_mutex_unlock(&cur_dev->mutex); - if ((err = usbmux_pullbulk(cur_dev->phone)) < 0) { - if (verbose >= 1) logmsg(LOG_ERR, "%s: error %d when reading from device", __func__, err); - break; + if ((err = usbmux_pullbulk(cur_dev->phone)) < 0) { + if (verbose >= 1) + logmsg(LOG_ERR, "%s: error %d when reading from device", + __func__, err); + break; + } } - } - if (verbose >= 3) logmsg(LOG_NOTICE, "%s: terminated", __func__); + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s: terminated", __func__); - return NULL; + return NULL; } /** @@ -520,286 +587,374 @@ static void *usbmuxd_bulk_reader_thread(void *arg) */ static void *usbmuxd_client_init_thread(void *arg) { - struct client_data *cdata; - struct usbmuxd_scan_request *s_req = NULL; - struct usbmuxd_device_info_record dev_info_rec; - struct usbmuxd_connect_request *c_req = NULL; + struct client_data *cdata; + struct usbmuxd_scan_request *s_req = NULL; + struct usbmuxd_device_info_record dev_info_rec; + struct usbmuxd_connect_request *c_req = NULL; + + struct usb_bus *bus; + struct usb_device *dev; + + int recv_len; + int found = 0; + int res; + int i; + + usbmux_device_t phone = NULL; + struct device_info *cur_dev = NULL; + + if (!arg) { + if (verbose >= 1) + logmsg(LOG_ERR, "%s[%x]: invalid client_data provided!", + __func__, THREAD); + return NULL; + } - struct usb_bus *bus; - struct usb_device *dev; + cdata = (struct client_data *) arg; + cdata->dead = 0; - int recv_len; - int found = 0; - int res; - int i; + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%x]: started (fd=%d)", __func__, THREAD, + cdata->socket); - usbmux_device_t phone = NULL; - struct device_info *cur_dev = NULL; + if ((recv_len = + usbmuxd_get_request(cdata->socket, (void **) &s_req, 0)) <= 0) { + if (verbose >= 2) + logmsg(LOG_ERR, "%s[%x]: No scan packet received, error %s", + __func__, THREAD, strerror(errno)); + goto leave; + } - if (!arg) { - if (verbose >= 1) logmsg(LOG_ERR, "%s[%x]: invalid client_data provided!", __func__, THREAD); - return NULL; - } - - cdata = (struct client_data*)arg; - cdata->dead = 0; - - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%x]: started (fd=%d)", __func__, THREAD, cdata->socket); - - if ((recv_len = usbmuxd_get_request(cdata->socket, (void**)&s_req, 0)) <= 0) { - if (verbose >= 2) logmsg(LOG_ERR, "%s[%x]: No scan packet received, error %s", __func__, THREAD, strerror(errno)); - goto leave; - } - - if ((recv_len == sizeof(struct usbmuxd_scan_request)) && (s_req->header.length == sizeof(struct usbmuxd_scan_request)) - && (s_req->header.reserved == 0) && (s_req->header.type == USBMUXD_SCAN)) { - // send success response - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%x]: Got scan packet!", __func__, THREAD); - usbmuxd_send_result(cdata->socket, s_req->header.tag, 0); - } else if ((recv_len == sizeof(struct usbmuxd_connect_request)) && (s_req->header.type == USBMUXD_CONNECT)) { - c_req = (struct usbmuxd_connect_request*)s_req; - s_req = NULL; - goto connect; - } else { - // send error response and exit - if (verbose >= 2) logmsg(LOG_ERR, "%s[%x]: Invalid scan packet received.", __func__, THREAD); - // TODO is this required?! - usbmuxd_send_result(cdata->socket, s_req->header.tag, EINVAL); - goto leave; - } - - pthread_mutex_lock(&usb_mutex); - // gather data about all iPhones/iPods attached - - if (verbose >= 5) logmsg(LOG_DEBUG, "%s[%x]: usb init", __func__, THREAD); - usb_init(); - if (verbose >= 5) logmsg(LOG_DEBUG, "%s[%x]: usb find busses", __func__, THREAD); - usb_find_busses(); - if (verbose >= 5) logmsg(LOG_DEBUG, "%s[%x]: usb find devices", __func__, THREAD); - usb_find_devices(); - - if (verbose >= 2) logmsg(LOG_NOTICE, "%s[%x]: Looking for attached devices...", __func__, THREAD); - - for (bus = usb_get_busses(); bus; bus = bus->next) { - for (dev = bus->devices; dev; dev = dev->next) { - if (dev->descriptor.idVendor == 0x05ac - && dev->descriptor.idProduct >= 0x1290 - && dev->descriptor.idProduct <= 0x1293) - { - if (verbose >= 1) logmsg(LOG_NOTICE, "%s[%x]: Found device on bus %d, id %d", __func__, THREAD, bus->location, dev->devnum); - found++; - - // construct packet - memset(&dev_info_rec, 0, sizeof(dev_info_rec)); - dev_info_rec.header.length = sizeof(dev_info_rec); - dev_info_rec.header.type = USBMUXD_DEVICE_INFO; - dev_info_rec.device.device_id = dev->devnum; - dev_info_rec.device.product_id = dev->descriptor.idProduct; - if (dev->descriptor.iSerialNumber) { - usb_dev_handle *udev; - //pthread_mutex_lock(&usbmux_mutex); - udev = usb_open(dev); - if (udev) { - usb_get_string_simple(udev, dev->descriptor.iSerialNumber, dev_info_rec.device.serial_number, sizeof(dev_info_rec.device.serial_number)+1); - usb_close(udev); - } - //pthread_mutex_unlock(&usbmux_mutex); - } + if ((recv_len == sizeof(struct usbmuxd_scan_request)) + && (s_req->header.length == sizeof(struct usbmuxd_scan_request)) + && (s_req->header.reserved == 0) + && (s_req->header.type == USBMUXD_SCAN)) { + // send success response + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%x]: Got scan packet!", __func__, + THREAD); + usbmuxd_send_result(cdata->socket, s_req->header.tag, 0); + } else if ((recv_len == sizeof(struct usbmuxd_connect_request)) + && (s_req->header.type == USBMUXD_CONNECT)) { + c_req = (struct usbmuxd_connect_request *) s_req; + s_req = NULL; + goto connect; + } else { + // send error response and exit + if (verbose >= 2) + logmsg(LOG_ERR, "%s[%x]: Invalid scan packet received.", + __func__, THREAD); + // TODO is this required?! + usbmuxd_send_result(cdata->socket, s_req->header.tag, EINVAL); + goto leave; + } + pthread_mutex_lock(&usb_mutex); + // gather data about all iPhones/iPods attached + + if (verbose >= 5) + logmsg(LOG_DEBUG, "%s[%x]: usb init", __func__, THREAD); + usb_init(); + if (verbose >= 5) + logmsg(LOG_DEBUG, "%s[%x]: usb find busses", __func__, THREAD); + usb_find_busses(); + if (verbose >= 5) + logmsg(LOG_DEBUG, "%s[%x]: usb find devices", __func__, THREAD); + usb_find_devices(); + + if (verbose >= 2) + logmsg(LOG_NOTICE, "%s[%x]: Looking for attached devices...", + __func__, THREAD); + + for (bus = usb_get_busses(); bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + if (dev->descriptor.idVendor == 0x05ac + && dev->descriptor.idProduct >= 0x1290 + && dev->descriptor.idProduct <= 0x1293) { + if (verbose >= 1) + logmsg(LOG_NOTICE, + "%s[%x]: Found device on bus %d, id %d", + __func__, THREAD, bus->location, dev->devnum); + found++; + + // construct packet + memset(&dev_info_rec, 0, sizeof(dev_info_rec)); + dev_info_rec.header.length = sizeof(dev_info_rec); + dev_info_rec.header.type = USBMUXD_DEVICE_INFO; + dev_info_rec.device.device_id = dev->devnum; + dev_info_rec.device.product_id = dev->descriptor.idProduct; + if (dev->descriptor.iSerialNumber) { + usb_dev_handle *udev; + //pthread_mutex_lock(&usbmux_mutex); + udev = usb_open(dev); + if (udev) { + usb_get_string_simple(udev, + dev->descriptor. + iSerialNumber, + dev_info_rec.device. + serial_number, + sizeof(dev_info_rec.device. + serial_number) + 1); + usb_close(udev); + } + //pthread_mutex_unlock(&usbmux_mutex); + } #ifdef DEBUG - if (verbose >= 4) print_buffer(stderr, (char*)&dev_info_rec, sizeof(dev_info_rec)); + if (verbose >= 4) + print_buffer(stderr, (char *) &dev_info_rec, + sizeof(dev_info_rec)); #endif - // send it - if (send_buf(cdata->socket, &dev_info_rec, sizeof(dev_info_rec)) <= 0) { - if (verbose >= 3) logmsg(LOG_ERR, "%s[%x]: Error: Could not send device info: %s", __func__, THREAD, strerror(errno)); - found--; + // send it + if (send_buf + (cdata->socket, &dev_info_rec, + sizeof(dev_info_rec)) <= 0) { + if (verbose >= 3) + logmsg(LOG_ERR, + "%s[%x]: Error: Could not send device info: %s", + __func__, THREAD, strerror(errno)); + found--; + } + } } - } } - } - pthread_mutex_unlock(&usb_mutex); - - if (found <= 0) { - if (verbose >= 1) logmsg(LOG_NOTICE, "%s[%x]: No attached iPhone/iPod devices found.", __func__, THREAD); - goto leave; - } - - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%x]: Waiting for connect request", __func__, THREAD); - - // now wait for connect request - //memset(&c_req, 0, sizeof(c_req)); - if ((recv_len = usbmuxd_get_request(cdata->socket, (void**)&c_req, 0)) <= 0) { - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%x]: Did not receive any connect request.", __func__, THREAD); - goto leave; - } - -connect: - - if (c_req->header.type != USBMUXD_CONNECT) { - if (verbose >= 2) logmsg(LOG_ERR, "%s[%x]: Unexpected packet of type %d received.", __func__, THREAD, c_req->header.type); - goto leave; - } - - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%x]: Setting up connection to usb device #%d on port %d", __func__, THREAD, c_req->device_id, ntohs(c_req->tcp_dport)); - - // find the device, and open usb connection - pthread_mutex_lock(&usbmux_mutex); - phone = NULL; - cur_dev = NULL; - // first check if we already have an open connection - if (devices) { - for (i = 0; i < device_count; i++) { - if (devices[i]) { - if (devices[i]->device_id == c_req->device_id) { - devices[i]->use_count++; - cur_dev = devices[i]; - phone = cur_dev->phone; - break; - } - } + pthread_mutex_unlock(&usb_mutex); + + if (found <= 0) { + if (verbose >= 1) + logmsg(LOG_NOTICE, + "%s[%x]: No attached iPhone/iPod devices found.", + __func__, THREAD); + goto leave; } - } - if (!phone) { - // if not found, make a new connection - if (verbose >= 2) logmsg(LOG_NOTICE, "%s[%x]: creating new usb connection, device_id=%d", __func__, THREAD, c_req->device_id); - pthread_mutex_lock(&usb_mutex); - if (usbmux_get_specific_device(0, c_req->device_id, &phone) < 0) { - pthread_mutex_unlock(&usb_mutex); - pthread_mutex_unlock(&usbmux_mutex); - if (verbose >= 1) logmsg(LOG_ERR, "%s[%x]: device_id %d could not be opened", __func__, THREAD, c_req->device_id); - usbmuxd_send_result(cdata->socket, c_req->header.tag, ENODEV); - goto leave; + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%x]: Waiting for connect request", __func__, + THREAD); + + // now wait for connect request + //memset(&c_req, 0, sizeof(c_req)); + if ((recv_len = + usbmuxd_get_request(cdata->socket, (void **) &c_req, 0)) <= 0) { + if (verbose >= 3) + logmsg(LOG_NOTICE, + "%s[%x]: Did not receive any connect request.", + __func__, THREAD); + goto leave; } - pthread_mutex_unlock(&usb_mutex); - - // create device object - if (verbose >= 3) logmsg(LOG_DEBUG, "%s[%x]: add to device list", __func__, THREAD); - cur_dev = (struct device_info*)malloc(sizeof(struct device_info)); - memset(cur_dev, 0, sizeof(struct device_info)); - cur_dev->use_count = 1; - cur_dev->device_id = c_req->device_id; - cur_dev->phone = phone; - cur_dev->bulk_reader = 0; - pthread_mutex_init(&cur_dev->mutex, NULL); - pthread_mutex_init(&cur_dev->writer_mutex, NULL); - - if (verbose >= 3) logmsg(LOG_DEBUG, "%s[%x]: device_count = %d", __func__, THREAD, device_count); - - // add to list of devices - devices = (struct device_info**)realloc(devices, sizeof(struct device_info*) * (device_count+1)); + + connect: + + if (c_req->header.type != USBMUXD_CONNECT) { + if (verbose >= 2) + logmsg(LOG_ERR, + "%s[%x]: Unexpected packet of type %d received.", + __func__, THREAD, c_req->header.type); + goto leave; + } + + if (verbose >= 3) + logmsg(LOG_NOTICE, + "%s[%x]: Setting up connection to usb device #%d on port %d", + __func__, THREAD, c_req->device_id, + ntohs(c_req->tcp_dport)); + + // find the device, and open usb connection + pthread_mutex_lock(&usbmux_mutex); + phone = NULL; + cur_dev = NULL; + // first check if we already have an open connection if (devices) { - devices[device_count] = cur_dev; - device_count++; + for (i = 0; i < device_count; i++) { + if (devices[i]) { + if (devices[i]->device_id == c_req->device_id) { + devices[i]->use_count++; + cur_dev = devices[i]; + phone = cur_dev->phone; + break; + } + } + } + } + if (!phone) { + // if not found, make a new connection + if (verbose >= 2) + logmsg(LOG_NOTICE, + "%s[%x]: creating new usb connection, device_id=%d", + __func__, THREAD, c_req->device_id); + + pthread_mutex_lock(&usb_mutex); + if (usbmux_get_specific_device(0, c_req->device_id, &phone) < 0) { + pthread_mutex_unlock(&usb_mutex); + pthread_mutex_unlock(&usbmux_mutex); + if (verbose >= 1) + logmsg(LOG_ERR, "%s[%x]: device_id %d could not be opened", + __func__, THREAD, c_req->device_id); + usbmuxd_send_result(cdata->socket, c_req->header.tag, ENODEV); + goto leave; + } + pthread_mutex_unlock(&usb_mutex); + + // create device object + if (verbose >= 3) + logmsg(LOG_DEBUG, "%s[%x]: add to device list", __func__, + THREAD); + cur_dev = + (struct device_info *) malloc(sizeof(struct device_info)); + memset(cur_dev, 0, sizeof(struct device_info)); + cur_dev->use_count = 1; + cur_dev->device_id = c_req->device_id; + cur_dev->phone = phone; + cur_dev->bulk_reader = 0; + pthread_mutex_init(&cur_dev->mutex, NULL); + pthread_mutex_init(&cur_dev->writer_mutex, NULL); + + if (verbose >= 3) + logmsg(LOG_DEBUG, "%s[%x]: device_count = %d", __func__, + THREAD, device_count); + + // add to list of devices + devices = + (struct device_info **) realloc(devices, + sizeof(struct device_info *) * + (device_count + 1)); + if (devices) { + devices[device_count] = cur_dev; + device_count++; + } + } else { + if (verbose >= 2) + logmsg(LOG_NOTICE, + "%s[%x]: reusing usb connection, device_id=%d", + __func__, THREAD, c_req->device_id); } - } else { - if (verbose >= 2) logmsg(LOG_NOTICE, "%s[%x]: reusing usb connection, device_id=%d", __func__, THREAD, c_req->device_id); - } - pthread_mutex_unlock(&usbmux_mutex); + pthread_mutex_unlock(&usbmux_mutex); - // setup connection to iPhone/iPod + // setup connection to iPhone/iPod // pthread_mutex_lock(&usbmux_mutex); - res = usbmux_new_client(cur_dev->phone, 0, ntohs(c_req->tcp_dport), &(cdata->muxclient)); + res = + usbmux_new_client(cur_dev->phone, 0, ntohs(c_req->tcp_dport), + &(cdata->muxclient)); // pthread_mutex_unlock(&usbmux_mutex); - if (res != 0) { - usbmuxd_send_result(cdata->socket, c_req->header.tag, res); - if (verbose >= 1) logmsg(LOG_ERR, "%s[%x]: mux_new_client returned %d, aborting.", __func__, THREAD, res); - goto leave; - } - - // start bulk reader thread (once per device) - pthread_mutex_lock(&cur_dev->mutex); - if (cur_dev->bulk_reader == 0) { - pthread_create(&cur_dev->bulk_reader, NULL, usbmuxd_bulk_reader_thread, cur_dev); - } - pthread_mutex_unlock(&cur_dev->mutex); - - // start connection handler thread - cdata->handler_dead = 0; - cdata->tag = c_req->header.tag; - cdata->dev = cur_dev; - if (pthread_create(&cdata->handler, NULL, usbmuxd_client_handler_thread, cdata) != 0) { - if (verbose >= 1) logmsg(LOG_ERR, "%s[%x]: could not create usbmuxd_client_handler_thread!", __func__, THREAD); - cdata->handler = 0; - goto leave; - } - - // wait for handler thread to finish its work - if (cdata->handler != 0) { - pthread_join(cdata->handler, NULL); - } - - if (verbose >= 2) logmsg(LOG_NOTICE, "%s[%x]: closing connection", __func__, THREAD); - - // time to clean up - if (cdata && cdata->muxclient) { // should be non-NULL - usbmux_free_client(cdata->muxclient); - } - -leave: - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%x]: terminating", __func__, THREAD); - - if (s_req) { - free(s_req); - } - if (c_req) { - free(c_req); - } - - // this has to be freed only if it's not in use anymore as it closes - // the USB connection - pthread_mutex_lock(&usbmux_mutex); - if (cur_dev) { + if (res != 0) { + usbmuxd_send_result(cdata->socket, c_req->header.tag, res); + if (verbose >= 1) + logmsg(LOG_ERR, + "%s[%x]: mux_new_client returned %d, aborting.", + __func__, THREAD, res); + goto leave; + } + // start bulk reader thread (once per device) pthread_mutex_lock(&cur_dev->mutex); - if (cur_dev->use_count > 1) { - if (verbose >= 2) logmsg(LOG_NOTICE, "%s[%x]: decreasing device use count (from %d to %d)", __func__, THREAD, cur_dev->use_count, cur_dev->use_count-1); - cur_dev->use_count--; - pthread_mutex_unlock(&cur_dev->mutex); - } else { - if (verbose >= 2) logmsg(LOG_NOTICE, "%s[%x]: last client disconnected, cleaning up", __func__, THREAD); - cur_dev->use_count = 0; - pthread_mutex_unlock(&cur_dev->mutex); - if (cur_dev->bulk_reader != 0) { - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%x]: joining bulk_reader...", __func__, THREAD); - pthread_join(cur_dev->bulk_reader, NULL); - } - pthread_mutex_lock(&usb_mutex); - usbmux_free_device(cur_dev->phone); - pthread_mutex_unlock(&usb_mutex); - pthread_mutex_destroy(&cur_dev->writer_mutex); - pthread_mutex_destroy(&cur_dev->mutex); - free(cur_dev); - cur_dev = NULL; - if (device_count > 1) { - struct device_info **newlist; - int j; - - newlist = (struct device_info**)malloc(sizeof(struct device_info*) * device_count-1); - for (i = 0; i < device_count; i++) { - if (devices[i] != NULL) { - newlist[j++] = devices[i]; - } + if (cur_dev->bulk_reader == 0) { + pthread_create(&cur_dev->bulk_reader, NULL, + usbmuxd_bulk_reader_thread, cur_dev); + } + pthread_mutex_unlock(&cur_dev->mutex); + + // start connection handler thread + cdata->handler_dead = 0; + cdata->tag = c_req->header.tag; + cdata->dev = cur_dev; + if (pthread_create + (&cdata->handler, NULL, usbmuxd_client_handler_thread, cdata) != 0) + { + if (verbose >= 1) + logmsg(LOG_ERR, + "%s[%x]: could not create usbmuxd_client_handler_thread!", + __func__, THREAD); + cdata->handler = 0; + goto leave; + } + // wait for handler thread to finish its work + if (cdata->handler != 0) { + pthread_join(cdata->handler, NULL); + } + + if (verbose >= 2) + logmsg(LOG_NOTICE, "%s[%x]: closing connection", __func__, THREAD); + + // time to clean up + if (cdata && cdata->muxclient) { // should be non-NULL + usbmux_free_client(cdata->muxclient); + } + + leave: + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%x]: terminating", __func__, THREAD); + + if (s_req) { + free(s_req); + } + if (c_req) { + free(c_req); + } + // this has to be freed only if it's not in use anymore as it closes + // the USB connection + pthread_mutex_lock(&usbmux_mutex); + if (cur_dev) { + pthread_mutex_lock(&cur_dev->mutex); + if (cur_dev->use_count > 1) { + if (verbose >= 2) + logmsg(LOG_NOTICE, + "%s[%x]: decreasing device use count (from %d to %d)", + __func__, THREAD, cur_dev->use_count, + cur_dev->use_count - 1); + cur_dev->use_count--; + pthread_mutex_unlock(&cur_dev->mutex); + } else { + if (verbose >= 2) + logmsg(LOG_NOTICE, + "%s[%x]: last client disconnected, cleaning up", + __func__, THREAD); + cur_dev->use_count = 0; + pthread_mutex_unlock(&cur_dev->mutex); + if (cur_dev->bulk_reader != 0) { + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%x]: joining bulk_reader...", + __func__, THREAD); + pthread_join(cur_dev->bulk_reader, NULL); + } + pthread_mutex_lock(&usb_mutex); + usbmux_free_device(cur_dev->phone); + pthread_mutex_unlock(&usb_mutex); + pthread_mutex_destroy(&cur_dev->writer_mutex); + pthread_mutex_destroy(&cur_dev->mutex); + free(cur_dev); + cur_dev = NULL; + if (device_count > 1) { + struct device_info **newlist; + int j; + + newlist = + (struct device_info **) + malloc(sizeof(struct device_info *) + * device_count - 1); + for (i = 0; i < device_count; i++) { + if (devices[i] != NULL) { + newlist[j++] = devices[i]; + } + } + free(devices); + devices = newlist; + device_count--; + } else { + free(devices); + devices = NULL; + device_count = 0; + } } - free(devices); - devices = newlist; - device_count--; - } else { - free(devices); - devices = NULL; - device_count = 0; - } } - } - pthread_mutex_unlock(&usbmux_mutex); + pthread_mutex_unlock(&usbmux_mutex); + + cdata->dead = 1; + close(cdata->socket); - cdata->dead = 1; - close(cdata->socket); - - if (verbose >= 3) logmsg(LOG_NOTICE, "%s[%x]: terminated", __func__, THREAD); + if (verbose >= 3) + logmsg(LOG_NOTICE, "%s[%x]: terminated", __func__, THREAD); - return NULL; + return NULL; } /** @@ -807,44 +962,42 @@ leave: */ static int daemonize() { - pid_t pid; - pid_t sid; + pid_t pid; + pid_t sid; - // already a daemon - if (getppid() == 1) return 0; + // already a daemon + if (getppid() == 1) + return 0; - pid = fork(); - if (pid < 0) { - exit(EXIT_FAILURE); - } - - if (pid > 0) { - // exit parent process - exit(EXIT_SUCCESS); - } - - // At this point we are executing as the child process - - // Change the file mode mask - umask(0); + pid = fork(); + if (pid < 0) { + exit(EXIT_FAILURE); + } - // Create a new SID for the child process - sid = setsid(); - if (sid < 0) { - return -1; - } + if (pid > 0) { + // exit parent process + exit(EXIT_SUCCESS); + } + // At this point we are executing as the child process - // Change the current working directory. - if ((chdir("/")) < 0) { - return -2; - } + // Change the file mode mask + umask(0); - // Redirect standard files to /dev/null - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); + // Create a new SID for the child process + sid = setsid(); + if (sid < 0) { + return -1; + } + // Change the current working directory. + if ((chdir("/")) < 0) { + return -2; + } + // Redirect standard files to /dev/null + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); - return 0; + return 0; } /** @@ -852,56 +1005,57 @@ static int daemonize() */ static void clean_exit(int sig) { - if (sig == SIGINT) { - if (verbose >= 1) fprintf(stderr, "CTRL+C pressed\n"); - } - quit_flag = 1; + if (sig == SIGINT) { + if (verbose >= 1) + fprintf(stderr, "CTRL+C pressed\n"); + } + quit_flag = 1; } static void usage() { - printf("usage: usbmuxd [options]\n"); - printf("\t-h|--help print this message.\n"); - printf("\t-v|--verbose be verbose\n"); - printf("\t-f|--foreground do not daemonize\n"); - printf("\n"); + printf("usage: usbmuxd [options]\n"); + printf("\t-h|--help print this message.\n"); + printf("\t-v|--verbose be verbose\n"); + printf("\t-f|--foreground do not daemonize\n"); + printf("\n"); } static void parse_opts(int argc, char **argv) { - static struct option longopts[] = { - { "help", 0, NULL, 'h' }, - { "foreground", 0, NULL, 'f' }, - { "verbose", 0, NULL, 'v' }, - { "exit-on-no-devices", 0, NULL, 'e' }, - { NULL, 0, NULL, 0} - }; - int c; - - while (1) { - c = getopt_long(argc, argv, "hfve", longopts, (int *) 0); - if (c == -1) { - break; - } + static struct option longopts[] = { + {"help", 0, NULL, 'h'}, + {"foreground", 0, NULL, 'f'}, + {"verbose", 0, NULL, 'v'}, + {"exit-on-no-devices", 0, NULL, 'e'}, + {NULL, 0, NULL, 0} + }; + int c; + + while (1) { + c = getopt_long(argc, argv, "hfve", longopts, (int *) 0); + if (c == -1) { + break; + } - switch (c) { - case 'h': - usage(); - exit(0); - case 'f': - foreground = 1; - break; - case 'v': - sock_stuff_set_verbose(++verbose); - break; - case 'e': - exit_on_no_devices = 1; - break; - default: - usage(); - exit(2); + switch (c) { + case 'h': + usage(); + exit(0); + case 'f': + foreground = 1; + break; + case 'v': + sock_stuff_set_verbose(++verbose); + break; + case 'e': + exit_on_no_devices = 1; + break; + default: + usage(); + exit(2); + } } - } } /** @@ -911,26 +1065,25 @@ static void parse_opts(int argc, char **argv) */ static int devices_attached() { - struct usb_bus *bus; - struct usb_device *dev; - int res = 0; - - usb_init(); - usb_find_busses(); - usb_find_devices(); - - for (bus = usb_get_busses(); bus; bus = bus->next) { - for (dev = bus->devices; dev; dev = dev->next) { - if (dev->descriptor.idVendor == 0x05ac - && dev->descriptor.idProduct >= 0x1290 - && dev->descriptor.idProduct <= 0x1293) - { - res++; - } + struct usb_bus *bus; + struct usb_device *dev; + int res = 0; + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + for (bus = usb_get_busses(); bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + if (dev->descriptor.idVendor == 0x05ac + && dev->descriptor.idProduct >= 0x1290 + && dev->descriptor.idProduct <= 0x1293) { + res++; + } + } } - } - return res; + return res; } /** @@ -938,233 +1091,261 @@ static int devices_attached() */ int main(int argc, char **argv) { - struct sockaddr_un c_addr; - socklen_t len = sizeof(struct sockaddr_un); - struct client_data *cdata = NULL; - struct client_data **children = NULL; - int children_capacity = DEFAULT_CHILDREN_CAPACITY; - int i; - int result = 0; - int cnt = 0; - FILE *lfd = NULL; - struct flock lock; - - parse_opts(argc, argv); - - argc -= optind; - argv += optind; - - if (!foreground) { - openlog("usbmuxd", LOG_PID, 0); - } - - if (verbose >= 2) logmsg(LOG_NOTICE, "starting"); - - // signal(SIGHUP, reload_conf); // none yet - signal(SIGINT, clean_exit); - signal(SIGQUIT, clean_exit); - signal(SIGTERM, clean_exit); - signal(SIGPIPE, SIG_IGN); - - // check for other running instance - lfd = fopen(LOCKFILE, "r"); - if (lfd) { - lock.l_type = 0; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - fcntl(fileno(lfd), F_GETLK, &lock); - fclose(lfd); - if (lock.l_type != F_UNLCK) { - logmsg(LOG_NOTICE, "another instance is already running. exiting."); - return -1; + struct sockaddr_un c_addr; + socklen_t len = sizeof(struct sockaddr_un); + struct client_data *cdata = NULL; + struct client_data **children = NULL; + int children_capacity = DEFAULT_CHILDREN_CAPACITY; + int i; + int result = 0; + int cnt = 0; + FILE *lfd = NULL; + struct flock lock; + + parse_opts(argc, argv); + + argc -= optind; + argv += optind; + + if (!foreground) { + openlog("usbmuxd", LOG_PID, 0); } - } - if (exit_on_no_devices) { - if (devices_attached() <= 0) { - logmsg(LOG_NOTICE, "no devices attached. exiting."); - return 0; + if (verbose >= 2) + logmsg(LOG_NOTICE, "starting"); + + // signal(SIGHUP, reload_conf); // none yet + signal(SIGINT, clean_exit); + signal(SIGQUIT, clean_exit); + signal(SIGTERM, clean_exit); + signal(SIGPIPE, SIG_IGN); + + // check for other running instance + lfd = fopen(LOCKFILE, "r"); + if (lfd) { + lock.l_type = 0; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + fcntl(fileno(lfd), F_GETLK, &lock); + fclose(lfd); + if (lock.l_type != F_UNLCK) { + logmsg(LOG_NOTICE, + "another instance is already running. exiting."); + return -1; + } } - } - fsock = create_unix_socket(USBMUXD_SOCKET_FILE); - if (fsock < 0) { - logmsg(LOG_ERR, "Could not create socket, exiting"); - if (!foreground) { - closelog(); + if (exit_on_no_devices) { + if (devices_attached() <= 0) { + logmsg(LOG_NOTICE, "no devices attached. exiting."); + return 0; + } } - return -1; - } - chmod(USBMUXD_SOCKET_FILE, 0666); + fsock = create_unix_socket(USBMUXD_SOCKET_FILE); + if (fsock < 0) { + logmsg(LOG_ERR, "Could not create socket, exiting"); + if (!foreground) { + closelog(); + } + return -1; + } - if (verbose >= 3) usbmux_set_debug(1); + chmod(USBMUXD_SOCKET_FILE, 0666); - if (!foreground) { - if (daemonize() < 0) { - fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n"); - syslog(LOG_ERR, "FATAL: Could not daemonize!"); - closelog(); - exit(EXIT_FAILURE); - } - } - - // now open the lockfile and place the lock - lfd = fopen(LOCKFILE, "w"); - if (lfd) { - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - if (fcntl(fileno(lfd), F_SETLK, &lock) == -1) { - logmsg(LOG_ERR, "ERROR: lockfile locking failed!"); - } - } + if (verbose >= 3) + usbmux_set_debug(1); - // drop elevated privileges - if (getuid() == 0 || geteuid() == 0) { - struct passwd *pw = getpwnam("nobody"); - if (pw) { - setuid(pw->pw_uid); - } else { - logmsg(LOG_ERR, "ERROR: Dropping privileges failed, check if user 'nobody' exists! Will now terminate."); - exit(EXIT_FAILURE); + if (!foreground) { + if (daemonize() < 0) { + fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n"); + syslog(LOG_ERR, "FATAL: Could not daemonize!"); + closelog(); + exit(EXIT_FAILURE); + } } + // now open the lockfile and place the lock + lfd = fopen(LOCKFILE, "w"); + if (lfd) { + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + if (fcntl(fileno(lfd), F_SETLK, &lock) == -1) { + logmsg(LOG_ERR, "ERROR: lockfile locking failed!"); + } + } + // drop elevated privileges + if (getuid() == 0 || geteuid() == 0) { + struct passwd *pw = getpwnam("nobody"); + if (pw) { + setuid(pw->pw_uid); + } else { + logmsg(LOG_ERR, + "ERROR: Dropping privileges failed, check if user 'nobody' exists! Will now terminate."); + exit(EXIT_FAILURE); + } - // security check - if (setuid(0) != -1) { - logmsg(LOG_ERR, "ERROR: Failed to drop privileges properly!"); - exit(EXIT_FAILURE); + // security check + if (setuid(0) != -1) { + logmsg(LOG_ERR, "ERROR: Failed to drop privileges properly!"); + exit(EXIT_FAILURE); + } + if (verbose >= 2) + logmsg(LOG_NOTICE, "Successfully dropped privileges"); } - if (verbose >= 2) logmsg(LOG_NOTICE, "Successfully dropped privileges"); - } - - // Reserve space for 10 clients which should be enough. If not, the - // buffer gets enlarged later. - children = (struct client_data**)malloc(sizeof(struct client_data*) * children_capacity); - if (!children) { - logmsg(LOG_ERR, "Out of memory when allocating memory for child threads. Terminating."); - if (!foreground) { - closelog(); + // Reserve space for 10 clients which should be enough. If not, the + // buffer gets enlarged later. + children = + (struct client_data **) malloc(sizeof(struct client_data *) * + children_capacity); + if (!children) { + logmsg(LOG_ERR, + "Out of memory when allocating memory for child threads. Terminating."); + if (!foreground) { + closelog(); + } + exit(EXIT_FAILURE); } - exit(EXIT_FAILURE); - } - memset(children, 0, sizeof(struct client_data*) * children_capacity); - - if (verbose >= 2) logmsg(LOG_NOTICE, "waiting for connection"); - while (!quit_flag) { - // Check the file descriptor before accepting a connection. - // If no connection attempt is made, just repeat... - result = check_fd(fsock, FD_READ, 1000); - if (result <= 0) { - if (result == 0) { - // cleanup - for (i = 0; i < children_capacity; i++) { - if (children[i]) { - if (children[i]->dead != 0) { - pthread_join(children[i]->thread, NULL); - if (verbose >= 3) logmsg(LOG_NOTICE, "reclaimed client thread (fd=%d)", children[i]->socket); - free(children[i]); - children[i] = NULL; - cnt++; + memset(children, 0, sizeof(struct client_data *) * children_capacity); + + if (verbose >= 2) + logmsg(LOG_NOTICE, "waiting for connection"); + while (!quit_flag) { + // Check the file descriptor before accepting a connection. + // If no connection attempt is made, just repeat... + result = check_fd(fsock, FD_READ, 1000); + if (result <= 0) { + if (result == 0) { + // cleanup + for (i = 0; i < children_capacity; i++) { + if (children[i]) { + if (children[i]->dead != 0) { + pthread_join(children[i]->thread, NULL); + if (verbose >= 3) + logmsg(LOG_NOTICE, + "reclaimed client thread (fd=%d)", + children[i]->socket); + free(children[i]); + children[i] = NULL; + cnt++; + } else { + cnt = 0; + } + } else { + cnt++; + } + } + + if ((children_capacity > DEFAULT_CHILDREN_CAPACITY) + && ((children_capacity - cnt) <= + DEFAULT_CHILDREN_CAPACITY)) { + children_capacity = DEFAULT_CHILDREN_CAPACITY; + children = + realloc(children, + sizeof(struct client_data *) * + children_capacity); + } + continue; } else { - cnt = 0; + if (verbose >= 3) + logmsg(LOG_ERR, "usbmuxd: select error: %s", + strerror(errno)); + continue; } - } else { - cnt++; - } } - if ((children_capacity > DEFAULT_CHILDREN_CAPACITY) - && ((children_capacity - cnt) <= DEFAULT_CHILDREN_CAPACITY)) { - children_capacity = DEFAULT_CHILDREN_CAPACITY; - children = realloc(children, sizeof(struct client_data*) * children_capacity); + cdata = (struct client_data *) malloc(sizeof(struct client_data)); + memset(cdata, 0, sizeof(struct client_data)); + if (!cdata) { + quit_flag = 1; + logmsg(LOG_ERR, "Error: Out of memory! Terminating."); + break; } - continue; - } else { - if (verbose >= 3) logmsg(LOG_ERR, "usbmuxd: select error: %s", strerror(errno)); - continue; - } - } - cdata = (struct client_data*)malloc(sizeof(struct client_data)); - memset(cdata, 0, sizeof(struct client_data)); - if (!cdata) { - quit_flag = 1; - logmsg(LOG_ERR, "Error: Out of memory! Terminating."); - break; - } - - cdata->socket = accept(fsock, (struct sockaddr*)&c_addr, &len); - if (cdata->socket < 0) { - free(cdata); - if (errno == EINTR) { - continue; - } else { - if (verbose >= 3) logmsg(LOG_ERR, "Error in accept: %s", strerror(errno)); - continue; - } - } + cdata->socket = accept(fsock, (struct sockaddr *) &c_addr, &len); + if (cdata->socket < 0) { + free(cdata); + if (errno == EINTR) { + continue; + } else { + if (verbose >= 3) + logmsg(LOG_ERR, "Error in accept: %s", + strerror(errno)); + continue; + } + } - if (verbose >= 1) logmsg(LOG_NOTICE, "new client connected (fd=%d)", cdata->socket); - - // create client thread: - if (pthread_create(&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0) { - for (i = 0; i < children_capacity; i++) { - if (children[i] == NULL) break; - } - if (i == children_capacity) { - // enlarge buffer - children_capacity++; - children = realloc(children, sizeof(struct client_data*) * children_capacity); - if (!children) { - logmsg(LOG_ERR, "Out of memory when enlarging child thread buffer"); + if (verbose >= 1) + logmsg(LOG_NOTICE, "new client connected (fd=%d)", + cdata->socket); + + // create client thread: + if (pthread_create + (&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0) + { + for (i = 0; i < children_capacity; i++) { + if (children[i] == NULL) + break; + } + if (i == children_capacity) { + // enlarge buffer + children_capacity++; + children = + realloc(children, + sizeof(struct client_data *) * + children_capacity); + if (!children) { + logmsg(LOG_ERR, + "Out of memory when enlarging child thread buffer"); + } + } + children[i] = cdata; + } else { + logmsg(LOG_ERR, "Failed to create client_init_thread."); + close(cdata->socket); + free(cdata); + cdata = NULL; } - } - children[i] = cdata; - } else { - logmsg(LOG_ERR, "Failed to create client_init_thread."); - close(cdata->socket); - free(cdata); - cdata = NULL; } - } - if (verbose >= 3) logmsg(LOG_NOTICE, "terminating"); + if (verbose >= 3) + logmsg(LOG_NOTICE, "terminating"); - // preparing for shutdown: wait for child threads to terminate (if any) - if (verbose >= 2) logmsg(LOG_NOTICE, "waiting for child threads to terminate..."); - for (i = 0; i < children_capacity; i++) { - if (children[i] != NULL) { - pthread_join(children[i]->thread, NULL); - free(children[i]); - } - } + // preparing for shutdown: wait for child threads to terminate (if any) + if (verbose >= 2) + logmsg(LOG_NOTICE, "waiting for child threads to terminate..."); + for (i = 0; i < children_capacity; i++) { + if (children[i] != NULL) { + pthread_join(children[i]->thread, NULL); + free(children[i]); + } + } - // delete the children set. - free(children); - children = NULL; + // delete the children set. + free(children); + children = NULL; - if (fsock >= 0) { - close(fsock); - } + if (fsock >= 0) { + close(fsock); + } - unlink(USBMUXD_SOCKET_FILE); + unlink(USBMUXD_SOCKET_FILE); - // unlock lock file and close it. - if (lfd) { - lock.l_type = F_UNLCK; - fcntl(fileno(lfd), F_SETLK, &lock); - fclose(lfd); - } + // unlock lock file and close it. + if (lfd) { + lock.l_type = F_UNLCK; + fcntl(fileno(lfd), F_SETLK, &lock); + fclose(lfd); + } - if (verbose >= 1) logmsg(LOG_NOTICE, "usbmuxd: terminated"); - if (!foreground) { - closelog(); - } + if (verbose >= 1) + logmsg(LOG_NOTICE, "usbmuxd: terminated"); + if (!foreground) { + closelog(); + } - return 0; + return 0; } - diff --git a/sock_stuff.c b/sock_stuff.c index 43fdf0e..b51d6ba 100644 --- a/sock_stuff.c +++ b/sock_stuff.c @@ -17,270 +17,282 @@ static int verbose = 0; void sock_stuff_set_verbose(int level) { - verbose = level; + verbose = level; } -int create_unix_socket (const char *filename) +int create_unix_socket(const char *filename) { - struct sockaddr_un name; - int sock; - size_t size; - - // remove if still present - unlink(filename); - - /* Create the socket. */ - sock = socket (PF_LOCAL, SOCK_STREAM, 0); - if (sock < 0) { - perror ("socket"); - return -1; - } - - /* Bind a name to the socket. */ - name.sun_family = AF_LOCAL; - strncpy (name.sun_path, filename, sizeof (name.sun_path)); - name.sun_path[sizeof (name.sun_path) - 1] = '\0'; - - /* The size of the address is - the offset of the start of the filename, - plus its length, - plus one for the terminating null byte. - Alternatively you can just do: - size = SUN_LEN (&name); - */ - size = (offsetof (struct sockaddr_un, sun_path) - + strlen (name.sun_path) + 1); - - if (bind (sock, (struct sockaddr *) &name, size) < 0) { - perror("bind"); - close(sock); - return -1; - } - - if (listen(sock, 10) < 0) { - perror("listen"); - close(sock); - return -1; - } - - return sock; + struct sockaddr_un name; + int sock; + size_t size; + + // remove if still present + unlink(filename); + + /* Create the socket. */ + sock = socket(PF_LOCAL, SOCK_STREAM, 0); + if (sock < 0) { + perror("socket"); + return -1; + } + + /* Bind a name to the socket. */ + name.sun_family = AF_LOCAL; + strncpy(name.sun_path, filename, sizeof(name.sun_path)); + name.sun_path[sizeof(name.sun_path) - 1] = '\0'; + + /* The size of the address is + the offset of the start of the filename, + plus its length, + plus one for the terminating null byte. + Alternatively you can just do: + size = SUN_LEN (&name); + */ + size = (offsetof(struct sockaddr_un, sun_path) + + strlen(name.sun_path) + 1); + + if (bind(sock, (struct sockaddr *) &name, size) < 0) { + perror("bind"); + close(sock); + return -1; + } + + if (listen(sock, 10) < 0) { + perror("listen"); + close(sock); + return -1; + } + + return sock; } int connect_unix_socket(const char *filename) { - struct sockaddr_un name; - int sfd = -1; - size_t size; - struct stat fst; - - // check if socket file exists... - if (stat(filename, &fst) != 0) { - if (verbose >= 2) fprintf(stderr, "%s: stat '%s': %s\n", __func__, filename, strerror(errno)); - return -1; - } - - // ... and if it is a unix domain socket - if (!S_ISSOCK(fst.st_mode)) { - if (verbose >= 2) fprintf(stderr, "%s: File '%s' is not a socket!\n", __func__, filename); - return -1; - } - - // make a new socket - if ((sfd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { - if (verbose >= 2) fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno)); - return -1; - } - - // and connect to 'filename' - name.sun_family = AF_LOCAL; - strncpy(name.sun_path, filename, sizeof(name.sun_path)); - name.sun_path[sizeof(name.sun_path) - 1] = 0; - - size = (offsetof (struct sockaddr_un, sun_path) - + strlen (name.sun_path) + 1); - - if (connect(sfd, (struct sockaddr*)&name, size) < 0) { - close(sfd); - if (verbose >= 2) fprintf(stderr, "%s: connect: %s\n", __func__, strerror(errno)); - return -1; - } - - return sfd; + struct sockaddr_un name; + int sfd = -1; + size_t size; + struct stat fst; + + // check if socket file exists... + if (stat(filename, &fst) != 0) { + if (verbose >= 2) + fprintf(stderr, "%s: stat '%s': %s\n", __func__, filename, + strerror(errno)); + return -1; + } + // ... and if it is a unix domain socket + if (!S_ISSOCK(fst.st_mode)) { + if (verbose >= 2) + fprintf(stderr, "%s: File '%s' is not a socket!\n", __func__, + filename); + return -1; + } + // make a new socket + if ((sfd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + if (verbose >= 2) + fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno)); + return -1; + } + // and connect to 'filename' + name.sun_family = AF_LOCAL; + strncpy(name.sun_path, filename, sizeof(name.sun_path)); + name.sun_path[sizeof(name.sun_path) - 1] = 0; + + size = (offsetof(struct sockaddr_un, sun_path) + + strlen(name.sun_path) + 1); + + if (connect(sfd, (struct sockaddr *) &name, size) < 0) { + close(sfd); + if (verbose >= 2) + fprintf(stderr, "%s: connect: %s\n", __func__, + strerror(errno)); + return -1; + } + + return sfd; } int create_socket(uint16_t port) { - int sfd = -1; - int yes = 1; - struct sockaddr_in saddr; - - if ( 0 > ( sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ) ) { - perror("socket()"); - return -1; - } - - if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { - perror("setsockopt()"); - close(sfd); - return -1; - } - - memset((void *)&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = htonl(INADDR_ANY); - saddr.sin_port = htons(port); - - if(0 > bind(sfd, (struct sockaddr *)&saddr , sizeof(saddr))) { - perror("bind()"); - close(sfd); - return -1; - } - - if (listen(sfd, 1) == -1) { - perror("listen()"); - close(sfd); - return -1; - } - - return sfd; + int sfd = -1; + int yes = 1; + struct sockaddr_in saddr; + + if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) { + perror("socket()"); + return -1; + } + + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { + perror("setsockopt()"); + close(sfd); + return -1; + } + + memset((void *) &saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + saddr.sin_port = htons(port); + + if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) { + perror("bind()"); + close(sfd); + return -1; + } + + if (listen(sfd, 1) == -1) { + perror("listen()"); + close(sfd); + return -1; + } + + return sfd; } int connect_socket(const char *addr, uint16_t port) { - int sfd = -1; - int yes = 1; - struct hostent *hp; - struct sockaddr_in saddr; - - if (!addr) { - errno = EINVAL; - return -1; - } - - if ((hp = gethostbyname(addr)) == NULL) { - if (verbose >= 2) fprintf(stderr, "%s: unknown host '%s'\n", __func__, addr); - return -1; - } - - if (!hp->h_addr) { - if (verbose >= 2) fprintf(stderr, "%s: gethostbyname returned NULL address!\n", __func__); - return -1; - } - - if ( 0 > ( sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ) ) { - perror("socket()"); - return -1; - } - - if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { - perror("setsockopt()"); - close(sfd); - return -1; - } - - memset((void *)&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = *(uint32_t*)hp->h_addr; - saddr.sin_port = htons(port); - - if (connect(sfd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0) { - perror("connect"); - close(sfd); - return -2; - } - - return sfd; + int sfd = -1; + int yes = 1; + struct hostent *hp; + struct sockaddr_in saddr; + + if (!addr) { + errno = EINVAL; + return -1; + } + + if ((hp = gethostbyname(addr)) == NULL) { + if (verbose >= 2) + fprintf(stderr, "%s: unknown host '%s'\n", __func__, addr); + return -1; + } + + if (!hp->h_addr) { + if (verbose >= 2) + fprintf(stderr, "%s: gethostbyname returned NULL address!\n", + __func__); + return -1; + } + + if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) { + perror("socket()"); + return -1; + } + + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { + perror("setsockopt()"); + close(sfd); + return -1; + } + + memset((void *) &saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = *(uint32_t *) hp->h_addr; + saddr.sin_port = htons(port); + + if (connect(sfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) { + perror("connect"); + close(sfd); + return -2; + } + + return sfd; } int check_fd(int fd, fd_mode fdm, unsigned int timeout) { - fd_set fds; - int sret; - int eagain; - struct timeval to; - - if (fd <= 0) { - if (verbose >= 2) fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd); - return -1; - } - - FD_ZERO(&fds); - FD_SET(fd, &fds); - - to.tv_sec = (time_t)(timeout/1000); - to.tv_usec = (time_t)((timeout-(to.tv_sec*1000))*1000); - - sret = -1; - - do { - eagain = 0; - switch(fdm) { - case FD_READ: - sret = select(fd+1,&fds,NULL,NULL,&to); - break; - case FD_WRITE: - sret = select(fd+1,NULL,&fds,NULL,&to); - break; - case FD_EXCEPT: - sret = select(fd+1,NULL,NULL,&fds,&to); - break; - default: + fd_set fds; + int sret; + int eagain; + struct timeval to; + + if (fd <= 0) { + if (verbose >= 2) + fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd); return -1; } - - if (sret < 0) { - switch(errno) { - case EINTR: - // interrupt signal in select - if (verbose >= 2) fprintf(stderr, "%s: EINTR\n", __func__); - eagain = 1; - break; - case EAGAIN: - if (verbose >= 2) fprintf(stderr, "%s: EAGAIN\n", __func__); - break; - default: - if (verbose >= 2) fprintf(stderr, "%s: select failed: %s\n", __func__, strerror(errno)); - return -1; - } - } - } while (eagain); - return sret; + FD_ZERO(&fds); + FD_SET(fd, &fds); + + to.tv_sec = (time_t) (timeout / 1000); + to.tv_usec = (time_t) ((timeout - (to.tv_sec * 1000)) * 1000); + + sret = -1; + + do { + eagain = 0; + switch (fdm) { + case FD_READ: + sret = select(fd + 1, &fds, NULL, NULL, &to); + break; + case FD_WRITE: + sret = select(fd + 1, NULL, &fds, NULL, &to); + break; + case FD_EXCEPT: + sret = select(fd + 1, NULL, NULL, &fds, &to); + break; + default: + return -1; + } + + if (sret < 0) { + switch (errno) { + case EINTR: + // interrupt signal in select + if (verbose >= 2) + fprintf(stderr, "%s: EINTR\n", __func__); + eagain = 1; + break; + case EAGAIN: + if (verbose >= 2) + fprintf(stderr, "%s: EAGAIN\n", __func__); + break; + default: + if (verbose >= 2) + fprintf(stderr, "%s: select failed: %s\n", __func__, + strerror(errno)); + return -1; + } + } + } while (eagain); + + return sret; } int recv_buf(int fd, void *data, size_t length) { - return recv_buf_timeout(fd, data, length, 0, RECV_TIMEOUT); + return recv_buf_timeout(fd, data, length, 0, RECV_TIMEOUT); } int peek_buf(int fd, void *data, size_t length) { - return recv_buf_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT); + return recv_buf_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT); } -int recv_buf_timeout(int fd, void *data, size_t length, int flags, unsigned int timeout) +int recv_buf_timeout(int fd, void *data, size_t length, int flags, + unsigned int timeout) { - int res; - int result; - - // check if data is available - res = check_fd(fd, FD_READ, timeout); - if (res <= 0) { - return res; - } - - // if we get here, there _is_ data available - result = recv(fd, data, length, flags); - if (res > 0 && result == 0) { - // but this is an error condition - if (verbose >= 3) fprintf(stderr, "%s: fd=%d recv returned 0\n", __func__, fd); - return -1; - } - return result; + int res; + int result; + + // check if data is available + res = check_fd(fd, FD_READ, timeout); + if (res <= 0) { + return res; + } + // if we get here, there _is_ data available + result = recv(fd, data, length, flags); + if (res > 0 && result == 0) { + // but this is an error condition + if (verbose >= 3) + fprintf(stderr, "%s: fd=%d recv returned 0\n", __func__, fd); + return -1; + } + return result; } int send_buf(int fd, void *data, size_t length) { - return send(fd, data, length, 0); + return send(fd, data, length, 0); } - diff --git a/sock_stuff.h b/sock_stuff.h index b9766ba..190f7e1 100644 --- a/sock_stuff.h +++ b/sock_stuff.h @@ -3,11 +3,10 @@ #include <stdint.h> -enum fd_mode -{ - FD_READ, - FD_WRITE, - FD_EXCEPT +enum fd_mode { + FD_READ, + FD_WRITE, + FD_EXCEPT }; typedef enum fd_mode fd_mode; @@ -19,11 +18,11 @@ int check_fd(int fd, fd_mode fdm, unsigned int timeout); int recv_buf(int fd, void *data, size_t size); int peek_buf(int fd, void *data, size_t size); -int recv_buf_timeout(int fd, void *data, size_t size, int flags, unsigned int timeout); +int recv_buf_timeout(int fd, void *data, size_t size, int flags, + unsigned int timeout); int send_buf(int fd, void *data, size_t size); void sock_stuff_set_verbose(int level); -#endif /* __SOCK_STUFF_H */ - +#endif /* __SOCK_STUFF_H */ @@ -50,7 +50,7 @@ static const uint32_t WINDOW_MAX = 5 * 1024; static const uint32_t WINDOW_INCREMENT = 512; typedef struct { - char* buffer; + char *buffer; int leftover; int capacity; } receivebuf_t; @@ -145,20 +145,20 @@ static void print_buffer(const char *data, const int length) int j; unsigned char c; - for(i=0; i<length; i+=16) { + for (i = 0; i < length; i += 16) { printf("%04x: ", i); - for (j=0;j<16;j++) { - if (i+j >= length) { + for (j = 0; j < 16; j++) { + if (i + j >= length) { printf(" "); continue; } - printf("%02hhx ", *(data+i+j)); + printf("%02hhx ", *(data + i + j)); } printf(" | "); - for(j=0;j<16;j++) { - if (i+j >= length) + for (j = 0; j < 16; j++) { + if (i + j >= length) break; - c = *(data+i+j); + c = *(data + i + j); if ((c < 32) || (c > 127)) { printf("."); continue; @@ -171,7 +171,7 @@ static void print_buffer(const char *data, const int length) } #endif -void hton_header(usbmux_tcp_header *hdr) +void hton_header(usbmux_tcp_header * hdr) { if (hdr) { hdr->length = htonl(hdr->length); @@ -181,7 +181,7 @@ void hton_header(usbmux_tcp_header *hdr) } } -void ntoh_header(usbmux_tcp_header *hdr) +void ntoh_header(usbmux_tcp_header * hdr) { if (hdr) { hdr->length = ntohl(hdr->length); @@ -197,7 +197,8 @@ void ntoh_header(usbmux_tcp_header *hdr) */ usbmux_version_header *version_header() { - usbmux_version_header *version = (usbmux_version_header *) malloc(sizeof(usbmux_version_header)); + usbmux_version_header *version = + (usbmux_version_header *) malloc(sizeof(usbmux_version_header)); version->type = 0; version->length = htonl(20); version->major = htonl(1); @@ -222,25 +223,34 @@ static int usbmux_config_usb_device(usbmux_device_t device) #if 0 log_debug_msg("checking configuration...\n"); if (device->__device->config->bConfigurationValue != 3) { - log_debug_msg("WARNING: usb device configuration is not 3 as expected!\n"); + log_debug_msg + ("WARNING: usb device configuration is not 3 as expected!\n"); } log_debug_msg("setting configuration...\n"); ret = usb_set_configuration(device->device, 3); if (ret != 0) { - log_debug_msg("Hm, usb_set_configuration returned %d: %s\n", ret, strerror(-ret)); + log_debug_msg("Hm, usb_set_configuration returned %d: %s\n", ret, + strerror(-ret)); #if LIBUSB_HAS_GET_DRIVER_NP log_debug_msg("trying to fix:\n"); log_debug_msg("-> detaching kernel driver... "); - ret = usb_detach_kernel_driver_np(device->device, device->__device->config->interface->altsetting->bInterfaceNumber); + ret = + usb_detach_kernel_driver_np(device->device, + device->__device->config-> + interface->altsetting-> + bInterfaceNumber); if (ret != 0) { - log_debug_msg("usb_detach_kernel_driver_np returned %d: %s\n", ret, strerror(-ret)); + log_debug_msg("usb_detach_kernel_driver_np returned %d: %s\n", + ret, strerror(-ret)); } else { log_debug_msg("done.\n"); log_debug_msg("setting configuration again... "); ret = usb_set_configuration(device->device, 3); if (ret != 0) { - log_debug_msg("Error: usb_set_configuration returned %d: %s\n", ret, strerror(-ret)); + log_debug_msg + ("Error: usb_set_configuration returned %d: %s\n", ret, + strerror(-ret)); log_debug_msg("--> trying to continue anyway...\n"); } else { log_debug_msg("done.\n"); @@ -257,7 +267,8 @@ static int usbmux_config_usb_device(usbmux_device_t device) log_debug_msg("claiming interface... "); ret = usb_claim_interface(device->usbdev, 1); if (ret != 0) { - log_debug_msg("Error: usb_claim_interface returned %d: %s\n", ret, strerror(-ret)); + log_debug_msg("Error: usb_claim_interface returned %d: %s\n", ret, + strerror(-ret)); return -ENODEV; } else { log_debug_msg("done.\n"); @@ -266,7 +277,7 @@ static int usbmux_config_usb_device(usbmux_device_t device) do { bytes = usb_bulk_read(device->usbdev, BULKIN, buf, 512, 800); } while (bytes > 0); - + return 0; } @@ -283,7 +294,8 @@ static int usbmux_config_usb_device(usbmux_device_t device) * descriptor on return. * @return 0 if ok, otherwise a negative errno value. */ -int usbmux_get_specific_device(int bus_n, int dev_n, usbmux_device_t * device) +int usbmux_get_specific_device(int bus_n, int dev_n, + usbmux_device_t * device) { struct usb_bus *bus; struct usb_device *dev; @@ -294,7 +306,8 @@ int usbmux_get_specific_device(int bus_n, int dev_n, usbmux_device_t * device) if (!device || (device && *device)) return -EINVAL; - usbmux_device_t newdevice = (usbmux_device_t) malloc(sizeof(struct usbmux_device_int)); + usbmux_device_t newdevice = + (usbmux_device_t) malloc(sizeof(struct usbmux_device_int)); // Initialize the struct newdevice->usbdev = NULL; @@ -314,40 +327,49 @@ int usbmux_get_specific_device(int bus_n, int dev_n, usbmux_device_t * device) // Set the device configuration for (bus = usb_get_busses(); bus; bus = bus->next) //if (bus->location == bus_n) - for (dev = bus->devices; dev != NULL; dev = dev->next) - if (dev->devnum == dev_n) { - newdevice->__device = dev; - newdevice->usbdev = usb_open(newdevice->__device); - if (usbmux_config_usb_device(newdevice) == 0) { - goto found; - } + for (dev = bus->devices; dev != NULL; dev = dev->next) + if (dev->devnum == dev_n) { + newdevice->__device = dev; + newdevice->usbdev = usb_open(newdevice->__device); + if (usbmux_config_usb_device(newdevice) == 0) { + goto found; } + } usbmux_free_device(newdevice); log_debug_msg("usbmux_get_specific_device: device not found\n"); return -ENODEV; -found: + found: // Send the version command to the device version = version_header(); - bytes = usb_bulk_write(newdevice->usbdev, BULKOUT, (char *) version, sizeof(*version), 800); + bytes = + usb_bulk_write(newdevice->usbdev, BULKOUT, (char *) version, + sizeof(*version), 800); if (bytes < 20) { log_debug_msg("%s: libusb did NOT send enough!\n", __func__); if (bytes < 0) { - log_debug_msg("%s: libusb gave me the error %d: %s (%s)\n", __func__, bytes, usb_strerror(), strerror(-bytes)); + log_debug_msg("%s: libusb gave me the error %d: %s (%s)\n", + __func__, bytes, usb_strerror(), + strerror(-bytes)); } } // Read the device's response - bytes = usb_bulk_read(newdevice->usbdev, BULKIN, (char *) version, sizeof(*version), 800); + bytes = + usb_bulk_read(newdevice->usbdev, BULKIN, (char *) version, + sizeof(*version), 800); // Check for bad response if (bytes < 20) { free(version); usbmux_free_device(newdevice); - log_debug_msg("%s: Invalid version message -- header too short.\n", __func__); + log_debug_msg("%s: Invalid version message -- header too short.\n", + __func__); if (bytes < 0) { - log_debug_msg("%s: libusb error message %d: %s (%s)\n", __func__, bytes, usb_strerror(), strerror(-bytes)); + log_debug_msg("%s: libusb error message %d: %s (%s)\n", + __func__, bytes, usb_strerror(), + strerror(-bytes)); return bytes; } return -EBADMSG; @@ -363,7 +385,8 @@ found: // Bad header usbmux_free_device(newdevice); free(version); - log_debug_msg("%s: Received a bad header/invalid version number.", __func__); + log_debug_msg("%s: Received a bad header/invalid version number.", + __func__); return -EBADMSG; } @@ -371,7 +394,7 @@ found: log_debug_msg("%s: Unknown error.\n", __func__); usbmux_free_device(newdevice); free(version); - return -EBADMSG; // if it got to this point it's gotta be bad + return -EBADMSG; // if it got to this point it's gotta be bad } /** Cleans up an usbmux_device_t structure, then frees the structure itself. @@ -435,25 +458,31 @@ int send_to_device(usbmux_device_t device, char *data, int datalen) int bytes = 0; #ifdef DEBUG - #ifdef DEBUG_MORE - printf("===============================\n%s: trying to send\n", __func__); +#ifdef DEBUG_MORE + printf("===============================\n%s: trying to send\n", + __func__); print_buffer(data, datalen); printf("===============================\n"); - #endif +#endif #endif do { if (retrycount > 3) { - log_debug_msg("EPIC FAIL! aborting on retry count overload.\n"); + log_debug_msg + ("EPIC FAIL! aborting on retry count overload.\n"); return -ECOMM; } - bytes = usb_bulk_write(device->usbdev, BULKOUT, data, datalen, timeout); + bytes = + usb_bulk_write(device->usbdev, BULKOUT, data, datalen, + timeout); if (bytes == -ETIMEDOUT) { // timed out waiting for write. log_debug_msg("usb_bulk_write timeout error.\n"); return bytes; } else if (bytes < 0) { - log_debug_msg("usb_bulk_write failed with error. err:%d (%s)(%s)\n", bytes, usb_strerror(), strerror(-bytes)); + log_debug_msg + ("usb_bulk_write failed with error. err:%d (%s)(%s)\n", + bytes, usb_strerror(), strerror(-bytes)); return bytes; } else if (bytes == 0) { log_debug_msg("usb_bulk_write sent nothing. retrying.\n"); @@ -461,22 +490,24 @@ int send_to_device(usbmux_device_t device, char *data, int datalen) retrycount++; continue; } else if (bytes < datalen) { - log_debug_msg("usb_bulk_write failed to send full dataload. %d of %d\n", bytes, datalen); + log_debug_msg + ("usb_bulk_write failed to send full dataload. %d of %d\n", + bytes, datalen); timeout = timeout * 4; retrycount++; data += bytes; datalen -= bytes; continue; } - } while(0); // fall out + } while (0); // fall out #ifdef DEBUG if (bytes > 0) { if (toto_debug > 0) { - printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - printf("%s: sent to device\n", __func__); - print_buffer(data, bytes); - printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + printf("%s: sent to device\n", __func__); + print_buffer(data, bytes); + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); } } #endif @@ -493,13 +524,16 @@ int send_to_device(usbmux_device_t device, char *data, int datalen) * * @return How many bytes were read in, or -1 on error. */ -int recv_from_device_timeout(usbmux_device_t device, char *data, int datalen, int timeoutmillis) +int recv_from_device_timeout(usbmux_device_t device, char *data, + int datalen, int timeoutmillis) { if (!device) return -EINVAL; //log_debug_msg("%s: attempting to receive %i bytes\n", __func__, datalen); - int bytes = usb_bulk_read(device->usbdev, BULKIN, data, datalen, timeoutmillis); + int bytes = + usb_bulk_read(device->usbdev, BULKIN, data, datalen, + timeoutmillis); // There are some things which are errors, others which are no problem. // It's not documented in libUSB, but it seems that the error values // returned are just negated ERRNO values. @@ -509,12 +543,14 @@ int recv_from_device_timeout(usbmux_device_t device, char *data, int datalen, in // picked up any data. no problem. return 0; } else { - fprintf(stderr, "%s: libusb gave me the error %d: %s (%s)\n", __func__, bytes, usb_strerror(), strerror(-bytes)); - log_debug_msg("%s: libusb gave me the error %d: %s (%s)\n", __func__, bytes, usb_strerror(), strerror(-bytes)); + fprintf(stderr, "%s: libusb gave me the error %d: %s (%s)\n", + __func__, bytes, usb_strerror(), strerror(-bytes)); + log_debug_msg("%s: libusb gave me the error %d: %s (%s)\n", + __func__, bytes, usb_strerror(), + strerror(-bytes)); } return bytes; } - #ifdef DEBUG if (bytes > 0) { if (toto_debug > 0) { @@ -538,7 +574,8 @@ int recv_from_device_timeout(usbmux_device_t device, char *data, int datalen, in */ usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port) { - usbmux_tcp_header *conn = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header)); + usbmux_tcp_header *conn = + (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header)); conn->type = htonl(6); conn->length = HEADERLEN; conn->sport = htons(s_port); @@ -566,7 +603,9 @@ static void delete_connection(usbmux_client_t connection) // update the global list of connections if (clients > 1) { - newlist = (usbmux_client_t *) malloc(sizeof(usbmux_client_t) * (clients - 1)); + newlist = + (usbmux_client_t *) malloc(sizeof(usbmux_client_t) * + (clients - 1)); int i = 0, j = 0; for (i = 0; i < clients; i++) { if (connlist[i] == connection) @@ -607,7 +646,9 @@ static void add_connection(usbmux_client_t connection) { pthread_mutex_lock(&usbmuxmutex); usbmux_client_t *newlist = - (usbmux_client_t *) realloc(connlist, sizeof(usbmux_client_t) * (clients + 1)); + (usbmux_client_t *) realloc(connlist, + sizeof(usbmux_client_t) * (clients + + 1)); newlist[clients] = connection; connlist = newlist; clients++; @@ -661,7 +702,8 @@ static uint16_t get_free_port() * @param client A mux TCP header for the connection which is used for tracking and data transfer. * @return 0 on success, a negative errno value otherwise. */ -int usbmux_new_client(usbmux_device_t device, uint16_t src_port, uint16_t dst_port, usbmux_client_t * client) +int usbmux_new_client(usbmux_device_t device, uint16_t src_port, + uint16_t dst_port, usbmux_client_t * client) { if (!device || !dst_port) return -EINVAL; @@ -670,11 +712,11 @@ int usbmux_new_client(usbmux_device_t device, uint16_t src_port, uint16_t dst_po if (!src_port) { // this is a special case, if we get 0, this is not good, so - return -EISCONN; // TODO: error code suitable? + return -EISCONN; // TODO: error code suitable? } - // Initialize connection stuff - usbmux_client_t new_connection = (usbmux_client_t) malloc(sizeof(struct usbmux_client_int)); + usbmux_client_t new_connection = + (usbmux_client_t) malloc(sizeof(struct usbmux_client_int)); new_connection->header = new_mux_packet(src_port, dst_port); // send TCP syn @@ -682,7 +724,8 @@ int usbmux_new_client(usbmux_device_t device, uint16_t src_port, uint16_t dst_po int err = 0; new_connection->header->tcp_flags = TCP_SYN; new_connection->header->length = new_connection->header->length; - new_connection->header->length16 = new_connection->header->length16; + new_connection->header->length16 = + new_connection->header->length16; new_connection->header->scnt = 0; new_connection->header->ocnt = 0; new_connection->device = device; @@ -697,8 +740,12 @@ int usbmux_new_client(usbmux_device_t device, uint16_t src_port, uint16_t dst_po new_connection->error = 0; new_connection->cleanup = 0; hton_header(new_connection->header); - log_debug_msg("%s: send_to_device (%d --> %d)\n", __func__, ntohs(new_connection->header->sport), ntohs(new_connection->header->dport)); - err = send_to_device(device, (char *) new_connection->header, sizeof(usbmux_tcp_header)); + log_debug_msg("%s: send_to_device (%d --> %d)\n", __func__, + ntohs(new_connection->header->sport), + ntohs(new_connection->header->dport)); + err = + send_to_device(device, (char *) new_connection->header, + sizeof(usbmux_tcp_header)); if (err >= 0) { *client = new_connection; return 0; @@ -732,7 +779,9 @@ int usbmux_free_client(usbmux_client_t client) client->header->length16 = 0x1C; hton_header(client->header); - err = send_to_device(client->device, (char*)client->header, sizeof(usbmux_tcp_header)); + err = + send_to_device(client->device, (char *) client->header, + sizeof(usbmux_tcp_header)); if (err < 0) { log_debug_msg("%s: error sending TCP_FIN\n", __func__); result = err; @@ -762,7 +811,8 @@ int usbmux_free_client(usbmux_client_t client) * * @return 0 on success or a negative errno value on error. */ -int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen, uint32_t * sent_bytes) +int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen, + uint32_t * sent_bytes) { if (!client->device || !client || !sent_bytes) return -EINVAL; @@ -781,7 +831,8 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen, uint clock_gettime(CLOCK_REALTIME, &ts); //ts.tv_sec += 1; ts.tv_nsec += 750 * 1000; - if (pthread_cond_timedwait(&client->wait, &client->mutex, &ts) == ETIMEDOUT) { + if (pthread_cond_timedwait(&client->wait, &client->mutex, &ts) == + ETIMEDOUT) { // timed out. optimistically grow the window and try to make progress client->wr_window += WINDOW_INCREMENT; } @@ -791,7 +842,7 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen, uint // client->scnt and client->ocnt should already be in host notation... // we don't need to change them juuuust yet. - char *buffer = (char *) malloc(blocksize + 2); // allow 2 bytes of safety padding + char *buffer = (char *) malloc(blocksize + 2); // allow 2 bytes of safety padding // Set the length client->header->length = blocksize; client->header->length16 = blocksize; @@ -802,7 +853,9 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen, uint memcpy(buffer, client->header, sizeof(usbmux_tcp_header)); memcpy(buffer + sizeof(usbmux_tcp_header), data, datalen); - log_debug_msg("%s: send_to_device(%d --> %d)\n", __func__, ntohs(client->header->sport), ntohs(client->header->dport)); + log_debug_msg("%s: send_to_device(%d --> %d)\n", __func__, + ntohs(client->header->sport), + ntohs(client->header->dport)); sendresult = send_to_device(client->device, buffer, blocksize); // Now that we've sent it off, we can clean up after our sloppy selves. if (buffer) @@ -812,7 +865,7 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen, uint ntoh_header(client->header); // update counts ONLY if the send succeeded. - if ((uint32_t)sendresult == blocksize) { + if ((uint32_t) sendresult == blocksize) { // Re-calculate scnt client->header->scnt += datalen; client->wr_window -= blocksize; @@ -826,12 +879,14 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen, uint return -ETIMEDOUT; } else if (sendresult < 0) { return sendresult; - } else if ((uint32_t)sendresult == blocksize) { + } else if ((uint32_t) sendresult == blocksize) { // actual number of data bytes sent. *sent_bytes = sendresult - HEADERLEN; return 0; } else { - fprintf(stderr, "usbsend managed to dump a packet that is not full size. %d of %d\n", sendresult, blocksize); + fprintf(stderr, + "usbsend managed to dump a packet that is not full size. %d of %d\n", + sendresult, blocksize); return -EBADMSG; } } @@ -844,14 +899,15 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen, uint * * @return number of bytes consumed (header + data) */ -uint32_t append_receive_buffer(usbmux_client_t client, char* packet) +uint32_t append_receive_buffer(usbmux_client_t client, char *packet) { - if (client == NULL || packet == NULL) return 0; + if (client == NULL || packet == NULL) + return 0; usbmux_tcp_header *header = (usbmux_tcp_header *) packet; - char* data = &packet[HEADERLEN]; + char *data = &packet[HEADERLEN]; uint32_t packetlen = ntohl(header->length); - uint32_t datalen = packetlen-HEADERLEN; + uint32_t datalen = packetlen - HEADERLEN; int dobroadcast = 0; @@ -860,7 +916,7 @@ uint32_t append_receive_buffer(usbmux_client_t client, char* packet) // we need to handle a few corner case tasks and book-keeping which // falls on our responsibility because we are the ones reading in // feedback. - if (client->header->scnt == 0 && client->header->ocnt == 0 ) { + if (client->header->scnt == 0 && client->header->ocnt == 0) { log_debug_msg("client is still waiting for handshake.\n"); if (header->tcp_flags == (TCP_SYN | TCP_ACK)) { log_debug_msg("yes, got syn+ack ; replying with ack.\n"); @@ -872,9 +928,14 @@ uint32_t append_receive_buffer(usbmux_client_t client, char* packet) hton_header(client->header); // push it to USB // TODO: need to check for error in the send here.... :( - log_debug_msg("%s: send_to_device (%d --> %d)\n", __func__, ntohs(client->header->sport), ntohs(client->header->dport)); - if (send_to_device(client->device, (char *)client->header, sizeof(usbmux_tcp_header)) <= 0) { - log_debug_msg("%s: error when pushing to usb...\n", __func__); + log_debug_msg("%s: send_to_device (%d --> %d)\n", __func__, + ntohs(client->header->sport), + ntohs(client->header->dport)); + if (send_to_device + (client->device, (char *) client->header, + sizeof(usbmux_tcp_header)) <= 0) { + log_debug_msg("%s: error when pushing to usb...\n", + __func__); } // need to revert some of the fields back to host notation. ntoh_header(client->header); @@ -885,7 +946,6 @@ uint32_t append_receive_buffer(usbmux_client_t client, char* packet) log_debug_msg("WOAH! client failed to get proper syn+ack.\n"); } } - // update TCP counters and windows. // // save the window that we're getting from the USB device. @@ -899,30 +959,33 @@ uint32_t append_receive_buffer(usbmux_client_t client, char* packet) char e_msg[128]; e_msg[0] = 0; if (datalen > 1) { - memcpy(e_msg, data+1, datalen-1); - e_msg[datalen-1] = 0; + memcpy(e_msg, data + 1, datalen - 1); + e_msg[datalen - 1] = 0; } // fetch the message - switch(data[0]) { - case 0: - // this is not an error, it's just a status message. - log_debug_msg("received status message: %s\n", e_msg); - datalen = 0; - break; - case 1: - log_debug_msg("received error message: %s\n", e_msg); - datalen = 0; - break; - default: - log_debug_msg("received unknown message (type 0x%02x): %s\n", data[0], e_msg); - //datalen = 0; // <-- we let this commented out for testing - break; + switch (data[0]) { + case 0: + // this is not an error, it's just a status message. + log_debug_msg("received status message: %s\n", e_msg); + datalen = 0; + break; + case 1: + log_debug_msg("received error message: %s\n", e_msg); + datalen = 0; + break; + default: + log_debug_msg + ("received unknown message (type 0x%02x): %s\n", + data[0], e_msg); + //datalen = 0; // <-- we let this commented out for testing + break; } } else { - log_debug_msg("peer sent connection reset. setting error: %d\n", client->error); + log_debug_msg + ("peer sent connection reset. setting error: %d\n", + client->error); } } - // the packet's ocnt tells us how much of our data the device has received. if (header->tcp_flags & TCP_ACK) { // this is a hacky magic number condition. it seems that once @@ -930,7 +993,7 @@ uint32_t append_receive_buffer(usbmux_client_t client, char* packet) // number, we quickly fall into connection reset problems. // Once we see the reported window size start falling off, // ut off and wait for solid acks to come back. - if (ntohs(header->window) < 256) + if (ntohs(header->window) < 256) client->wr_window = 0; // check what just got acked. @@ -938,21 +1001,24 @@ uint32_t append_receive_buffer(usbmux_client_t client, char* packet) // we got some kind of ack, but it hasn't caught up // with the pending that have been sent. pthread_cond_broadcast(&client->wr_wait); - } else if (ntohl(header->ocnt) > /*client->wr_pending_scnt*/ client->header->scnt) { - fprintf(stderr, "WTF?! acks overtook pending outstanding. %u,%u\n", ntohl(header->ocnt), client->wr_pending_scnt); + } else if (ntohl(header->ocnt) > + /*client->wr_pending_scnt */ client->header->scnt) { + fprintf(stderr, + "WTF?! acks overtook pending outstanding. %u,%u\n", + ntohl(header->ocnt), client->wr_pending_scnt); } else { // reset the window client->wr_window = WINDOW_MAX; pthread_cond_broadcast(&client->wr_wait); } } - // the packet's scnt will be our new ocnt. client->header->ocnt = ntohl(header->scnt); // ensure there is enough space, either by first malloc or realloc if (datalen > 0) { - log_debug_msg("%s: putting %d bytes into client's recv_buffer\n", __func__, datalen); + log_debug_msg("%s: putting %d bytes into client's recv_buffer\n", + __func__, datalen); if (client->r_len == 0) dobroadcast = 1; @@ -960,7 +1026,8 @@ uint32_t append_receive_buffer(usbmux_client_t client, char* packet) client->recv_buffer = malloc(datalen); client->r_len = 0; } else { - client->recv_buffer = realloc(client->recv_buffer, client->r_len + datalen); + client->recv_buffer = + realloc(client->recv_buffer, client->r_len + datalen); } memcpy(&client->recv_buffer[client->r_len], data, datalen); @@ -982,7 +1049,7 @@ uint32_t append_receive_buffer(usbmux_client_t client, char* packet) * because we're only called from one location, pullbulk, where the lock * is already held. */ -usbmux_client_t find_client(usbmux_tcp_header* recv_header) +usbmux_client_t find_client(usbmux_tcp_header * recv_header) { // remember, as we're looking for the client, the receive header is // coming from the USB into our client. This means that when we check @@ -1017,17 +1084,19 @@ int usbmux_pullbulk(usbmux_device_t device) return -EINVAL; int res = 0; - static const int DEFAULT_CAPACITY = 128*1024; + static const int DEFAULT_CAPACITY = 128 * 1024; if (device->usbReceive.buffer == NULL) { device->usbReceive.capacity = DEFAULT_CAPACITY; device->usbReceive.buffer = malloc(device->usbReceive.capacity); device->usbReceive.leftover = 0; } - // start the cursor off just ahead of the leftover. - char* cursor = &device->usbReceive.buffer[device->usbReceive.leftover]; + char *cursor = &device->usbReceive.buffer[device->usbReceive.leftover]; // pull in content, note that the amount we can pull is capacity minus leftover - int readlen = recv_from_device_timeout(device, cursor, device->usbReceive.capacity - device->usbReceive.leftover, 3000); + int readlen = + recv_from_device_timeout(device, cursor, + device->usbReceive.capacity - + device->usbReceive.leftover, 3000); if (readlen < 0) { res = readlen; //fprintf(stderr, "recv_from_device_timeout gave us an error.\n"); @@ -1036,7 +1105,6 @@ int usbmux_pullbulk(usbmux_device_t device) if (readlen > 0) { //fprintf(stdout, "recv_from_device_timeout pulled an extra %d bytes\n", readlen); } - // the amount of content we have to work with is the remainder plus // what we managed to read device->usbReceive.leftover += readlen; @@ -1050,23 +1118,29 @@ int usbmux_pullbulk(usbmux_device_t device) break; usbmux_tcp_header *header = (usbmux_tcp_header *) cursor; - log_debug_msg("%s: recv_from_device_timeout (%d --> %d)\n", __func__, ntohs(header->sport), ntohs(header->dport)); + log_debug_msg("%s: recv_from_device_timeout (%d --> %d)\n", + __func__, ntohs(header->sport), + ntohs(header->dport)); // now that we have a header, check if there is sufficient data // to construct a full packet, including its data uint32_t packetlen = ntohl(header->length); - if ((uint32_t)device->usbReceive.leftover < packetlen) { - fprintf(stderr, "%s: not enough data to construct a full packet\n", __func__); + if ((uint32_t) device->usbReceive.leftover < packetlen) { + fprintf(stderr, + "%s: not enough data to construct a full packet\n", + __func__); break; } - // ok... find the client this packet will get stuffed to. usbmux_client_t client = find_client(header); if (client == NULL) { - log_debug_msg("WARNING: client for packet cannot be found. dropping packet.\n"); + log_debug_msg + ("WARNING: client for packet cannot be found. dropping packet.\n"); } else { // stuff the data - log_debug_msg("%s: found client, calling append_receive_buffer\n", __func__); + log_debug_msg + ("%s: found client, calling append_receive_buffer\n", + __func__); append_receive_buffer(client, cursor); // perhaps this is too general, == -ECONNRESET @@ -1075,7 +1149,9 @@ int usbmux_pullbulk(usbmux_device_t device) pthread_mutex_lock(&client->mutex); if (client->cleanup) { pthread_mutex_unlock(&client->mutex); - log_debug_msg("freeing up connection (%d->%d)\n", ntohs(client->header->sport), ntohs(client->header->dport)); + log_debug_msg("freeing up connection (%d->%d)\n", + ntohs(client->header->sport), + ntohs(client->header->dport)); delete_connection(client); } else { pthread_mutex_unlock(&client->mutex); @@ -1096,9 +1172,10 @@ int usbmux_pullbulk(usbmux_device_t device) // // if there are no leftovers, we just leave the datastructure as is, // and re-use the block next time. - if (device->usbReceive.leftover > 0 && cursor != device->usbReceive.buffer) { + if (device->usbReceive.leftover > 0 + && cursor != device->usbReceive.buffer) { log_debug_msg("%s: we got a leftover, so handle it\n", __func__); - char* newbuff = malloc(DEFAULT_CAPACITY); + char *newbuff = malloc(DEFAULT_CAPACITY); memcpy(newbuff, cursor, device->usbReceive.leftover); free(device->usbReceive.buffer); device->usbReceive.buffer = newbuff; @@ -1133,7 +1210,9 @@ int usbmux_get_error(usbmux_client_t client) * * @return 0 on success or a negative errno value on failure. */ -int usbmux_recv_timeout(usbmux_client_t client, char *data, uint32_t datalen, uint32_t * recv_bytes, int timeout) +int usbmux_recv_timeout(usbmux_client_t client, char *data, + uint32_t datalen, uint32_t * recv_bytes, + int timeout) { if (!client || !data || datalen == 0 || !recv_bytes) @@ -1147,15 +1226,15 @@ int usbmux_recv_timeout(usbmux_client_t client, char *data, uint32_t datalen, ui if (timeout > 0 && (client->recv_buffer == NULL || client->r_len == 0)) { struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += timeout/1000; - ts.tv_nsec += (timeout-((int)(timeout/1000))*1000)*1000; + ts.tv_sec += timeout / 1000; + ts.tv_nsec += (timeout - ((int) (timeout / 1000)) * 1000) * 1000; pthread_cond_timedwait(&client->wait, &client->mutex, &ts); } *recv_bytes = 0; if (client->recv_buffer != NULL && client->r_len > 0) { uint32_t foolen = datalen; - if ((int)foolen > client->r_len) + if ((int) foolen > client->r_len) foolen = client->r_len; memcpy(data, client->recv_buffer, foolen); *recv_bytes = foolen; @@ -1163,7 +1242,7 @@ int usbmux_recv_timeout(usbmux_client_t client, char *data, uint32_t datalen, ui // preserve any left-over unread amounts. int remainder = client->r_len - foolen; if (remainder > 0) { - char* newbuf = malloc(remainder); + char *newbuf = malloc(remainder); memcpy(newbuf, client->recv_buffer + foolen, remainder); client->r_len = remainder; free(client->recv_buffer); |