Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Sep 1, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
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
14 changes: 7 additions & 7 deletions cpp/examples/master-gprs/ExampleListenCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,11 @@ void ExampleListenCallbacks::OnFirstFrame(uint64_t sessionid,

// do we already have a session with this outstation?
const auto iter = std::find_if(this->sessions.begin(), this->sessions.end(),
[&](const auto& item) { return item.address == header.src; });
[&](const auto& item) { return item.address == header.addresses.source; });
if (iter != this->sessions.end())
{

std::cout << "Already connected to outstation w/ address " << header.src << ". Closing first connection."
std::cout << "Already connected to outstation w/ address " << header.addresses.source << ". Closing first connection."
<< std::endl;

// if so, shutdown the existing session
Expand All @@ -165,22 +165,22 @@ void ExampleListenCallbacks::OnFirstFrame(uint64_t sessionid,
MasterStackConfig config;

// use the master and outstation addresses that the outstation is using
config.link.LocalAddr = header.dest;
config.link.RemoteAddr = header.src;
config.link.LocalAddr = header.addresses.destination;
config.link.RemoteAddr = header.addresses.source;

// don't disable unsolicited reporting when the master comes online
config.master.disableUnsolOnStartup = false;
// don't perform an integrity scan when the application layer comes online
config.master.startupIntegrityClassMask = ClassField::None();

const auto session
= acceptor.AcceptSession(GetSessionName(header.src, sessionid), std::make_shared<ExampleSOEHandler>(header.src),
= acceptor.AcceptSession(GetSessionName(header.addresses.source, sessionid), std::make_shared<ExampleSOEHandler>(header.addresses.source),
std::make_shared<DefaultMasterApplication>(), config);

// add to the list
this->sessions.emplace_back(SessionInfo{sessionid, header.src, session});
this->sessions.emplace_back(SessionInfo{sessionid, header.addresses.source, session});

std::cout << "Outstation session start: " << header.src << std::endl;
std::cout << "Outstation session start: " << header.addresses.source << std::endl;
}

void ExampleListenCallbacks::OnConnectionClose(uint64_t sessionid,
Expand Down
1 change: 1 addition & 0 deletions cpp/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ set(opendnp3_src
./src/gen/objects/Group121.cpp
./src/gen/objects/Group122.cpp

./src/link/Addresses.cpp
./src/link/CRC.cpp
./src/link/LinkContext.cpp
./src/link/LinkFrame.cpp
Expand Down
2 changes: 2 additions & 0 deletions cpp/lib/include/opendnp3/link/Addresses.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ struct Addresses
return !((*this) == other);
}

bool IsBroadcast() const;

uint16_t source = 0;
uint16_t destination = 0;
};
Expand Down
10 changes: 2 additions & 8 deletions cpp/lib/include/opendnp3/link/LinkHeaderFields.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,13 @@ struct LinkHeaderFields
{
LinkHeaderFields();

LinkHeaderFields(LinkFunction func, bool isMaster, bool fcb, bool fcvdfc, uint16_t dest, uint16_t src_);

Addresses ToAddresses() const
{
return Addresses(src, dest);
}
LinkHeaderFields(LinkFunction func, bool isMaster, bool fcb, bool fcvdfc, Addresses addresses);

LinkFunction func;
bool isFromMaster;
bool fcb;
bool fcvdfc;
uint16_t dest;
uint16_t src;
Addresses addresses;
};

} // namespace opendnp3
Expand Down
4 changes: 2 additions & 2 deletions cpp/lib/src/channel/IOHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,12 @@ void IOHandler::OnNewChannel(const std::shared_ptr<IAsyncChannel>& channel)

bool IOHandler::OnFrame(const LinkHeaderFields& header, const ser4cpp::rseq_t& userdata)
{
if (this->SendToSession(Addresses(header.src, header.dest), header, userdata))
if (this->SendToSession(header.addresses, header, userdata))
{
return true;
}

FORMAT_LOG_BLOCK(this->logger, flags::WARN, "Frame w/ unknown route, source: %i, dest %i", header.src, header.dest);
FORMAT_LOG_BLOCK(this->logger, flags::WARN, "Frame w/ unknown route, source: %i, dest %i", header.addresses.source, header.addresses.destination);
return false;
}

Expand Down
34 changes: 34 additions & 0 deletions cpp/lib/src/link/Addresses.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2013-2019 Automatak, LLC
*
* Licensed to Green Energy Corp (www.greenenergycorp.com) and Automatak
* LLC (www.automatak.com) under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Green Energy Corp and Automatak LLC license
* this file to you under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may obtain
* a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "opendnp3/link/Addresses.h"

#include "link/LinkLayerConstants.h"

namespace opendnp3
{

bool Addresses::IsBroadcast() const
{
return this->destination == LinkBroadcastAddress::DontConfirm ||
this->destination == LinkBroadcastAddress::ShallConfirm ||
this->destination == LinkBroadcastAddress::OptionalConfirm;
}

} // namespace opendnp3
39 changes: 30 additions & 9 deletions cpp/lib/src/link/LinkContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,20 +334,41 @@ bool LinkContext::OnFrame(const LinkHeaderFields& header, const ser4cpp::rseq_t&
return false;
}

if (header.dest != config.LocalAddr)
if (header.addresses.destination != config.LocalAddr && !header.addresses.IsBroadcast())
{
++statistics.numUnknownDestination;
this->listener->OnUnknownDestinationAddress(header.dest);
this->listener->OnUnknownDestinationAddress(header.addresses.destination);
return false;
}

if (header.src != config.RemoteAddr && !config.respondToAnySource)
if (header.addresses.source != config.RemoteAddr && !config.respondToAnySource)
{
++statistics.numUnknownSource;
this->listener->OnUnknownSourceAddress(header.src);
this->listener->OnUnknownSourceAddress(header.addresses.source);
return false;
}

if(header.addresses.IsBroadcast())
{
// Broadcast addresses can only be used for sending data.
// If confirmed data is used, no response is sent back.
if(header.func == LinkFunction::PRI_UNCONFIRMED_USER_DATA)
{
this->PushDataUp(Message(header.addresses, userdata));
return true;
}
else if(header.func == LinkFunction::PRI_CONFIRMED_USER_DATA)
{
pSecState = &pSecState->OnConfirmedUserData(*this, header.addresses.source, header.fcb, true, Message(header.addresses, userdata));
}
else
{
FORMAT_LOG_BLOCK(logger, flags::WARN, "Received invalid function (%s) with broadcast destination address", LinkFunctionToString(header.func));
++statistics.numUnexpectedFrame;
return false;
}
}

// reset the keep-alive timestamp
this->lastMessageTimestamp = Timestamp(this->executor->get_time());

Expand All @@ -366,20 +387,20 @@ bool LinkContext::OnFrame(const LinkHeaderFields& header, const ser4cpp::rseq_t&
pPriState = &pPriState->OnNotSupported(*this, header.fcvdfc);
break;
case (LinkFunction::PRI_TEST_LINK_STATES):
pSecState = &pSecState->OnTestLinkStatus(*this, header.src, header.fcb);
pSecState = &pSecState->OnTestLinkStatus(*this, header.addresses.source, header.fcb);
break;
case (LinkFunction::PRI_RESET_LINK_STATES):
pSecState = &pSecState->OnResetLinkStates(*this, header.src);
pSecState = &pSecState->OnResetLinkStates(*this, header.addresses.source);
break;
case (LinkFunction::PRI_REQUEST_LINK_STATUS):
pSecState = &pSecState->OnRequestLinkStatus(*this, header.src);
pSecState = &pSecState->OnRequestLinkStatus(*this, header.addresses.source);
break;
case (LinkFunction::PRI_CONFIRMED_USER_DATA):
pSecState
= &pSecState->OnConfirmedUserData(*this, header.src, header.fcb, Message(header.ToAddresses(), userdata));
= &pSecState->OnConfirmedUserData(*this, header.addresses.source, header.fcb, false, Message(header.addresses, userdata));
break;
case (LinkFunction::PRI_UNCONFIRMED_USER_DATA):
this->PushDataUp(Message(header.ToAddresses(), userdata));
this->PushDataUp(Message(header.addresses, userdata));
break;
default:
break;
Expand Down
7 changes: 4 additions & 3 deletions cpp/lib/src/link/LinkHeaderFields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@
namespace opendnp3
{
LinkHeaderFields::LinkHeaderFields()
: func(LinkFunction::INVALID), isFromMaster(false), fcb(false), fcvdfc(false), dest(0), src(0)
: func(LinkFunction::INVALID), isFromMaster(false), fcb(false), fcvdfc(false), addresses(Addresses())
{
}

LinkHeaderFields::LinkHeaderFields(
LinkFunction func_, bool isMaster_, bool fcb_, bool fcvdfc_, uint16_t dest_, uint16_t src_)
: func(func_), isFromMaster(isMaster_), fcb(fcb_), fcvdfc(fcvdfc_), dest(dest_), src(src_)
LinkFunction func_, bool isMaster_, bool fcb_, bool fcvdfc_, Addresses addresses_)
: func(func_), isFromMaster(isMaster_), fcb(fcb_), fcvdfc(fcvdfc_), addresses(addresses_)
{
}

} // namespace opendnp3
8 changes: 8 additions & 0 deletions cpp/lib/src/link/LinkLayerConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ const uint8_t LPDU_DATA_PLUS_CRC_SIZE = 18;
const uint8_t LPDU_MAX_USER_DATA_SIZE = 250;
const uint16_t LPDU_MAX_FRAME_SIZE = 292; // 10(header) + 250 (user data) + 32 (block CRC's) = 292 frame bytes

// Broadcast addresses
enum LinkBroadcastAddress : uint16_t
{
DontConfirm = 0xFFFD,
ShallConfirm = 0xFFFE,
OptionalConfirm = 0xFFFF,
};

/// Indices for use with buffers containing link headers
enum LinkHeaderIndex : uint8_t
{
Expand Down
2 changes: 1 addition & 1 deletion cpp/lib/src/link/LinkLayerParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ LinkLayerParser::State LinkLayerParser::ParseBody()
void LinkLayerParser::PushFrame(IFrameSink& sink)
{
LinkHeaderFields fields(header.GetFuncEnum(), header.IsFromMaster(), header.IsFcbSet(), header.IsFcvDfcSet(),
header.GetDest(), header.GetSrc());
Addresses(header.GetSrc(), header.GetDest()));

sink.OnFrame(fields, userData);

Expand Down
8 changes: 6 additions & 2 deletions cpp/lib/src/link/SecLinkLayerStates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ SecStateBase& SLLS_NotReset::OnTestLinkStatus(LinkContext& ctx, uint16_t /*sourc
SecStateBase& SLLS_NotReset::OnConfirmedUserData(LinkContext& ctx,
uint16_t /*source*/,
bool /*fcb*/,
bool /*isBroadcast*/,
const Message& /*message*/)
{
++ctx.statistics.numUnexpectedFrame;
Expand Down Expand Up @@ -94,9 +95,12 @@ SecStateBase& SLLS_Reset::OnTestLinkStatus(LinkContext& ctx, uint16_t source, bo
return *this;
}

SecStateBase& SLLS_Reset::OnConfirmedUserData(LinkContext& ctx, uint16_t source, bool fcb, const Message& message)
SecStateBase& SLLS_Reset::OnConfirmedUserData(LinkContext& ctx, uint16_t source, bool fcb, bool isBroadcast, const Message& message)
{
ctx.QueueAck(source);
if(!isBroadcast)
{
ctx.QueueAck(source);
}

if (ctx.nextReadFCB == fcb)
{
Expand Down
8 changes: 5 additions & 3 deletions cpp/lib/src/link/SecLinkLayerStates.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class SecStateBase
virtual SecStateBase& OnRequestLinkStatus(LinkContext&, uint16_t source) = 0;

virtual SecStateBase& OnTestLinkStatus(LinkContext&, uint16_t source, bool fcb) = 0;
virtual SecStateBase& OnConfirmedUserData(LinkContext&, uint16_t source, bool fcb, const Message& message) = 0;
virtual SecStateBase& OnConfirmedUserData(LinkContext&, uint16_t source, bool fcb, bool isBroadcast, const Message& message) = 0;

virtual SecStateBase& OnTxReady(LinkContext& ctx);

Expand All @@ -65,6 +65,7 @@ template<class NextState> class SLLS_TransmitWaitBase : public SecStateBase
virtual SecStateBase& OnConfirmedUserData(LinkContext&,
uint16_t source,
bool fcb,
bool isBroadcast,
const Message& message) override final;
};

Expand Down Expand Up @@ -98,6 +99,7 @@ template<class NextState>
SecStateBase& SLLS_TransmitWaitBase<NextState>::OnConfirmedUserData(LinkContext& ctx,
uint16_t source,
bool fcb,
bool isBroadcast,
const Message& message)
{
SIMPLE_LOG_BLOCK(ctx.logger, flags::WARN, "Ignoring link frame, remote is flooding");
Expand All @@ -112,7 +114,7 @@ class SLLS_NotReset final : public SecStateBase
public:
MACRO_STATE_SINGLETON_INSTANCE(SLLS_NotReset);

virtual SecStateBase& OnConfirmedUserData(LinkContext&, uint16_t source, bool fcb, const Message& message) override;
virtual SecStateBase& OnConfirmedUserData(LinkContext&, uint16_t source, bool fcb, bool isBroadcast, const Message& message) override;
virtual SecStateBase& OnResetLinkStates(LinkContext&, uint16_t source) override;
virtual SecStateBase& OnRequestLinkStatus(LinkContext&, uint16_t source) override;
virtual SecStateBase& OnTestLinkStatus(LinkContext&, uint16_t source, bool fcb) override;
Expand All @@ -125,7 +127,7 @@ class SLLS_Reset final : public SecStateBase
{
MACRO_STATE_SINGLETON_INSTANCE(SLLS_Reset);

virtual SecStateBase& OnConfirmedUserData(LinkContext&, uint16_t source, bool fcb, const Message& message) override;
virtual SecStateBase& OnConfirmedUserData(LinkContext&, uint16_t source, bool fcb, bool isBroadcast, const Message& message) override;
virtual SecStateBase& OnResetLinkStates(LinkContext&, uint16_t source) override;
virtual SecStateBase& OnRequestLinkStatus(LinkContext&, uint16_t source) override;
virtual SecStateBase& OnTestLinkStatus(LinkContext&, uint16_t source, bool fcb) override;
Expand Down
4 changes: 2 additions & 2 deletions cpp/lib/src/master/DefaultListenCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ void DefaultListenCallbacks::OnFirstFrame(uint64_t sessionid,

// full implementations will look up config information for the SRC address

config.link.LocalAddr = header.dest;
config.link.RemoteAddr = header.src;
config.link.LocalAddr = header.addresses.destination;
config.link.RemoteAddr = header.addresses.source;

auto soe = std::make_shared<PrintingSOEHandler>();
auto app = std::make_shared<DefaultMasterApplication>();
Expand Down
Loading