Skip to content

Commit

Permalink
EIPScanner-8 Implement DiscoverManager
Browse files Browse the repository at this point in the history
  • Loading branch information
atimin committed Dec 17, 2019
1 parent a7d3d5d commit 649f032
Show file tree
Hide file tree
Showing 14 changed files with 200 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ ADD / /code
RUN mkdir build
WORKDIR build
RUN cmake -DTEST_ENABLED=ON -DEXAMPLE_ENABLED=ON /code
RUN cmake --build .
RUN cmake --build . -- -j
10 changes: 9 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ services:
build: .
volumes:
- .:/code
command: examples/explicit_implicit_messaging
command: examples/discovery_example
networks:
testing_net:
ipv4_address: 172.28.1.1
Expand All @@ -22,6 +22,14 @@ services:
testing_net:
ipv4_address: 172.28.1.3

opener_adapter2:
build: docker/opener
working_dir: /OpENer/bin/posix/src/ports/POSIX
command: ./OpENer eth0
networks:
testing_net:
ipv4_address: 172.28.1.7

gdbserver:
build:
context: docker/gdbserver
Expand Down
5 changes: 4 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ add_executable(file_object_example FileObjectExample.cpp)
target_link_libraries(file_object_example EIPScanner)

add_executable(parameter_object_example ParameterObjectExample.cpp)
target_link_libraries(parameter_object_example EIPScanner)
target_link_libraries(parameter_object_example EIPScanner)

add_executable(discovery_example DiscoveryManagerExample.cpp)
target_link_libraries(discovery_example EIPScanner)
23 changes: 23 additions & 0 deletions examples/DiscoveryManagerExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Created by Aleksey Timin on 12/17/19.
//

#include <DiscoveryManager.h>
#include <utils/Logger.h>

using eipScanner::DiscoveryManager;
using eipScanner::utils::Logger;
using eipScanner::utils::LogLevel;

int main() {
Logger::setLogLevel(LogLevel::DEBUG);

DiscoveryManager discoveryManager("172.28.255.255", 0xAF12, std::chrono::seconds(1));
auto devices = discoveryManager.discovery();

for (auto& device : devices) {
Logger(LogLevel::INFO) << "Discovered device: "
<< device.identityObject.getProductName()
<< " with address " << device.socketAddress.toString();
}
}
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ set(SOURCE_FILES

BaseObject.cpp
ConnectionManager.cpp
DiscoveryManager.cpp
FileObject.cpp
IdentityObject.cpp
IOConnection.cpp
Expand Down
108 changes: 108 additions & 0 deletions src/DiscoveryManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//
// Created by Aleksey Timin on 12/17/19.
//
#include <system_error>
#include <cerrno>

#include "eip/EncapsPacketFactory.h"
#include "sockets/UDPSocket.h"
#include "utils/Logger.h"
#include "utils/Buffer.h"

#include "DiscoveryManager.h"

namespace eipScanner {
using namespace cip;

using eip::EncapsPacketFactory;
using eip::EncapsPacket;
using eip::EncapsStatusCodes;
using eip::EncapsCommands;

using sockets::EndPoint;
using sockets::UDPSocket;
using utils::LogLevel;
using utils::Logger;
using utils::Buffer;

DiscoveryManager::DiscoveryManager(const std::string& broadCastAddress, int port,
std::chrono::milliseconds receiveTimout)
: _broadCastAddress(broadCastAddress, port)
, _receiveTimout(receiveTimout) {
}

DiscoveryManager::~DiscoveryManager() = default;

IdentityItem::Vec DiscoveryManager::discovery() const {
eipScanner::IdentityItem::Vec devices;

auto socket = makeSocket();
socket->Send(EncapsPacketFactory().createListIdentityPacket().pack());

try {
for(;;) {
auto header = socket->Receive(EncapsPacket::HEADER_SIZE);
auto len = EncapsPacket::getLengthFromHeader(header);

EncapsPacket receivedPacket;
receivedPacket.expand(socket->Receive(EncapsPacket::HEADER_SIZE + len));

if (receivedPacket.getStatusCode() == EncapsStatusCodes::SUCCESS
&& receivedPacket.getCommand() == EncapsCommands::LIST_IDENTITY) {

Buffer buffer(receivedPacket.getData());
CipUint count;
buffer >> count;
for (int i = 1; i <= count; ++i) {
CipUint ignore;
buffer >> ignore >> ignore >> ignore;
sockets::EndPoint socketAddr("", 0);

buffer >> socketAddr;

CipUint vendorId, deviceType, productCode;
CipRevision revision;
CipWord status;
CipUdint serialNumber;
CipShortString productName;

buffer >> vendorId >> deviceType >> productCode
>> revision >> status
>> serialNumber >> productName;

IdentityObject identityObject(i);
identityObject.setVendorId(vendorId);
identityObject.setDeviceType(deviceType);
identityObject.setProductCode(productCode);
identityObject.setRevision(revision);
identityObject.setStatus(status);
identityObject.setSerialNumber(serialNumber);
identityObject.setProductName(productName.toStdString());

devices.push_back(IdentityItem{.identityObject=identityObject, .socketAddress=socketAddr});
}
} else {
//TODO: Handle exception.
}
}
} catch (std::system_error& er) {
if (er.code().value() != EAGAIN) {
throw er;
}
}

return devices;
}

sockets::BaseSocket::UPtr DiscoveryManager::makeSocket() const {
auto socket = std::make_unique<UDPSocket>(_broadCastAddress);
socket->setRecvTimeout(_receiveTimout);

int broadcast = 1;
if(setsockopt(socket->getSocketFd(), SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0) {
throw std::system_error(errno, std::generic_category());
}

return socket;
}
}
34 changes: 34 additions & 0 deletions src/DiscoveryManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Created by Aleksey Timin on 12/17/19.
//

#ifndef EIPSCANNER_DISCOVERYMANAGER_H
#define EIPSCANNER_DISCOVERYMANAGER_H

#include "IdentityObject.h"

namespace eipScanner {

struct IdentityItem {
using Vec = std::vector<IdentityItem>;

IdentityObject identityObject;
sockets::EndPoint socketAddress;
};

class DiscoveryManager {
public:
explicit DiscoveryManager(const std::string& broadCastAddress, int port, std::chrono::milliseconds receiveTimout);
~DiscoveryManager();

IdentityItem::Vec discovery() const;
protected:
virtual sockets::BaseSocket::UPtr makeSocket() const;

private:
sockets::EndPoint _broadCastAddress;
std::chrono::milliseconds _receiveTimout;
};
}

#endif //EIPSCANNER_DISCOVERYMANAGER_H
2 changes: 1 addition & 1 deletion src/SessionInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace eipScanner {
EncapsPacket SessionInfo::sendAndReceive(const EncapsPacket& packet) const {
_socket.Send(packet.pack());
auto header = _socket.Receive(EncapsPacket::HEADER_SIZE);
auto length = EncapsPacket::GetLengthFromHeader(header);
auto length = EncapsPacket::getLengthFromHeader(header);
auto data = _socket.Receive(length);

header.insert(header.end(), data.begin(), data.end());
Expand Down
2 changes: 1 addition & 1 deletion src/eip/EncapsPacket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ namespace eip {
_length = data.size();
}

size_t EncapsPacket::GetLengthFromHeader(const std::vector<uint8_t> data) {
size_t EncapsPacket::getLengthFromHeader(const std::vector<uint8_t>& data) {
std::vector<uint8_t> lengthVector(data.begin() + 2, data.begin() + 4);
Buffer buf(lengthVector);

Expand Down
2 changes: 1 addition & 1 deletion src/eip/EncapsPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace eip {
class EncapsPacket {
public:
static const size_t HEADER_SIZE = 24;
static size_t GetLengthFromHeader(const std::vector<uint8_t> data);
static size_t getLengthFromHeader(const std::vector<uint8_t>& data);

EncapsPacket();
~EncapsPacket();
Expand Down
7 changes: 7 additions & 0 deletions src/eip/EncapsPacketFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,12 @@ namespace eip {

return packet;
}

EncapsPacket EncapsPacketFactory::createListIdentityPacket() const {
EncapsPacket packet;
packet.setCommand(EncapsCommands::LIST_IDENTITY);
packet.setSessionHandle(0);
return packet;
}
}
}
1 change: 1 addition & 0 deletions src/eip/EncapsPacketFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace eip {
EncapsPacket createUnRegisterSessionPacket(cip::CipUdint sessionHandle) const;
EncapsPacket createSendRRDataPacket(cip::CipUdint sessionHandle,
cip::CipUint timeout, std::vector<uint8_t> data) const;
EncapsPacket createListIdentityPacket() const;
};
}
}
Expand Down
1 change: 1 addition & 0 deletions src/sockets/BaseSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace sockets {
public:
using BeginReceiveHandler = std::function<void(BaseSocket&)>;
using SPtr = std::shared_ptr<BaseSocket>;
using UPtr = std::unique_ptr<BaseSocket>;

explicit BaseSocket(EndPoint endPoint);
BaseSocket(std::string host, int port);
Expand Down
8 changes: 8 additions & 0 deletions test/eip/TestEncapsPacketFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,11 @@ TEST(TestEncapsPacketFactory, ShouldCreateSendRRDataPacket) {
EncapsPacket packet = EncapsPacketFactory().createSendRRDataPacket(0xaabbccdd, 100, data);
EXPECT_EQ(expectedPacket, packet.pack());
}

TEST(TestEncapsPacketFactory, ShouldCreateListIdentityPacket) {
std::vector<uint8_t> expectedPacket = {0x63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0};

EncapsPacket packet = EncapsPacketFactory().createListIdentityPacket();
EXPECT_EQ(expectedPacket, packet.pack());
}

0 comments on commit 649f032

Please sign in to comment.