Skip to content

RSDK-10435: Dial direct #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
a56574f
make dial_options a struct
lia-viam Apr 11, 2025
d86eac7
wip: direct dial
lia-viam Apr 15, 2025
4d5f8aa
get auth token successfully
stuqdog Apr 16, 2025
6eb0fdd
make calls successfully
stuqdog Apr 16, 2025
d247cc8
we can still verify server certs
stuqdog Apr 17, 2025
4b7e4c2
cleanup
stuqdog Apr 17, 2025
c41325b
cleanup2
stuqdog Apr 17, 2025
c549c07
docs
lia-viam Apr 22, 2025
a21c424
Merge branch 'main' into dial-direct
lia-viam Apr 24, 2025
41e6960
use instance for global token
lia-viam Apr 24, 2025
d0c3f21
remove dtor logging
lia-viam Apr 24, 2025
1f41cad
Merge branch 'fix/dtor-log' into dial-direct
lia-viam Apr 24, 2025
a53494a
newline
lia-viam Apr 24, 2025
bbc0adf
join if joinable
lia-viam Apr 24, 2025
a3add02
Merge branch 'fix/dtor-log' into dial-direct
lia-viam Apr 24, 2025
1ae3732
Merge branch 'main' into dial-direct
lia-viam May 1, 2025
c3ff877
spacing and variable simplification
lia-viam May 1, 2025
7d8175b
reset parent to prevent double close
lia-viam May 2, 2025
26c2225
do not disable webrtc by default
lia-viam May 2, 2025
0cd8723
revert dtor logging
lia-viam May 2, 2025
d3cdb58
unshare robot client
lia-viam May 2, 2025
c0e2197
Merge branch 'main' of github.com:viamrobotics/viam-cpp-sdk into dial…
lia-viam May 5, 2025
beab7d2
include fixes and helper rename
lia-viam May 5, 2025
89104c9
document direct dial uri
lia-viam May 5, 2025
8d68fd2
factor auth request into helper function
lia-viam May 5, 2025
29cfd35
fix doxygen comment
lia-viam May 5, 2025
fde961c
ifdef namespace alias
lia-viam May 5, 2025
44d8601
use ifdef for direct dial
lia-viam May 12, 2025
c7d8b4c
replace with custom unique_ptr deleters
lia-viam May 12, 2025
afa6c70
fix if stmt
lia-viam May 12, 2025
8ba5efa
overhaul options and refresh interval
lia-viam May 13, 2025
95dc5f8
add include
lia-viam May 14, 2025
f86011f
Merge branch 'main' of github.com:viamrobotics/viam-cpp-sdk into dial…
lia-viam May 14, 2025
4a82a6d
silence unused var warning on ifdef
lia-viam May 14, 2025
8e99746
client context gets token from channel ctor
lia-viam May 14, 2025
a8b858d
sdk overhaul for channel/token
lia-viam May 15, 2025
2e2b2ec
test code update
lia-viam May 15, 2025
67aec53
update complex module rpc clients
lia-viam May 15, 2025
5a3d47c
const viam channel
lia-viam May 15, 2025
350f0ff
linter fixes
lia-viam May 15, 2025
fa1f598
Merge branch 'main' of github.com:viamrobotics/viam-cpp-sdk into dial…
lia-viam May 15, 2025
cb7ec67
typo fix
lia-viam May 15, 2025
ed6bfed
remove no longer needed friend decl
lia-viam May 15, 2025
2c7a942
linter
lia-viam May 15, 2025
5f9d3b1
Merge branch 'main' of github.com:viamrobotics/viam-cpp-sdk into dial…
lia-viam May 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/viam/api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@ if (VIAMCPPSDK_USE_DYNAMIC_PROTOS)
${PROTO_GEN_DIR}/component/switch/v1/switch.grpc.pb.cc
${PROTO_GEN_DIR}/component/switch/v1/switch.grpc.pb.h
${PROTO_GEN_DIR}/component/switch/v1/switch.pb.cc
${PROTO_GEN_DIR}/proto/rpc/v1/auth.pb.h
${PROTO_GEN_DIR}/proto/rpc/v1/auth.pb.cc
${PROTO_GEN_DIR}/proto/rpc/v1/auth.grpc.pb.h
${PROTO_GEN_DIR}/proto/rpc/v1/auth.grpc.pb.cc
${PROTO_GEN_DIR}/component/switch/v1/switch.pb.h
${PROTO_GEN_DIR}/google/api/annotations.pb.cc
${PROTO_GEN_DIR}/google/api/annotations.pb.h
Expand Down Expand Up @@ -361,6 +365,8 @@ target_sources(viamapi
${PROTO_GEN_DIR}/component/servo/v1/servo.pb.cc
${PROTO_GEN_DIR}/component/switch/v1/switch.grpc.pb.cc
${PROTO_GEN_DIR}/component/switch/v1/switch.pb.cc
${PROTO_GEN_DIR}/proto/rpc/v1/auth.grpc.pb.cc
${PROTO_GEN_DIR}/proto/rpc/v1/auth.pb.cc
${PROTO_GEN_DIR}/google/api/annotations.pb.cc
${PROTO_GEN_DIR}/google/api/http.pb.cc
${PROTO_GEN_DIR}/google/api/httpbody.pb.cc
Expand Down Expand Up @@ -425,6 +431,8 @@ target_sources(viamapi
${PROTO_GEN_DIR}/../../viam/api/component/servo/v1/servo.pb.h
${PROTO_GEN_DIR}/../../viam/api/component/switch/v1/switch.grpc.pb.h
${PROTO_GEN_DIR}/../../viam/api/component/switch/v1/switch.pb.h
${PROTO_GEN_DIR}/../../viam/api/proto/rpc/v1/auth.grpc.pb.h
${PROTO_GEN_DIR}/../../viam/api/proto/rpc/v1/auth.pb.h
${PROTO_GEN_DIR}/../../viam/api/google/api/annotations.pb.h
${PROTO_GEN_DIR}/../../viam/api/google/api/http.pb.h
${PROTO_GEN_DIR}/../../viam/api/google/api/httpbody.pb.h
Expand Down
4 changes: 2 additions & 2 deletions src/viam/examples/camera/example_camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ int main() try {
// dial_options.credentials = credentials;

// This is for an example. Care should be taken before exercising this option in production.
dial_options.set_allow_insecure_downgrade(
(credentials.type().empty() && credentials.payload().empty()));
dial_options.allow_insecure_downgrade =
(credentials.type().empty() && credentials.payload().empty());

// Set the refresh interval of the robot (in seconds) (0 = auto refresh) and the dial
// options
Expand Down
6 changes: 2 additions & 4 deletions src/viam/examples/dial/example_dial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ int main() {
DialOptions dial_options;
std::string type = "<your authentication type>";
std::string payload = "<your authentication payload>";
Credentials credentials(type, payload);
dial_options.set_credentials(credentials);
boost::optional<DialOptions> opts(dial_options);
dial_options.credentials = Credentials(type, payload);
std::string address(uri);
Options options(1, opts);
Options options(1, dial_options);

// connect to robot, ensure we can refresh it
std::shared_ptr<RobotClient> robot = RobotClient::at_address(address, options);
Expand Down
16 changes: 9 additions & 7 deletions src/viam/examples/dial_api_key/example_dial_api_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,30 @@ int main(int argc, char* argv[]) {
"uri", po::value<std::string>(), "URI of robot")(
"entity", po::value<std::string>(), "api key ID")(
"api-key", po::value<std::string>(), "api key secret");

po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);

if (vm.count("help")) {
std::cout << desc << std::endl;
return 0;
}
boost::optional<DialOptions> opts;

DialOptions opts;

if (vm.count("entity") && vm.count("api-key")) {
DialOptions dial_options;
dial_options.set_entity(vm["entity"].as<std::string>());
opts.auth_entity = vm["entity"].as<std::string>();
Credentials credentials("api-key", vm["api-key"].as<std::string>());
dial_options.set_credentials(credentials);
opts = dial_options;
opts.credentials = credentials;
}
Options options(1, opts);

// connect to robot, ensure we can refresh it
std::shared_ptr<RobotClient> robot =
RobotClient::at_address(vm["uri"].as<std::string>(), options);
RobotClient::at_address(vm["uri"].as<std::string>(), Options(1, opts));

// ensure we can query resources
std::vector<Name> resource_names = robot->resource_names();

VIAM_SDK_LOG(info) << "Resources:";
for (const Name& resource : resource_names) {
VIAM_SDK_LOG(info) << resource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ int main(int argc, char* argv[]) try {
// secret. Please see other examples for more details on
// connecting to robots with the C++ SDK.
viam::sdk::DialOptions dial_options;
dial_options.set_entity(opt_api_key_id.get());
dial_options.set_credentials(viam::sdk::Credentials("api-key", opt_api_key.get()));
dial_options.auth_entity = opt_api_key_id.get();
dial_options.credentials = viam::sdk::Credentials("api-key", opt_api_key.get());

auto robot =
vsdk::RobotClient::at_address(opt_robot_host.get(), {0, {std::move(dial_options)}});
Expand Down
2 changes: 1 addition & 1 deletion src/viam/examples/modules/complex/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int main() {

const char* uri = "http://localhost:8080/"; // replace with your URI if connecting securely
DialOptions dial_options;
dial_options.set_allow_insecure_downgrade(true); // set to false if connecting securely
dial_options.allow_insecure_downgrade = true; // set to false if connecting securely

// Uncomment and fill out your credentials details if connecting securely
// std::string type = "<your authentication type>";
Expand Down
2 changes: 1 addition & 1 deletion src/viam/examples/modules/simple/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ int main() {

const char* uri = "http://localhost:8080/"; // replace with your URI if connecting securely
DialOptions dial_options;
dial_options.set_allow_insecure_downgrade(true); // set to false if connecting securely
dial_options.allow_insecure_downgrade = true; // set to false if connecting securely

// Uncomment and fill out your credentials details if connecting securely
// std::string type = "<your authentication type>";
Expand Down
4 changes: 2 additions & 2 deletions src/viam/examples/motor/example_motor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ int main() try {
// dial_options.credentials = credentials;

// This is for an example. Care should be taken before exercising this option in production.
dial_options.set_allow_insecure_downgrade(
(credentials.type().empty() && credentials.payload().empty()));
dial_options.allow_insecure_downgrade =
(credentials.type().empty() && credentials.payload().empty());

// Set the refresh interval of the robot (in seconds) (0 = auto refresh) and the dial
// options
Expand Down
7 changes: 7 additions & 0 deletions src/viam/sdk/common/client_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <grpcpp/client_context.h>
#include <grpcpp/support/status.h>

#include <viam/sdk/common/private/instance.hpp>
#include <viam/sdk/common/private/version_metadata.hpp>
#include <viam/sdk/log/logging.hpp>

Expand All @@ -30,6 +31,12 @@ void set_name(...) {} // NOLINT(cert-dcl50-cpp)
ClientContext::ClientContext() : wrapped_context_(std::make_unique<GrpcClientContext>()) {
set_client_ctx_authority_();
add_viam_client_version_();

const std::string& token =
Instance::current(Instance::Creation::open_existing).impl_->direct_dial_token;
if (!token.empty()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little surprised to see this as a global, but maybe I'm misunderstanding. But if you had one channel that was doing direct dial and another that wasn't, wouldn't this by trying to add this metadata to the contexts for both channels?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yes, although I'm not sure how common/feasible such a situation would be in practice, or if we should error out if we detect that kind of thing? cc @stuqdog

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this is a good question. I'm not sure how common such a situation is in practice currently, but I do think it's certainly feasible and I could imagine a case where, e.g., someone is connecting to two machines at once and would prefer to use direct gRPC but is required to use webRTC for some of its added functionality on one of the machines only.

For that matter, even if both channels were dialing direct, if they were dialing to different machines then the token would only be valid for one of them! So yeah, probably tokens should either not be global or (if that's not feasible) should be keyed to a particular channel.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm ok so this is probably something we should handle better. i'll try to look into the architecture and see how to make this work probably on a per channel basis

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@acmorrow after much wailing and gnashing of teeth we figured out a way to do this without a global, thereby ballooning the surface area of this PR considerably.

wrapped_context_->AddMetadata("authorization", "Bearer " + token);
}
}

ClientContext::~ClientContext() = default;
Expand Down
2 changes: 2 additions & 0 deletions src/viam/sdk/common/instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class Instance {
private:
friend class Registry;
friend class LogManager;
friend class ViamChannel;
friend class ClientContext;

struct Impl;
std::unique_ptr<Impl> impl_;
Expand Down
5 changes: 5 additions & 0 deletions src/viam/sdk/common/private/instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ namespace sdk {
struct Instance::Impl {
Registry registry;
LogManager log_mgr;

// When dialing directly to gpc (no rust-utils/webrtc) there is global state in the form of a
// bearer token that needs to be added as metadata to every client call. This variable stores
// the auth token; see client_helper.cpp and dial.cpp for access.
std::string direct_dial_token;
};

} // namespace sdk
Expand Down
5 changes: 2 additions & 3 deletions src/viam/sdk/module/service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,12 @@ ModuleService::ModuleService(int argc,
}

ModuleService::~ModuleService() {
// TODO(RSDK-5509): Run registered cleanup functions here.
VIAM_SDK_LOG(info) << "Shutting down gracefully.";
VIAM_SDK_LOG(info) << "Shutting down gracefully.\n";
server_->shutdown();

if (parent_) {
try {
parent_->close();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was causing a double call to stop_all, the second one happening after disconnecting from the robot

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does conan now give us a vehicle for building the entire dependency tree under ASAN and UBSAN?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yes in theory but it's probably pretty tricky, see here for discussion (old conan docs) https://docs.conan.io/1/howtos/sanitizers.html

parent_.reset();
} catch (const std::exception& exc) {
VIAM_SDK_LOG(error) << exc.what();
}
Expand Down
2 changes: 1 addition & 1 deletion src/viam/sdk/module/service.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class ModuleService {

std::unique_ptr<Module> module_;

std::shared_ptr<RobotClient> parent_;
std::unique_ptr<RobotClient> parent_;
std::string parent_addr_;

std::unique_ptr<Server> server_;
Expand Down
8 changes: 4 additions & 4 deletions src/viam/sdk/robot/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ void RobotClient::log(const std::string& name,
}
}

std::shared_ptr<RobotClient> RobotClient::with_channel(ViamChannel channel,
std::unique_ptr<RobotClient> RobotClient::with_channel(ViamChannel channel,
const Options& options) {
auto robot = std::make_shared<RobotClient>(std::move(channel));
auto robot = std::make_unique<RobotClient>(std::move(channel));
robot->refresh_interval_ = std::chrono::seconds{options.refresh_interval()};
robot->should_refresh_ = (robot->refresh_interval_ > std::chrono::seconds{0});
if (robot->should_refresh_) {
Expand All @@ -283,7 +283,7 @@ std::shared_ptr<RobotClient> RobotClient::with_channel(ViamChannel channel,
return robot;
};

std::shared_ptr<RobotClient> RobotClient::at_address(const std::string& address,
std::unique_ptr<RobotClient> RobotClient::at_address(const std::string& address,
const Options& options) {
const char* uri = address.c_str();
auto robot =
Expand All @@ -292,7 +292,7 @@ std::shared_ptr<RobotClient> RobotClient::at_address(const std::string& address,
return robot;
};

std::shared_ptr<RobotClient> RobotClient::at_local_socket(const std::string& address,
std::unique_ptr<RobotClient> RobotClient::at_local_socket(const std::string& address,
const Options& options) {
const std::string addr = "unix://" + address;
auto robot = RobotClient::with_channel(
Expand Down
6 changes: 3 additions & 3 deletions src/viam/sdk/robot/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,21 +91,21 @@ class RobotClient {
/// @brief Create a robot client connected to the robot at the provided address.
/// @param address The address of the robot (IP address, URI, URL, etc.)
/// @param options Options for connecting and refreshing.
static std::shared_ptr<RobotClient> at_address(const std::string& address,
static std::unique_ptr<RobotClient> at_address(const std::string& address,
const Options& options);

/// @brief Creates a robot client connected to the robot at the provided local socket.
/// @param address The local socket of the robot (a .sock file, etc.).
/// @param options Options for connecting and refreshing.
/// Creates a direct connection to the robot using the `unix://` scheme.
/// Only useful for connecting to robots across Unix sockets.
static std::shared_ptr<RobotClient> at_local_socket(const std::string& address,
static std::unique_ptr<RobotClient> at_local_socket(const std::string& address,
const Options& options);

/// @brief Creates a robot client connected to the provided channel.
/// @param channel The channel to connect with.
/// @param options Options for connecting and refreshing.
static std::shared_ptr<RobotClient> with_channel(ViamChannel channel, const Options& options);
static std::unique_ptr<RobotClient> with_channel(ViamChannel channel, const Options& options);

std::vector<Name> resource_names() const;

Expand Down
Loading
Loading