#include "base/bind.h"
#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/time/time.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_device_client.h"
namespace {
-// TODO(armansito): Add bindings for these to service_constants.h
-// (crbug.com/256889)
-const char kShillErrorFailure[] = "org.chromium.flimflam.Error.Failure";
-const char kShillErrorNotSupported[] =
- "org.chromium.flimflam.Error.NotSupported";
-
std::string GetErrorNameForShillError(const std::string& shill_error_name) {
- // TODO(armansito): Use the new SIM error names once the ones below get
- // deprecated (crbug.com/256855)
- if (shill_error_name == kShillErrorFailure)
+ if (shill_error_name == shill::kErrorResultFailure)
return NetworkDeviceHandler::kErrorFailure;
- if (shill_error_name == kShillErrorNotSupported)
+ if (shill_error_name == shill::kErrorResultNotSupported)
return NetworkDeviceHandler::kErrorNotSupported;
- if (shill_error_name == shill::kErrorIncorrectPinMsg)
+ if (shill_error_name == shill::kErrorResultIncorrectPin)
return NetworkDeviceHandler::kErrorIncorrectPin;
- if (shill_error_name == shill::kErrorPinBlockedMsg)
+ if (shill_error_name == shill::kErrorResultPinBlocked)
return NetworkDeviceHandler::kErrorPinBlocked;
- if (shill_error_name == shill::kErrorPinRequiredMsg)
+ if (shill_error_name == shill::kErrorResultPinRequired)
return NetworkDeviceHandler::kErrorPinRequired;
+ if (shill_error_name == shill::kErrorResultNotFound)
+ return NetworkDeviceHandler::kErrorDeviceMissing;
return NetworkDeviceHandler::kErrorUnknown;
}
base::Bind(&HandleShillCallFailure, device_path, error_callback));
}
+// Struct containing TDLS Operation parameters.
+struct TDLSOperationParams {
+ TDLSOperationParams() : retry_count(0) {}
+ std::string operation;
+ std::string ip_or_mac_address;
+ int retry_count;
+};
+
+// Forward declare for PostDelayedTask.
+void CallPerformTDLSOperation(
+ const std::string& device_path,
+ const TDLSOperationParams& params,
+ const network_handler::StringResultCallback& callback,
+ const network_handler::ErrorCallback& error_callback);
+
+void TDLSSuccessCallback(
+ const std::string& device_path,
+ const TDLSOperationParams& params,
+ const network_handler::StringResultCallback& callback,
+ const network_handler::ErrorCallback& error_callback,
+ const std::string& result) {
+ std::string event_desc = "TDLSSuccessCallback: " + params.operation;
+ if (!result.empty())
+ event_desc += ": " + result;
+ NET_LOG_EVENT(event_desc, device_path);
+ if (params.operation != shill::kTDLSSetupOperation) {
+ if (!callback.is_null())
+ callback.Run(result);
+ return;
+ }
+
+ if (!result.empty())
+ NET_LOG_ERROR("Unexpected TDLS result: " + result, device_path);
+
+ // Send a delayed Status request after a successful Setup call.
+ TDLSOperationParams status_params;
+ status_params.operation = shill::kTDLSStatusOperation;
+ status_params.ip_or_mac_address = params.ip_or_mac_address;
+
+ const int64 kRequestStatusDelayMs = 500;
+ base::TimeDelta request_delay;
+ if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
+ request_delay = base::TimeDelta::FromMilliseconds(kRequestStatusDelayMs);
+
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CallPerformTDLSOperation,
+ device_path, status_params, callback, error_callback),
+ request_delay);
+}
+
+void TDLSErrorCallback(
+ const std::string& device_path,
+ const TDLSOperationParams& params,
+ const network_handler::StringResultCallback& callback,
+ const network_handler::ErrorCallback& error_callback,
+ const std::string& dbus_error_name,
+ const std::string& dbus_error_message) {
+ // If a Setup operation receives an InProgress error, retry.
+ const int kMaxRetries = 5;
+ if (params.operation == shill::kTDLSSetupOperation &&
+ dbus_error_name == shill::kErrorResultInProgress &&
+ params.retry_count < kMaxRetries) {
+ TDLSOperationParams retry_params = params;
+ ++retry_params.retry_count;
+ NET_LOG_EVENT(base::StringPrintf("TDLS Retry: %d", params.retry_count),
+ device_path);
+ const int64 kReRequestDelayMs = 1000;
+ base::TimeDelta request_delay;
+ if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
+ request_delay = base::TimeDelta::FromMilliseconds(kReRequestDelayMs);
+
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CallPerformTDLSOperation,
+ device_path, retry_params, callback, error_callback),
+ request_delay);
+ return;
+ }
+
+ NET_LOG_ERROR("TDLS Error:" + dbus_error_name + ":" + dbus_error_message,
+ device_path);
+ if (error_callback.is_null())
+ return;
+
+ const std::string error_name =
+ dbus_error_name == shill::kErrorResultInProgress ?
+ NetworkDeviceHandler::kErrorTimeout : NetworkDeviceHandler::kErrorUnknown;
+ const std::string& error_detail = params.ip_or_mac_address;
+ scoped_ptr<base::DictionaryValue> error_data(
+ network_handler::CreateDBusErrorData(
+ device_path, error_name, error_detail,
+ dbus_error_name, dbus_error_message));
+ error_callback.Run(error_name, error_data.Pass());
+}
+
+void CallPerformTDLSOperation(
+ const std::string& device_path,
+ const TDLSOperationParams& params,
+ const network_handler::StringResultCallback& callback,
+ const network_handler::ErrorCallback& error_callback) {
+ NET_LOG_EVENT("CallPerformTDLSOperation: " + params.operation, device_path);
+ DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation(
+ dbus::ObjectPath(device_path),
+ params.operation,
+ params.ip_or_mac_address,
+ base::Bind(&TDLSSuccessCallback,
+ device_path, params, callback, error_callback),
+ base::Bind(&TDLSErrorCallback,
+ device_path, params, callback, error_callback));
+}
+
} // namespace
NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() {
ApplyCellularAllowRoamingToShill();
}
+void NetworkDeviceHandlerImpl::SetWifiTDLSEnabled(
+ const std::string& ip_or_mac_address,
+ bool enabled,
+ const network_handler::StringResultCallback& callback,
+ const network_handler::ErrorCallback& error_callback) {
+ const DeviceState* device_state =
+ network_state_handler_->GetDeviceStateByType(NetworkTypePattern::WiFi());
+ if (!device_state) {
+ if (error_callback.is_null())
+ return;
+ scoped_ptr<base::DictionaryValue> error_data(new base::DictionaryValue);
+ error_data->SetString(network_handler::kErrorName, kErrorDeviceMissing);
+ error_callback.Run(kErrorDeviceMissing, error_data.Pass());
+ return;
+ }
+ TDLSOperationParams params;
+ params.operation = enabled ? shill::kTDLSSetupOperation
+ : shill::kTDLSTeardownOperation;
+ params.ip_or_mac_address = ip_or_mac_address;
+ CallPerformTDLSOperation(
+ device_state->path(), params, callback, error_callback);
+}
+
+void NetworkDeviceHandlerImpl::GetWifiTDLSStatus(
+ const std::string& ip_or_mac_address,
+ const network_handler::StringResultCallback& callback,
+ const network_handler::ErrorCallback& error_callback) {
+ const DeviceState* device_state =
+ network_state_handler_->GetDeviceStateByType(NetworkTypePattern::WiFi());
+ if (!device_state) {
+ if (error_callback.is_null())
+ return;
+ scoped_ptr<base::DictionaryValue> error_data(new base::DictionaryValue);
+ error_data->SetString(network_handler::kErrorName, kErrorDeviceMissing);
+ error_callback.Run(kErrorDeviceMissing, error_data.Pass());
+ return;
+ }
+ TDLSOperationParams params;
+ params.operation = shill::kTDLSStatusOperation;
+ params.ip_or_mac_address = ip_or_mac_address;
+ CallPerformTDLSOperation(
+ device_state->path(), params, callback, error_callback);
+}
+
void NetworkDeviceHandlerImpl::DeviceListChanged() {
ApplyCellularAllowRoamingToShill();
}