mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-27 13:57:09 +00:00
128 lines
2.4 KiB
Go
128 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/bluele/gcache"
|
|
)
|
|
|
|
const cacheSize = 500
|
|
|
|
// On every connect and accept, we lookup the local addr
|
|
// As this is expensive, we cache the result
|
|
var fdAddrCache = gcache.New(cacheSize).LRU().Expiration(15 * time.Second).Build()
|
|
|
|
type fdCacheKey struct {
|
|
pid int
|
|
fd int
|
|
}
|
|
type fdCacheValue struct {
|
|
addr uint32
|
|
port uint16
|
|
}
|
|
|
|
func getCachedLocalAddr(pid, fd int) (uint32, uint16, error) {
|
|
key := fdCacheKey{pid, fd}
|
|
val, err := fdAddrCache.Get(key)
|
|
if val != nil {
|
|
return val.(fdCacheValue).addr, val.(fdCacheValue).port, nil
|
|
}
|
|
|
|
addr, port, err := getLocalAddr(pid, fd)
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
fdAddrCache.Set(key, fdCacheValue{addr, port})
|
|
return addr, port, nil
|
|
}
|
|
|
|
// On every connect or accept, we cache the syscall that caused
|
|
// it for matching with a connection from conntrack
|
|
var syscallCache = gcache.New(cacheSize).LRU().Expiration(15 * time.Second).Build()
|
|
|
|
type syscallCacheKey struct {
|
|
localAddr uint32
|
|
localPort uint16
|
|
}
|
|
type syscallCacheValue *syscall
|
|
|
|
// One ever conntrack connection, we cache it by local addr, port to match with
|
|
// a future syscall
|
|
var conntrackCache = gcache.New(cacheSize).LRU().Expiration(15 * time.Second).Build()
|
|
|
|
type conntrackCacheKey syscallCacheKey
|
|
|
|
// And keep a list of successfully matched connection, for us to close out
|
|
// when we get the close syscall
|
|
|
|
func main() {
|
|
ftrace, err := NewFtracer()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
ftrace.start()
|
|
defer ftrace.stop()
|
|
|
|
syscalls := make(chan *syscall, 100)
|
|
go ftrace.events(syscalls)
|
|
|
|
onSocket := func(s *syscall) {
|
|
|
|
}
|
|
|
|
onConnection := func(s *syscall) {
|
|
if s.returnCode != 0 {
|
|
return
|
|
}
|
|
|
|
fdStr, ok := s.args["fd"]
|
|
if !ok {
|
|
panic("no pid")
|
|
}
|
|
fd64, err := strconv.ParseInt(fdStr, 32, 16)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fd := int(fd64)
|
|
|
|
addr, port, err := getCachedLocalAddr(s.pid, fd)
|
|
if err != nil {
|
|
fmt.Printf("Failed to get local addr for pid=%d fd=%d: %v\n", s.pid, fd, err)
|
|
return
|
|
}
|
|
|
|
fmt.Printf("%+v %d %d\n", s, addr, port)
|
|
syscallCache.Set(syscallCacheKey{addr, port}, s)
|
|
}
|
|
|
|
onAccept := func(s *syscall) {
|
|
|
|
}
|
|
|
|
onClose := func(s *syscall) {
|
|
|
|
}
|
|
|
|
fmt.Println("Started")
|
|
|
|
for {
|
|
select {
|
|
case s := <-syscalls:
|
|
|
|
switch s.name {
|
|
case "socket":
|
|
onSocket(s)
|
|
case "connect":
|
|
onConnection(s)
|
|
case "accept", "accept4":
|
|
onAccept(s)
|
|
case "close":
|
|
onClose(s)
|
|
}
|
|
}
|
|
}
|
|
}
|