Skip to content

Commit

Permalink
fix(plc4go/bacnet): several fixes
Browse files Browse the repository at this point in the history
+ fixed issues with defaults
+ fixed String stackoverflows
+ transport apdu instead of bvlc from reader
+ fixed delegate not exposing interface
  • Loading branch information
sruehl committed Nov 21, 2022
1 parent 461946a commit b28801f
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 132 deletions.
157 changes: 110 additions & 47 deletions plc4go/internal/bacnetip/ApplicationLayer.go

Large diffs are not rendered by default.

11 changes: 3 additions & 8 deletions plc4go/internal/bacnetip/ApplicationModule.go
Expand Up @@ -91,7 +91,7 @@ func NewDeviceInfoCache() *DeviceInfoCache {
}

func (d *DeviceInfoCache) String() string {
return fmt.Sprintf("%#q", d)
return fmt.Sprintf("DeviceInfoCache(%d)", len(d.cache))
}

// HasDeviceInfo Return true if cache has information about the device.
Expand Down Expand Up @@ -271,7 +271,7 @@ func (a *Application) Request(apdu _PDU) error {
log.Debug().Msgf("Request\n%s", apdu)

// double-check the input is the right kind of APDU
switch apdu.(type) {
switch apdu.GetMessage().(type) {
case readWriteModel.APDUUnconfirmedRequestExactly, readWriteModel.APDUConfirmedRequestExactly:
default:
return errors.New("APDU expected")
Expand Down Expand Up @@ -386,14 +386,9 @@ func (a *ApplicationIOController) _AppComplete(address net.Addr, apdu _PDU) erro
func (a *ApplicationIOController) _AppRequest(apdu _PDU) {
log.Debug().Msgf("_AppRequest\n%s", apdu)

if err := a.Request(apdu); err != nil {
log.Error().Err(err).Msg("Uh oh")
return
}

// send it downstream, bypass the guard
if err := a.Application.Request(apdu); err != nil {
log.Error().Err(err).Msg("Uh oh")
log.Error().Stack().Err(err).Msg("Uh oh")
return
}

Expand Down
4 changes: 4 additions & 0 deletions plc4go/internal/bacnetip/CommunicationsModule.go
Expand Up @@ -51,6 +51,10 @@ func _New_PCI(pduUserData interface{}, pduSource Address, pduDestination Address
return &_PCI{pduUserData, pduSource, pduDestination}
}

func (p *_PCI) String() string {
return fmt.Sprintf("pduUserData:\n%s\n, pduSource: %s, pduDestination: %s", p.pduUserData, &p.pduSource, &p.pduDestination)
}

// _Client is an interface used for documentation
type _Client interface {
Request(pdu _PDU) error
Expand Down
19 changes: 14 additions & 5 deletions plc4go/internal/bacnetip/IOCBModule.go
Expand Up @@ -554,16 +554,23 @@ func (i *IOController) AbortIO(iocb _IOCB, err error) error {
return nil
}

type _IOQController interface {
ProcessIO(iocb _IOCB) error
}

type IOQController struct {
*IOController
state IOQControllerStates
activeIOCB _IOCB
ioQueue *IOQueue
waitTime time.Duration
rootStruct _IOQController
}

func NewIOQController(name string) (*IOQController, error) {
i := &IOQController{}
func NewIOQController(name string, rootStruct _IOQController) (*IOQController, error) {
i := &IOQController{
rootStruct: rootStruct,
}
var err error
i.IOController, err = NewIOController(name, i)
if err != nil {
Expand Down Expand Up @@ -636,7 +643,7 @@ func (i *IOQController) RequestIO(iocb _IOCB) error {
return nil
}

if err := i.ProcessIO(iocb); err != nil {
if err := i.rootStruct.ProcessIO(iocb); err != nil {
log.Debug().Err(err).Msgf("ProcessIO error")
if err := i.Abort(err); err != nil {
return errors.Wrap(err, "error sending abort")
Expand Down Expand Up @@ -797,7 +804,7 @@ type SieveQueue struct {
func NewSieveQueue(fn func(apdu _PDU), address net.Addr) (*SieveQueue, error) {
s := &SieveQueue{}
var err error
s.IOQController, err = NewIOQController(address.String())
s.IOQController, err = NewIOQController(address.String(), s)
if err != nil {
return nil, errors.Wrap(err, "error creating a IOQController")
}
Expand All @@ -812,7 +819,9 @@ func (s *SieveQueue) ProcessIO(iocb _IOCB) error {
log.Debug().Msgf("ProcessIO %s", iocb)

// this is now an active request
s.ActiveIO(iocb)
if err := s.ActiveIO(iocb); err != nil {
return errors.Wrap(err, "error on active io")
}

// send the request
s.requestFn(iocb.getRequest())
Expand Down
30 changes: 22 additions & 8 deletions plc4go/internal/bacnetip/PDU.go
Expand Up @@ -66,6 +66,10 @@ type AddressTuple[L any, R any] struct {
Right R
}

func (a *AddressTuple[L, R]) String() string {
return fmt.Sprintf("(%v, %v)", a.Left, a.Right)
}

var _field_address = regexp.MustCompile(`((?:\d+)|(?:0x(?:[0-9A-Fa-f][0-9A-Fa-f])+))`)
var _ip_address_port = regexp.MustCompile(`(\d+\.\d+\.\d+\.\d+)(?::(\d+))?`)
var _ip_address_mask_port = regexp.MustCompile(`(\d+\.\d+\.\d+\.\d+)(?:/(\d+))?(?::(\d+))?`)
Expand Down Expand Up @@ -123,12 +127,12 @@ func NewAddress(args ...interface{}) (*Address, error) {
switch a.AddrType {
case LOCAL_STATION_ADDRESS:
a.AddrType = REMOTE_STATION_ADDRESS
var net = (args[0]).(uint16)
a.AddrNet = &net
var addrNet = (args[0]).(uint16)
a.AddrNet = &addrNet
case LOCAL_BROADCAST_ADDRESS:
a.AddrType = REMOTE_BROADCAST_ADDRESS
var net = (args[0]).(uint16)
a.AddrNet = &net
var addrNet = (args[0]).(uint16)
a.AddrNet = &addrNet
default:
return nil, errors.New("unrecognized address ctor form")
}
Expand Down Expand Up @@ -296,10 +300,7 @@ func (a *Address) Equals(other interface{}) bool {
}

func (a *Address) String() string {
if a == nil {
return "<nil>"
}
return fmt.Sprintf("Address{AddrType: %s, AddrNet: %d, AddrAddress: %x, AddrLen: %d, AddrRoute: %d, AddrIP: %d, AddrMask: %d, AddrHost: %d, AddrSubnet: %d, AddrPort: %d, AddrTuple: %v, AddrBroadcastTuple: %v}", a.AddrType, a.AddrNet, a.AddrAddress, a.AddrLen, a.AddrRoute, a.AddrIP, a.AddrMask, a.AddrHost, a.AddrSubnet, a.AddrPort, a.AddrTuple, a.AddrBroadcastTuple)
return fmt.Sprintf("%#v", a)
}

func portToUint16(port []byte) uint16 {
Expand Down Expand Up @@ -429,6 +430,10 @@ type PCI struct {
networkPriority readWriteModel.NPDUNetworkPriority
}

func (p *PCI) String() string {
return fmt.Sprintf("PCI{%s, expectingReply: %t, networkPriority: %s}", p._PCI, p.expectingReply, p.networkPriority)
}

func NewPCI(msg spi.Message, pduSource Address, pduDestination Address, expectingReply bool, networkPriority readWriteModel.NPDUNetworkPriority) *PCI {
return &PCI{
_New_PCI(msg, pduSource, pduDestination),
Expand All @@ -439,6 +444,7 @@ func NewPCI(msg spi.Message, pduSource Address, pduDestination Address, expectin

type _PDU interface {
spi.Message
GetMessage() spi.Message
GetPDUSource() Address
GetPDUDestination() Address
GetExpectingReply() bool
Expand Down Expand Up @@ -507,6 +513,10 @@ func WithPDUNetworkPriority(networkPriority readWriteModel.NPDUNetworkPriority)
}
}

func (p *PDU) GetMessage() spi.Message {
return p.Message
}

func (p *PDU) GetPDUSource() Address {
return p.pduSource
}
Expand All @@ -522,3 +532,7 @@ func (p *PDU) GetExpectingReply() bool {
func (p *PDU) GetNetworkPriority() readWriteModel.NPDUNetworkPriority {
return p.networkPriority
}

func (p *PDU) String() string {
return fmt.Sprintf("PDU{\n%s,\n%s}", p.Message, p._PCI)
}
61 changes: 1 addition & 60 deletions plc4go/internal/bacnetip/Reader.go
Expand Up @@ -22,7 +22,6 @@ package bacnetip
import (
"context"
"fmt"
"math"
"time"

apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
Expand All @@ -40,19 +39,8 @@ type Reader struct {
messageCodec spi.MessageCodec
tm *spi.RequestTransactionManager

// TODO make them configurable
protocolVersion uint8
hopCount uint8
maxSegmentsAccepted readWriteModel.MaxSegmentsAccepted
maxApduLengthAccepted readWriteModel.MaxApduLengthAccepted
srcAddress *struct {
NetworkAddress uint16
Address []byte
}
dstAddress struct {
NetworkAddress uint16
Address []byte
}
}

func NewReader(invokeIdGenerator *InvokeIdGenerator, messageCodec spi.MessageCodec, tm *spi.RequestTransactionManager) *Reader {
Expand All @@ -61,8 +49,6 @@ func NewReader(invokeIdGenerator *InvokeIdGenerator, messageCodec spi.MessageCod
messageCodec: messageCodec,
tm: tm,

protocolVersion: 1,
hopCount: 255,
maxSegmentsAccepted: readWriteModel.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS,
maxApduLengthAccepted: readWriteModel.MaxApduLengthAccepted_NUM_OCTETS_1476,
}
Expand Down Expand Up @@ -142,58 +128,13 @@ func (m *Reader) Read(ctx context.Context, readRequest apiModel.PlcReadRequest)
serviceRequest.GetLengthInBytes(),
)

// build npdu
sourceSpecified := m.srcAddress != nil
var sourceNetworkAddress *uint16
var sourceLength *uint8
var sourceAddress []uint8
if sourceSpecified {
sourceSpecified = true
sourceNetworkAddress = &m.srcAddress.NetworkAddress
sourceLengthValue := len(m.srcAddress.Address)
if sourceLengthValue > math.MaxUint8 {
result <- &spiModel.DefaultPlcReadRequestResult{
Request: readRequest,
Response: nil,
Err: errors.New("source address length overflows"),
}
return
}
sourceLengthValueUint8 := uint8(sourceLengthValue)
sourceLength = &sourceLengthValueUint8
sourceAddress = m.srcAddress.Address
if sourceLengthValueUint8 == 0 {
// If we define the len 0 we must not send the array
sourceAddress = nil
}
}
control := readWriteModel.NewNPDUControl(false, true, sourceSpecified, true, readWriteModel.NPDUNetworkPriority_NORMAL_MESSAGE)
destinationLengthValue := len(m.dstAddress.Address)
if destinationLengthValue > math.MaxUint8 {
result <- &spiModel.DefaultPlcReadRequestResult{
Request: readRequest,
Response: nil,
Err: errors.New("destination address length overflows"),
}
return
}
destinationNetworkAddress := &m.dstAddress.NetworkAddress
destinationLengthValueUint8 := uint8(destinationLengthValue)
destinationtLength := &destinationLengthValueUint8
destinationAddress := m.dstAddress.Address
if len(m.dstAddress.Address) == 0 {
// If we define the len 0 we must not send the array
destinationAddress = nil
}
npdu := readWriteModel.NewNPDU(m.protocolVersion, control, destinationNetworkAddress, destinationtLength, destinationAddress, sourceNetworkAddress, sourceLength, sourceAddress, &m.hopCount, nil, apdu, 0)
bvlc := readWriteModel.NewBVLCOriginalUnicastNPDU(npdu, 0)
// Start a new request-transaction (Is ended in the response-handler)
transaction := m.tm.StartTransaction()
transaction.Submit(func() {

// Send the over the wire
log.Trace().Msg("Send ")
if err := m.messageCodec.SendRequest(ctx, bvlc, func(message spi.Message) bool {
if err := m.messageCodec.SendRequest(ctx, apdu, func(message spi.Message) bool {
bvlc, ok := message.(readWriteModel.BVLCExactly)
if !ok {
log.Debug().Msgf("Received strange type %T", bvlc)
Expand Down
8 changes: 4 additions & 4 deletions plc4go/internal/bacnetip/local/Device.go
Expand Up @@ -25,10 +25,10 @@ import (
)

type LocalDeviceObject struct {
NumberOfAPDURetries uint
APDUTimeout uint
SegmentationSupported readWriteModel.BACnetSegmentation
APDUSegmentTimeout uint
NumberOfAPDURetries *uint
APDUTimeout *uint
SegmentationSupported *readWriteModel.BACnetSegmentation
APDUSegmentTimeout *uint
MaxSegmentsAccepted *readWriteModel.MaxSegmentsAccepted
MaximumApduLengthAccepted *readWriteModel.MaxApduLengthAccepted
App interface{}
Expand Down
2 changes: 2 additions & 0 deletions plc4go/tests/drivers/tests/manual_bacnet_driver_test.go
Expand Up @@ -28,12 +28,14 @@ import (
_ "github.com/apache/plc4x/plc4go/tests/initializetest"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/rs/zerolog/pkgerrors"
"os"
"testing"
)

func TestManualBacnetDriver(t *testing.T) {
t.Skip()
zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack
log.Logger = log.
With().Caller().Logger().
Output(zerolog.ConsoleWriter{Out: os.Stderr}).
Expand Down

0 comments on commit b28801f

Please sign in to comment.