Brillo开发: system/webservd代码分析 – libwebserv

libwebserv(system/webservd/libwebserv)是weaved(system/weaved)的一个子模块。weaved通过libwebserv向webservd添加request handler,而libweabsrv又是通过D-Bus与webservd进行通信。

  • weaved – libwebserv – 初始化

weaved调用libwebserv的入口函数的流程为:

-> main() @ system/weaved/buffet/main.cc
-> brillo::Daemon::Run() @ external/libbrillo/brillo/daemons/daemon.cc
-> brillo::DBusServiceDaemon::OnInit() @ external/libbrillo/brillo/daemons/dbus_daemon.cc
-> buffet::Daemon::RegisterDBusObjectsAsync() @ system/weaved/buffet/main.cc
-> buffet::Manager::RestartWeave() @ system/weaved/buffet/manager.cc
-> buffet::WebServClient::WebServClient() @ system/weaved/buffet/webserv_client.cc
-> libwebserv::Server::ConnectToServerViaDBus() @ system/webservd/libwebserv/server.cc
-> libwebserv::DBusServer::Connect() @ system/webservd/libwebserv/dbus_server.cc

这里,我们重点看一下bufffer::WebServvClient::WebServClient()与libwebserv::DBusServer::Connect()这两个方法。首先我们看一下buffet::WebServClient::WebServClient()做了些什么:

WebServClient::WebServClient(
    const scoped_refptr<dbus::Bus>& bus,
    brillo::dbus_utils::AsyncEventSequencer* sequencer,
    const base::Closure& server_available_callback)
    : server_available_callback_{server_available_callback} {
  web_server_ = libwebserv::Server::ConnectToServerViaDBus(
      bus, buffet::dbus_constants::kServiceName,
      sequencer->GetHandler("Server::Connect failed.", true),
      base::Bind(&base::DoNothing),
      base::Bind(&base::DoNothing));
  web_server_->OnProtocolHandlerConnected(
      base::Bind(&WebServClient::OnProtocolHandlerConnected,
                 weak_ptr_factory_.GetWeakPtr()));
  web_server_->OnProtocolHandlerDisconnected(
      base::Bind(&WebServClient::OnProtocolHandlerDisconnected,
                 weak_ptr_factory_.GetWeakPtr()));
}

可以看到这里设置了protocol handler connected/disconnected callback, 当protocol handler added/removed时,就会回调这个callback。

接着我们再看一下libwebserv::DBusServer::Connect()方法:

void DBusServer::Connect(
    const scoped_refptr<dbus::Bus>& bus,
    const std::string& service_name,
    const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
    const base::Closure& on_server_online,
    const base::Closure& on_server_offline) {
  service_name_ = service_name;
  dbus_object_.reset(new brillo::dbus_utils::DBusObject{
      nullptr, bus, dbus_adaptor_->GetObjectPath()});
  dbus_adaptor_->RegisterWithDBusObject(dbus_object_.get());
  dbus_object_->RegisterAsync(cb);
  on_server_online_ = on_server_online;
  on_server_offline_ = on_server_offline;
  object_manager_.reset(new org::chromium::WebServer::ObjectManagerProxy{bus});
  object_manager_->SetServerAddedCallback(
      base::Bind(&DBusServer::Online, base::Unretained(this)));
  object_manager_->SetServerRemovedCallback(
      base::Bind(&DBusServer::Offline, base::Unretained(this)));
  object_manager_->SetProtocolHandlerAddedCallback(
      base::Bind(&DBusServer::ProtocolHandlerAdded, base::Unretained(this)));
  object_manager_->SetProtocolHandlerRemovedCallback(
      base::Bind(&DBusServer::ProtocolHandlerRemoved, base::Unretained(this)));
}

可以看到这里设置了webservd server online/offline callback,同时还设置了protocol handler added/removed callback。

  • weaved – libwebserv – protocol handler added/removed callback

调用过程如下:

-> ...
-> dbus::ObjectManager::OnGetManagedObjects() @ external/libchrome/dbus/object_manager.cc
-> dbus::ObjectManager::UpdateObject() @ external/libchrome/dbus/object_manager.cc
-> org::chromium::WebServer::ObjectManagerProxy::ObjectAdded() @ ${OUT}/gen/SHARED_LIBRARIES/libwebservd-client-internal_intermediates/dbus_bindings/include/webservd/dbus-proxies.h
-> base::Callback<>::Run() @ external/libchrome/base/callback.h
-> libwebserv::DBusServer::ProtocolHandlerAdded() @ system/webserved/libwebserv/dbus_server.cc
-> buffet::WebServClient::OnProtocolHandlerConnected() @ system/weaved/buffet/webserv_client.cc
-> base::Callback<>::Run() @ external/libchrome/base/callback.h
-> buffet::Manager::CreateDevice() @ system/weaved/buffet/manager.cc

先看一下org::chromium::WebServer::ObjectManagerProxy::ObjectAdded()方法:

class ObjectManagerProxy : public dbus::ObjectManager::Interface {
  // ...
  void ObjectAdded(
      const dbus::ObjectPath& object_path,
      const std::string& interface_name) override {
    // ...
    if (interface_name == "org.chromium.WebServer.ProtocolHandler") {
      auto property_set =
          static_cast<org::chromium::WebServer::ProtocolHandlerProxy::PropertySet*>(
              dbus_object_manager_->GetProperties(object_path, interface_name));
      std::unique_ptr<org::chromium::WebServer::ProtocolHandlerProxy> protocol_handler_proxy{
        new org::chromium::WebServer::ProtocolHandlerProxy{bus_, object_path, property_set}
      };
      auto p = protocol_handler_instances_.emplace(object_path, std::move(protocol_handler_proxy));
      if (!on_protocol_handler_added_.is_null())
        on_protocol_handler_added_.Run(p.first->second.get());
      return;
    }
  // ...
}

可以看到这里调用了on_protocol_handler_added_.Run(), 即调用libwebserv::DBusServer::ProtocolHandlerAdded()方法:

void DBusServer::ProtocolHandlerAdded(
    org::chromium::WebServer::ProtocolHandlerProxyInterface* handler) {
  VLOG(1) << "Server-side protocol handler with ID '" << handler->id()
          << "' is on-line (" << handler->name() << ")";

  protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());
  DBusProtocolHandler* registered_handler =
      GetProtocolHandlerImpl(handler->name());
  if (registered_handler) {
    protocol_handlers_ids_.emplace(handler->id(), registered_handler);
    registered_handler->Connect(handler);
    if (!on_protocol_handler_connected_.is_null())
      on_protocol_handler_connected_.Run(registered_handler);
  }
}

可以看到,最后会去调用on_protocol_handler_connected_.Run(registered_handler)即调用buffer::WebServClient::OnProtocolHandlerConnected(callback):

void WebServClient::OnProtocolHandlerConnected(
    libwebserv::ProtocolHandler* protocol_handler) {
  if (protocol_handler->GetName() == libwebserv::ProtocolHandler::kHttp) {
    http_port_ = *protocol_handler->GetPorts().begin();
  } else if (protocol_handler->GetName() ==
             libwebserv::ProtocolHandler::kHttps) {
    https_port_ = *protocol_handler->GetPorts().begin();
    certificate_ = protocol_handler->GetCertificateFingerprint();
  }
  if (https_port_ && https_port_)
    server_available_callback_.Run();
}

可以看到,最后会去调用server_available_callback_.Run()即调用Manager::CreateDevice():

void Manager::CreateDevice() {
  if (device_)
    return;

  device_ = weave::Device::Create(config_.get(), task_runner_.get(),
                                  http_client_.get(), shill_client_.get(),
                                  mdns_client_.get(), web_serv_client_.get(),
                                  shill_client_.get(), bluetooth_client_.get());

  LoadTraitDefinitions(options_.config_options, device_.get());
  LoadCommandDefinitions(options_.config_options, device_.get());
  LoadStateDefinitions(options_.config_options, device_.get());
  LoadStateDefaults(options_.config_options, device_.get());

  device_->AddSettingsChangedCallback(
      base::Bind(&Manager::OnConfigChanged, weak_ptr_factory_.GetWeakPtr()));

  device_->AddTraitDefsChangedCallback(
      base::Bind(&Manager::OnTraitDefsChanged,
                 weak_ptr_factory_.GetWeakPtr()));
  device_->AddStateChangedCallback(
      base::Bind(&Manager::OnComponentTreeChanged,
                 weak_ptr_factory_.GetWeakPtr()));
  device_->AddComponentTreeChangedCallback(
      base::Bind(&Manager::OnComponentTreeChanged,
                 weak_ptr_factory_.GetWeakPtr()));

  device_->AddGcdStateChangedCallback(
      base::Bind(&Manager::OnGcdStateChanged, weak_ptr_factory_.GetWeakPtr()));

  device_->AddPairingChangedCallbacks(
      base::Bind(&Manager::OnPairingStart, weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&Manager::OnPairingEnd, weak_ptr_factory_.GetWeakPtr()));

  device_->AddCommandHandler(kBaseComponent, kRebootCommand,
                             base::Bind(&Manager::OnRebootDevice,
                                        weak_ptr_factory_.GetWeakPtr()));

  CreateServicesForClients();
}
  • weaved – libwebserv – add request handler

调用过程如下:

a. 通过libwebserv::DBusProtocolHandler::Connect() add request handler to webservd:

-> ...
-> dbus::ObjectManager::OnGetManagedObjects() @ external/libchrome/dbus/object_manager.cc
-> dbus::ObjectManager::UpdateObject() @ external/libchrome/dbus/object_manager.cc
-> org::chromium::WebServer::ObjectManagerProxy::ObjectAdded() @ ${OUT}/gen/SHARED_LIBRARIES/libwebservd-client-internal_intermediates/dbus_bindings/include/webservd/dbus-proxies.h
-> base::Callback<>::Run() @ external/libchrome/base/callback.h
-> libwebserv::DBusServer::ProtocolHandlerAdded() @ system/webserved/libwebserv/dbus_server.cc
-> libwebserv::DBusProtocolHandler::Connect() @ system/webservd/libwebserv/dbus_protocol_handler.cc
-> org::chromium::WebServer::ProtocolHandlerProxy::AddRequestHandlerAsync()

b. 通过libwebserv::DBusProtocolHandler::AddHandler() add request handler to webservd:

-> ...
-> dbus::ObjectManager::OnGetManagedObjects() @ external/libchrome/dbus/object_manager.cc
-> dbus::ObjectManager::UpdateObject() @ external/libchrome/dbus/object_manager.cc
-> org::chromium::WebServer::ObjectManagerProxy::ObjectAdded() @ ${OUT}/gen/SHARED_LIBRARIES/libwebservd-client-internal_intermediates/dbus_bindings/include/webservd/dbus-proxies.h
-> base::Callback<>::Run() @ external/libchrome/base/callback.h
-> libwebserv::DBusServer::ProtocolHandlerAdded() @ system/webserved/libwebserv/dbus_server.cc
-> buffet::WebServClient::OnProtocolHandlerConnected() @ system/weaved/buffet/webserv_client.cc
-> base::Callback<>::Run() @ external/libchrome/base/callback.h
-> buffet::Manager::CreateDevice() @ system/weaved/buffet/manager.cc
-> weave::Device::Create() @ external/libweave/src/device_manager.cc
-> weave::DeviceManager::DeviceManager() @ external/libweave/src/device_manager.cc
-> weave::DeviceManager::StartPrivet() @ external/libweave/src/device_manager.cc
-> weave::weave::privet::Manager::Start() @ external/libweave/src/privet/privet_manager.cc
-> buffet::WebServClient::AddHttpRequestHandler() @ system/weaved/buffet/webserv_client.cc
-> libwebserv::DBusProtocolHandler::AddHandlerCallback() @ system/webservd/libwebserv/dbus_protocol_handler.cc
-> libwebserv::DBusProtocolHandler::AddHandler() @ system/webservd/libwebserv/dbus_protool_handler.cc
-> org::chromium::WebServer::ProtocolHandlerProxy::AddRequestHandlerAsync()

libwebserv::DBusServer::ProtocolHandlerAdded()相关代码如下:

void DBusServer::ProtocolHandlerAdded(                                                              
    org::chromium::WebServer::ProtocolHandlerProxyInterface* handler) {                             
  VLOG(0) << "Server-side protocol handler with ID '" << handler->id()                              
          << "' is on-line (" << handler->name() << ")";                                            
                                                                                                    
  protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());                        
  DBusProtocolHandler* registered_handler =                                                         
      GetProtocolHandlerImpl(handler->name());                                                      
  if (registered_handler) {                                                                         
    protocol_handlers_ids_.emplace(handler->id(), registered_handler);                              
    registered_handler->Connect(handler);                                                           
    if (!on_protocol_handler_connected_.is_null())                                                  
      on_protocol_handler_connected_.Run(registered_handler);                                       
  }                                                                                                 
}

NOTE: on_protocol_handler_connected_.Run()实际上就是调用buffet::WebServClient::OnProtocolHandlerConnected()方法。

  • weaved – libwebserv – 关于protocol handler

从代码中可以看到weaved进程中只有两个DBusProtocolHander实例:

  1. http protocol handler: 处理http相关的request
  2. https protocol handler: 处理http & https相关的request

每个DBusProtocolHander实例中,可以有多个ProtocolHandlerProxyInterface (protocol handler client)。

  • weaved – libwebserv – process request

如执行:

$ adb shell curl -H "Authorization: Privet anonymous" -k https://localhost/privet/info

调用过程如下:

-> ...
-> base::Callback<> @ external/libchrome/base/callback.h
-> libwebserv::DBusServer::RequestHandler::ProcessRequest() @ system/webserved/libwebserv/dbus_server.cc
-> libwebserv::DBusProtocolHandler::ProcessRequest() @ system/webservd/libwebserv/dbus_protocol_handler.cc
-> libwebserv::RequestHandlerCallback::HandleRquest() @ system/webservd/libwebserv/request_handler_callback.cc
-> base::Callback<>::Run() @ external/libchrome/base/callback.h:396
-> base::internal::Invoker<>::Run() @ external/libchrome/base/bind_internal.h:343
-> base::internal::InvokeHelper<>::MakeItSo() @ external/libchrome/base/bind_internal.h:303
-> base::internal::RunableAdapter<>::Run() @ external/libchrome/base/bind_internal.h:176
-> buffet::WebServClient::OnRequest() @ system/weaved/buffet/webserv_client.cc
-> base::Callback<>::Run() @ external/libchrome/base/callback.h
-> base::internal::Invoker<>::Run() @ external/libchrome/base/bind_internal.h:343
-> base::internal::InvokeHelper<>::MakeItSo() @ external/libchrome/base/bind_internal.h:303
-> base::internal::RunnableAdapter<>::Run() @external/libchrome/base/bind_internal.h:176
-> weave::privet::Manager::PrivetRequestHandler() @ external/libweave/src/privet/privet_manager.cc
-> weave::privet::Manager::PrivetRequestHandlerWithData() @ external/libweave/src/privet/privet_manager.cc
-> weave::privet::PrivetHandler::HandleInfo() @ external/libweave/src/privet/privet_handler.cc
  • weaved – libwebserv – complete request

同样执行:

$ adb shell curl -H "Authorization: Privet anonymous" -k https://localhost/privet/info

调用过程如下:

-> ...
-> weave::privet::Manager::PrivetRequestHandler() @ external/libweave/src/privet/privet_manager.cc
-> weave::privet::Manager::PrivetRequestHandlerWithData() @ external/libweave/src/privet/privet_manager.cc
-> weave::privet::PrivetHandler::HandleInfo() @ external/libweave/src/privet/privet_handler.cc
-> base::Callback<>::Run() @ external/libchrome/base/callback.h
-> base::internal::Invoker<>::Run() @ external/libchrome/base/bind_internal.h:343
-> weave::privet::Manager::PrivetResponseHandler() @ external/libweave/src/privet/privet_manager.cc
-> libwebserv::ResponseImpl::ReplyWithText() @ system/webservd/libwebserv/response.cc
-> libwebserv::ResponseImpl::Reply() @ system/webservd/libwebserv/response.cc
-> libwebserv::ResponseImpl::SendResponse() @ system/webservd/libwebserv/response.cc
-> libwebserv::DBusProtocolHandler::CompleteRequest() @ system/webservd/libwebserv/dbus_protocol_handler.cc

发表评论

电子邮件地址不会被公开。 必填项已用*标注