/** * Connects to the mobilesync service on the specified device. * * @param device The device to connect to. * @param service The service descriptor returned by lockdownd_start_service. * @param client Pointer that will be set to a newly allocated * #mobilesync_client_t upon successful return. * * @retval MOBILESYNC_E_SUCCESS on success * @retval MOBILESYNC_E_INVALID_ARG if one or more parameters are invalid * @retval DEVICE_LINK_SERVICE_E_BAD_VERSION if the mobilesync version on * the device is newer. */ mobilesync_error_t mobilesync_client_new(idevice_t device, lockdownd_service_descriptor_t service, mobilesync_client_t * client) { if (!device || !service || service->port == 0 || !client || *client) return MOBILESYNC_E_INVALID_ARG; device_link_service_client_t dlclient = NULL; mobilesync_error_t ret = mobilesync_error(device_link_service_client_new(device, service, &dlclient)); if (ret != MOBILESYNC_E_SUCCESS) { return ret; } mobilesync_client_t client_loc = (mobilesync_client_t) malloc(sizeof(struct mobilesync_client_private)); client_loc->parent = dlclient; client_loc->direction = MOBILESYNC_SYNC_DIR_DEVICE_TO_COMPUTER; client_loc->data_class = NULL; /* perform handshake */ ret = mobilesync_error(device_link_service_version_exchange(dlclient, MSYNC_VERSION_INT1, MSYNC_VERSION_INT2)); if (ret != MOBILESYNC_E_SUCCESS) { debug_info("version exchange failed, error %d", ret); mobilesync_client_free(client_loc); return ret; } *client = client_loc; return ret; }
mobilesync_error_t mobilesync_client_new(iphone_device_t device, int dst_port, mobilesync_client_t * client) { if (!device || dst_port == 0 || !client || *client) return MOBILESYNC_E_INVALID_ARG; mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR; /* Attempt connection */ iphone_connection_t connection = NULL; if (iphone_device_connect(device, dst_port, &connection) != IPHONE_E_SUCCESS) { return ret; } mobilesync_client_t client_loc = (mobilesync_client_t) malloc(sizeof(struct mobilesync_client_int)); client_loc->connection = connection; /* perform handshake */ plist_t array = NULL; /* first receive version */ ret = mobilesync_recv(client_loc, &array); plist_t msg_node = plist_find_node_by_string(array, "DLMessageVersionExchange"); plist_t ver_1 = plist_get_next_sibling(msg_node); plist_t ver_2 = plist_get_next_sibling(ver_1); plist_type ver_1_type = plist_get_node_type(ver_1); plist_type ver_2_type = plist_get_node_type(ver_2); if (PLIST_UINT == ver_1_type && PLIST_UINT == ver_2_type) { uint64_t ver_1_val = 0; uint64_t ver_2_val = 0; plist_get_uint_val(ver_1, &ver_1_val); plist_get_uint_val(ver_2, &ver_2_val); plist_free(array); array = NULL; if (ver_1_type == PLIST_UINT && ver_2_type == PLIST_UINT && ver_1_val == MSYNC_VERSION_INT1 && ver_2_val == MSYNC_VERSION_INT2) { array = plist_new_array(); plist_array_append_item(array, plist_new_string("DLMessageVersionExchange")); plist_array_append_item(array, plist_new_string("DLVersionsOk")); ret = mobilesync_send(client_loc, array); plist_free(array); array = NULL; ret = mobilesync_recv(client_loc, &array); plist_t rep_node = plist_find_node_by_string(array, "DLMessageDeviceReady"); if (rep_node) { ret = MOBILESYNC_E_SUCCESS; *client = client_loc; } else { ret = MOBILESYNC_E_BAD_VERSION; } plist_free(array); array = NULL; } } if (MOBILESYNC_E_SUCCESS != ret) mobilesync_client_free(client_loc); return ret; }