plc4go/tools/plc4xpcapanalyzer/internal/pcaphandler/pcaphandler.go (57 lines of code) (raw):
/*
* 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 pcaphandler
import (
"time"
"github.com/gopacket/gopacket"
"github.com/gopacket/gopacket/pcap"
"github.com/pkg/errors"
)
// GetPacketSource gets a packet source from a handle
func GetPacketSource(handle *pcap.Handle) *gopacket.PacketSource {
return gopacket.NewPacketSource(handle, handle.LinkType())
}
// GetIndexedPcapHandle returns a *pcap.Handle, the number of packages found and an index which maps timestamp to
// absolute package number
func GetIndexedPcapHandle(file, filterExpression string) (handle *pcap.Handle, numberOfPackages int, timestampToIndexMap map[time.Time]int, err error) {
timestampToIndexMap = make(map[time.Time]int)
// Count absolute packages and set timestamp map
temporaryHandle, err := GetPcapHandle(file, "")
if err != nil {
return nil, 0, nil, err
}
defer temporaryHandle.Close()
packetSource := GetPacketSource(temporaryHandle)
packages := 0
for packet := range packetSource.Packets() {
if packet == nil {
break
}
packages++
timestampToIndexMap[packet.Metadata().Timestamp] = packages
}
// Just count filtered packages
temporaryFilteredHandle, err := GetPcapHandle(file, filterExpression)
if err != nil {
return nil, 0, nil, err
}
defer temporaryFilteredHandle.Close()
filteredPacketSource := GetPacketSource(temporaryFilteredHandle)
packages = 0
for packet := range filteredPacketSource.Packets() {
if packet == nil {
break
}
packages++
}
pcapHandle, err := GetPcapHandle(file, filterExpression)
if err != nil {
return nil, 0, nil, err
}
return pcapHandle, packages, timestampToIndexMap, nil
}
// GetPcapHandle returns a *pcap.Handle and panics if an error occurs
func GetPcapHandle(file, filterExpression string) (*pcap.Handle, error) {
handle, err := pcap.OpenOffline(file)
if err != nil {
return nil, errors.Wrap(err, "error open offline")
}
if filterExpression != "" {
if err := handle.SetBPFFilter(filterExpression); err != nil {
return nil, errors.Wrap(err, "error setting BPF filter")
}
}
return handle, nil
}