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 <sru...@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 +}