You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2021/09/17 18:40:48 UTC

[plc4x] 07/08: feat(pl4go): Added initial pcap transport

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 580454ffe9f5eb4ef9841cff236dabeb0d397e52
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Sep 17 20:33:18 2021 +0200

    feat(pl4go): Added initial pcap transport
---
 plc4go/go.mod                                      |   4 +-
 plc4go/go.sum                                      |  13 ++
 .../plc4go/spi/transports/pcap/Transport.go        | 173 +++++++++++++++++++++
 3 files changed, 188 insertions(+), 2 deletions(-)

diff --git a/plc4go/go.mod b/plc4go/go.mod
index fe7d241..016d3eb 100644
--- a/plc4go/go.mod
+++ b/plc4go/go.mod
@@ -24,6 +24,7 @@ go 1.16
 require (
 	github.com/ajankovic/xdiff v0.0.1
 	github.com/elastic/go-licenser v0.3.1 // indirect
+	github.com/google/gopacket v1.1.19
 	github.com/icza/bitio v1.0.0
 	github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4
 	github.com/pkg/errors v0.9.1
@@ -31,7 +32,6 @@ require (
 	github.com/snksoft/crc v1.1.0
 	github.com/subchen/go-xmldom v1.1.2
 	github.com/tebeka/go2xunit v1.4.10 // indirect
-	golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
-	golang.org/x/tools v0.1.5 // indirect
+	golang.org/x/tools v0.1.6 // indirect
 	gotest.tools/gotestsum v1.7.0 // indirect
 )
diff --git a/plc4go/go.sum b/plc4go/go.sum
index b834a94..dd14d14 100644
--- a/plc4go/go.sum
+++ b/plc4go/go.sum
@@ -13,6 +13,8 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
+github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
 github.com/icza/bitio v1.0.0 h1:squ/m1SHyFeCA6+6Gyol1AxV9nmPPlJFT8c2vKdj3U8=
@@ -42,9 +44,12 @@ github.com/tebeka/go2xunit v1.4.10 h1:0UO+9YoLpXTZ0DL9XbTmIIibgmKBGiwroo8uhFMSyR
 github.com/tebeka/go2xunit v1.4.10/go.mod h1:wmc9jKT7KlU4QLU6DNTaIXNnYNOjKKNlp6mjOS0UrqY=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -53,6 +58,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
@@ -66,20 +72,27 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
+golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.6 h1:SIasE1FVIQOWz2GEAHFOmoW7xchJcqlucjSULTL0Ag4=
+golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/plc4go/internal/plc4go/spi/transports/pcap/Transport.go b/plc4go/internal/plc4go/spi/transports/pcap/Transport.go
new file mode 100644
index 0000000..ed81c02
--- /dev/null
+++ b/plc4go/internal/plc4go/spi/transports/pcap/Transport.go
@@ -0,0 +1,173 @@
+/*
+ * 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
+ *
+ *   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.
+ */
+
+package pcap
+
+import (
+	"bufio"
+	"bytes"
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/transports"
+	"github.com/google/gopacket/pcap"
+	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+	"net/url"
+	"sync"
+)
+
+type TransportType string
+
+const (
+	UDP TransportType = "udp"
+	TCP TransportType = "tcp"
+)
+
+type Transport struct {
+}
+
+func NewTransport() *Transport {
+	return &Transport{}
+}
+
+func (m Transport) GetTransportCode() string {
+	return "pcap"
+}
+
+func (m Transport) GetTransportName() string {
+	return "PCAP(NG) Playback Transport"
+}
+
+func (m Transport) CreateTransportInstance(transportUrl url.URL, options map[string][]string) (transports.TransportInstance, error) {
+	var transportType = TCP
+	if val, ok := options["transport-type"]; ok {
+		transportType = TransportType(val[0])
+	}
+	var portRange = ""
+	if val, ok := options["transport-port-range"]; ok {
+		portRange = val[0]
+	}
+
+	transportInstance := NewPcapTransportInstance(transportUrl.Path, transportType, portRange, &m)
+
+	castFunc := func(typ interface{}) (transports.TransportInstance, error) {
+		if transportInstance, ok := typ.(transports.TransportInstance); ok {
+			return transportInstance, nil
+		}
+		return nil, errors.New("couldn't cast to TransportInstance")
+	}
+	return castFunc(transportInstance)
+}
+
+type TransportInstance struct {
+	transportFile string
+	transportType TransportType
+	portRange     string
+	connected     bool
+	transport     *Transport
+	reader        *bufio.Reader
+	handle        *pcap.Handle
+	mutex         sync.Mutex
+}
+
+func NewPcapTransportInstance(transportFile string, transportType TransportType, portRange string, transport *Transport) *TransportInstance {
+	return &TransportInstance{
+		transportFile: transportFile,
+		transportType: transportType,
+		portRange:     portRange,
+		transport:     transport,
+	}
+}
+
+func (m *TransportInstance) Connect() error {
+	handle, err := pcap.OpenOffline(m.transportFile)
+	if err != nil {
+		return err
+	}
+	filter := string(m.transportType)
+	if m.portRange != "" {
+		filter += " dst port " + m.portRange
+	}
+	if err := handle.SetBPFFilter(filter); err != nil {
+		return err
+	}
+	m.handle = handle
+	m.connected = true
+	return nil
+}
+
+func (m *TransportInstance) Close() error {
+	m.handle.Close()
+	m.connected = false
+	return nil
+}
+
+func (m *TransportInstance) IsConnected() bool {
+	return m.connected
+}
+
+func (m *TransportInstance) GetNumReadableBytes() (uint32, error) {
+	if err := m.checkForNextPackage(); err != nil {
+		return 0, err
+	}
+	if m.reader == nil {
+		return 0, nil
+	}
+	_, _ = m.reader.Peek(1)
+	return uint32(m.reader.Buffered()), nil
+}
+
+func (m *TransportInstance) PeekReadableBytes(numBytes uint32) ([]uint8, error) {
+	if m.reader == nil {
+		return nil, errors.New("error peeking from transport. No reader available")
+	}
+	return m.reader.Peek(int(numBytes))
+}
+
+func (m *TransportInstance) Read(numBytes uint32) ([]uint8, error) {
+	if m.reader == nil {
+		return nil, errors.New("error reading from transport. No reader available")
+	}
+	data := make([]uint8, numBytes)
+	for i := uint32(0); i < numBytes; i++ {
+		val, err := m.reader.ReadByte()
+		if err != nil {
+			return nil, errors.Wrap(err, "error reading")
+		}
+		data[i] = val
+	}
+	return data, nil
+}
+
+func (m *TransportInstance) Write(_ []uint8) error {
+	panic("Write to pcap not supported")
+}
+
+func (m *TransportInstance) checkForNextPackage() error {
+	m.mutex.Lock()
+	defer m.mutex.Lock()
+	// TODO: this will only work with the first packet and after this we are done
+	if m.reader == nil {
+		packetData, captureInfo, err := m.handle.ReadPacketData()
+		log.Info().Msgf("Read new package %v", captureInfo)
+		if err != nil {
+			return err
+		}
+		m.reader = bufio.NewReader(bytes.NewBuffer(packetData))
+	}
+	return nil
+}