// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma // de Barcelona (UAB). // // This work is licensed under the terms of the MIT license. // For a copy, see . #pragma once #include "carla/Debug.h" #include "carla/streaming/EndPoint.h" #include "carla/streaming/Token.h" #include "carla/streaming/detail/Types.h" #include #include #include namespace carla { namespace streaming { namespace detail { #pragma pack(push, 1) struct token_data { stream_id_type stream_id = 0u; uint16_t port = 0u; enum class protocol : uint8_t { not_set, tcp, udp } protocol = protocol::not_set; enum class address : uint8_t { not_set, ip_v4, ip_v6 } address_type = address::not_set; union { boost::asio::ip::address_v4::bytes_type v4; boost::asio::ip::address_v6::bytes_type v6; } address; }; #pragma pack(pop) static_assert( sizeof(token_data) == sizeof(Token::data), "Size shouldn't be more than" " v6 address : 128" " + state : 16" " + port : 16" " + stream id : 32" " -----------------" " 192"); /// Serializes a stream endpoint. Contains all the necessary information for a /// client to subscribe to a stream. class token_type { private: template static constexpr auto get_protocol() { static_assert( std::is_same::value || std::is_same::value, "Invalid protocol."); return std::is_same::value ? token_data::protocol::tcp : token_data::protocol::udp; } template boost::asio::ip::basic_endpoint

get_endpoint() const { DEBUG_ASSERT(is_valid()); DEBUG_ASSERT(get_protocol

() == _token.protocol); return {get_address(), _token.port}; } public: template explicit token_type( stream_id_type stream_id, const EndPoint &ep) { _token.stream_id = stream_id; _token.port = ep.port(); _token.protocol = get_protocol(); set_address(ep.address()); } template explicit token_type( stream_id_type stream_id, EndPoint ep) { _token.stream_id = stream_id; _token.port = ep.port(); _token.protocol = get_protocol(); } token_type() = default; token_type(const token_type &) = default; token_type(const Token &rhs); explicit token_type(token_data data) { _token = data; } operator Token() const; // We need to return a reference here so we can use the address of the // stream id to send it as buffer. const auto &get_stream_id() const { return _token.stream_id; } void set_stream_id(stream_id_type id) { _token.stream_id = id; } bool has_address() const { return _token.address_type != token_data::address::not_set; } void set_address(const boost::asio::ip::address &addr); boost::asio::ip::address get_address() const; auto get_port() const { return _token.port; } bool is_valid() const { return has_address() && ((_token.protocol != token_data::protocol::not_set) && (_token.address_type != token_data::address::not_set)); } bool address_is_v4() const { return _token.address_type == token_data::address::ip_v4; } bool address_is_v6() const { return _token.address_type == token_data::address::ip_v6; } bool protocol_is_udp() const { return _token.protocol == token_data::protocol::udp; } bool protocol_is_tcp() const { return _token.protocol == token_data::protocol::tcp; } template bool has_same_protocol(const boost::asio::ip::basic_endpoint &) const { return _token.protocol == get_protocol(); } boost::asio::ip::udp::endpoint to_udp_endpoint() const { return get_endpoint(); } boost::asio::ip::tcp::endpoint to_tcp_endpoint() const { return get_endpoint(); } private: friend class Dispatcher; token_data _token; }; } // namespace detail } // namespace streaming } // namespace carla