diff options
author | Casey Dahlin <sadmac@google.com> | 2016-03-02 14:09:10 -0800 |
---|---|---|
committer | Casey Dahlin <sadmac@google.com> | 2016-03-04 15:33:40 -0800 |
commit | f42e5599a6bb293ce2e9d471db788db3c1c75047 (patch) | |
tree | 5cb4799705a982b6f63b9c38a15ea5f2cd9be27c | |
parent | 06322e3a69d193e9d73839dbd05e936de0220f06 (diff) | |
download | webservd-f42e5599a6bb293ce2e9d471db788db3c1c75047.tar.gz |
Properly handle disconnected server from libwebservandroid-n-preview-1
The DBus back end implemented fault tolerance, so that libwebserv could
ignore the disappearance of the server. We didn't carry this forward.
This actually breaks if a user tries to connect, grab protocol handlers,
and register all in one go, as when we connect, we don't actually
establish the connection until the next main loop iteration.
Change-Id: Ia8b7efb5f6b024eb3668759a53a03061c6dc136c
Test: Sanity test now successfully registers request handlers.
Bug: 27204884
-rw-r--r-- | libwebserv/binder_request_handler.h | 6 | ||||
-rw-r--r-- | libwebserv/binder_server.cc | 125 |
2 files changed, 80 insertions, 51 deletions
diff --git a/libwebserv/binder_request_handler.h b/libwebserv/binder_request_handler.h index b3f38e6..b42ddd2 100644 --- a/libwebserv/binder_request_handler.h +++ b/libwebserv/binder_request_handler.h @@ -23,14 +23,14 @@ namespace libwebserv { class BinderRequestHandler : public android::webservd::BnRequestHandler { public: explicit BinderRequestHandler( - std::unique_ptr<libwebserv::RequestHandlerInterface> handler) - : handler_(std::move(handler)) {} + libwebserv::RequestHandlerInterface* handler) + : handler_(handler) {} android::binder::Status ProcessRequest( const android::sp<android::webservd::IHttpRequest>& request) override; private: - std::unique_ptr<libwebserv::RequestHandlerInterface> handler_; + libwebserv::RequestHandlerInterface* handler_; DISALLOW_COPY_AND_ASSIGN(BinderRequestHandler); }; diff --git a/libwebserv/binder_server.cc b/libwebserv/binder_server.cc index c7a7491..e4abd7f 100644 --- a/libwebserv/binder_server.cc +++ b/libwebserv/binder_server.cc @@ -38,6 +38,58 @@ using std::vector; namespace libwebserv { +class RequestHandlerRegistration { + public: + RequestHandlerRegistration(const string& url, + const string& method, + unique_ptr<RequestHandlerInterface> handler) + : url_(url), + method_(method), + handler_(std::move(handler)), + binder_handler_(new BinderRequestHandler(handler_.get())) {} + + ~RequestHandlerRegistration() { DropRemotes(); } + + void AddRemote(sp<IProtocolHandler> handler) { + string guid; + + if (!handler->AddRequestHandler(url_, + method_, + binder_handler_, + &guid).isOk()) { + LOG(WARNING) << "Remote protocol handler failed to " + << "register new request handler."; + } + + protos_.emplace_back(handler, guid); + } + + void DropRemotes() { + for (auto& proto : protos_) { + if (!proto.first->RemoveRequestHandler(proto.second).isOk()) { + LOG(WARNING) << "Could not remove request handler from remote."; + } + } + } + + private: + string url_; + string method_; + unique_ptr<RequestHandlerInterface> handler_; + sp<IRequestHandler> binder_handler_; + vector<pair<sp<IProtocolHandler>, string>> protos_; + + DISALLOW_COPY_AND_ASSIGN(RequestHandlerRegistration); +}; + +// This is libwebserv's binder based process local protocol +// handler. It wraps around a group of remote protocol handlers +// that share a common name. It exists independently of the +// lifetime of the remote protocol handlers and is created on +// either of: +// 1) The local process requests a protocol handler by name +// 2) We connect to the remote webservd process and it has a protocol +// handler with the given name. class BinderProtocolHandler : public ProtocolHandler { public: explicit BinderProtocolHandler(const string& name) @@ -73,34 +125,27 @@ class BinderProtocolHandler : public ProtocolHandler { protocols_.insert(protocol); remote_handlers_.push_back(handler); + for (auto& request_handler : request_handler_ids_) { + request_handler.second->AddRemote(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); - } + unique_ptr<RequestHandlerRegistration> registration( + new RequestHandlerRegistration(url, method, std::move(handler))); + + for (sp<IProtocolHandler> remote : remote_handlers_) { + registration->AddRemote(remote); } int id = last_handler_id_++; - handler_ids_.emplace(id, guids); + + request_handler_ids_.emplace(id, std::move(registration)); + return id; } @@ -115,31 +160,14 @@ class BinderProtocolHandler : public ProtocolHandler { } 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; + return request_handler_ids_.erase(handler_id) > 0; } 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."; - } - } + for (auto& it : request_handler_ids_) { + it.second->DropRemotes(); } - handler_ids_.clear(); remote_handlers_.clear(); } @@ -171,10 +199,9 @@ class BinderProtocolHandler : public ProtocolHandler { 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_; + // Map of local handler IDs to objects containing the various bits of IPC + // state we need to maintain those handlers on the remote end. + map<int,unique_ptr<RequestHandlerRegistration>> request_handler_ids_; DISALLOW_COPY_AND_ASSIGN(BinderProtocolHandler); }; @@ -221,8 +248,7 @@ void BinderServer::ClearLocalState() { bool BinderServer::BuildLocalState(sp<IBinder> server) { remote_server_ = android::interface_cast<RemoteServer>(server); vector<sp<IBinder>> remote_raw_binders; - if (!remote_server_->GetProtocolHandlers(nullptr, - &remote_raw_binders).isOk()) { + if (!remote_server_->GetProtocolHandlers("", &remote_raw_binders).isOk()) { // Possibly the server died, this is not necessarily an error. LOG(INFO) << "Webservd failed to tell us about protocol handlers."; return false; @@ -243,8 +269,8 @@ bool BinderServer::BuildLocalState(sp<IBinder> server) { 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 = local_protocol_handlers_.emplace(name, + std::move(local_handler)).first; } it->second->AddRemote(remote_handler); @@ -264,7 +290,10 @@ ProtocolHandler* BinderServer::GetProtocolHandler(const string& name) { auto it = local_protocol_handlers_.find(name); if (it == local_protocol_handlers_.end()) { - return nullptr; + unique_ptr<BinderProtocolHandler> local_handler( + new BinderProtocolHandler(name)); + it = local_protocol_handlers_.emplace(name, + std::move(local_handler)).first; } return it->second.get(); |