.. _program_listing_file_foxglove_src_server_service.cpp: Program Listing for File service.cpp ==================================== |exhale_lsh| :ref:`Return to documentation for file ` (``foxglove/src/server/service.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include #include #include using std::string_view_literals::operator""sv; namespace foxglove { void ServiceMessageSchema::writeTo(foxglove_service_message_schema* c) const noexcept { c->encoding = {this->encoding.data(), this->encoding.length()}; c->schema.name = {this->schema.name.data(), this->schema.name.length()}; c->schema.encoding = {this->schema.encoding.data(), this->schema.encoding.length()}; c->schema.data = reinterpret_cast(this->schema.data); c->schema.data_len = this->schema.data_len; } void ServiceSchema::writeTo( foxglove_service_schema* c, std::array& msg_schemas ) const noexcept { c->name = {this->name.data(), this->name.length()}; if (this->request.has_value()) { this->request->writeTo(msg_schemas.data()); c->request = msg_schemas.data(); } else { c->request = nullptr; } if (this->response.has_value()) { this->response->writeTo(&msg_schemas[1]); c->response = &msg_schemas[1]; } else { c->response = nullptr; } } ServiceRequest::ServiceRequest(const foxglove_service_request* r) noexcept : service_name(r->service_name.data, r->service_name.len) , client_id(r->client_id) , call_id(r->call_id) , encoding(r->encoding.data, r->encoding.len) , payload( reinterpret_cast(r->payload.data), reinterpret_cast(r->payload.data + r->payload.len) ) {} void ServiceResponder::Deleter::operator()(foxglove_service_responder* ptr) const noexcept { auto message = "Internal server error: Service failed to send a response"sv; foxglove_service_respond_error(ptr, {message.data(), message.length()}); } void ServiceResponder::respondOk(const std::byte* data, size_t size) && noexcept { auto* ptr = impl_.release(); foxglove_service_respond_ok(ptr, {reinterpret_cast(data), size}); } void ServiceResponder::respondError(std::string_view message) && noexcept { auto* ptr = impl_.release(); foxglove_service_respond_error(ptr, {message.data(), message.length()}); } FoxgloveResult Service::create( std::string_view name, ServiceSchema& schema, ServiceHandler& handler ) { std::array msg_schemas{}; foxglove_service_schema c_schema; schema.writeTo(&c_schema, msg_schemas); foxglove_service* ptr = nullptr; auto error = foxglove_service_create( &ptr, {name.data(), name.length()}, &c_schema, &handler, []( const void* context, const foxglove_service_request* c_request, foxglove_service_responder* c_responder ) { const auto* handler = static_cast(context); ServiceRequest request(c_request); ServiceResponder responder(c_responder); try { (*handler)(request, std::move(responder)); } catch (const std::exception& exc) { warn() << "Service handler failed: " << exc.what(); } } ); if (error != foxglove_error::FOXGLOVE_ERROR_OK) { return tl::unexpected(static_cast(error)); } return Service(ptr); } void Service::Deleter::operator()(foxglove_service* ptr) const noexcept { foxglove_service_free(ptr); } foxglove_service* Service::release() noexcept { return impl_.release(); } } // namespace foxglove