SWIGEXPORT jshort JNICALL Java_org_robovm_libimobiledevice_binding_libimobiledeviceJNI_idevice_1connection_1receive_1timeout(JNIEnv *jenv, jclass jcls, jlong jarg1, jstring jarg2, jint jarg3, jlong jarg4, jobject jarg4_, jlong jarg5) { jshort jresult = 0 ; idevice_connection_t arg1 = (idevice_connection_t) 0 ; char *arg2 = (char *) 0 ; uint32_t arg3 ; uint32_t *arg4 = (uint32_t *) 0 ; unsigned int arg5 ; idevice_error_t result; (void)jenv; (void)jcls; (void)jarg4_; arg1 = *(idevice_connection_t *)&jarg1; arg2 = 0; if (jarg2) { arg2 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg2, 0); if (!arg2) return 0; } arg3 = (uint32_t)jarg3; arg4 = *(uint32_t **)&jarg4; arg5 = (unsigned int)jarg5; result = (idevice_error_t)idevice_connection_receive_timeout(arg1,arg2,arg3,arg4,arg5); jresult = (jshort)result; if (arg2) (*jenv)->ReleaseStringUTFChars(jenv, jarg2, (const char *)arg2); return jresult; }
static idevice_error_t idevice_connection_receive_all(idevice_connection_t connection, char * data, uint32_t length, unsigned int timeout) { size_t cur_bytes_received = 0; size_t total_bytes_received = 0; size_t bytes_left = length; idevice_error_t res = IDEVICE_E_SUCCESS; uint64_t start_time = get_time_ms(); uint64_t time_passed = 0; while ((total_bytes_received < length) && (time_passed <= timeout)) { res = idevice_connection_receive_timeout(connection, data + total_bytes_received, bytes_left, &cur_bytes_received, timeout - (unsigned int)time_passed); if (IDEVICE_E_SUCCESS != res) { error("ERROR: Unable to receive data\n"); break; } total_bytes_received += cur_bytes_received; bytes_left -= cur_bytes_received; time_passed = get_time_ms() - start_time; } /* Check if we've failed to receive the requested amount of data */ if ((IDEVICE_E_SUCCESS == res) && (total_bytes_received < length)) { /* Timeout */ return IDEVICE_E_NOT_ENOUGH_DATA; } return res; }
/** * Receives a plist using the given property list service client. * Internally used generic plist receive function. * * @param client The property list service client to use for receiving * @param plist pointer to a plist_t that will point to the received plist * upon successful return * @param timeout Maximum time in milliseconds to wait for data. * * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL, * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR * when an unspecified error occurs. */ static property_list_service_error_t internal_plist_receive_timeout(property_list_service_client_t client, plist_t *plist, unsigned int timeout) { property_list_service_error_t res = PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; uint32_t pktlen = 0; uint32_t bytes = 0; if (!client || (client && !client->connection) || !plist) { return PROPERTY_LIST_SERVICE_E_INVALID_ARG; } idevice_connection_receive_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, timeout); debug_info("initial read=%i", bytes); if (bytes < 4) { debug_info("initial read failed!"); return PROPERTY_LIST_SERVICE_E_MUX_ERROR; } else { pktlen = be32toh(pktlen); if (pktlen < (1 << 24)) { /* prevent huge buffers */ uint32_t curlen = 0; char *content = NULL; debug_info("%d bytes following", pktlen); content = (char*)malloc(pktlen); while (curlen < pktlen) { idevice_connection_receive(client->connection, content+curlen, pktlen-curlen, &bytes); if (bytes <= 0) { res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; break; } debug_info("received %d bytes", bytes); curlen += bytes; } if (!memcmp(content, "bplist00", 8)) { plist_from_bin(content, pktlen, plist); } else { /* iOS 4.3+ hack: plist data might contain invalid characters, thus we convert those to spaces */ for (bytes = 0; bytes < pktlen-1; bytes++) { if ((content[bytes] >= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) content[bytes] = 0x20; } plist_from_xml(content, pktlen, plist); } if (*plist) { debug_plist(*plist); res = PROPERTY_LIST_SERVICE_E_SUCCESS; } else { res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; } free(content); content = NULL; } else { res = PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; } } return res; }
static void *thread_device_to_client(void *data) { socket_info_t* socket_info = (socket_info_t*)data; idevice_error_t res = IDEVICE_E_UNKNOWN_ERROR; int recv_len; int sent; char buffer[131072]; debug("%s: started thread...\n", __func__); debug("%s: client_fd = %d\n", __func__, socket_info->client_fd); debug("%s: server fd = %d\n", __func__, socket_info->server_fd); while (!quit_flag && !socket_info->stop_dtoc && socket_info->client_fd > 0 && socket_info->server_fd > 0) { debug("%s: receiving data from device...\n", __func__); res = idevice_connection_receive_timeout(socket_info->device_connection, buffer, sizeof(buffer), (uint32_t*)&recv_len, 5000); if (recv_len <= 0) { if (recv_len == 0 && res == IDEVICE_E_SUCCESS) { // try again continue; } else { fprintf(stderr, "recv failed: %s\n", strerror(errno)); break; } } else { /* send to device */ debug("%s: sending data to client...\n", __func__); sent = socket_send(socket_info->client_fd, buffer, recv_len); if (sent < recv_len) { if (sent <= 0) { fprintf(stderr, "send failed: %s\n", strerror(errno)); break; } else { fprintf(stderr, "only sent %d from %d bytes\n", sent, recv_len); } } else { // sending succeeded, receive from device debug("%s: pushed %d bytes to client\n", __func__, sent); } } } debug("%s: shutting down...\n", __func__); socket_shutdown(socket_info->client_fd, SHUT_RDWR); socket_close(socket_info->client_fd); socket_info->client_fd = -1; socket_info->stop_ctod = 1; return NULL; }
/** * Receives data using the given service client with specified timeout. * * @param client The service client to use for receiving * @param data Buffer that will be filled with the data received * @param size Number of bytes to receive * @param received Number of bytes received (can be NULL to ignore) * @param timeout Maximum time in milliseconds to wait for data. * * @return SERVICE_E_SUCCESS on success, * SERVICE_E_INVALID_ARG when one or more parameters are * invalid, SERVICE_E_MUX_ERROR when a communication error * occurs, or SERVICE_E_UNKNOWN_ERROR when an unspecified * error occurs. */ service_error_t service_receive_with_timeout(service_client_t client, char* data, uint32_t size, uint32_t *received, unsigned int timeout) { service_error_t res = SERVICE_E_UNKNOWN_ERROR; int bytes = 0; if (!client || (client && !client->connection) || !data || (size == 0)) { return SERVICE_E_INVALID_ARG; } res = idevice_to_service_error(idevice_connection_receive_timeout(client->connection, data, size, (uint32_t*)&bytes, timeout)); if (bytes <= 0) { debug_info("could not read data"); } if (received) { *received = (uint32_t)bytes; } return res; }
int main(int argc, char* argv[]) { idevice_t device = NULL; lockdownd_client_t lockdownd = NULL; afc_client_t afc = NULL; idevice_error_t device_error = IDEVICE_E_SUCCESS; lockdownd_error_t lockdownd_error = LOCKDOWN_E_SUCCESS; afc_error_t afc_error = AFC_E_SUCCESS; int i; const char* udid = NULL; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--extract")) { extract_raw_crash_reports = 1; continue; } else if (!strcmp(argv[i], "-k") || !strcmp(argv[i], "--keep")) { keep_crash_reports = 1; continue; } else if (target_directory == NULL) { target_directory = argv[i]; continue; } else { print_usage(argc, argv); return 0; } } /* ensure a target directory was supplied */ if (!target_directory) { print_usage(argc, argv); return 0; } /* check if target directory exists */ if (!file_exists(target_directory)) { fprintf(stderr, "ERROR: Directory '%s' does not exist.\n", target_directory); print_usage(argc, argv); return 0; } device_error = idevice_new(&device, udid); if (device_error != IDEVICE_E_SUCCESS) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } return -1; } lockdownd_error = lockdownd_client_new_with_handshake(device, &lockdownd, "idevicecrashreport"); if (lockdownd_error != LOCKDOWN_E_SUCCESS) { fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", lockdownd_error); idevice_free(device); return -1; } /* start crash log mover service */ lockdownd_service_descriptor_t service = NULL; lockdownd_error = lockdownd_start_service(lockdownd, "com.apple.crashreportmover", &service); if (lockdownd_error != LOCKDOWN_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } /* trigger move operation on device */ idevice_connection_t connection = NULL; device_error = idevice_connect(device, service->port, &connection); if(device_error != IDEVICE_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } /* read "ping" message which indicates the crash logs have been moved to a safe harbor */ char *ping = malloc(4); int attempts = 0; while ((strncmp(ping, "ping", 4) != 0) && (attempts > 10)) { uint32_t bytes = 0; device_error = idevice_connection_receive_timeout(connection, ping, 4, &bytes, 2000); if ((bytes == 0) && (device_error == IDEVICE_E_SUCCESS)) { attempts++; continue; } else if (device_error < 0) { fprintf(stderr, "ERROR: Crash logs could not be moved. Connection interrupted.\n"); break; } } idevice_disconnect(connection); free(ping); if (service) { lockdownd_service_descriptor_free(service); service = NULL; } if (device_error != IDEVICE_E_SUCCESS || attempts > 10) { fprintf(stderr, "ERROR: Failed to receive ping message from crash report mover.\n"); lockdownd_client_free(lockdownd); idevice_free(device); return -1; } lockdownd_error = lockdownd_start_service(lockdownd, "com.apple.crashreportcopymobile", &service); if (lockdownd_error != LOCKDOWN_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } lockdownd_client_free(lockdownd); afc = NULL; afc_error = afc_client_new(device, service, &afc); if(afc_error != AFC_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } /* recursively copy crash reports from the device to a local directory */ if (afc_client_copy_and_remove_crash_reports(afc, ".", target_directory) < 0) { fprintf(stderr, "ERROR: Failed to get crash reports from device.\n"); afc_client_free(afc); idevice_free(device); return -1; } printf("Done.\n"); afc_client_free(afc); idevice_free(device); return 0; }