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()
74#endif 74#endif
75} 75}
76 76
77static int receive_packet(int sfd, struct usbmuxd_header *header, void **payload, int timeout)
78{
79 int recv_len;
80 struct usbmuxd_header hdr;
81 char *payload_loc = NULL;
82
83 header->length = 0;
84 header->version = 0;
85 header->message = 0;
86 header->tag = 0;
87
88 recv_len = recv_buf_timeout(sfd, &hdr, sizeof(hdr), 0, timeout);
89 if (recv_len < 0) {
90 return recv_len;
91 } else if (recv_len < sizeof(hdr)) {
92 return recv_len;
93 }
94
95 uint32_t payload_size = hdr.length - sizeof(hdr);
96 if (payload_size > 0) {
97 payload_loc = (char*)malloc(payload_size);
98 if (recv_buf_timeout(sfd, payload_loc, payload_size, 0, 5000) != payload_size) {
99 fprintf(stderr, "%s: Error receiving payload of size %d\n", __func__, payload_size);
100 free(payload_loc);
101 return -EBADMSG;
102 }
103 }
104
105 *payload = payload_loc;
106
107 memcpy(header, &hdr, sizeof(hdr));
108
109 return hdr.length;
110}
111
77/** 112/**
78 * Retrieves the result code to a previously sent request. 113 * Retrieves the result code to a previously sent request.
79 */ 114 */
80static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result) 115static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result)
81{ 116{
82 struct usbmuxd_result_msg res; 117 struct usbmuxd_header hdr;
83 int recv_len; 118 int recv_len;
119 uint32_t *res = NULL;
84 120
85 if (!result) { 121 if (!result) {
86 return -EINVAL; 122 return -EINVAL;
87 } 123 }
124 *result = -1;
88 125
89 if ((recv_len = recv_buf(sfd, &res, sizeof(res))) <= 0) { 126 if ((recv_len = receive_packet(sfd, &hdr, (void**)&res, 5000)) < 0) {
90 perror("recv"); 127 fprintf(stderr, "%s: Error receiving packet: %d\n", __func__, errno);
128 if (res)
129 free(res);
91 return -errno; 130 return -errno;
92 } else { 131 }
93 if ((recv_len == sizeof(res)) 132 if (recv_len < sizeof(hdr)) {
94 && (res.header.length == (uint32_t) recv_len) 133 fprintf(stderr, "%s: Received packet is too small!\n", __func__);
95 && (res.header.version == USBMUXD_PROTOCOL_VERSION) 134 if (res)
96 && (res.header.message == MESSAGE_RESULT) 135 free(res);
97 ) { 136 return -EPROTO;
98 *result = res.result;
99 if (res.header.tag == tag) {
100 return 1;
101 } else {
102 return 0;
103 }
104 }
105 } 137 }
106 138
107 return -1; 139 if (hdr.message == MESSAGE_RESULT) {
140 int ret = 0;
141 if (res && (hdr.tag == tag)) {
142 memcpy(result, res, sizeof(uint32_t));
143 ret = 1;
144 }
145 if (res)
146 free(res);
147 return ret;
148 }
149 fprintf(stderr, "%s: Unexpected message of type %d received!\n", __func__, hdr.message);
150 if (res)
151 free(res);
152 return -EPROTO;
108} 153}
109 154
155
110/** 156/**
111 * Generates an event, i.e. calls the callback function. 157 * Generates an event, i.e. calls the callback function.
112 * A reference to a populated usbmuxd_event_t with information about the event 158 * A reference to a populated usbmuxd_event_t with information about the event
@@ -163,8 +209,8 @@ static int usbmuxd_listen()
163 return -1; 209 return -1;
164 } 210 }
165 if (usbmuxd_get_result(sfd, req.header.tag, &res) && (res != 0)) { 211 if (usbmuxd_get_result(sfd, req.header.tag, &res) && (res != 0)) {
166 fprintf(stderr, "%s: ERROR: did not get OK\n", __func__);
167 close(sfd); 212 close(sfd);
213 fprintf(stderr, "%s: ERROR: did not get OK but %d\n", __func__, res);
168 return -1; 214 return -1;
169 } 215 }
170 216
@@ -177,12 +223,11 @@ static int usbmuxd_listen()
177 */ 223 */
178int get_next_event(int sfd, usbmuxd_event_cb_t callback, void *user_data) 224int get_next_event(int sfd, usbmuxd_event_cb_t callback, void *user_data)
179{ 225{
180 int recv_len;
181 struct usbmuxd_header hdr; 226 struct usbmuxd_header hdr;
227 void *payload = NULL;
182 228
183 /* block until we receive something */ 229 /* block until we receive something */
184 recv_len = recv_buf_timeout(sfd, &hdr, sizeof(hdr), 0, 0); 230 if (receive_packet(sfd, &hdr, &payload, 0) < 0) {
185 if (recv_len < 0) {
186 // when then usbmuxd connection fails, 231 // when then usbmuxd connection fails,
187 // generate remove events for every device that 232 // generate remove events for every device that
188 // is still present so applications know about it 233 // 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)
190 generate_event(callback, dev, UE_DEVICE_REMOVE, user_data); 235 generate_event(callback, dev, UE_DEVICE_REMOVE, user_data);
191 collection_remove(&devices, dev); 236 collection_remove(&devices, dev);
192 } ENDFOREACH 237 } ENDFOREACH
193 return recv_len; 238 return -EIO;
194 } else if (recv_len == sizeof(hdr)) { 239 }
195 if (hdr.message == MESSAGE_DEVICE_ADD) {
196 struct usbmuxd_device_record dev;
197 usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t));
198 if (!devinfo) {
199 fprintf(stderr, "%s: Out of memory!\n", __func__);
200 return -1;
201 }
202 240
203 if (hdr.length != sizeof(struct usbmuxd_header)+sizeof(struct usbmuxd_device_record)) { 241 if ((hdr.length > sizeof(hdr)) && !payload) {
204 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))); 242 fprintf(stderr, "%s: Invalid packet received, payload is missing!\n", __func__);
205 } 243 return -EBADMSG;
206 recv_len = recv_buf_timeout(sfd, &dev, hdr.length - sizeof(struct usbmuxd_header), 0, 5000); 244 }
207 if (recv_len != (hdr.length - sizeof(struct usbmuxd_header))) {
208 fprintf(stderr, "%s: ERROR: Could not receive packet\n", __func__);
209 return recv_len;
210 }
211 245
212 devinfo->handle = dev.device_id; 246 if (hdr.message == MESSAGE_DEVICE_ADD) {
213 devinfo->product_id = dev.product_id; 247 struct usbmuxd_device_record *dev = payload;
214 memset(devinfo->uuid, '\0', sizeof(devinfo->uuid)); 248 usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t));
215 memcpy(devinfo->uuid, dev.serial_number, sizeof(devinfo->uuid)); 249 if (!devinfo) {
250 fprintf(stderr, "%s: Out of memory!\n", __func__);
251 free(payload);
252 return -1;
253 }
216 254
217 collection_add(&devices, devinfo); 255 devinfo->handle = dev->device_id;
218 generate_event(callback, devinfo, UE_DEVICE_ADD, user_data); 256 devinfo->product_id = dev->product_id;
219 } else if (hdr.message == MESSAGE_DEVICE_REMOVE) { 257 memset(devinfo->uuid, '\0', sizeof(devinfo->uuid));
220 uint32_t handle; 258 memcpy(devinfo->uuid, dev->serial_number, sizeof(devinfo->uuid));
221 usbmuxd_device_info_t *dev;
222 259
223 if (hdr.length != sizeof(struct usbmuxd_header)+sizeof(uint32_t)) { 260 collection_add(&devices, devinfo);
224 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))); 261 generate_event(callback, devinfo, UE_DEVICE_ADD, user_data);
225 } 262 } else if (hdr.message == MESSAGE_DEVICE_REMOVE) {
226 recv_len = recv_buf_timeout(sfd, &handle, sizeof(uint32_t), 0, 5000); 263 uint32_t handle;
227 if (recv_len != sizeof(uint32_t)) { 264 usbmuxd_device_info_t *devinfo;
228 fprintf(stderr, "%s: ERROR: Could not receive packet\n", __func__);
229 return recv_len;
230 }
231 265
232 dev = devices_find(handle); 266 memcpy(&handle, payload, sizeof(uint32_t));
233 if (!dev) { 267
234 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); 268 devinfo = devices_find(handle);
235 } else { 269 if (!devinfo) {
236 generate_event(callback, dev, UE_DEVICE_REMOVE, user_data); 270 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);
237 collection_remove(&devices, dev);
238 }
239 } else { 271 } else {
240 fprintf(stderr, "%s: Unknown message type %d length %d\n", __func__, hdr.message, hdr.length); 272 generate_event(callback, devinfo, UE_DEVICE_REMOVE, user_data);
273 collection_remove(&devices, devinfo);
241 } 274 }
242 } else { 275 } else {
243 fprintf(stderr, "%s: ERROR: incomplete packet received!\n", __func__); 276 fprintf(stderr, "%s: Unexpected message type %d length %d received!\n", __func__, hdr.message, hdr.length);
277 }
278 if (payload) {
279 free(payload);
244 } 280 }
245 return 0; 281 return 0;
246} 282}
@@ -311,11 +347,11 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
311 int sfd; 347 int sfd;
312 int listen_success = 0; 348 int listen_success = 0;
313 uint32_t res; 349 uint32_t res;
314 int recv_len;
315 usbmuxd_device_info_t *newlist = NULL; 350 usbmuxd_device_info_t *newlist = NULL;
316 struct usbmuxd_header hdr; 351 struct usbmuxd_header hdr;
317 struct usbmuxd_device_record dev_info; 352 struct usbmuxd_device_record *dev_info;
318 int dev_cnt = 0; 353 int dev_cnt = 0;
354 void *payload = NULL;
319 355
320 sfd = connect_usbmuxd_socket(); 356 sfd = connect_usbmuxd_socket();
321 if (sfd < 0) { 357 if (sfd < 0) {
@@ -336,10 +372,10 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
336 if (usbmuxd_get_result(sfd, s_req.header.tag, &res) && (res == 0)) { 372 if (usbmuxd_get_result(sfd, s_req.header.tag, &res) && (res == 0)) {
337 listen_success = 1; 373 listen_success = 1;
338 } else { 374 } else {
375 close(sfd);
339 fprintf(stderr, 376 fprintf(stderr,
340 "%s: Did not get response to scan request (with result=0)...\n", 377 "%s: Did not get response to scan request (with result=0)...\n",
341 __func__); 378 __func__);
342 close(sfd);
343 return res; 379 return res;
344 } 380 }
345 } 381 }
@@ -352,45 +388,35 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
352 *device_list = NULL; 388 *device_list = NULL;
353 // receive device list 389 // receive device list
354 while (1) { 390 while (1) {
355 if (recv_buf_timeout(sfd, &hdr, sizeof(hdr), 0, 1000) == sizeof(hdr)) { 391 if (receive_packet(sfd, &hdr, &payload, 1000) > 0) {
356 if ((hdr.length < 48) || (hdr.length > sizeof(hdr)+sizeof(dev_info))) { 392 if (hdr.message == MESSAGE_DEVICE_ADD) {
357 // invalid packet size received! 393 dev_info = payload;
358 fprintf(stderr,
359 "%s: Invalid packet size (%d) received when expecting a device info record.\n",
360 __func__, hdr.length);
361 break;
362 }
363
364 recv_len = recv_buf(sfd, &dev_info, hdr.length - sizeof(hdr));
365 if (recv_len <= 0) {
366 fprintf(stderr,
367 "%s: Error when receiving device info record\n",
368 __func__);
369 break;
370 } else if ((uint32_t) recv_len < hdr.length - sizeof(hdr)) {
371 fprintf(stderr,
372 "%s: received less data than specified in header!\n", __func__);
373 } else {
374 newlist = (usbmuxd_device_info_t *) realloc(*device_list, sizeof(usbmuxd_device_info_t) * (dev_cnt + 1)); 394 newlist = (usbmuxd_device_info_t *) realloc(*device_list, sizeof(usbmuxd_device_info_t) * (dev_cnt + 1));
375 if (newlist) { 395 if (newlist) {
376 newlist[dev_cnt].handle = 396 newlist[dev_cnt].handle =
377 (int) dev_info.device_id; 397 (int) dev_info->device_id;
378 newlist[dev_cnt].product_id = 398 newlist[dev_cnt].product_id =
379 dev_info.product_id; 399 dev_info->product_id;
380 memset(newlist[dev_cnt].uuid, '\0', 400 memset(newlist[dev_cnt].uuid, '\0',
381 sizeof(newlist[dev_cnt].uuid)); 401 sizeof(newlist[dev_cnt].uuid));
382 memcpy(newlist[dev_cnt].uuid, 402 memcpy(newlist[dev_cnt].uuid,
383 dev_info.serial_number, 403 dev_info->serial_number,
384 sizeof(newlist[dev_cnt].uuid)); 404 sizeof(newlist[dev_cnt].uuid));
385 *device_list = newlist; 405 *device_list = newlist;
386 dev_cnt++; 406 dev_cnt++;
387 } else { 407 } else {
388 fprintf(stderr, 408 fprintf(stderr,
389 "%s: ERROR: out of memory when trying to realloc!\n", 409 "%s: ERROR: out of memory when trying to realloc!\n",
390 __func__); 410 __func__);
411 if (payload)
412 free(payload);
391 break; 413 break;
392 } 414 }
415 } else {
416 fprintf(stderr, "%s: Unexpected message %d\n", __func__, hdr.message);
393 } 417 }
418 if (payload)
419 free(payload);
394 } else { 420 } else {
395 // we _should_ have all of them now. 421 // we _should_ have all of them now.
396 // or perhaps an error occured. 422 // or perhaps an error occured.