Skip to content

Commit

Permalink
refactor(plc4go/bacnetip): move bacgopes part into sub directory
Browse files Browse the repository at this point in the history
  • Loading branch information
sruehl committed Sep 4, 2024
1 parent 2666383 commit 8c7f35c
Show file tree
Hide file tree
Showing 454 changed files with 2,490 additions and 35,173 deletions.
209 changes: 209 additions & 0 deletions plc4go/internal/bacnetip/ApplicationLayerMessageCodec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses 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
*
* https://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.
*/

package bacnetip

import (
"context"
"fmt"
"net"
"net/url"
"time"

"github.com/pkg/errors"
"github.com/rs/zerolog"

"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes"
"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
"github.com/apache/plc4x/plc4go/spi"
"github.com/apache/plc4x/plc4go/spi/transports/udp"
)

// ApplicationLayerMessageCodec is a wrapper for MessageCodec which takes care of segmentation, retries etc.
//
//go:generate go run ../../tools/plc4xgenerator/gen.go -type=ApplicationLayerMessageCodec
type ApplicationLayerMessageCodec struct {
bipSimpleApplication *bacgopes.BIPSimpleApplication
messageCode *MessageCodec
deviceInfoCache bacgopes.DeviceInfoCache

localAddress *net.UDPAddr `stringer:"true"`
remoteAddress *net.UDPAddr `stringer:"true"`

log zerolog.Logger `ignore:"true"`
}

func NewApplicationLayerMessageCodec(localLog zerolog.Logger, udpTransport *udp.Transport, transportUrl url.URL, options map[string][]string, localAddress *net.UDPAddr, remoteAddress *net.UDPAddr) (*ApplicationLayerMessageCodec, error) {
// TODO: currently this is done by the BIP down below
// Have the transport create a new transport-instance.
//transportInstance, err := udpTransport.CreateTransportInstanceForLocalAddress(transportUrl, options, localAddress)
//if err != nil {
// return nil, errors.Wrap(err, "error creating transport instance")
//}
a := &ApplicationLayerMessageCodec{
localAddress: localAddress,
remoteAddress: remoteAddress,

log: localLog,
}
address, err := bacgopes.NewAddress(localLog, localAddress)
if err != nil {
return nil, errors.Wrap(err, "error creating address")
}
// TODO: workaround for strange address parsing
address.AddrTuple = bacgopes.NewAddressTuple(fmt.Sprintf("%d.%d.%d.%d", address.AddrAddress[0], address.AddrAddress[1], address.AddrAddress[2], address.AddrAddress[3]), *address.AddrPort)
application, err := bacgopes.NewBIPSimpleApplication(localLog, &bacgopes.LocalDeviceObject{
NumberOfAPDURetries: func() *uint { retries := uint(10); return &retries }(),
}, *address, &a.deviceInfoCache, nil)
if err != nil {
return nil, err
}
a.bipSimpleApplication = application
// TODO: this is currently done by the BIP
//a.messageCode = NewMessageCodec(transportInstance)
return a, nil
}

func (m *ApplicationLayerMessageCodec) GetCodec() spi.MessageCodec {
return m
}

func (m *ApplicationLayerMessageCodec) Connect() error {
// TODO: this is currently done by the BIP
// return m.messageCode.Connect()
return nil
}

func (m *ApplicationLayerMessageCodec) ConnectWithContext(ctx context.Context) error {
// TODO: this is currently done by the BIP
// return m.messageCode.ConnectWithContext(ctx)
return nil
}

func (m *ApplicationLayerMessageCodec) Disconnect() error {
if err := m.bipSimpleApplication.Close(); err != nil {
m.log.Error().Err(err).Msg("error closing application")
}
return m.messageCode.Disconnect()
}

func (m *ApplicationLayerMessageCodec) IsRunning() bool {
return m.messageCode.IsRunning()
}

func (m *ApplicationLayerMessageCodec) Send(message spi.Message) error {
address, err := bacgopes.NewAddress(m.log, m.remoteAddress)
if err != nil {
return err
}
iocb, err := bacgopes.NewIOCB(m.log, bacgopes.NewPDU(message, bacgopes.WithPDUDestination(address)), address)
if err != nil {
return errors.Wrap(err, "error creating IOCB")
}
go func() {
go func() {
if err := m.bipSimpleApplication.RequestIO(iocb); err != nil {
m.log.Debug().Err(err).Msg("errored")
}
}()
iocb.Wait()
if err := iocb.GetIOError(); err != nil {
// TODO: handle error
fmt.Printf("Err: %v\n", err)
} else if iocb.GetIOResponse() != nil {
// TODO: response?
fmt.Printf("Response: %v\n", iocb.GetIOResponse())
} else {
// TODO: what now?
}
}()
return nil
}

func (m *ApplicationLayerMessageCodec) Expect(ctx context.Context, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError, ttl time.Duration) error {
// TODO: implement me
panic("not yet implemented")
}

func (m *ApplicationLayerMessageCodec) SendRequest(ctx context.Context, message spi.Message, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError, ttl time.Duration) error {
address, err := bacgopes.NewAddress(m.log, m.remoteAddress)
if err != nil {
return err
}
iocb, err := bacgopes.NewIOCB(m.log, bacgopes.NewPDU(message, bacgopes.WithPDUDestination(address)), address)
if err != nil {
return errors.Wrap(err, "error creating IOCB")
}
go func() {
go func() {
if err := m.bipSimpleApplication.RequestIO(iocb); err != nil {

}
}()
iocb.Wait()
if err := iocb.GetIOError(); err != nil {
if err := handleError(err); err != nil {
m.log.Debug().Err(err).Msg("error handling error")
return
}
} else if response := iocb.GetIOResponse(); response != nil {
// TODO: we wrap it into a BVLC for now. Once we change the Readers etc. to accept apdus we can remove that
tempBVLC := model.NewBVLCOriginalUnicastNPDU(
model.NewNPDU(
0,
model.NewNPDUControl(
false,
false,
false,
false,
model.NPDUNetworkPriority_NORMAL_MESSAGE,
),
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
response.GetRootMessage().(model.APDU),
0,
),
0,
)
if acceptsMessage(tempBVLC) {
if err := handleMessage(
tempBVLC,
); err != nil {
m.log.Debug().Err(err).Msg("error handling message")
return
}
}
} else {
// TODO: what now?
}
}()
return nil
}

func (m *ApplicationLayerMessageCodec) GetDefaultIncomingMessageChannel() chan spi.Message {
// TODO: this is currently done by the BIP
//return m.messageCode.GetDefaultIncomingMessageChannel()
return make(chan spi.Message)
}
40 changes: 32 additions & 8 deletions plc4go/internal/bacnetip/ApplicationLayerMessageCodec_plc4xgen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8c7f35c

Please sign in to comment.