summary refs log tree commit diff
diff options
context:
space:
mode:
authorNewe <speedy.wolfy@outlook.com>2021-05-21 11:13:17 +0200
committerNewe <speedy.wolfy@outlook.com>2021-05-21 11:13:17 +0200
commit7d40250c11077d6717388412479a65bb8826960b (patch)
tree38fe9b264f6e1bdfe0f08c7a75597012dc9ea4f7
parentMerge branch 'master' of https://github.com/discord-open-source/discord-voice (diff)
downloadserver-7d40250c11077d6717388412479a65bb8826960b.tar.xz
[add] Basic project structure
-rw-r--r--.gitignore139
-rw-r--r--CMakeLists.txt32
-rw-r--r--README.md14
-rw-r--r--config.json1
-rw-r--r--src/main.cpp36
-rw-r--r--src/protodefs/include/protos.grpc.pb.cc86
-rw-r--r--src/protodefs/include/protos.grpc.pb.h295
-rw-r--r--src/protodefs/include/protos.pb.cc487
-rw-r--r--src/protodefs/include/protos.pb.h413
-rw-r--r--src/protodefs/protos.proto24
-rw-r--r--src/rpcStub.cpp24
-rw-r--r--src/rpcStub.hpp10
-rw-r--r--src/rtcPeerHandler.cpp57
-rw-r--r--src/rtcPeerHandler.hpp29
-rw-r--r--src/rtcServer.hpp0
15 files changed, 1542 insertions, 105 deletions
diff --git a/.gitignore b/.gitignore
index 5c7cd31d..788c5adb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,105 +1,34 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-lerna-debug.log*
-
-# Diagnostic reports (https://nodejs.org/api/report.html)
-report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
-
-# Runtime data
-pids
-*.pid
-*.seed
-*.pid.lock
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-*.lcov
-
-# nyc test coverage
-.nyc_output
-
-# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# Bower dependency directory (https://bower.io/)
-bower_components
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (https://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directories
-node_modules/
-jspm_packages/
-
-# TypeScript v1 declaration files
-typings/
-
-# TypeScript cache
-*.tsbuildinfo
-
-# Optional npm cache directory
-.npm
-
-# Optional eslint cache
-.eslintcache
-
-# Microbundle cache
-.rpt2_cache/
-.rts2_cache_cjs/
-.rts2_cache_es/
-.rts2_cache_umd/
-
-# Optional REPL history
-.node_repl_history
-
-# Output of 'npm pack'
-*.tgz
-
-# Yarn Integrity file
-.yarn-integrity
-
-# dotenv environment variables file
-.env
-.env.test
-
-# parcel-bundler cache (https://parceljs.org/)
-.cache
-
-# Next.js build output
-.next
-
-# Nuxt.js build / generate output
-.nuxt
-dist
-
-# Gatsby files
-.cache/
-# Comment in the public line in if your project uses Gatsby and *not* Next.js
-# https://nextjs.org/blog/next-9-1#public-directory-support
-# public
-
-# vuepress build output
-.vuepress/dist
-
-# Serverless directories
-.serverless/
-
-# FuseBox cache
-.fusebox/
-
-# DynamoDB Local files
-.dynamodb/
-
-# TernJS port file
-.tern-port
-.DS_Store
\ No newline at end of file
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.o
+
+# Directories
+build/
+.vscode/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..cebd3adf
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.15)
+project(fosscord-media)
+
+set(CMAKE_CXX_STANDARD 17)
+
+find_package(Threads REQUIRED)
+find_package(Protobuf REQUIRED)
+find_package(gRPC CONFIG REQUIRED)
+find_package(absl REQUIRED)
+find_package(nlohmann_json REQUIRED)
+
+file(GLOB SourceFiles ${PROJECT_SOURCE_DIR}/src/*.cpp)
+
+file(GLOB ProtoFiles ${PROJECT_SOURCE_DIR}/src/protodefs/*.proto)
+set(PROTOBUF_INPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/protodefs)
+set(PROTOBUF_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/protodefs/include)
+
+foreach(file ${ProtoFiles})
+    execute_process(COMMAND "LD_LIBRARY_PATH=/usr/local/lib protoc --proto_path=\"${PROTOBUF_INPUT_DIRECTORY}\" 
+	--cpp_out=\"${PROJECT_SOURCE_DIR}/src/protodefs/include\" --grpc_out=\"${PROJECT_SOURCE_DIR}/src/protodefs/include\" 
+	--plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin protos.proto"
+            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
+endforeach()
+
+
+include_directories(${Protobuf_INCLUDE_DIRS})
+
+#protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ProtoFiles) 
+
+add_executable(${CMAKE_PROJECT_NAME} ${SourceFiles})
+
+target_link_libraries(${CMAKE_PROJECT_NAME} datachannel gRPC::grpc++ absl::base absl::synchronization absl::strings ${Protobuf_LIBRARIES} nlohmann_json::nlohmann_json)
\ No newline at end of file
diff --git a/README.md b/README.md
index ecd3c7ca..4ddd4708 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,16 @@
 # Fosscord-media
 A Fosscord media (voice and video) server
+
+
+## Installation
+### Prerequisites
+- Install the [libdatachannel](https://github.com/paullouisageneau/libdatachannel) library
+- Install the [gRPC](https://github.com/grpc/grpc) library
+
+### Building 
+
+```bash
+$ cmake
+$ cd build
+$ make
+```
diff --git a/config.json b/config.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/config.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 00000000..3f131512
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,36 @@
+//   $$$$$$\                                                                   $$\                           
+//  $$  __$$\                                                                  $$ |                          
+//  $$ /  \__|$$$$$$\   $$$$$$$\  $$$$$$$\  $$$$$$$\  $$$$$$\   $$$$$$\   $$$$$$$ |                          
+//  $$$$\    $$  __$$\ $$  _____|$$  _____|$$  _____|$$  __$$\ $$  __$$\ $$  __$$ |                          
+//  $$  _|   $$ /  $$ |\$$$$$$\  \$$$$$$\  $$ /      $$ /  $$ |$$ |  \__|$$ /  $$ |                          
+//  $$ |     $$ |  $$ | \____$$\  \____$$\ $$ |      $$ |  $$ |$$ |      $$ |  $$ |                          
+//  $$ |     \$$$$$$  |$$$$$$$  |$$$$$$$  |\$$$$$$$\ \$$$$$$  |$$ |      \$$$$$$$ |                          
+//  \__|      \______/ \_______/ \_______/  \_______| \______/ \__|       \_______|                          
+//                                                                                                           
+//                                                                                                           
+//                                                                                                           
+//                       $$\                      $$$$$$\                                                    
+//                       \__|                    $$  __$$\                                                   
+//  $$\    $$\  $$$$$$\  $$\  $$$$$$$\  $$$$$$\  $$ /  \__| $$$$$$\   $$$$$$\ $$\    $$\  $$$$$$\   $$$$$$\  
+//  \$$\  $$  |$$  __$$\ $$ |$$  _____|$$  __$$\ \$$$$$$\  $$  __$$\ $$  __$$\\$$\  $$  |$$  __$$\ $$  __$$\ 
+//   \$$\$$  / $$ /  $$ |$$ |$$ /      $$$$$$$$ | \____$$\ $$$$$$$$ |$$ |  \__|\$$\$$  / $$$$$$$$ |$$ |  \__|
+//    \$$$  /  $$ |  $$ |$$ |$$ |      $$   ____|$$\   $$ |$$   ____|$$ |       \$$$  /  $$   ____|$$ |      
+//     \$  /   \$$$$$$  |$$ |\$$$$$$$\ \$$$$$$$\ \$$$$$$  |\$$$$$$$\ $$ |        \$  /   \$$$$$$$\ $$ |      
+//      \_/     \______/ \__| \_______| \_______| \______/  \_______|\__|         \_/     \_______|\__|      
+//                                                                                                           
+//                                                                                                           
+//                                                                                                           
+
+
+#include "rtcPeerHandler.hpp" //HAndle peer connection requests
+#include "rpcStub.hpp" //Handle gRPC communications between the different fosscord elements
+
+int main (int argc, char** argv){
+
+	auto handler = std::make_shared<rtcPeerHandler>();
+    auto rpcHandler = std::unique_ptr<rpcStub>();
+
+	std::cout << "Server created" <<std::endl;
+
+    return 0;
+}
\ No newline at end of file
diff --git a/src/protodefs/include/protos.grpc.pb.cc b/src/protodefs/include/protos.grpc.pb.cc
new file mode 100644
index 00000000..26914fad
--- /dev/null
+++ b/src/protodefs/include/protos.grpc.pb.cc
@@ -0,0 +1,86 @@
+// Generated by the gRPC C++ plugin.
+// If you make any local change, they will be lost.
+// source: protos.proto
+
+#include "protos.pb.h"
+#include "protos.grpc.pb.h"
+
+#include <functional>
+#include <grpcpp/impl/codegen/async_stream.h>
+#include <grpcpp/impl/codegen/async_unary_call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/client_unary_call.h>
+#include <grpcpp/impl/codegen/client_callback.h>
+#include <grpcpp/impl/codegen/message_allocator.h>
+#include <grpcpp/impl/codegen/method_handler.h>
+#include <grpcpp/impl/codegen/rpc_service_method.h>
+#include <grpcpp/impl/codegen/server_callback.h>
+#include <grpcpp/impl/codegen/server_callback_handlers.h>
+#include <grpcpp/impl/codegen/server_context.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/impl/codegen/sync_stream.h>
+namespace fosscordMedia {
+
+static const char* fosscordInternals_method_names[] = {
+  "/fosscordMedia.fosscordInternals/sendRequest",
+};
+
+std::unique_ptr< fosscordInternals::Stub> fosscordInternals::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {
+  (void)options;
+  std::unique_ptr< fosscordInternals::Stub> stub(new fosscordInternals::Stub(channel, options));
+  return stub;
+}
+
+fosscordInternals::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options)
+  : channel_(channel), rpcmethod_sendRequest_(fosscordInternals_method_names[0], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel)
+  {}
+
+::grpc::Status fosscordInternals::Stub::sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::fosscordMedia::rpcResponse* response) {
+  return ::grpc::internal::BlockingUnaryCall< ::fosscordMedia::rpcRequest, ::fosscordMedia::rpcResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_sendRequest_, context, request, response);
+}
+
+void fosscordInternals::Stub::experimental_async::sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response, std::function<void(::grpc::Status)> f) {
+  ::grpc::internal::CallbackUnaryCall< ::fosscordMedia::rpcRequest, ::fosscordMedia::rpcResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_sendRequest_, context, request, response, std::move(f));
+}
+
+void fosscordInternals::Stub::experimental_async::sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response, ::grpc::experimental::ClientUnaryReactor* reactor) {
+  ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_sendRequest_, context, request, response, reactor);
+}
+
+::grpc::ClientAsyncResponseReader< ::fosscordMedia::rpcResponse>* fosscordInternals::Stub::PrepareAsyncsendRequestRaw(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) {
+  return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::fosscordMedia::rpcResponse, ::fosscordMedia::rpcRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_sendRequest_, context, request);
+}
+
+::grpc::ClientAsyncResponseReader< ::fosscordMedia::rpcResponse>* fosscordInternals::Stub::AsyncsendRequestRaw(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) {
+  auto* result =
+    this->PrepareAsyncsendRequestRaw(context, request, cq);
+  result->StartCall();
+  return result;
+}
+
+fosscordInternals::Service::Service() {
+  AddMethod(new ::grpc::internal::RpcServiceMethod(
+      fosscordInternals_method_names[0],
+      ::grpc::internal::RpcMethod::NORMAL_RPC,
+      new ::grpc::internal::RpcMethodHandler< fosscordInternals::Service, ::fosscordMedia::rpcRequest, ::fosscordMedia::rpcResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
+          [](fosscordInternals::Service* service,
+             ::grpc::ServerContext* ctx,
+             const ::fosscordMedia::rpcRequest* req,
+             ::fosscordMedia::rpcResponse* resp) {
+               return service->sendRequest(ctx, req, resp);
+             }, this)));
+}
+
+fosscordInternals::Service::~Service() {
+}
+
+::grpc::Status fosscordInternals::Service::sendRequest(::grpc::ServerContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response) {
+  (void) context;
+  (void) request;
+  (void) response;
+  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+}
+
+
+}  // namespace fosscordMedia
+
diff --git a/src/protodefs/include/protos.grpc.pb.h b/src/protodefs/include/protos.grpc.pb.h
new file mode 100644
index 00000000..0f7f5881
--- /dev/null
+++ b/src/protodefs/include/protos.grpc.pb.h
@@ -0,0 +1,295 @@
+// Generated by the gRPC C++ plugin.
+// If you make any local change, they will be lost.
+// source: protos.proto
+// Original file comments:
+// LD_LIBRARY_PATH=/usr/local/lib protoc --proto_path="/data/fosscord-media/src/protodefs" --cpp_out="/data/fosscord-media/src/protodefs/include" --grpc_out="/data/fosscord-media/src/protodefs/include" --plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin protos.proto
+//
+#ifndef GRPC_protos_2eproto__INCLUDED
+#define GRPC_protos_2eproto__INCLUDED
+
+#include "protos.pb.h"
+
+#include <functional>
+#include <grpc/impl/codegen/port_platform.h>
+#include <grpcpp/impl/codegen/async_generic_service.h>
+#include <grpcpp/impl/codegen/async_stream.h>
+#include <grpcpp/impl/codegen/async_unary_call.h>
+#include <grpcpp/impl/codegen/client_callback.h>
+#include <grpcpp/impl/codegen/client_context.h>
+#include <grpcpp/impl/codegen/completion_queue.h>
+#include <grpcpp/impl/codegen/message_allocator.h>
+#include <grpcpp/impl/codegen/method_handler.h>
+#include <grpcpp/impl/codegen/proto_utils.h>
+#include <grpcpp/impl/codegen/rpc_method.h>
+#include <grpcpp/impl/codegen/server_callback.h>
+#include <grpcpp/impl/codegen/server_callback_handlers.h>
+#include <grpcpp/impl/codegen/server_context.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/stub_options.h>
+#include <grpcpp/impl/codegen/sync_stream.h>
+
+namespace fosscordMedia {
+
+class fosscordInternals final {
+ public:
+  static constexpr char const* service_full_name() {
+    return "fosscordMedia.fosscordInternals";
+  }
+  class StubInterface {
+   public:
+    virtual ~StubInterface() {}
+    virtual ::grpc::Status sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::fosscordMedia::rpcResponse* response) = 0;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::fosscordMedia::rpcResponse>> AsyncsendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::fosscordMedia::rpcResponse>>(AsyncsendRequestRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::fosscordMedia::rpcResponse>> PrepareAsyncsendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::fosscordMedia::rpcResponse>>(PrepareAsyncsendRequestRaw(context, request, cq));
+    }
+    class experimental_async_interface {
+     public:
+      virtual ~experimental_async_interface() {}
+      virtual void sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response, std::function<void(::grpc::Status)>) = 0;
+      #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      virtual void sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response, ::grpc::ClientUnaryReactor* reactor) = 0;
+      #else
+      virtual void sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0;
+      #endif
+    };
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+    typedef class experimental_async_interface async_interface;
+    #endif
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+    async_interface* async() { return experimental_async(); }
+    #endif
+    virtual class experimental_async_interface* experimental_async() { return nullptr; }
+  private:
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::fosscordMedia::rpcResponse>* AsyncsendRequestRaw(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientAsyncResponseReaderInterface< ::fosscordMedia::rpcResponse>* PrepareAsyncsendRequestRaw(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) = 0;
+  };
+  class Stub final : public StubInterface {
+   public:
+    Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
+    ::grpc::Status sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::fosscordMedia::rpcResponse* response) override;
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::fosscordMedia::rpcResponse>> AsyncsendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::fosscordMedia::rpcResponse>>(AsyncsendRequestRaw(context, request, cq));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::fosscordMedia::rpcResponse>> PrepareAsyncsendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::fosscordMedia::rpcResponse>>(PrepareAsyncsendRequestRaw(context, request, cq));
+    }
+    class experimental_async final :
+      public StubInterface::experimental_async_interface {
+     public:
+      void sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response, std::function<void(::grpc::Status)>) override;
+      #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      void sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response, ::grpc::ClientUnaryReactor* reactor) override;
+      #else
+      void sendRequest(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response, ::grpc::experimental::ClientUnaryReactor* reactor) override;
+      #endif
+     private:
+      friend class Stub;
+      explicit experimental_async(Stub* stub): stub_(stub) { }
+      Stub* stub() { return stub_; }
+      Stub* stub_;
+    };
+    class experimental_async_interface* experimental_async() override { return &async_stub_; }
+
+   private:
+    std::shared_ptr< ::grpc::ChannelInterface> channel_;
+    class experimental_async async_stub_{this};
+    ::grpc::ClientAsyncResponseReader< ::fosscordMedia::rpcResponse>* AsyncsendRequestRaw(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientAsyncResponseReader< ::fosscordMedia::rpcResponse>* PrepareAsyncsendRequestRaw(::grpc::ClientContext* context, const ::fosscordMedia::rpcRequest& request, ::grpc::CompletionQueue* cq) override;
+    const ::grpc::internal::RpcMethod rpcmethod_sendRequest_;
+  };
+  static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
+
+  class Service : public ::grpc::Service {
+   public:
+    Service();
+    virtual ~Service();
+    virtual ::grpc::Status sendRequest(::grpc::ServerContext* context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response);
+  };
+  template <class BaseClass>
+  class WithAsyncMethod_sendRequest : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithAsyncMethod_sendRequest() {
+      ::grpc::Service::MarkMethodAsync(0);
+    }
+    ~WithAsyncMethod_sendRequest() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status sendRequest(::grpc::ServerContext* /*context*/, const ::fosscordMedia::rpcRequest* /*request*/, ::fosscordMedia::rpcResponse* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestsendRequest(::grpc::ServerContext* context, ::fosscordMedia::rpcRequest* request, ::grpc::ServerAsyncResponseWriter< ::fosscordMedia::rpcResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  typedef WithAsyncMethod_sendRequest<Service > AsyncService;
+  template <class BaseClass>
+  class ExperimentalWithCallbackMethod_sendRequest : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    ExperimentalWithCallbackMethod_sendRequest() {
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      ::grpc::Service::
+    #else
+      ::grpc::Service::experimental().
+    #endif
+        MarkMethodCallback(0,
+          new ::grpc::internal::CallbackUnaryHandler< ::fosscordMedia::rpcRequest, ::fosscordMedia::rpcResponse>(
+            [this](
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+                   ::grpc::CallbackServerContext*
+    #else
+                   ::grpc::experimental::CallbackServerContext*
+    #endif
+                     context, const ::fosscordMedia::rpcRequest* request, ::fosscordMedia::rpcResponse* response) { return this->sendRequest(context, request, response); }));}
+    void SetMessageAllocatorFor_sendRequest(
+        ::grpc::experimental::MessageAllocator< ::fosscordMedia::rpcRequest, ::fosscordMedia::rpcResponse>* allocator) {
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0);
+    #else
+      ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(0);
+    #endif
+      static_cast<::grpc::internal::CallbackUnaryHandler< ::fosscordMedia::rpcRequest, ::fosscordMedia::rpcResponse>*>(handler)
+              ->SetMessageAllocator(allocator);
+    }
+    ~ExperimentalWithCallbackMethod_sendRequest() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status sendRequest(::grpc::ServerContext* /*context*/, const ::fosscordMedia::rpcRequest* /*request*/, ::fosscordMedia::rpcResponse* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+    virtual ::grpc::ServerUnaryReactor* sendRequest(
+      ::grpc::CallbackServerContext* /*context*/, const ::fosscordMedia::rpcRequest* /*request*/, ::fosscordMedia::rpcResponse* /*response*/)
+    #else
+    virtual ::grpc::experimental::ServerUnaryReactor* sendRequest(
+      ::grpc::experimental::CallbackServerContext* /*context*/, const ::fosscordMedia::rpcRequest* /*request*/, ::fosscordMedia::rpcResponse* /*response*/)
+    #endif
+      { return nullptr; }
+  };
+  #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+  typedef ExperimentalWithCallbackMethod_sendRequest<Service > CallbackService;
+  #endif
+
+  typedef ExperimentalWithCallbackMethod_sendRequest<Service > ExperimentalCallbackService;
+  template <class BaseClass>
+  class WithGenericMethod_sendRequest : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithGenericMethod_sendRequest() {
+      ::grpc::Service::MarkMethodGeneric(0);
+    }
+    ~WithGenericMethod_sendRequest() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status sendRequest(::grpc::ServerContext* /*context*/, const ::fosscordMedia::rpcRequest* /*request*/, ::fosscordMedia::rpcResponse* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+  };
+  template <class BaseClass>
+  class WithRawMethod_sendRequest : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawMethod_sendRequest() {
+      ::grpc::Service::MarkMethodRaw(0);
+    }
+    ~WithRawMethod_sendRequest() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status sendRequest(::grpc::ServerContext* /*context*/, const ::fosscordMedia::rpcRequest* /*request*/, ::fosscordMedia::rpcResponse* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestsendRequest(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
+  class ExperimentalWithRawCallbackMethod_sendRequest : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    ExperimentalWithRawCallbackMethod_sendRequest() {
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      ::grpc::Service::
+    #else
+      ::grpc::Service::experimental().
+    #endif
+        MarkMethodRawCallback(0,
+          new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>(
+            [this](
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+                   ::grpc::CallbackServerContext*
+    #else
+                   ::grpc::experimental::CallbackServerContext*
+    #endif
+                     context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->sendRequest(context, request, response); }));
+    }
+    ~ExperimentalWithRawCallbackMethod_sendRequest() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status sendRequest(::grpc::ServerContext* /*context*/, const ::fosscordMedia::rpcRequest* /*request*/, ::fosscordMedia::rpcResponse* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+    virtual ::grpc::ServerUnaryReactor* sendRequest(
+      ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/)
+    #else
+    virtual ::grpc::experimental::ServerUnaryReactor* sendRequest(
+      ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/)
+    #endif
+      { return nullptr; }
+  };
+  template <class BaseClass>
+  class WithStreamedUnaryMethod_sendRequest : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithStreamedUnaryMethod_sendRequest() {
+      ::grpc::Service::MarkMethodStreamed(0,
+        new ::grpc::internal::StreamedUnaryHandler<
+          ::fosscordMedia::rpcRequest, ::fosscordMedia::rpcResponse>(
+            [this](::grpc::ServerContext* context,
+                   ::grpc::ServerUnaryStreamer<
+                     ::fosscordMedia::rpcRequest, ::fosscordMedia::rpcResponse>* streamer) {
+                       return this->StreamedsendRequest(context,
+                         streamer);
+                  }));
+    }
+    ~WithStreamedUnaryMethod_sendRequest() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable regular version of this method
+    ::grpc::Status sendRequest(::grpc::ServerContext* /*context*/, const ::fosscordMedia::rpcRequest* /*request*/, ::fosscordMedia::rpcResponse* /*response*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    // replace default version of method with streamed unary
+    virtual ::grpc::Status StreamedsendRequest(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::fosscordMedia::rpcRequest,::fosscordMedia::rpcResponse>* server_unary_streamer) = 0;
+  };
+  typedef WithStreamedUnaryMethod_sendRequest<Service > StreamedUnaryService;
+  typedef Service SplitStreamedService;
+  typedef WithStreamedUnaryMethod_sendRequest<Service > StreamedService;
+};
+
+}  // namespace fosscordMedia
+
+
+#endif  // GRPC_protos_2eproto__INCLUDED
diff --git a/src/protodefs/include/protos.pb.cc b/src/protodefs/include/protos.pb.cc
new file mode 100644
index 00000000..1e88f216
--- /dev/null
+++ b/src/protodefs/include/protos.pb.cc
@@ -0,0 +1,487 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: protos.proto
+
+#include "protos.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
+namespace fosscordMedia {
+constexpr rpcRequest::rpcRequest(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : a_(0){}
+struct rpcRequestDefaultTypeInternal {
+  constexpr rpcRequestDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~rpcRequestDefaultTypeInternal() {}
+  union {
+    rpcRequest _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT rpcRequestDefaultTypeInternal _rpcRequest_default_instance_;
+constexpr rpcResponse::rpcResponse(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : b_(0){}
+struct rpcResponseDefaultTypeInternal {
+  constexpr rpcResponseDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~rpcResponseDefaultTypeInternal() {}
+  union {
+    rpcResponse _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT rpcResponseDefaultTypeInternal _rpcResponse_default_instance_;
+}  // namespace fosscordMedia
+static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_protos_2eproto[2];
+static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_protos_2eproto = nullptr;
+static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_protos_2eproto = nullptr;
+
+const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_protos_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::fosscordMedia::rpcRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::fosscordMedia::rpcRequest, a_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::fosscordMedia::rpcResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::fosscordMedia::rpcResponse, b_),
+};
+static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, -1, sizeof(::fosscordMedia::rpcRequest)},
+  { 6, -1, sizeof(::fosscordMedia::rpcResponse)},
+};
+
+static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::fosscordMedia::_rpcRequest_default_instance_),
+  reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::fosscordMedia::_rpcResponse_default_instance_),
+};
+
+const char descriptor_table_protodef_protos_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
+  "\n\014protos.proto\022\rfosscordMedia\"\027\n\nrpcRequ"
+  "est\022\t\n\001a\030\001 \001(\005\"\030\n\013rpcResponse\022\t\n\001b\030\001 \001(\005"
+  "2[\n\021fosscordInternals\022F\n\013sendRequest\022\031.f"
+  "osscordMedia.rpcRequest\032\032.fosscordMedia."
+  "rpcResponse\"\000b\006proto3"
+  ;
+static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_protos_2eproto_once;
+const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_protos_2eproto = {
+  false, false, 181, descriptor_table_protodef_protos_2eproto, "protos.proto", 
+  &descriptor_table_protos_2eproto_once, nullptr, 0, 2,
+  schemas, file_default_instances, TableStruct_protos_2eproto::offsets,
+  file_level_metadata_protos_2eproto, file_level_enum_descriptors_protos_2eproto, file_level_service_descriptors_protos_2eproto,
+};
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_protos_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_protos_2eproto);
+  return descriptor_table_protos_2eproto.file_level_metadata[index];
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_protos_2eproto(&descriptor_table_protos_2eproto);
+namespace fosscordMedia {
+
+// ===================================================================
+
+class rpcRequest::_Internal {
+ public:
+};
+
+rpcRequest::rpcRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:fosscordMedia.rpcRequest)
+}
+rpcRequest::rpcRequest(const rpcRequest& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message() {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  a_ = from.a_;
+  // @@protoc_insertion_point(copy_constructor:fosscordMedia.rpcRequest)
+}
+
+void rpcRequest::SharedCtor() {
+a_ = 0;
+}
+
+rpcRequest::~rpcRequest() {
+  // @@protoc_insertion_point(destructor:fosscordMedia.rpcRequest)
+  SharedDtor();
+  _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+void rpcRequest::SharedDtor() {
+  GOOGLE_DCHECK(GetArena() == nullptr);
+}
+
+void rpcRequest::ArenaDtor(void* object) {
+  rpcRequest* _this = reinterpret_cast< rpcRequest* >(object);
+  (void)_this;
+}
+void rpcRequest::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void rpcRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+
+void rpcRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:fosscordMedia.rpcRequest)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  a_ = 0;
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* rpcRequest::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  while (!ctx->Done(&ptr)) {
+    ::PROTOBUF_NAMESPACE_ID::uint32 tag;
+    ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+    CHK_(ptr);
+    switch (tag >> 3) {
+      // int32 a = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) {
+          a_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+          CHK_(ptr);
+        } else goto handle_unusual;
+        continue;
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->SetLastTag(tag);
+          goto success;
+        }
+        ptr = UnknownFieldParse(tag,
+            _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+            ptr, ctx);
+        CHK_(ptr != nullptr);
+        continue;
+      }
+    }  // switch
+  }  // while
+success:
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto success;
+#undef CHK_
+}
+
+::PROTOBUF_NAMESPACE_ID::uint8* rpcRequest::_InternalSerialize(
+    ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:fosscordMedia.rpcRequest)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // int32 a = 1;
+  if (this->a() != 0) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_a(), target);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:fosscordMedia.rpcRequest)
+  return target;
+}
+
+size_t rpcRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:fosscordMedia.rpcRequest)
+  size_t total_size = 0;
+
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // int32 a = 1;
+  if (this->a() != 0) {
+    total_size += 1 +
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
+        this->_internal_a());
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize(
+        _internal_metadata_, total_size, &_cached_size_);
+  }
+  int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void rpcRequest::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:fosscordMedia.rpcRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const rpcRequest* source =
+      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<rpcRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:fosscordMedia.rpcRequest)
+    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:fosscordMedia.rpcRequest)
+    MergeFrom(*source);
+  }
+}
+
+void rpcRequest::MergeFrom(const rpcRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:fosscordMedia.rpcRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.a() != 0) {
+    _internal_set_a(from._internal_a());
+  }
+}
+
+void rpcRequest::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:fosscordMedia.rpcRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void rpcRequest::CopyFrom(const rpcRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:fosscordMedia.rpcRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool rpcRequest::IsInitialized() const {
+  return true;
+}
+
+void rpcRequest::InternalSwap(rpcRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  swap(a_, other->a_);
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata rpcRequest::GetMetadata() const {
+  return GetMetadataStatic();
+}
+
+
+// ===================================================================
+
+class rpcResponse::_Internal {
+ public:
+};
+
+rpcResponse::rpcResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:fosscordMedia.rpcResponse)
+}
+rpcResponse::rpcResponse(const rpcResponse& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message() {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  b_ = from.b_;
+  // @@protoc_insertion_point(copy_constructor:fosscordMedia.rpcResponse)
+}
+
+void rpcResponse::SharedCtor() {
+b_ = 0;
+}
+
+rpcResponse::~rpcResponse() {
+  // @@protoc_insertion_point(destructor:fosscordMedia.rpcResponse)
+  SharedDtor();
+  _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+void rpcResponse::SharedDtor() {
+  GOOGLE_DCHECK(GetArena() == nullptr);
+}
+
+void rpcResponse::ArenaDtor(void* object) {
+  rpcResponse* _this = reinterpret_cast< rpcResponse* >(object);
+  (void)_this;
+}
+void rpcResponse::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void rpcResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+
+void rpcResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:fosscordMedia.rpcResponse)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  b_ = 0;
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* rpcResponse::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  while (!ctx->Done(&ptr)) {
+    ::PROTOBUF_NAMESPACE_ID::uint32 tag;
+    ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+    CHK_(ptr);
+    switch (tag >> 3) {
+      // int32 b = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) {
+          b_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+          CHK_(ptr);
+        } else goto handle_unusual;
+        continue;
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->SetLastTag(tag);
+          goto success;
+        }
+        ptr = UnknownFieldParse(tag,
+            _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+            ptr, ctx);
+        CHK_(ptr != nullptr);
+        continue;
+      }
+    }  // switch
+  }  // while
+success:
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto success;
+#undef CHK_
+}
+
+::PROTOBUF_NAMESPACE_ID::uint8* rpcResponse::_InternalSerialize(
+    ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:fosscordMedia.rpcResponse)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // int32 b = 1;
+  if (this->b() != 0) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_b(), target);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:fosscordMedia.rpcResponse)
+  return target;
+}
+
+size_t rpcResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:fosscordMedia.rpcResponse)
+  size_t total_size = 0;
+
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // int32 b = 1;
+  if (this->b() != 0) {
+    total_size += 1 +
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
+        this->_internal_b());
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize(
+        _internal_metadata_, total_size, &_cached_size_);
+  }
+  int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void rpcResponse::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:fosscordMedia.rpcResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const rpcResponse* source =
+      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<rpcResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:fosscordMedia.rpcResponse)
+    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:fosscordMedia.rpcResponse)
+    MergeFrom(*source);
+  }
+}
+
+void rpcResponse::MergeFrom(const rpcResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:fosscordMedia.rpcResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.b() != 0) {
+    _internal_set_b(from._internal_b());
+  }
+}
+
+void rpcResponse::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:fosscordMedia.rpcResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void rpcResponse::CopyFrom(const rpcResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:fosscordMedia.rpcResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool rpcResponse::IsInitialized() const {
+  return true;
+}
+
+void rpcResponse::InternalSwap(rpcResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  swap(b_, other->b_);
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata rpcResponse::GetMetadata() const {
+  return GetMetadataStatic();
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace fosscordMedia
+PROTOBUF_NAMESPACE_OPEN
+template<> PROTOBUF_NOINLINE ::fosscordMedia::rpcRequest* Arena::CreateMaybeMessage< ::fosscordMedia::rpcRequest >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::fosscordMedia::rpcRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::fosscordMedia::rpcResponse* Arena::CreateMaybeMessage< ::fosscordMedia::rpcResponse >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::fosscordMedia::rpcResponse >(arena);
+}
+PROTOBUF_NAMESPACE_CLOSE
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
diff --git a/src/protodefs/include/protos.pb.h b/src/protodefs/include/protos.pb.h
new file mode 100644
index 00000000..bc310678
--- /dev/null
+++ b/src/protodefs/include/protos.pb.h
@@ -0,0 +1,413 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: protos.proto
+
+#ifndef GOOGLE_PROTOBUF_INCLUDED_protos_2eproto
+#define GOOGLE_PROTOBUF_INCLUDED_protos_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3015000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3015008 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata_lite.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_protos_2eproto
+PROTOBUF_NAMESPACE_OPEN
+namespace internal {
+class AnyMetadata;
+}  // namespace internal
+PROTOBUF_NAMESPACE_CLOSE
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_protos_2eproto {
+  static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[2]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
+  static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
+  static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
+};
+extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_protos_2eproto;
+::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_protos_2eproto_metadata_getter(int index);
+namespace fosscordMedia {
+class rpcRequest;
+struct rpcRequestDefaultTypeInternal;
+extern rpcRequestDefaultTypeInternal _rpcRequest_default_instance_;
+class rpcResponse;
+struct rpcResponseDefaultTypeInternal;
+extern rpcResponseDefaultTypeInternal _rpcResponse_default_instance_;
+}  // namespace fosscordMedia
+PROTOBUF_NAMESPACE_OPEN
+template<> ::fosscordMedia::rpcRequest* Arena::CreateMaybeMessage<::fosscordMedia::rpcRequest>(Arena*);
+template<> ::fosscordMedia::rpcResponse* Arena::CreateMaybeMessage<::fosscordMedia::rpcResponse>(Arena*);
+PROTOBUF_NAMESPACE_CLOSE
+namespace fosscordMedia {
+
+// ===================================================================
+
+class rpcRequest PROTOBUF_FINAL :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:fosscordMedia.rpcRequest) */ {
+ public:
+  inline rpcRequest() : rpcRequest(nullptr) {}
+  virtual ~rpcRequest();
+  explicit constexpr rpcRequest(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+  rpcRequest(const rpcRequest& from);
+  rpcRequest(rpcRequest&& from) noexcept
+    : rpcRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline rpcRequest& operator=(const rpcRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline rpcRequest& operator=(rpcRequest&& from) noexcept {
+    if (GetArena() == from.GetArena()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return GetMetadataStatic().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return GetMetadataStatic().reflection;
+  }
+  static const rpcRequest& default_instance() {
+    return *internal_default_instance();
+  }
+  static inline const rpcRequest* internal_default_instance() {
+    return reinterpret_cast<const rpcRequest*>(
+               &_rpcRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  friend void swap(rpcRequest& a, rpcRequest& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(rpcRequest* other) {
+    if (other == this) return;
+    if (GetArena() == other->GetArena()) {
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(rpcRequest* other) {
+    if (other == this) return;
+    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline rpcRequest* New() const final {
+    return CreateMaybeMessage<rpcRequest>(nullptr);
+  }
+
+  rpcRequest* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
+    return CreateMaybeMessage<rpcRequest>(arena);
+  }
+  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void CopyFrom(const rpcRequest& from);
+  void MergeFrom(const rpcRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize(
+      ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  inline void SharedCtor();
+  inline void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(rpcRequest* other);
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+    return "fosscordMedia.rpcRequest";
+  }
+  protected:
+  explicit rpcRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+  private:
+  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
+    return ::descriptor_table_protos_2eproto_metadata_getter(kIndexInFileMessages);
+  }
+
+  public:
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kAFieldNumber = 1,
+  };
+  // int32 a = 1;
+  void clear_a();
+  ::PROTOBUF_NAMESPACE_ID::int32 a() const;
+  void set_a(::PROTOBUF_NAMESPACE_ID::int32 value);
+  private:
+  ::PROTOBUF_NAMESPACE_ID::int32 _internal_a() const;
+  void _internal_set_a(::PROTOBUF_NAMESPACE_ID::int32 value);
+  public:
+
+  // @@protoc_insertion_point(class_scope:fosscordMedia.rpcRequest)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  ::PROTOBUF_NAMESPACE_ID::int32 a_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_protos_2eproto;
+};
+// -------------------------------------------------------------------
+
+class rpcResponse PROTOBUF_FINAL :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:fosscordMedia.rpcResponse) */ {
+ public:
+  inline rpcResponse() : rpcResponse(nullptr) {}
+  virtual ~rpcResponse();
+  explicit constexpr rpcResponse(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+  rpcResponse(const rpcResponse& from);
+  rpcResponse(rpcResponse&& from) noexcept
+    : rpcResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline rpcResponse& operator=(const rpcResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline rpcResponse& operator=(rpcResponse&& from) noexcept {
+    if (GetArena() == from.GetArena()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return GetMetadataStatic().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return GetMetadataStatic().reflection;
+  }
+  static const rpcResponse& default_instance() {
+    return *internal_default_instance();
+  }
+  static inline const rpcResponse* internal_default_instance() {
+    return reinterpret_cast<const rpcResponse*>(
+               &_rpcResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  friend void swap(rpcResponse& a, rpcResponse& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(rpcResponse* other) {
+    if (other == this) return;
+    if (GetArena() == other->GetArena()) {
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(rpcResponse* other) {
+    if (other == this) return;
+    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline rpcResponse* New() const final {
+    return CreateMaybeMessage<rpcResponse>(nullptr);
+  }
+
+  rpcResponse* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
+    return CreateMaybeMessage<rpcResponse>(arena);
+  }
+  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void CopyFrom(const rpcResponse& from);
+  void MergeFrom(const rpcResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize(
+      ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  inline void SharedCtor();
+  inline void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(rpcResponse* other);
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+    return "fosscordMedia.rpcResponse";
+  }
+  protected:
+  explicit rpcResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+  private:
+  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
+    return ::descriptor_table_protos_2eproto_metadata_getter(kIndexInFileMessages);
+  }
+
+  public:
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kBFieldNumber = 1,
+  };
+  // int32 b = 1;
+  void clear_b();
+  ::PROTOBUF_NAMESPACE_ID::int32 b() const;
+  void set_b(::PROTOBUF_NAMESPACE_ID::int32 value);
+  private:
+  ::PROTOBUF_NAMESPACE_ID::int32 _internal_b() const;
+  void _internal_set_b(::PROTOBUF_NAMESPACE_ID::int32 value);
+  public:
+
+  // @@protoc_insertion_point(class_scope:fosscordMedia.rpcResponse)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  ::PROTOBUF_NAMESPACE_ID::int32 b_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_protos_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// rpcRequest
+
+// int32 a = 1;
+inline void rpcRequest::clear_a() {
+  a_ = 0;
+}
+inline ::PROTOBUF_NAMESPACE_ID::int32 rpcRequest::_internal_a() const {
+  return a_;
+}
+inline ::PROTOBUF_NAMESPACE_ID::int32 rpcRequest::a() const {
+  // @@protoc_insertion_point(field_get:fosscordMedia.rpcRequest.a)
+  return _internal_a();
+}
+inline void rpcRequest::_internal_set_a(::PROTOBUF_NAMESPACE_ID::int32 value) {
+  
+  a_ = value;
+}
+inline void rpcRequest::set_a(::PROTOBUF_NAMESPACE_ID::int32 value) {
+  _internal_set_a(value);
+  // @@protoc_insertion_point(field_set:fosscordMedia.rpcRequest.a)
+}
+
+// -------------------------------------------------------------------
+
+// rpcResponse
+
+// int32 b = 1;
+inline void rpcResponse::clear_b() {
+  b_ = 0;
+}
+inline ::PROTOBUF_NAMESPACE_ID::int32 rpcResponse::_internal_b() const {
+  return b_;
+}
+inline ::PROTOBUF_NAMESPACE_ID::int32 rpcResponse::b() const {
+  // @@protoc_insertion_point(field_get:fosscordMedia.rpcResponse.b)
+  return _internal_b();
+}
+inline void rpcResponse::_internal_set_b(::PROTOBUF_NAMESPACE_ID::int32 value) {
+  
+  b_ = value;
+}
+inline void rpcResponse::set_b(::PROTOBUF_NAMESPACE_ID::int32 value) {
+  _internal_set_b(value);
+  // @@protoc_insertion_point(field_set:fosscordMedia.rpcResponse.b)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace fosscordMedia
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_protos_2eproto
diff --git a/src/protodefs/protos.proto b/src/protodefs/protos.proto
new file mode 100644
index 00000000..a8c9f845
--- /dev/null
+++ b/src/protodefs/protos.proto
@@ -0,0 +1,24 @@
+syntax = "proto3";
+
+package fosscordMedia;
+
+service fosscordInternals{
+	rpc requestProtocol(voiceRequest) returns (voiceAnswer) {}
+}
+
+message voiceRequest{ //OP1 from gw
+	uint64 userid = 1;
+	uint64 guildid = 2;
+	string IP=3;
+	uint32 port=4;
+	string protocol=5;
+	string rtcConnectionId=6;
+}
+
+message voiceAnswer{//OP2 and OP4 to gw
+	string ip=1;
+	uint32 port=3;
+	repeated string modes=2;
+	int32 ssrc=4;
+	string audioCodec=5;
+}
\ No newline at end of file
diff --git a/src/rpcStub.cpp b/src/rpcStub.cpp
new file mode 100644
index 00000000..3d848924
--- /dev/null
+++ b/src/rpcStub.cpp
@@ -0,0 +1,24 @@
+#include "rpcStub.hpp"
+
+class fossCordInternalsImpl final : public fosscordMedia::fosscordInternals::Service{
+	grpc::Status sendRequest(
+		grpc::ServerContext* ctx,
+		const fosscordMedia::rpcRequest* req,
+		fosscordMedia::rpcResponse* resp
+	) override{
+		resp->set_b(333);
+		return grpc::Status::OK;
+	}
+
+};
+
+rpcStub::rpcStub(int port){
+	grpc::ServerBuilder builder;
+
+	fossCordInternalsImpl* service;
+	builder.AddListeningPort("0.0.0.0:8057", grpc::InsecureServerCredentials() );
+	builder.RegisterService(service);
+
+	std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
+	std::cout << "Server listening on port 8057 " << std::endl;
+}
\ No newline at end of file
diff --git a/src/rpcStub.hpp b/src/rpcStub.hpp
new file mode 100644
index 00000000..9da80cda
--- /dev/null
+++ b/src/rpcStub.hpp
@@ -0,0 +1,10 @@
+#include <grpc++/grpc++.h>
+#include "protodefs/include/protos.grpc.pb.h"
+
+class rpcStub{
+	public:
+		rpcStub(int port);
+	private:
+		std::unique_ptr<grpc::Server> server;
+
+};
\ No newline at end of file
diff --git a/src/rtcPeerHandler.cpp b/src/rtcPeerHandler.cpp
new file mode 100644
index 00000000..4696c4c7
--- /dev/null
+++ b/src/rtcPeerHandler.cpp
@@ -0,0 +1,57 @@
+#include "rtcPeerHandler.hpp"
+rtcPeerHandler::rtcPeerHandler()
+{
+	rtc::InitLogger(rtc::LogLevel::Verbose, NULL);
+}
+
+void rtcPeerHandler::initiateConnection(std::string peerIP, int peerPort)
+{
+	//Socket connection between client and server
+	SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
+	sockaddr_in addr;
+	addr.sin_addr.s_addr = inet_addr(peerIP.c_str());
+	addr.sin_port = htons(peerPort);
+	addr.sin_family = AF_INET;
+
+	rtc::Configuration conf;
+	conf.enableIceTcp = false;
+	conf.disableAutoNegotiation = false;
+
+	auto pc = std::make_shared<rtc::PeerConnection>(conf);
+
+	rtc::Description::Audio media("audio", rtc::Description::Direction::SendRecv);
+	media.addOpusCodec(96);
+	media.setBitrate(64); 
+
+
+	auto track = pc->addTrack(media);
+
+	//auto session = std::make_shared<rtc::MediaHandler>();
+
+	//track->setMediaHandler(session);
+
+	rtc::Reliability rtcRel;
+	rtcRel.unordered = true;
+	rtcRel.type = rtc::Reliability::Type::Timed;
+	rtcRel.rexmit =  500;
+
+	rtc::DataChannelInit rtcConf;
+	rtcConf.reliability = rtcRel;
+	rtcConf.negotiated = false;
+
+	pc->onStateChange([](rtc::PeerConnection::State state) {
+        std::cout << "State: " << state << std::endl;
+        if (state == rtc::PeerConnection::State::Disconnected ||
+            state == rtc::PeerConnection::State::Failed ||
+            state == rtc::PeerConnection::State::Closed) {
+            // remove disconnected client
+        }
+    });
+
+	pc->onGatheringStateChange(
+		[](rtc::PeerConnection::GatheringState state) { std::cout << "Gathering State: " << state << std::endl; });
+
+
+	pc->createDataChannel("Fosscord voice connection", rtcConf);
+}
+   
\ No newline at end of file
diff --git a/src/rtcPeerHandler.hpp b/src/rtcPeerHandler.hpp
new file mode 100644
index 00000000..030f41fa
--- /dev/null
+++ b/src/rtcPeerHandler.hpp
@@ -0,0 +1,29 @@
+#include "libdatachannel/rtc.hpp"
+#include <iostream>
+#include <memory>
+#include "nlohmann/json.hpp"
+#include <array>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+#include <arpa/inet.h>
+typedef int SOCKET;
+#endif
+
+using json = nlohmann::json;
+
+class rtcPeerHandler{
+public:
+	rtcPeerHandler();
+	void initiateConnection(std::string peerIP, int peerPort);
+
+	struct client
+	{
+		std::shared_ptr<rtc::PeerConnection> pc;
+		std::shared_ptr<rtc::DataChannel> dc;
+	};
+
+private:
+	std::map<SOCKET, client> clients;
+};
\ No newline at end of file
diff --git a/src/rtcServer.hpp b/src/rtcServer.hpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/rtcServer.hpp