pw_rpc: Generic method invocations and tests

- Restructure the BUILD.gn file to define the pw_rpc server library with
  a template. This makes it simple to build different versions of the
  pw_rpc server library.
- Define the ServerContext class, which provides context for a
  particular RPC invocation.
- Have the server invoke RPCs if it finds a method with matching IDs.
- Implement a test version of the Method class and expand the server
  tests.

Change-Id: Id1f46a88f2618a649d72f8c694ee829aef80588c
diff --git a/pw_rpc/BUILD.gn b/pw_rpc/BUILD.gn
index 5226243..37aeba1 100644
--- a/pw_rpc/BUILD.gn
+++ b/pw_rpc/BUILD.gn
@@ -18,32 +18,69 @@
 
 config("default_config") {
   include_dirs = [ "public" ]
+  visibility = [ ":*" ]
 }
 
-source_set("pw_rpc") {
-  deps = [ ":protos_pwpb" ]
+# pw_rpc servers depend on the protobuf library used to encode and decode
+# requests and responses when invoking methods. This template is used to create
+# instances of the pw_rpc server library with different implementations.
+#
+# The implementation parameter must refer to a library that provides the
+# definition of the Method class in pw_rpc/internal/method.h. The Method class
+# provides the Invoke function, which handles the server use to call into the
+# RPC functions themselves.
+template("_pw_rpc_server_library") {
+  assert(defined(invoker.implementation),
+         "_pw_rpc_server_library requires an implementation to be set")
+
+  source_set(target_name) {
+    forward_variables_from(invoker, "*")
+
+    public_configs = [ ":default_config" ]
+    public_deps = [
+      ":common",
+      dir_pw_span,
+      dir_pw_status,
+      implementation,
+    ]
+    deps = [
+      dir_pw_assert,
+      dir_pw_log,
+    ]
+    public = [
+      "public/pw_rpc/server.h",
+      "public/pw_rpc/server_context.h",
+    ]
+    sources = [
+      "public/pw_rpc/internal/service.h",
+      "public/pw_rpc/internal/service_registry.h",
+      "server.cc",
+      "service.cc",
+      "service_registry.cc",
+    ]
+    allow_circular_includes_from = [ implementation ]
+    friend = [ ":*" ]
+  }
+}
+
+# Classes with no dependencies on the protobuf library for method invocations.
+source_set("common") {
   public_configs = [ ":default_config" ]
   public_deps = [
+    ":protos_pwpb",
     dir_pw_assert,
-    dir_pw_log,
     dir_pw_span,
     dir_pw_status,
   ]
-  public = [
-    "public/pw_rpc/channel.h",
-    "public/pw_rpc/server.h",
-  ]
+  public = [ "public/pw_rpc/channel.h" ]
   sources = [
     "channel.cc",
     "packet.cc",
+    "public/pw_rpc/internal/base_method.h",
     "public/pw_rpc/internal/packet.h",
-    "public/pw_rpc/internal/service.h",
-    "public/pw_rpc/internal/service_registry.h",
-    "server.cc",
-    "service.cc",
-    "service_registry.cc",
   ]
   friend = [ ":*" ]
+  visibility = [ ":*" ]
 }
 
 pw_proto_library("protos") {
@@ -61,18 +98,37 @@
   ]
 }
 
-pw_test("server_test") {
-  deps = [
-    ":protos_pwpb",
-    ":pw_rpc",
-  ]
-  sources = [ "server_test.cc" ]
+# RPC server for tests only. A mock method implementation is used.
+_pw_rpc_server_library("test_server") {
+  implementation = ":test_method"
+  visibility = [ ":*" ]
+}
+
+config("test_config") {
+  include_dirs = [ "test_public" ]
+  visibility = [ ":test_method" ]
+}
+
+source_set("test_method") {
+  public_configs = [ ":test_config" ]
+  public = [ "test_public/pw_rpc/internal/method.h" ]
+  public_deps = [ ":common" ]
+  visibility = [ ":test_server" ]
 }
 
 pw_test("packet_test") {
   deps = [
-    ":pw_rpc",
+    ":common",
     dir_pw_protobuf,
   ]
   sources = [ "packet_test.cc" ]
 }
+
+pw_test("server_test") {
+  deps = [
+    ":protos_pwpb",
+    ":test_server",
+    dir_pw_assert,
+  ]
+  sources = [ "server_test.cc" ]
+}