void SDMMD_USBMuxListenerSend(SDMMD_USBMuxListenerRef listener, struct USBMuxPacket **packet) { listener->ivars.semaphore = dispatch_semaphore_create(0x0); SDMMD_USBMuxSend(listener->ivars.socket, *packet); dispatch_semaphore_wait(listener->ivars.semaphore, (*packet)->timeout); CFMutableArrayRef updateWithRemove = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0x0, listener->ivars.responses); struct USBMuxPacket *responsePacket = NULL; uint32_t removeCounter = 0x0; for (uint32_t i = 0x0; i < CFArrayGetCount(listener->ivars.responses); i++) { struct USBMuxPacket *response = (struct USBMuxPacket *)CFArrayGetValueAtIndex(listener->ivars.responses, i); if ((*packet)->body.tag == response->body.tag) { responsePacket = response; CFArrayRemoveValueAtIndex(updateWithRemove, i-removeCounter); removeCounter++; } } CFSafeRelease(listener->ivars.responses); listener->ivars.responses = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0x0, updateWithRemove); CFSafeRelease(updateWithRemove); USBMuxPacketRelease(*packet); if (!responsePacket) { responsePacket = (struct USBMuxPacket *)calloc(0x1, sizeof(struct USBMuxPacket)); } *packet = responsePacket; dispatch_release(listener->ivars.semaphore); }
void SDMMD_USBMuxListenerSend(SDMMD_USBMuxListenerRef listener, struct USBMuxPacket **packet) { __block struct USBMuxPacket *block_packet = *packet; dispatch_sync(listener->ivars.operationQueue, ^{ // This semaphore will be signaled when a response is received listener->ivars.semaphore = dispatch_semaphore_create(0); // Send the outgoing packet SDMMD_USBMuxSend(listener->ivars.socket, block_packet); // Wait for a response-type packet to be received dispatch_semaphore_wait(listener->ivars.semaphore, block_packet->timeout); CFMutableArrayRef updateWithRemove = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, listener->ivars.responses); // Search responses for a packet that matches the one sent struct USBMuxPacket *responsePacket = NULL; uint32_t removeCounter = 0; for (uint32_t i = 0; i < CFArrayGetCount(listener->ivars.responses); i++) { struct USBMuxPacket *response = (struct USBMuxPacket *)CFArrayGetValueAtIndex(listener->ivars.responses, i); if ((*packet)->body.tag == response->body.tag) { // Equal tags indicate response to request if (responsePacket) { // Found additional response, destroy old one USBMuxPacketRelease(responsePacket); } // Each matching packet is removed from the responses list responsePacket = response; CFArrayRemoveValueAtIndex(updateWithRemove, i - removeCounter); removeCounter++; } } if (responsePacket == NULL) { // Didn't find an appropriate response, initialize an empty packet to return responsePacket = (struct USBMuxPacket *)calloc(1, sizeof(struct USBMuxPacket)); } CFSafeRelease(listener->ivars.responses); listener->ivars.responses = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, updateWithRemove); CFSafeRelease(updateWithRemove); // Destroy sent packet USBMuxPacketRelease(block_packet); // Return response packet to caller block_packet = responsePacket; // Discard "waiting for response" semaphore dispatch_release(listener->ivars.semaphore); });