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 {