summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2010-05-24 17:52:53 +0200
committerGravatar Nikias Bassen2010-05-26 01:39:28 +0200
commit00c3c56e38f10d0f20145d5735b2fc0fd926555d (patch)
treec2bedffae6cd0e1113bc50f957c6f1a7dd1506be
parent3e7f2cd0d7ef6c0c7d91b63f65567a729f123ba2 (diff)
downloadusbmuxd-00c3c56e38f10d0f20145d5735b2fc0fd926555d.tar.gz
usbmuxd-00c3c56e38f10d0f20145d5735b2fc0fd926555d.tar.bz2
libusbmuxd: add generic receive_packet function and use it
-rw-r--r--libusbmuxd/libusbmuxd.c208
1 files changed, 117 insertions, 91 deletions
diff --git a/libusbmuxd/libusbmuxd.c b/libusbmuxd/libusbmuxd.c
index 9d54a88..db8d1d4 100644
--- a/libusbmuxd/libusbmuxd.c
+++ b/libusbmuxd/libusbmuxd.c
@@ -74,39 +74,85 @@ static int connect_usbmuxd_socket()
#endif
}
+static int receive_packet(int sfd, struct usbmuxd_header *header, void **payload, int timeout)
+{
+ int recv_len;
+ struct usbmuxd_header hdr;
+ char *payload_loc = NULL;
+
+ header->length = 0;
+ header->version = 0;
+ header->message = 0;
+ header->tag = 0;
+
+ recv_len = recv_buf_timeout(sfd, &hdr, sizeof(hdr), 0, timeout);
+ if (recv_len < 0) {
+ return recv_len;
+ } else if (recv_len < sizeof(hdr)) {
+ return recv_len;
+ }
+
+ uint32_t payload_size = hdr.length - sizeof(hdr);
+ if (payload_size > 0) {
+ payload_loc = (char*)malloc(payload_size);
+ if (recv_buf_timeout(sfd, payload_loc, payload_size, 0, 5000) != payload_size) {
+ fprintf(stderr, "%s: Error receiving payload of size %d\n", __func__, payload_size);
+ free(payload_loc);
+ return -EBADMSG;
+ }
+ }
+
+ *payload = payload_loc;
+
+ memcpy(header, &hdr, sizeof(hdr));
+
+ return hdr.length;
+}
+
/**
* Retrieves the result code to a previously sent request.
*/
static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result)
{
- struct usbmuxd_result_msg res;
+ struct usbmuxd_header hdr;
int recv_len;
+ uint32_t *res = NULL;
if (!result) {
return -EINVAL;
}
+ *result = -1;
- if ((recv_len = recv_buf(sfd, &res, sizeof(res))) <= 0) {
- perror("recv");
+ if ((recv_len = receive_packet(sfd, &hdr, (void**)&res, 5000)) < 0) {
+ fprintf(stderr, "%s: Error receiving packet: %d\n", __func__, errno);
+ if (res)
+ free(res);
return -errno;
- } else {
- if ((recv_len == sizeof(res))
- && (res.header.length == (uint32_t) recv_len)
- && (res.header.version == USBMUXD_PROTOCOL_VERSION)
- && (res.header.message == MESSAGE_RESULT)
- ) {
- *result = res.result;
- if (res.header.tag == tag) {
- return 1;
- } else {
- return 0;
- }
- }
+ }
+ if (recv_len < sizeof(hdr)) {
+ fprintf(stderr, "%s: Received packet is too small!\n", __func__);
+ if (res)
+ free(res);
+ return -EPROTO;
}
- return -1;
+ if (hdr.message == MESSAGE_RESULT) {
+ int ret = 0;
+ if (res && (hdr.tag == tag)) {
+ memcpy(result, res, sizeof(uint32_t));
+ ret = 1;
+ }
+ if (res)
+ free(res);
+ return ret;
+ }
+ fprintf(stderr, "%s: Unexpected message of type %d received!\n", __func__, hdr.message);
+ if (res)
+ free(res);
+ return -EPROTO;
}
+
/**
* Generates an event, i.e. calls the callback function.
* A reference to a populated usbmuxd_event_t with information about the event
@@ -163,8 +209,8 @@ static int usbmuxd_listen()
return -1;
}
if (usbmuxd_get_result(sfd, req.header.tag, &res) && (res != 0)) {
- fprintf(stderr, "%s: ERROR: did not get OK\n", __func__);
close(sfd);
+ fprintf(stderr, "%s: ERROR: did not get OK but %d\n", __func__, res);
return -1;
}
@@ -177,12 +223,11 @@ static int usbmuxd_listen()
*/
int get_next_event(int sfd, usbmuxd_event_cb_t callback, void *user_data)
{
- int recv_len;
struct usbmuxd_header hdr;
+ void *payload = NULL;
/* block until we receive something */
- recv_len = recv_buf_timeout(sfd, &hdr, sizeof(hdr), 0, 0);
- if (recv_len < 0) {
+ if (receive_packet(sfd, &hdr, &payload, 0) < 0) {
// when then usbmuxd connection fails,
// generate remove events for every device that
// is still present so applications know about it
@@ -190,57 +235,48 @@ int get_next_event(int sfd, usbmuxd_event_cb_t callback, void *user_data)
generate_event(callback, dev, UE_DEVICE_REMOVE, user_data);
collection_remove(&devices, dev);
} ENDFOREACH
- return recv_len;
- } else if (recv_len == sizeof(hdr)) {
- if (hdr.message == MESSAGE_DEVICE_ADD) {
- struct usbmuxd_device_record dev;
- usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t));
- if (!devinfo) {
- fprintf(stderr, "%s: Out of memory!\n", __func__);
- return -1;
- }
+ return -EIO;
+ }
- if (hdr.length != sizeof(struct usbmuxd_header)+sizeof(struct usbmuxd_device_record)) {
- fprintf(stderr, "%s: WARNING: unexpected packet size %d for MESSAGE_DEVICE_ADD (expected %d)!\n", __func__, hdr.length, (int)(sizeof(struct usbmuxd_header)+sizeof(struct usbmuxd_device_record)));
- }
- recv_len = recv_buf_timeout(sfd, &dev, hdr.length - sizeof(struct usbmuxd_header), 0, 5000);
- if (recv_len != (hdr.length - sizeof(struct usbmuxd_header))) {
- fprintf(stderr, "%s: ERROR: Could not receive packet\n", __func__);
- return recv_len;
- }
+ if ((hdr.length > sizeof(hdr)) && !payload) {
+ fprintf(stderr, "%s: Invalid packet received, payload is missing!\n", __func__);
+ return -EBADMSG;
+ }
- devinfo->handle = dev.device_id;
- devinfo->product_id = dev.product_id;
- memset(devinfo->uuid, '\0', sizeof(devinfo->uuid));
- memcpy(devinfo->uuid, dev.serial_number, sizeof(devinfo->uuid));
+ if (hdr.message == MESSAGE_DEVICE_ADD) {
+ struct usbmuxd_device_record *dev = payload;
+ usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t));
+ if (!devinfo) {
+ fprintf(stderr, "%s: Out of memory!\n", __func__);
+ free(payload);
+ return -1;
+ }
- collection_add(&devices, devinfo);
- generate_event(callback, devinfo, UE_DEVICE_ADD, user_data);
- } else if (hdr.message == MESSAGE_DEVICE_REMOVE) {
- uint32_t handle;
- usbmuxd_device_info_t *dev;
+ devinfo->handle = dev->device_id;
+ devinfo->product_id = dev->product_id;
+ memset(devinfo->uuid, '\0', sizeof(devinfo->uuid));
+ memcpy(devinfo->uuid, dev->serial_number, sizeof(devinfo->uuid));
- if (hdr.length != sizeof(struct usbmuxd_header)+sizeof(uint32_t)) {
- fprintf(stderr, "%s: WARNING: unexpected packet size %d for MESSAGE_DEVICE_REMOVE (expected %d)!\n", __func__, hdr.length, (int)(sizeof(struct usbmuxd_header)+sizeof(uint32_t)));
- }
- recv_len = recv_buf_timeout(sfd, &handle, sizeof(uint32_t), 0, 5000);
- if (recv_len != sizeof(uint32_t)) {
- fprintf(stderr, "%s: ERROR: Could not receive packet\n", __func__);
- return recv_len;
- }
+ collection_add(&devices, devinfo);
+ generate_event(callback, devinfo, UE_DEVICE_ADD, user_data);
+ } else if (hdr.message == MESSAGE_DEVICE_REMOVE) {
+ uint32_t handle;
+ usbmuxd_device_info_t *devinfo;
- dev = devices_find(handle);
- if (!dev) {
- fprintf(stderr, "%s: WARNING: got device remove message for handle %d, but couldn't find the corresponding handle in the device list. This event will be ignored.\n", __func__, handle);
- } else {
- generate_event(callback, dev, UE_DEVICE_REMOVE, user_data);
- collection_remove(&devices, dev);
- }
+ memcpy(&handle, payload, sizeof(uint32_t));
+
+ devinfo = devices_find(handle);
+ if (!devinfo) {
+ fprintf(stderr, "%s: WARNING: got device remove message for handle %d, but couldn't find the corresponding handle in the device list. This event will be ignored.\n", __func__, handle);
} else {
- fprintf(stderr, "%s: Unknown message type %d length %d\n", __func__, hdr.message, hdr.length);
+ generate_event(callback, devinfo, UE_DEVICE_REMOVE, user_data);
+ collection_remove(&devices, devinfo);
}
} else {
- fprintf(stderr, "%s: ERROR: incomplete packet received!\n", __func__);
+ fprintf(stderr, "%s: Unexpected message type %d length %d received!\n", __func__, hdr.message, hdr.length);
+ }
+ if (payload) {
+ free(payload);
}
return 0;
}
@@ -311,11 +347,11 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
int sfd;
int listen_success = 0;
uint32_t res;
- int recv_len;
usbmuxd_device_info_t *newlist = NULL;
struct usbmuxd_header hdr;
- struct usbmuxd_device_record dev_info;
+ struct usbmuxd_device_record *dev_info;
int dev_cnt = 0;
+ void *payload = NULL;
sfd = connect_usbmuxd_socket();
if (sfd < 0) {
@@ -336,10 +372,10 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
if (usbmuxd_get_result(sfd, s_req.header.tag, &res) && (res == 0)) {
listen_success = 1;
} else {
+ close(sfd);
fprintf(stderr,
"%s: Did not get response to scan request (with result=0)...\n",
__func__);
- close(sfd);
return res;
}
}
@@ -352,45 +388,35 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
*device_list = NULL;
// receive device list
while (1) {
- if (recv_buf_timeout(sfd, &hdr, sizeof(hdr), 0, 1000) == sizeof(hdr)) {
- if ((hdr.length < 48) || (hdr.length > sizeof(hdr)+sizeof(dev_info))) {
- // invalid packet size received!
- fprintf(stderr,
- "%s: Invalid packet size (%d) received when expecting a device info record.\n",
- __func__, hdr.length);
- break;
- }
-
- recv_len = recv_buf(sfd, &dev_info, hdr.length - sizeof(hdr));
- if (recv_len <= 0) {
- fprintf(stderr,
- "%s: Error when receiving device info record\n",
- __func__);
- break;
- } else if ((uint32_t) recv_len < hdr.length - sizeof(hdr)) {
- fprintf(stderr,
- "%s: received less data than specified in header!\n", __func__);
- } else {
+ if (receive_packet(sfd, &hdr, &payload, 1000) > 0) {
+ if (hdr.message == MESSAGE_DEVICE_ADD) {
+ dev_info = payload;
newlist = (usbmuxd_device_info_t *) realloc(*device_list, sizeof(usbmuxd_device_info_t) * (dev_cnt + 1));
if (newlist) {
newlist[dev_cnt].handle =
- (int) dev_info.device_id;
+ (int) dev_info->device_id;
newlist[dev_cnt].product_id =
- dev_info.product_id;
+ dev_info->product_id;
memset(newlist[dev_cnt].uuid, '\0',
sizeof(newlist[dev_cnt].uuid));
memcpy(newlist[dev_cnt].uuid,
- dev_info.serial_number,
+ dev_info->serial_number,
sizeof(newlist[dev_cnt].uuid));
*device_list = newlist;
dev_cnt++;
} else {
fprintf(stderr,
- "%s: ERROR: out of memory when trying to realloc!\n",
- __func__);
+ "%s: ERROR: out of memory when trying to realloc!\n",
+ __func__);
+ if (payload)
+ free(payload);
break;
}
+ } else {
+ fprintf(stderr, "%s: Unexpected message %d\n", __func__, hdr.message);
}
+ if (payload)
+ free(payload);
} else {
// we _should_ have all of them now.
// or perhaps an error occured.