Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
29 changes: 27 additions & 2 deletions include/Transmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,10 @@ namespace LibFlute {
short port, uint64_t tsi, unsigned short mtu,
uint32_t rate_limit,
boost::asio::io_context& io_context,
const std::optional<boost::asio::ip::udp::endpoint> &tunnel_endpoint = std::nullopt,
const std::optional<boost::asio::ip::udp::endpoint>& tunnel_endpoint = std::nullopt,
FdtNamespace fdt_namespace = FileDeliveryTable::FDT_NS_NONE,
bool active = true);
bool active = true,
const std::optional<std::string>& source_address = std::nullopt);

/**
* Default destructor.
Expand Down Expand Up @@ -505,6 +506,29 @@ namespace LibFlute {
Transmitter &endpoint(boost::asio::ip::udp::endpoint &&destination);
/**@}*/

/**
* Get the optional source address for the FLUTE session
*
* @return The optional source address being used.
*/
const std::optional<boost::asio::ip::address> &source_address() const { return _source_address; };

/**@{*/
/**
* Set the source address for FLUTE session
*
* Sets the optional source address to use for FLUTE session packets. If the UDP Tunnel Address is not set then the outgoing
* socket will be bound to this address, if set. When a UDP Tunnel Address is set then this provides the source address for
* encapsulated packets. If the source address is not set then a local address will be selected automatically.
*
* @param source The IP source address to use for FLUTE packets.
*
* @return This Transmitter object.
*/
Transmitter &source_address(const std::optional<boost::asio::ip::address> &source);
Transmitter &source_address(std::optional<boost::asio::ip::address> &&source);
/**@}*/

/**
* Enable IPSEC ESP encryption of FLUTE payloads.
*
Expand Down Expand Up @@ -601,6 +625,7 @@ namespace LibFlute {

void handle_send_to(const boost::system::error_code& error);
boost::asio::ip::udp::endpoint _endpoint;
std::optional<boost::asio::ip::address> _source_address;
boost::asio::ip::udp::socket _socket;
boost::asio::io_context& _io_context;
boost::asio::deadline_timer _send_timer;
Expand Down
27 changes: 24 additions & 3 deletions src/Transmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,10 @@ Transmitter::Transmitter ( const std::string& address, short port,
uint64_t tsi, unsigned short mtu, uint32_t rate_limit,
boost::asio::io_context& io_context,
const std::optional<boost::asio::ip::udp::endpoint> &tunnel_endpoint,
Transmitter::FdtNamespace fdt_namespace, bool active )
Transmitter::FdtNamespace fdt_namespace, bool active,
const std::optional<std::string> &source_address )
: _endpoint(boost::asio::ip::make_address(address), port)
, _source_address()
, _socket(io_context, _endpoint.protocol())
, _io_context(io_context)
, _send_timer(io_context)
Expand All @@ -476,6 +478,9 @@ Transmitter::Transmitter ( const std::string& address, short port,
, _tunnel_local_address()
, _active(active)
{
if (source_address) {
_source_address = boost::asio::ip::make_address(source_address.value());
}
_max_payload = mtu -
20 - // IPv4 header
8 - // UDP header
Expand All @@ -494,6 +499,10 @@ Transmitter::Transmitter ( const std::string& address, short port,
_socket.set_option(boost::asio::ip::multicast::enable_loopback(true));
_socket.set_option(boost::asio::ip::udp::socket::reuse_address(true));

if (_source_address && !_tunnel_endpoint) {
_socket.bind(boost::asio::ip::udp::endpoint(_source_address.value(),0));
}

_fec_oti = FecOti{
.encoding_id = FecScheme::CompactNoCode,
.encoding_symbol_length = _max_payload,
Expand Down Expand Up @@ -570,6 +579,18 @@ auto Transmitter::endpoint(boost::asio::ip::udp::endpoint &&destination) -> Tran
return *this;
}

auto Transmitter::source_address(const std::optional<boost::asio::ip::address> &source_address) -> Transmitter&
{
_source_address = source_address;
return *this;
}

auto Transmitter::source_address(std::optional<boost::asio::ip::address> &&source_address) -> Transmitter&
{
_source_address = std::move(source_address);
return *this;
}

auto Transmitter::enable_ipsec(uint32_t spi, const std::string& key) -> void
{
IpSec::enable_esp(spi, _mcast_address, IpSec::Direction::Out, key);
Expand Down Expand Up @@ -731,8 +752,8 @@ auto Transmitter::send_next_packet() -> void
send_endpoint = _tunnel_endpoint.value();
data_size = packet->size() + 20 /* IP header */ + 8 /* UDP header */;
data = new char[data_size];
create_udp_pkt(data+20, _endpoint, packet->data(), packet->size(), _tunnel_local_address);
create_ip_hdr(data, _endpoint, data_size, _tunnel_local_address);
create_udp_pkt(data+20, _endpoint, packet->data(), packet->size(), _source_address?_source_address.value():_tunnel_local_address);
create_ip_hdr(data, _endpoint, data_size, _source_address?_source_address.value():_tunnel_local_address);
} else {
send_endpoint = _endpoint;
data = packet->data();
Expand Down
Loading