Build libwebserv protocol handler proxy and stub out request handler Change-Id: Ibfbca0ac631e76414f475f7f7eb5564a298ab198 Test: Build continues to succeed in Binder mode Bug: 27204884
diff --git a/libwebserv/binder_server.cc b/libwebserv/binder_server.cc index ced4ba8..4ac8636 100644 --- a/libwebserv/binder_server.cc +++ b/libwebserv/binder_server.cc
@@ -12,22 +12,191 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "libwebserv/binder_server.h" - #include "webserv_common/binder_constants.h" -#include "libwebserv/protocol_handler.h" +#include "libwebserv/binder_server.h" +#include "libwebserv/protocol_handler.h" +#include "libwebserv/request_handler_callback.h" + +#include "android/webservd/BnRequestHandler.h" + +#include <map> +#include <set> #include <string> #include <vector> using android::sp; using android::IBinder; using android::binder::Status; +using android::webservd::IHttpRequest; +using android::webservd::IProtocolHandler; +using android::webservd::IRequestHandler; +using std::map; +using std::pair; +using std::set; using std::string; +using std::unique_ptr; using std::vector; namespace libwebserv { +class BinderRequestHandler : public android::webservd::BnRequestHandler { + public: + explicit BinderRequestHandler(unique_ptr<RequestHandlerInterface> handler) + : handler_(std::move(handler)) {} + + Status ProcessRequest(const sp<IHttpRequest>& request) override { + (void)request; + return Status::ok(); + } + + private: + unique_ptr<RequestHandlerInterface> handler_; + + DISALLOW_COPY_AND_ASSIGN(BinderRequestHandler); +}; + +class BinderProtocolHandler : public ProtocolHandler { + public: + explicit BinderProtocolHandler(const string& name) + : name_(name) {} + + virtual ~BinderProtocolHandler() { + ResetRemoteProtocolHandlers(); + } + + bool AddRemote(sp<IProtocolHandler> handler) { + string name; + int32_t port; + string protocol; + + if (!handler->GetName(&name).isOk()) { + LOG(INFO) << "Could not get name of remote protocol handler."; + return false; + } + + CHECK(name == name_); + + if (!handler->GetPort(&port).isOk()) { + LOG(INFO) << "Could not get port for remote protocol handler."; + return false; + } + + if (!handler->GetProtocol(&protocol).isOk()) { + LOG(INFO) << "Could not get protocol for remote protocol handler."; + return false; + } + + ports_.insert(uint16_t(port)); + protocols_.insert(protocol); + remote_handlers_.push_back(handler); + + return true; + } + + int AddHandler(const string& url, + const string& method, + unique_ptr<RequestHandlerInterface> handler) override { + sp<IRequestHandler> binder_handler( + new BinderRequestHandler(std::move(handler))); + set<pair<sp<IProtocolHandler>, string>> guids; + + // Add this local request handler to each remote protocol handler + // associated with this local protocol handler. + for (sp<IProtocolHandler> handler : remote_handlers_) { + string guid; + + if (!handler->AddRequestHandler(url, + method, + binder_handler, + &guid).isOk()) { + LOG(WARNING) << "Remote protocol handler failed to " + << "register new request handler."; + } else { + guids.emplace(handler, guid); + } + } + + int id = last_handler_id_++; + handler_ids_.emplace(id, guids); + return id; + } + + int AddHandlerCallback( + const string& url, + const string& method, + const base::Callback<RequestHandlerInterface::HandlerSignature>& + handler_callback) override { + std::unique_ptr<RequestHandlerInterface> handler{ + new RequestHandlerCallback{handler_callback}}; + return AddHandler(url, method, std::move(handler)); + } + + bool RemoveHandler(int handler_id) override { + auto it = handler_ids_.find(handler_id); + + if (it == handler_ids_.end()) { + return false; + } + + for (const pair<sp<IProtocolHandler>,string>& remote : it->second) { + if (!remote.first->RemoveRequestHandler(remote.second).isOk()) { + LOG(WARNING) << "Could not remove request handler from remote."; + } + } + + return true; + } + + void ResetRemoteProtocolHandlers() { + for (auto it : handler_ids_) { + for (auto remote : it.second) { + if (!remote.first->RemoveRequestHandler(remote.second).isOk()) { + LOG(INFO) << "Could not remove request handler from remote."; + } + } + } + + handler_ids_.clear(); + remote_handlers_.clear(); + } + + bool IsConnected() const override { return !remote_handlers_.empty(); } + string GetName() const override { return name_; } + set<uint16_t> GetPorts() const override { return ports_; } + set<string> GetProtocols() const override { return protocols_; } + + brillo::Blob GetCertificateFingerprint() const override { + brillo::Blob result; + + for (auto& handler : remote_handlers_) { + Status status = handler->GetCertificateFingerprint(&result); + if (!status.isOk()) { + LOG(WARNING) << "Could not get certificate fingerprint " + << "from protocol handler: " << status; + } else if (!result.empty()) { + break; + } + } + + return result; + } + + private: + int last_handler_id_ = 0; + set<uint16_t> ports_; + set<string> protocols_; + string name_; + vector<sp<IProtocolHandler>> remote_handlers_; + + // Map of handler ID numbers as returned by AddHandler to pairs of + // IProtocolHandler pointers and string handler GUIDs as returned by the + // daemon. + map<int,set<pair<sp<IProtocolHandler>,string>>> handler_ids_; + + DISALLOW_COPY_AND_ASSIGN(BinderProtocolHandler); +}; + BinderServer::BinderServer(brillo::MessageLoop* message_loop, const base::Closure& on_server_online, const base::Closure& on_server_offline, @@ -59,14 +228,10 @@ base::TimeDelta::FromSeconds(1)); } - void BinderServer::ClearLocalState() { - // Remove all references to remote protocol handlers from our local wrappers. - - // TODO(wiley) Define this method - //for (auto& local_handler: local_protocol_handlers_) { - // local_handler.second->ResetRemoteProtocolHandlers(); - //} + for (auto& local_handler: local_protocol_handlers_) { + local_handler.second->ResetRemoteProtocolHandlers(); + } remote_server_.clear(); } @@ -90,11 +255,17 @@ LOG(INFO) << "Remote handler could not report its name."; return false; } - // TODO(wiley) Look for a BinderPHGroup by that name in local_handlers_ - // Create a new BinderPHGroup if necessary - // Add it to the map under |name| - // Update |it| appropriately - // Tell |it| about |remote_handler| + + auto it = local_protocol_handlers_.find(name); + + if (it == local_protocol_handlers_.end()) { + unique_ptr<BinderProtocolHandler> local_handler( + new BinderProtocolHandler(name)); + local_protocol_handlers_[name] = std::move(local_handler); + it = local_protocol_handlers_.find(name); + } + + it->second->AddRemote(remote_handler); } return true; } @@ -107,10 +278,14 @@ return GetProtocolHandler(ProtocolHandler::kHttps); } -ProtocolHandler* BinderServer::GetProtocolHandler(const string& /*name*/) { - // TODO(sadmac) Once BuildLocalState populates the map of protocol handlers, - // use it to return a result here. - return nullptr; +ProtocolHandler* BinderServer::GetProtocolHandler(const string& name) { + auto it = local_protocol_handlers_.find(name); + + if (it == local_protocol_handlers_.end()) { + return nullptr; + } + + return it->second.get(); } bool BinderServer::IsConnected() const {