callgraph/sysdig/records.go

98 lines
1.9 KiB
Go

package sysdig
import (
"encoding/csv"
"fmt"
"io"
"log"
"net"
"strconv"
"strings"
)
const (
RX = iota
TX
)
type Record struct {
Host, Container, Process string
Pid, Tid uint64
Proto string
ServerIp net.IP
ServerPort uint16
ClientIp net.IP
ClientPort uint16
Direction int
Bytes uint64
}
func ParseOutput(result string) ([]Record, error) {
r := csv.NewReader(strings.NewReader(result))
r.Comma = '\t'
var records []Record
for {
record, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
if record[0] == "host" {
continue
}
pid, err := strconv.ParseUint(record[3], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid pid %s: %v", record[2], err)
}
tid, err := strconv.ParseUint(record[4], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid tid %s: %v", record[3], err)
}
sip := net.ParseIP(record[6])
if sip == nil {
return nil, fmt.Errorf("invalid ip '%s'", record[6])
}
sport, err := strconv.ParseUint(record[7], 10, 16)
if err != nil {
return nil, fmt.Errorf("invalid port %s: %v", record[7], err)
}
cip := net.ParseIP(record[8])
if cip == nil {
return nil, fmt.Errorf("invalid ip '%s'", record[8])
}
cport, err := strconv.ParseUint(record[9], 10, 16)
if err != nil {
return nil, fmt.Errorf("invalid port %s: %v", record[9], err)
}
var direction int
if record[10] == "rx" {
direction = RX
} else {
direction = TX
}
bytes, err := strconv.ParseUint(record[11], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid transmission size %s: %v", record[11], err)
}
records = append(records, Record{
record[0],
record[1],
record[2],
pid,
tid,
record[5],
sip,
uint16(sport),
cip,
uint16(cport),
direction,
bytes,
})
}
return records, nil
}