Skip to content

Commit

Permalink
dronecore_server: make a library out of the grpc server
Browse files Browse the repository at this point in the history
* Required for some platforms (e.g. iOS)
* Rename dronecore_server into libdronecore_backend and backend_bin
* Use smart pointers and references instead of pointers
  • Loading branch information
JonasVautherin committed Feb 15, 2018
1 parent e57829d commit 5e17e66
Show file tree
Hide file tree
Showing 12 changed files with 224 additions and 168 deletions.
2 changes: 1 addition & 1 deletion core/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ void Device::set_disconnected()
_parent->notify_on_timeout(_target_uuid);

// Let's reset the flag hope again for the next time we see this target.
_target_uuid_initialized = 0;
_target_uuid_initialized = false;
}

{
Expand Down
92 changes: 31 additions & 61 deletions grpc/server/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,67 +1,33 @@
cmake_minimum_required(VERSION 2.8)

file(STRINGS ${PLUGINS_DIR}/plugins.conf PLUGINS_LIST)
set(COMPONENTS_LIST core action mission telemetry)

set(PROTOC_BINARY ${CMAKE_BINARY_DIR}/../default/third_party/protobuf/bin/protoc)
set(GRPC_CPP_PLUGIN_BINARY ${CMAKE_BINARY_DIR}/../default/third_party/grpc/bin/grpc_cpp_plugin)
include(cmake/compile_proto.cmake)

if(NOT EXISTS ${PROTOC_BINARY} OR NOT EXISTS ${GRPC_CPP_PLUGIN_BINARY})
message(FATAL_ERROR "Could not find 'protoc' or 'grpc_cpp_plugin' in the 'default' build folder. Please build for your host first (`make BUILD_DRONECORESERVER=YES default`).")
endif()
foreach(COMPONENT_NAME ${COMPONENTS_LIST})
compile_proto_pb(${COMPONENT_NAME} PB_COMPILED_SOURCE)
list(APPEND PB_COMPILED_SOURCES ${PB_COMPILED_SOURCE})

add_custom_command(OUTPUT core/core.grpc.pb.cc
COMMAND ${PROTOC_BINARY}
-I ${PROTO_DIR}
--grpc_out=.
--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN_BINARY}
${PROTO_DIR}/core/core.proto;
)

add_custom_command(OUTPUT core/core.pb.cc
COMMAND ${PROTOC_BINARY}
-I ${PROTO_DIR}
--cpp_out=.
${PROTO_DIR}/core/core.proto
)

foreach(PLUGIN ${PLUGINS_LIST})
add_custom_command(OUTPUT ${PLUGIN}/${PLUGIN}.grpc.pb.cc
COMMAND ${PROTOC_BINARY}
-I ${PROTO_DIR}
--grpc_out=.
--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN_BINARY}
--cpp_out=.
${PROTO_DIR}/${PLUGIN}/${PLUGIN}.proto
)
endforeach()

foreach(PLUGIN ${PLUGINS_LIST})
add_custom_command(OUTPUT ${PLUGIN}/${PLUGIN}.pb.cc
COMMAND ${PROTOC_BINARY}
-I ${PROTO_DIR}
--cpp_out=.
${PROTO_DIR}/${PLUGIN}/${PLUGIN}.proto
)
compile_proto_grpc(${COMPONENT_NAME} GRPC_COMPILED_SOURCE)
list(APPEND GRPC_COMPILED_SOURCES ${GRPC_COMPILED_SOURCE})
endforeach()

set(PLUGINS_SRC dronecore_server.cpp core/core.pb.cc core/core.grpc.pb.cc)
foreach(PLUGIN ${PLUGINS_LIST})
list(APPEND PLUGINS_SRC ${PLUGIN}/${PLUGIN}.pb.cc)
list(APPEND PLUGINS_SRC ${PLUGIN}/${PLUGIN}.grpc.pb.cc)
endforeach()

add_executable(dronecore_server ${PLUGINS_SRC})
add_library(backend
backend.cpp
${GRPC_COMPILED_SOURCES}
${PB_COMPILED_SOURCES}
)

target_compile_options(
dronecore_server
PUBLIC
-Wno-unused-parameter
-Wno-shadow
target_link_libraries(backend
dronecore
dronecore_action
dronecore_mission
dronecore_telemetry
gRPC::grpc++
)

target_include_directories(
dronecore_server
PUBLIC
target_include_directories(backend
PRIVATE
${CMAKE_SOURCE_DIR}/core
${CMAKE_SOURCE_DIR}/plugins/action
${CMAKE_SOURCE_DIR}/plugins/mission
Expand All @@ -70,12 +36,16 @@ target_include_directories(
${PLUGINS_DIR}
)

target_link_libraries(
dronecore_server
add_executable(backend_bin
dronecore_server.cpp
)

target_link_libraries(backend_bin
backend
dronecore
dronecore_action
dronecore_mission
dronecore_telemetry
gRPC::grpc++
dl
)

target_include_directories(backend_bin
PRIVATE
${CMAKE_SOURCE_DIR}/core
)
104 changes: 104 additions & 0 deletions grpc/server/src/backend.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include "backend.h"

#include <grpc/grpc.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/security/server_credentials.h>

#include "action/actionrpc_impl.h"
#include "core/corerpc_impl.h"
#include "log.h"
#include "mission/missionrpc_impl.h"
#include "telemetry/telemetryrpc_impl.h"

namespace dronecore::backend {

int DroneCoreBackend::run(const int mavlink_listen_port)
{
if (int returnCode = connectToVehicle(mavlink_listen_port) != 0) {
return returnCode;
}

grpc::ServerBuilder builder;
setupPort(builder);

CoreServiceImpl core(dc);
builder.RegisterService(&core);

Action action(&dc.device());
ActionServiceImpl actionService(action);
builder.RegisterService(&actionService);

Mission mission(&dc.device());
MissionServiceImpl missionService(mission);
builder.RegisterService(&missionService);

Telemetry telemetry(&dc.device());
TelemetryServiceImpl telemetryService(telemetry);
builder.RegisterService(&telemetryService);

server = builder.BuildAndStart();
LogInfo() << "Server started";
server->Wait();

return 0;
}

int DroneCoreBackend::connectToVehicle(const int port)
{
if (!addUdpConnection(port)) {
return 1;
}

logUUIDOnTimeout();
waitForDiscovery();
}

bool DroneCoreBackend::addUdpConnection(const int port)
{
dronecore::DroneCore::ConnectionResult connection_result = dc.add_udp_connection(port);

if (connection_result != DroneCore::ConnectionResult::SUCCESS) {
LogErr() << "Connection failed: " << DroneCore::connection_result_str(connection_result);
return false;
}

return true;
}

void DroneCoreBackend::logUUIDOnTimeout()
{
dc.register_on_timeout([](uint64_t uuid) {
LogInfo() << "Device timed out [UUID: " << uuid << "]";
});
}

void DroneCoreBackend::waitForDiscovery()
{
LogInfo() << "Waiting to discover device...";
auto discoveryFuture = wrapped_register_on_discover();
discoveryFuture.wait();
LogInfo() << "Device discovered [UUID: " << discoveryFuture.get() << "]";
}

std::future<uint64_t> DroneCoreBackend::wrapped_register_on_discover()
{
auto promise = std::make_shared<std::promise<uint64_t>>();
auto future = promise->get_future();

dc.register_on_discover([promise](uint64_t uuid) {
promise->set_value(uuid);
});

return future;
}

void DroneCoreBackend::setupPort(grpc::ServerBuilder &builder)
{
std::string server_address("0.0.0.0:50051");
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
LogInfo() << "Server set to listen on " << server_address;
}

} //namespace dronecore::backend
31 changes: 31 additions & 0 deletions grpc/server/src/backend.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <future>
#include <grpc++/server.h>
#include <memory>

#include "dronecore.h"

namespace dronecore::backend {

class DroneCoreBackend
{
public:
DroneCoreBackend() {}
~DroneCoreBackend() {}

int run(const int mavlink_listen_port = 14540);

private:
int connectToVehicle(int port);
bool addUdpConnection(int port);
void logUUIDOnTimeout();
void waitForDiscovery();
std::future<uint64_t> wrapped_register_on_discover();

int runServer();
void setupPort(grpc::ServerBuilder &builder);

dronecore::DroneCore dc;
std::unique_ptr<grpc::Server> server;
};

} // namespace dronecore::backend
30 changes: 30 additions & 0 deletions grpc/server/src/cmake/compile_proto.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
set(PROTOC_BINARY ${CMAKE_BINARY_DIR}/../default/third_party/protobuf/bin/protoc)
set(GRPC_CPP_PLUGIN_BINARY ${CMAKE_BINARY_DIR}/../default/third_party/grpc/bin/grpc_cpp_plugin)

if(NOT EXISTS ${PROTOC_BINARY} OR NOT EXISTS ${GRPC_CPP_PLUGIN_BINARY})
message(FATAL_ERROR "Could not find 'protoc' or 'grpc_cpp_plugin' in the 'default' build folder. Please build for your host first (`make BUILD_DRONECORESERVER=YES default`).")
endif()

function(compile_proto_pb COMPONENT_NAME PB_COMPILED_SOURCE)
add_custom_command(OUTPUT ${COMPONENT_NAME}/${COMPONENT_NAME}.pb.cc
COMMAND ${PROTOC_BINARY}
-I ${PROTO_DIR}
--cpp_out=.
${PROTO_DIR}/${COMPONENT_NAME}/${COMPONENT_NAME}.proto
)

set(PB_COMPILED_SOURCE ${COMPONENT_NAME}/${COMPONENT_NAME}.pb.cc PARENT_SCOPE)
endfunction()

function(compile_proto_grpc COMPONENT_NAME GRPC_COMPILED_SOURCES)
add_custom_command(OUTPUT ${COMPONENT_NAME}/${COMPONENT_NAME}.grpc.pb.cc
COMMAND ${PROTOC_BINARY}
-I ${PROTO_DIR}
--grpc_out=.
--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN_BINARY}
--cpp_out=.
${PROTO_DIR}/${COMPONENT_NAME}/${COMPONENT_NAME}.proto
)

set(GRPC_COMPILED_SOURCE ${COMPONENT_NAME}/${COMPONENT_NAME}.grpc.pb.cc PARENT_SCOPE)
endfunction()
12 changes: 5 additions & 7 deletions grpc/server/src/core/corerpc_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,16 @@ using namespace dronecore;
class CoreServiceImpl final: public rpc::core::CoreService::Service
{
public:
CoreServiceImpl(DroneCore *dc_obj)
{
dc = dc_obj;
}
CoreServiceImpl(DroneCore &dc)
: dc(dc) {}

Status SubscribeDevices(ServerContext *context,
const rpc::core::SubscribeDevicesRequest *request,
ServerWriter<rpc::core::Device> *writer) override
{
std::vector<uint64_t> list = dc->device_uuids();
std::vector<uint64_t> list = dc.device_uuids();

for (auto uuid : dc->device_uuids()) {
for (auto uuid : dc.device_uuids()) {
auto *rpc_uuid = new rpc::core::UUID();
rpc_uuid->set_value(uuid);

Expand All @@ -34,5 +32,5 @@ class CoreServiceImpl final: public rpc::core::CoreService::Service
}

private:
DroneCore *dc;
DroneCore &dc;
};
71 changes: 3 additions & 68 deletions grpc/server/src/dronecore_server.cpp
Original file line number Diff line number Diff line change
@@ -1,72 +1,7 @@
#include <iostream>
#include <fstream>
#include <thread>
#include <chrono>
#include <cstdint>
#include <future>

#include <grpc/grpc.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/security/server_credentials.h>

#include "dronecore.h"
#include "log.h"
#include "action/actionrpc_impl.h"
#include "core/core.grpc.pb.h"
#include "core/corerpc_impl.h"
#include "mission/missionrpc_impl.h"
#include "telemetry/telemetryrpc_impl.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::ServerReader;
using grpc::ServerReaderWriter;
using grpc::Status;

using namespace dronecore;
using namespace std::placeholders;

static DroneCore dc;

template<typename T> ::grpc::Service *createInstances(DroneCore *dc_obj) { return new T(dc_obj); }

int RunServer()
{
DroneCore::ConnectionResult connection_result = dc.add_udp_connection(14540);

if (connection_result != DroneCore::ConnectionResult::SUCCESS) {
LogErr() << "Connection failed: " << DroneCore::connection_result_str(connection_result);
return 1;
}

LogInfo() << "Waiting to discover device...";
dc.register_on_discover([](uint64_t uuid) {
LogInfo() << "Device discovered [UUID: " << uuid << "]";
});
dc.register_on_timeout([](uint64_t uuid) {
LogInfo() << "Device timed out [UUID: " << uuid << "]";
});

std::string server_address("0.0.0.0:50051");

ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());

CoreServiceImpl service(&dc);
builder.RegisterService(&service);
builder.RegisterService(createInstances<ActionServiceImpl>(&dc));
builder.RegisterService(createInstances<TelemetryServiceImpl>(&dc));
builder.RegisterService(createInstances<MissionServiceImpl>(&dc));

std::unique_ptr<Server> server(builder.BuildAndStart());
LogInfo() << "Server listening on " << server_address;
server->Wait();
}
#include "backend.h"

int main(int argc, char **argv)
{
return RunServer();
dronecore::backend::DroneCoreBackend backend;
backend.run();
}
Loading

0 comments on commit 5e17e66

Please sign in to comment.