-
Notifications
You must be signed in to change notification settings - Fork 54
/
sniffer.go
87 lines (70 loc) · 2.08 KB
/
sniffer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package driver
import (
"context"
"errors"
"io"
"log"
"net"
"sync"
"github.com/SAP/go-hdb/driver/internal/exp/slog"
p "github.com/SAP/go-hdb/driver/internal/protocol"
"github.com/SAP/go-hdb/driver/unicode/cesu8"
)
// A Sniffer is a simple proxy for logging hdb protocol requests and responses.
type Sniffer struct {
logger *slog.Logger
conn net.Conn
dbConn net.Conn
}
// NewSniffer creates a new sniffer instance. The conn parameter is the net.Conn connection, where the Sniffer
// is listening for hdb protocol calls. The dbAddr is the hdb host port address in "host:port" format.
func NewSniffer(conn net.Conn, dbConn net.Conn) *Sniffer {
return &Sniffer{
logger: slog.Default().With(slog.String("conn", conn.RemoteAddr().String())),
conn: conn,
dbConn: dbConn,
}
}
func pipeData(wg *sync.WaitGroup, conn net.Conn, dbConn net.Conn, wr io.Writer) {
defer wg.Done()
mwr := io.MultiWriter(dbConn, wr)
trd := io.TeeReader(conn, mwr)
buf := make([]byte, 1000)
var err error
for err == nil {
_, err = trd.Read(buf)
}
}
func readMsg(ctx context.Context, prd *p.Reader) error {
// TODO complete for non generic parts, see internal/protocol/parts/newGenPartReader for details
return prd.IterateParts(ctx, func(kind p.PartKind, attrs p.PartAttributes, read func(part p.Part) error) error {
return nil
})
}
func logData(ctx context.Context, wg *sync.WaitGroup, prd *p.Reader) {
defer wg.Done()
if err := prd.ReadProlog(ctx); err != nil {
panic(err)
}
var err error
for !errors.Is(err, io.EOF) {
err = readMsg(ctx, prd)
}
}
// Run starts the protocol request and response logging.
func (s *Sniffer) Run() error {
clientRd, clientWr := io.Pipe()
dbRd, dbWr := io.Pipe()
ctx := context.Background()
wg := &sync.WaitGroup{}
wg.Add(4)
go pipeData(wg, s.conn, s.dbConn, clientWr)
go pipeData(wg, s.dbConn, s.conn, dbWr)
pClientRd := p.NewClientReader(clientRd, true, s.logger, cesu8.DefaultDecoder)
pDBRd := p.NewDBReader(dbRd, true, s.logger, cesu8.DefaultDecoder)
go logData(ctx, wg, pClientRd)
go logData(ctx, wg, pDBRd)
wg.Wait()
log.Println("end run")
return nil
}