Skip to content

Commit

Permalink
Merge branch 'feature/assign_temp_ip' into 'main'
Browse files Browse the repository at this point in the history
Add new command "set-temporary-ip" to set temporary IP

See merge request syntron/support/csr/ifm3d/ifm3d!410
  • Loading branch information
NikitaS20 committed Nov 19, 2024
2 parents aa440a8 + e179c0e commit 9b13f80
Show file tree
Hide file tree
Showing 10 changed files with 368 additions and 69 deletions.
2 changes: 2 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Add `set-temporary-ip` subcommand under `discover` command to set temporary IP to device which is in wrong sub-net

### Added
- Add new subcommands `app` and `device` under import and export subcommands
Expand Down
7 changes: 7 additions & 0 deletions modules/device/include/ifm3d/device/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,13 @@ namespace ifm3d
*/
static std::vector<ifm3d::IFMNetworkDevice> DeviceDiscovery();

/**
* @brief This function Provides a way to set temporary IP.
* @param[in] mac The MAC address of the device
* @param[in] temp_ip The temporary IP to be set to device
*/
static void SetTempIPAddress(std::string mac, std::string temp_ip);

/**
* Factory function for instantiating the proper subclass based on h/w
* probing.
Expand Down
11 changes: 11 additions & 0 deletions modules/device/src/libifm3d_device/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,17 @@ ifm3d::Device::DeviceDiscovery()
return devices;
}

//================================================
// Function for Setting Temporary IP Address
//================================================

void
ifm3d::Device::SetTempIPAddress(std::string mac, std::string temp_ip)
{
ifm3d::IFMDeviceDiscovery ifm_discovery;
ifm_discovery.SetTemporaryIP(mac, temp_ip);
}

//================================================
// Factory function for making cameras
//================================================
Expand Down
196 changes: 182 additions & 14 deletions modules/device/src/libifm3d_device/discovery.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <thread>
#include <system_error>
#include <ifm3d/device/ifm_network_device.h>
#include <cstddef>
#ifdef __unix__
# include <arpa/inet.h>
# include <sys/socket.h>
Expand All @@ -33,6 +34,9 @@ namespace ifm3d
/** Broadcast request magic number. */
constexpr uint32_t BCAST_MAGIC_REQUEST = 0x1020efcf;

/** Broadcast ipchange magic number. */
constexpr uint32_t BCAST_MAGIC_IPCHANGE = 0x1020efce;

/** It signalize that network device is not in same subnet. */
constexpr uint32_t BCAST_FLAG_WRONGSUBNET = 0x0001;

Expand Down Expand Up @@ -111,6 +115,28 @@ namespace ifm3d
char devicename[256];
};

/** Broadcast ipchange packet structure. */
struct BcastIPChange
{
/** Default magic number 0x1020efce. */
uint32_t magic;

/** Port to send reply to. */
uint16_t replyPort;

/** Unused. */
uint16_t reserved1;

/** Temporary ip address that should be set. */
uint32_t tempIP;

/** Unused. */
uint16_t reserved2;

/** Mac address of interface to change. */
uint8_t mac[6];
};

namespace
{
inline const std::string
Expand All @@ -122,6 +148,24 @@ namespace ifm3d
return ss.str();
}

inline const uint32_t
str2Address(const std::string addr)
{
uint32_t str_addr = 0;
std::stringstream ss(addr);
std::string octet;
int shift = 24;

while (std::getline(ss, octet, '.'))
{
uint32_t num = std::stoi(octet);
str_addr |= (num << shift);
shift -= 8;
}

return str_addr;
}

inline const std::string
uint8Mac2macStr(uint8_t* mac, size_t size = 6)
{
Expand All @@ -133,11 +177,27 @@ namespace ifm3d
for (size_t i = 0; i + 1 < size; i++)
{
converttoHexandAppend(mac[i]);
ss << "::";
ss << ":";
}
converttoHexandAppend(mac[size - 1]);
return ss.str();
}

inline std::array<uint8_t, 6>
macStr2MacUint8(const std::string& mac_str)
{
std::array<uint8_t, 6> mac;
std::stringstream ss(mac_str);
std::string byte_str;
int i = 0;

while (std::getline(ss, byte_str, ':') && i < 6)
{
mac[i] = static_cast<uint8_t>(std::stoul(byte_str, nullptr, 16));
++i;
}
return mac;
}
}

IFMNetworkDevice::IFMNetworkDevice(
Expand Down Expand Up @@ -262,6 +322,30 @@ namespace ifm3d
std::placeholders::_2));
}

/*Sends the data on the endpoint
*@param data Data to be send on endpoint
*@param Endpoint to send the data.
**/
void
SendIPChangeCall(Data& data, asio::ip::udp::endpoint& remote_endpoint)
{
int offsetPortInData = offsetof(BcastIPChange, replyPort);

if (offsetPortInData > 0 && offsetPortInData < data.size())
{
unsigned short local_port = ntohs(socket_.local_endpoint().port());
data[offsetPortInData] = (local_port & 0xFF);
data[offsetPortInData + 1] = ((local_port >> 8) & 0xFF);
}

socket_.async_send_to(asio::buffer((char*)data.data(), data.size()),
remote_endpoint,
std::bind(&UDPConnection::_HandleSend,
this,
std::placeholders::_1,
std::placeholders::_2));
}

/*Grab data on the local endpoint till the timeout occur*/
void
GrabData()
Expand Down Expand Up @@ -393,7 +477,9 @@ namespace ifm3d
{BCAST_MAGIC_REQUEST,
[](size_t size) -> size_t { return sizeof(BcastRequest) - size; }},
{BCAST_MAGIC_REPLY,
[](size_t size) -> size_t { return sizeof(BcastReply) - size; }}};
[](size_t size) -> size_t { return sizeof(BcastReply) - size; }},
{BCAST_MAGIC_IPCHANGE,
[](size_t size) -> size_t { return sizeof(BcastIPChange) - size; }}};

const unsigned int THREADS_FOR_IO_OPERATIONS = 3;

Expand All @@ -408,6 +494,22 @@ namespace ifm3d
std::thread(std::bind([&] { io_context_.run(); })));
}
}

~IFMDeviceDiscovery()
{
/* stop the io_context */
io_context_.stop();

// wait for all threads to complete
for (std::thread& thread : thread_pool_)
{
if (thread.joinable())
{
thread.join();
}
}
}

IFMDeviceDiscovery(IFMDeviceDiscovery&&) = delete;
IFMDeviceDiscovery& operator=(IFMDeviceDiscovery&&) = delete;
IFMDeviceDiscovery(IFMDeviceDiscovery&) = delete;
Expand Down Expand Up @@ -449,18 +551,6 @@ namespace ifm3d
/* get the device list this will block the thread
till all NIC are scanned for devices */
auto devices = _GetDeviceList();

/* stop the io_context after getting list */
io_context_.stop();

// wait for all threads to complete
for (std::thread& thread : thread_pool_)
{
if (thread.joinable())
{
thread.join();
}
}
}
catch (std::exception& e)
{
Expand All @@ -469,6 +559,18 @@ namespace ifm3d
return device_list_;
}

void
SetTemporaryIP(std::string mac_address, std::string temp_ip)
{
auto addresses = _GetAllInterfaceAddress();

/* broadcast IP change request on all interfaces */
for (const auto& address : addresses)
{
_SendIPChangeBCast(mac_address, temp_ip, address);
}
}

private:
std::vector<std::string>
_GetAllInterfaceAddress()
Expand Down Expand Up @@ -597,6 +699,10 @@ namespace ifm3d
std::lock_guard<std::mutex> lock(device_list_lock_);
device_list_.push_back(ifm_device);
}
if (magic_value == BCAST_MAGIC_IPCHANGE)
{
std::cout << std::endl << "BCAST_IPCHANGE Packet received";
}
}
}
/* return the discovered device list*/
Expand Down Expand Up @@ -633,6 +739,68 @@ namespace ifm3d
cv_.notify_one();
}

/* Broadcast the IP change request */
void
_SendIPChangeBCast(std::string mac_address,
std::string temp_ip,
std::string interface_ip)
{
try
{
BcastIPChange ipc;
Data data;
data.resize(sizeof(BcastIPChange));
ipc.magic = htonl(BCAST_MAGIC_IPCHANGE);
ipc.tempIP = htonl(str2Address(temp_ip));
std::array<uint8_t, 6> mac_array = macStr2MacUint8(mac_address);
uint8_t* mac = mac_array.data();
memcpy(ipc.mac, mac, sizeof(ipc.mac));
std::memcpy(data.data(), &ipc, sizeof(BcastIPChange));

/** getting the netmask of the interface */
auto netmask = asio::ip::address_v4::netmask(
asio::ip::address_v4::from_string(interface_ip));

/**broadcast of the interface */
auto broadcast_address_of_interface =
asio::ip::address_v4::broadcast(
asio::ip::address_v4::from_string(interface_ip),
netmask)
.to_string();

/* create a local broadcast endpoint */
asio::ip::udp::endpoint broadcast_endpoint = asio::ip::udp::endpoint(
asio::ip::address::from_string(broadcast_address_of_interface),
BCAST_DEFAULT_PORT);

/* create a local endpoint */
asio::ip::udp::endpoint local_endpoint =
asio::ip::udp::endpoint(asio::ip::udp::v4(), BCAST_DEFAULT_PORT);

auto con =
std::make_shared<UDPConnection>(io_context_, local_endpoint);
con->RegisterOnReceive(std::bind(&IFMDeviceDiscovery::_OnReceive,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3));
con->RegisterOnClose(
std::bind(&IFMDeviceDiscovery::_RemoveConnection,
this,
std::placeholders::_1));

/* send BcastIPChange to device */
con->SendIPChangeCall(data, broadcast_endpoint);

connection_list_.push_back(con);
}
catch (std::exception& e)
{
std::cerr << std::endl
<< "ifm3d exception: " << e.what() << std::endl;
}
}

asio::io_context io_context_;
asio::executor_work_guard<asio::io_service::executor_type> work_guard_;
std::mutex con_mutex_;
Expand Down
9 changes: 5 additions & 4 deletions modules/tools/include/ifm3d/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <ifm3d/tools/legacy/app_types_app.h>
#include <ifm3d/tools/common/config_set_app.h>
#include <ifm3d/tools/ovp8xx/config_ovp8xx_app.h>
#include <ifm3d/tools/legacy/cp_app.h>
#include <ifm3d/tools/ovp8xx/diagnostic_app.h>
#include <ifm3d/tools/common/discover_app.h>
Expand All @@ -27,19 +28,19 @@
#include <ifm3d/tools/legacy/import_device_app.h>
#include <ifm3d/tools/ovp8xx/jsonschema_app.h>
#include <ifm3d/tools/legacy/ls_app.h>
#include <ifm3d/tools/legacy/o3d3xx_app.h>
#include <ifm3d/tools/legacy/o3x_app.h>
#include <ifm3d/tools/ovp8xx/ovp8xx_app.h>
#include <ifm3d/tools/legacy/passwd_app.h>
#include <ifm3d/tools/common/reboot_app.h>
#include <ifm3d/tools/ovp8xx/remove_app.h>
#include <ifm3d/tools/common/reset_app.h>
#include <ifm3d/tools/ovp8xx/reset_ovp8xx_app.h>
#include <ifm3d/tools/legacy/rm_app.h>
#include <ifm3d/tools/ovp8xx/save_init_app.h>
#include <ifm3d/tools/common/set_temp_ip_app.h>
#include <ifm3d/tools/legacy/time_app.h>
#include <ifm3d/tools/common/trace_app.h>
#include <ifm3d/tools/legacy/o3d3xx_app.h>
#include <ifm3d/tools/legacy/o3x_app.h>
#include <ifm3d/tools/ovp8xx/ovp8xx_app.h>
#include <ifm3d/tools/ovp8xx/config_ovp8xx_app.h>

#if defined(BUILD_MODULE_FRAMEGRABBER)
# include <ifm3d/tools/common/fg/hz_app.h>
Expand Down
6 changes: 6 additions & 0 deletions modules/tools/include/ifm3d/tools/command.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ namespace ifm3d
return parent ? parent->CheckCompatibility() : true;
}

CLI::App*
GetSubcommandApp()
{
return this->_context;
}

private:
Command* _parent = nullptr;
std::vector<std::shared_ptr<Command>> _subcommands;
Expand Down
1 change: 1 addition & 0 deletions modules/tools/include/ifm3d/tools/common/discover_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace ifm3d
std::string GetDeviceType(const ifm3d::Device::Ptr& cam);
virtual CLI::App* CreateCommand(CLI::App* parent) override;

CLI::App* subcmd_set_temp_ip;
}; // end: class

} // end: namespace ifm3d
Expand Down
Loading

0 comments on commit 9b13f80

Please sign in to comment.