Skip to content

fix: add timeout when awaiting notification response #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 28, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions IOSDeviceLib/Declarations.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ extern "C"
{
CFSocketNativeHandle AMDServiceConnectionGetSocket(ServiceConnRef con);
long AMDServiceConnectionReceive(ServiceConnRef, void *, long);
void AMDServiceConnectionInvalidate(ServiceConnRef);
long AMDServiceConnectionSendMessage(ServiceConnRef serviceConnection, CFDictionaryRef message, CFPropertyListFormat format);
unsigned AMDeviceSecureStartService(AMDeviceRef device, CFStringRef service_name, unsigned int *unknown, ServiceConnRef * handle);
unsigned AMDeviceNotificationSubscribe(void(*f)(const DevicePointer*), long, long, long, HANDLE*);
Expand Down
15 changes: 5 additions & 10 deletions IOSDeviceLib/IOSDeviceLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,6 @@ void cleanup_file_resources(const std::string& device_identifier, const std::str
AFCConnectionClose(afc_connection_to_close);
devices[device_identifier].apps_cache.erase(application_identifier);
}

if (devices[device_identifier].services.count(kHouseArrest))
{
devices[device_identifier].services.erase(kHouseArrest);
}
}

void cleanup_file_resources(const std::string& device_identifier)
Expand Down Expand Up @@ -982,13 +977,13 @@ void get_application_infos(std::string device_identifier, std::string method_id)

CFStringRef cf_app_type_value = create_CFString("User");
const void *client_opts_values_arr[] = { cf_app_type_value, cf_return_attributes_array };
CFDictionaryRef clinet_opts_dict = CFDictionaryCreate(NULL, client_opts_keys_arr, client_opts_values_arr, 2, NULL, NULL);
CFDictionaryRef client_opts_dict = CFDictionaryCreate(NULL, client_opts_keys_arr, client_opts_values_arr, 2, NULL, NULL);

CFStringRef cf_command_key = create_CFString("Command");
CFStringRef cf_client_options_key = create_CFString("ClientOptions");
const void *keys_arr[] = { cf_command_key, cf_client_options_key };
CFStringRef cf_command_value = create_CFString("Browse");
const void *values_arr[] = { cf_command_value, clinet_opts_dict };
const void *values_arr[] = { cf_command_value, client_opts_dict };
CFDictionaryRef dict_command = CFDictionaryCreate(NULL, keys_arr, values_arr, 2, NULL, NULL);

send_con_message(serviceInfo.connection, dict_command);
Expand All @@ -998,7 +993,7 @@ void get_application_infos(std::string device_identifier, std::string method_id)
CFRelease(cf_app_type_key);
CFRelease(cf_return_attrs_key);
CFRelease(cf_app_type_value);
CFRelease(clinet_opts_dict);
CFRelease(client_opts_dict);
CFRelease(cf_command_key);
CFRelease(cf_client_options_key);
CFRelease(cf_command_value);
Expand All @@ -1007,7 +1002,7 @@ void get_application_infos(std::string device_identifier, std::string method_id)
std::vector<json> livesync_app_infos;
while (true)
{
std::map<std::string, boost::any> dict = receive_con_message(serviceInfo.connection);
std::map<std::string, boost::any> dict = receive_con_message(serviceInfo.connection, device_identifier, method_id, 0);
PRINT_ERROR_AND_RETURN_IF_FAILED_RESULT(dict.count(kErrorKey), boost::any_cast<std::string>(dict[kErrorKey]).c_str(), device_identifier, method_id);
if (dict.empty() || (dict.count(kStatusKey) && has_complete_status(dict)))
{
Expand Down Expand Up @@ -1181,7 +1176,7 @@ void await_notification_response(std::string device_identifier, AwaitNotificatio
PRINT_ERROR_AND_RETURN_IF_FAILED_RESULT(connection == nullptr, invalid_connection_error_message.c_str(), device_identifier, method_id);

ServiceInfo currentNotificationProxy = devices[device_identifier].services[kNotificationProxy];
std::map<std::string, boost::any> response = receive_con_message(connection);
std::map<std::string, boost::any> response = receive_con_message(connection, device_identifier, method_id, await_notification_response_info.timeout);
if (response.size())
{
PRINT_ERROR_AND_RETURN_IF_FAILED_RESULT(response.count(kErrorKey), boost::any_cast<std::string>(response[kErrorKey]).c_str(), device_identifier, method_id);
Expand Down
19 changes: 18 additions & 1 deletion IOSDeviceLib/SocketHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,26 @@
#include "PlistCpp/Plist.hpp"
#include "PlistCpp/PlistDate.hpp"

void setTimeout(std::function<void()> operation, int timeout) {
std::thread([=]() {
std::this_thread::sleep_for(std::chrono::milliseconds(timeout * 1000));
operation();
}).detach();
}

std::mutex receive_con_message_mutex;
std::map<std::string, boost::any> receive_con_message(ServiceConnRef con)
std::map<std::string, boost::any> receive_con_message(ServiceConnRef con, std::string device_identifier, std::string method_id, int timeout)
{
receive_con_message_mutex.lock();

bool isSuccessful = false;

setTimeout([=]() {
if (!isSuccessful) {
AMDServiceConnectionInvalidate(con);
}
}, timeout);

std::map<std::string, boost::any> dict;
char *buffer = new char[4];
int bytes_read = AMDServiceConnectionReceive(con, buffer, 4);
Expand All @@ -23,6 +39,7 @@ std::map<std::string, boost::any> receive_con_message(ServiceConnRef con)
if (bytes_read > 0)
{
Plist::readPlist(buffer, res, dict);
isSuccessful = true;
}
}

Expand Down
2 changes: 1 addition & 1 deletion IOSDeviceLib/SocketHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ LengthEncodedMessage get_message_with_encoded_length(const char* message, long l
int send_message(const char* message, SOCKET socket, long long length = -1);
int send_message(std::string message, SOCKET socket, long long length = -1);
long send_con_message(HANDLE* serviceConnection, CFDictionaryRef message);
std::map<std::string, boost::any> receive_con_message(HANDLE* con);
std::map<std::string, boost::any> receive_con_message(HANDLE* con, std::string device_identifier, std::string method_id, int timeout);
std::map<std::string, boost::any> receive_message(SOCKET socket, int timeout = 5);
std::string receive_message_raw(SOCKET socket, int size = 1000);

Expand Down