static void * rproxy_thread_proc(void * parameter) { control_thread_context_t * context = (control_thread_context_t *)parameter; struct bufferevent * control_event = NULL; /* Create a bufferevent for the control socket */ if (0 != create_control_socket_event(context->ev_base, context, &control_event)) { error("ERROR: Failed to configure the reverse proxy control socket\n"); goto cleanup; } /* Run the event loop */ if (0 != event_base_dispatch(context->ev_base)) { error("ERROR: Failed to start the reverse proxy's event loop\n"); } /* Cleanup */ cleanup: if (control_event) { bufferevent_free(control_event); } idevice_disconnect(context->control_connection); free(context); return NULL; }
/** * Frees a PropertyList service. * * @param client The property list service to free. * * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client is invalid, or a * PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when another error occured. */ property_list_service_error_t property_list_service_client_free(property_list_service_client_t client) { if (!client) return PROPERTY_LIST_SERVICE_E_INVALID_ARG; property_list_service_error_t err = idevice_to_property_list_service_error(idevice_disconnect(client->connection)); free(client); return err; }
void asr_free(asr_client_t asr) { if (asr != NULL) { if (asr->connection != NULL) { idevice_disconnect(asr->connection); asr->connection = NULL; } free(asr); asr = NULL; } }
SWIGEXPORT jshort JNICALL Java_org_robovm_libimobiledevice_binding_libimobiledeviceJNI_idevice_1disconnect(JNIEnv *jenv, jclass jcls, jlong jarg1) { jshort jresult = 0 ; idevice_connection_t arg1 = (idevice_connection_t) 0 ; idevice_error_t result; (void)jenv; (void)jcls; arg1 = *(idevice_connection_t *)&jarg1; result = (idevice_error_t)idevice_disconnect(arg1); jresult = (jshort)result; return jresult; }
/** * Frees a service instance. * * @param client The service instance to free. * * @return SERVICE_E_SUCCESS on success, * SERVICE_E_INVALID_ARG when client is invalid, or a * SERVICE_E_UNKNOWN_ERROR when another error occured. */ service_error_t service_client_free(service_client_t client) { if (!client) return SERVICE_E_INVALID_ARG; service_error_t err = idevice_to_service_error(idevice_disconnect(client->connection)); free(client); client = NULL; return err; }
static int handle_connect_msg(control_thread_context_t * context) { idevice_connection_t client_connection = NULL; if (IDEVICE_E_SUCCESS != rproxy_create_connection(context->device, context->connection_port, CLIENT_CONNECTION_START_STRING, &client_connection)) { error("ERROR: Failed to connect to connection port\n"); goto cleanup; } plist_t dict = NULL; if (0 != rproxy_recv_dict(client_connection, &dict, RPROXY_RECV_TIMEOUT)) { error("ERROR: Failed receive connection protocol's dict\n"); goto cleanup; } /* Parse the connection protocol version from the response */ uint64_t conn_protocol_ver = 0; if (get_plist_uint_val(dict, "ConnProtoVersion", &conn_protocol_ver) < 0) { error("ERROR: Invalid connection protocol plist\n"); goto cleanup; } if (CONNECTION_PROTOCOL_VERSION != conn_protocol_ver) { error("WARNING: connection protocol mismatch (received "PRIu64", expected "PRIu64")", conn_protocol_ver, CONNECTION_PROTOCOL_VERSION); } /* FIXME: Check\Store the identifier? */ /* Create a new socks client for the connection (and start handling the new connection) */ if (0 != socks5_add_client_socket(context->ev_base, client_connection)) { error("ERROR: Failed to initialize socks client\n"); goto cleanup; } return 0; cleanup: if (client_connection) { idevice_disconnect(client_connection); } return -1; }
/** * Frees up an AFC client. If the connection was created by the * client itself, the connection will be closed. * * @param client The client to free. */ afc_error_t afc_client_free(afc_client_t client) { if (!client || !client->afc_packet) return AFC_E_INVALID_ARG; if (client->own_connection && client->connection) { idevice_disconnect(client->connection); client->connection = NULL; } free(client->afc_packet); #ifdef WIN32 DeleteCriticalSection(&client->mutex); #else pthread_mutex_destroy(&client->mutex); #endif free(client); return AFC_E_SUCCESS; }
/** * Makes a connection to the AFC service on the device. * This function calls afc_client_new_from_connection() after creating * a connection to the specified device and port. * * @see afc_client_new_from_connection * * @param device The device to connect to. * @param port The destination port. * @param client Pointer that will be set to a newly allocated afc_client_t * upon successful return. * * @return AFC_E_SUCCESS on success, AFC_E_INVALID_ARG if device or port is * invalid, AFC_E_MUX_ERROR if the connection cannot be established, * or AFC_E_NO_MEM if there is a memory allocation problem. */ afc_error_t afc_client_new(idevice_t device, uint16_t port, afc_client_t * client) { if (!device || port==0) return AFC_E_INVALID_ARG; /* attempt connection */ idevice_connection_t connection = NULL; if (idevice_connect(device, port, &connection) != IDEVICE_E_SUCCESS) { return AFC_E_MUX_ERROR; } afc_error_t err = afc_client_new_from_connection(connection, client); if (err != AFC_E_SUCCESS) { idevice_disconnect(connection); } else { (*client)->own_connection = 1; } return err; }
static int rproxy_create_connection(idevice_t device, uint16_t port, const char * start_msg, idevice_connection_t * connection) { idevice_connection_t new_connection = NULL; /* Connect to the proxt port on the device */ if (IDEVICE_E_SUCCESS != idevice_connect(device, port, &new_connection)) { goto cleanup; } /* Send the start string, including the null terminator */ uint32_t msg_size = strlen(start_msg) + 1; if (IDEVICE_E_SUCCESS != idevice_connection_send_all(new_connection, start_msg, msg_size)) { goto cleanup; } *connection = new_connection; return 0; cleanup: if (new_connection) { idevice_disconnect(new_connection); } return -1; }
int main(int argc, char *argv[]) { lockdownd_client_t lockdown = NULL; idevice_t device = NULL; idevice_connection_t connection = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; thread_t th; const char* udid = NULL; lockdownd_service_descriptor_t service = NULL; uint16_t local_port = 0; int result = EXIT_SUCCESS; int i; /* bind signals */ signal(SIGINT, clean_exit); signal(SIGTERM, clean_exit); #ifndef WIN32 signal(SIGQUIT, clean_exit); signal(SIGPIPE, SIG_IGN); #endif /* parse cmdline arguments */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { debug_mode = 1; idevice_set_debug_level(1); socket_set_verbose(3); 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 EXIT_SUCCESS; } else if (atoi(argv[i]) > 0) { local_port = atoi(argv[i]); continue; } else { print_usage(argc, argv); return EXIT_SUCCESS; } } /* a PORT is mandatory */ if (!local_port) { fprintf(stderr, "Please specify a PORT.\n"); print_usage(argc, argv); goto leave_cleanup; } /* start services and connect to device */ ret = idevice_new(&device, udid); if (ret != IDEVICE_E_SUCCESS) { if (udid) { fprintf(stderr, "No device found with udid %s, is it plugged in?\n", udid); } else { fprintf(stderr, "No device found, is it plugged in?\n"); } result = EXIT_FAILURE; goto leave_cleanup; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lockdown, "idevicedebugserverproxy")) { fprintf(stderr, "Could not connect to lockdownd. Exiting.\n"); result = EXIT_FAILURE; goto leave_cleanup; } if ((lockdownd_start_service(lockdown, "com.apple.debugserver", &service) != LOCKDOWN_E_SUCCESS) || !service || !service->port) { fprintf(stderr, "Could not start com.apple.debugserver!\nPlease make sure to mount the developer disk image first.\n"); result = EXIT_FAILURE; goto leave_cleanup; } if (idevice_connect(device, service->port, &connection) != IDEVICE_E_SUCCESS) { fprintf(stderr, "Connection to debugserver port %d failed!\n", (int)service->port); result = EXIT_FAILURE; goto leave_cleanup; } /* free lockdown connection if running as it is not needed anymore */ if (lockdown) { lockdownd_client_free(lockdown); lockdown = NULL; } /* setup and create socket endpoint */ socket_info_t socket_info; socket_info.device_connection = connection; socket_info.local_port = local_port; socket_info.remote_port = service->port; if (service) { lockdownd_service_descriptor_free(service); service = NULL; } /* create local socket */ socket_info.server_fd = socket_create(socket_info.local_port); if (socket_info.server_fd < 0) { fprintf(stderr, "Could not create socket\n"); result = EXIT_FAILURE; goto leave_cleanup; } while (!quit_flag) { debug("%s: Waiting for connection on local port %d\n", __func__, socket_info.local_port); /* wait for client */ socket_info.client_fd = socket_accept(socket_info.server_fd, socket_info.local_port); if (socket_info.client_fd < 0) { debug("%s: Continuing...\n", __func__); continue; } debug("%s: Handling new client connection...\n", __func__); if (thread_create(&th, connection_handler, (void*)&socket_info) != 0) { fprintf(stderr, "Could not start connection handler.\n"); socket_shutdown(socket_info.server_fd, SHUT_RDWR); socket_close(socket_info.server_fd); } } debug("%s: Shutting down debugserver proxy...\n", __func__); leave_cleanup: if (connection) { idevice_disconnect(connection); } if (lockdown) { lockdownd_client_free(lockdown); } if (device) { idevice_free(device); } return result; }
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; }
int rproxy_start(idevice_t device, rproxy_client_t * client) { struct rproxy_client_private * new_client = NULL; idevice_connection_t control_connection = NULL; control_thread_context_t * thread_ctx = NULL; struct event_base * ev_base = NULL; #ifdef WIN32 /* Initialize Winsock */ WSADATA wsaData = { 0 }; if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) { error("ERROR: Failed to initialize Winsock\n"); return -1; } #endif /* Initialize libevent */ event_set_fatal_callback(libevent_fatal_cb); event_set_log_callback(libevent_log_cb); #ifdef WIN32 if (0 != evthread_use_windows_threads()) { error("ERROR: Failed to initialize libevent's threading support\n"); goto cleanup; } #else if (0 != evthread_use_pthreads()) { error("ERROR: Failed to initialize libevent's threading support\n"); goto cleanup; } #endif #ifdef _DEBUG event_enable_debug_mode(); #endif /* Create a new client struct */ new_client = (rproxy_client_private *)calloc(1, sizeof(rproxy_client_private)); if (NULL == new_client) { error("ERROR: Out of memory\n"); goto cleanup; } /* Create an event base */ new_client->ev_base = event_base_new(); if (NULL == new_client->ev_base) { error("ERROR: Failed to initialize libevent\n"); goto cleanup; } /* Connect to the proxy service */ uint16_t conn_port = 0; int i = 0; for (i = 1; i <= CONTROL_CONNTECTION_ATTEMPTS; i++) { if (0 == rproxy_connect_control_service(device, &control_connection, &conn_port)) { break; } if (CONTROL_CONNTECTION_ATTEMPTS == i) { error("ERROR: Failed to initialize reverse proxy connection\n"); goto cleanup; } sleep(CONTROL_CONNTECTION_ATTEMPTS_INTERVAL); debug("Failed to connect to the proxy, retrying...\n"); } /* Start a new thread for the reverse proxy event loop */ thread_ctx = (control_thread_context_t *)calloc(1, sizeof(control_thread_context_t)); if (NULL == thread_ctx) { error("ERROR: Out of memory\n"); goto cleanup; } thread_ctx->device = device; thread_ctx->control_connection = control_connection; thread_ctx->connection_port = (uint16_t)conn_port; thread_ctx->ev_base = new_client->ev_base; if (0 != thread_create(&(new_client->thread), rproxy_thread_proc, thread_ctx)) { error("ERROR: Failed to start the reverse proxy thread\n"); goto cleanup; } info("Reverse proxy is running\n"); *client = new_client; return 0; cleanup: if (control_connection) { idevice_disconnect(control_connection); } if (new_client) { if (new_client->ev_base) { event_base_free(new_client->ev_base); } free(new_client); } if (thread_ctx) { free(thread_ctx); } #ifdef WIN32 WSACleanup(); #endif return -1; }
static int rproxy_connect_control_service(idevice_t device, idevice_connection_t * control_connection, uint16_t * connection_port) { plist_t dict = NULL; /* Connect to the proxy service */ idevice_connection_t new_connection = NULL; if (IDEVICE_E_SUCCESS != rproxy_create_connection(device, REVERSE_PROXY_MUX_PORT, CONTROL_CONNECTION_START_STRING, &new_connection)) { error("ERROR: Failed to connect to the proxy service\n"); goto cleanup; } /* Send the BeginCtrl command */ dict = plist_new_dict(); plist_dict_set_item(dict, "Command", plist_new_string("BeginCtrl")); plist_dict_set_item(dict, "CtrlProtoVersion", plist_new_uint(CONTROL_PROTOCOL_VERSION)); if (0 != rproxy_send_dict(new_connection, dict)) { error("ERROR: Failed send BeginCtrl command to the service\n"); goto cleanup; } plist_free(dict); dict = NULL; /* Get the BeginCtrl's response */ if (0 != rproxy_recv_dict(new_connection, &dict, RPROXY_RECV_TIMEOUT)) { error("ERROR: Failed receive a response for BeginCtrl\n"); goto cleanup; } /* Parse the recieved protocol version */ uint64_t device_ctrl_proto_ver = 0; if (get_plist_uint_val(dict, "CtrlProtoVersion", &device_ctrl_proto_ver) < 0) { error("ERROR: Device response to BeginCtrl doesn't contain a protocol version\n"); goto cleanup; } if (CONTROL_PROTOCOL_VERSION != device_ctrl_proto_ver) { error("ERROR: Proxy protocol version mismatch: expected "PRIu64", device reported "PRIu64"\n", CONTROL_PROTOCOL_VERSION, device_ctrl_proto_ver); goto cleanup; } /* Parse the connection port from the response */ uint64_t received_conn_port = 0; if (get_plist_uint_val(dict, "ConnPort", &received_conn_port) < 0) { error("ERROR: Device response to BeginCtrl is missing a connection port\n"); goto cleanup; } debug("Reverse proxy connection port: %us", (uint16_t)received_conn_port); plist_free(dict); dict = NULL; *control_connection = new_connection; *connection_port = (uint16_t)received_conn_port; return 0; cleanup: if (dict) { plist_free(dict); } if (new_connection) { idevice_disconnect(new_connection); } return -1; }
void asr_close(idevice_connection_t asr) { if (asr != NULL) { idevice_disconnect(asr); asr = NULL; } }