@@ -15,6 +15,7 @@ import (
15
15
"syscall"
16
16
"time"
17
17
18
+ "github.com/buger/goreplay/proto"
18
19
"github.com/buger/goreplay/size"
19
20
"github.com/buger/goreplay/tcp"
20
21
@@ -59,9 +60,13 @@ type Listener struct {
59
60
loopIndex int
60
61
Reading chan bool // this channel is closed when the listener has started reading packets
61
62
PcapOptions
62
- Engine EngineType
63
- ports []uint16 // src or/and dst ports
64
- trackResponse bool
63
+ Engine EngineType
64
+ ports []uint16 // src or/and dst ports
65
+ trackResponse bool
66
+ expiry time.Duration
67
+ allowIncomplete bool
68
+ messages chan * tcp.Message
69
+ protocol tcp.TCPProtocol
65
70
66
71
host string // pcap file name or interface (name, hardware addr, index or ip address)
67
72
@@ -121,7 +126,7 @@ func (eng *EngineType) String() (e string) {
121
126
// NewListener creates and initialize a new Listener. if transport or/and engine are invalid/unsupported
122
127
// is "tcp" and "pcap", are assumed. l.Engine and l.Transport can help to get the values used.
123
128
// if there is an error it will be associated with getting network interfaces
124
- func NewListener (host string , ports []uint16 , transport string , engine EngineType , trackResponse bool ) (l * Listener , err error ) {
129
+ func NewListener (host string , ports []uint16 , transport string , engine EngineType , protocol tcp. TCPProtocol , trackResponse bool , expiry time. Duration , allowIncomplete bool ) (l * Listener , err error ) {
125
130
l = & Listener {}
126
131
127
132
l .host = host
@@ -139,6 +144,11 @@ func NewListener(host string, ports []uint16, transport string, engine EngineTyp
139
144
l .closeDone = make (chan struct {})
140
145
l .quit = make (chan struct {})
141
146
l .Reading = make (chan bool )
147
+ l .expiry = expiry
148
+ l .allowIncomplete = allowIncomplete
149
+ l .protocol = protocol
150
+ l .messages = make (chan * tcp.Message , 10000 )
151
+
142
152
switch engine {
143
153
default :
144
154
l .Engine = EnginePcap
@@ -171,8 +181,8 @@ func (l *Listener) SetPcapOptions(opts PcapOptions) {
171
181
// Listen listens for packets from the handles, and call handler on every packet received
172
182
// until the context done signal is sent or there is unrecoverable error on all handles.
173
183
// this function must be called after activating pcap handles
174
- func (l * Listener ) Listen (ctx context.Context , handler PacketHandler ) (err error ) {
175
- l .read (handler )
184
+ func (l * Listener ) Listen (ctx context.Context ) (err error ) {
185
+ l .read ()
176
186
done := ctx .Done ()
177
187
select {
178
188
case <- done :
@@ -185,11 +195,11 @@ func (l *Listener) Listen(ctx context.Context, handler PacketHandler) (err error
185
195
}
186
196
187
197
// ListenBackground is like listen but can run concurrently and signal error through channel
188
- func (l * Listener ) ListenBackground (ctx context.Context , handler PacketHandler ) chan error {
198
+ func (l * Listener ) ListenBackground (ctx context.Context ) chan error {
189
199
err := make (chan error , 1 )
190
200
go func () {
191
201
defer close (err )
192
- if e := l .Listen (ctx , handler ); err != nil {
202
+ if e := l .Listen (ctx ); err != nil {
193
203
err <- e
194
204
}
195
205
}()
@@ -332,11 +342,34 @@ func (l *Listener) SocketHandle(ifi pcap.Interface) (handle Socket, err error) {
332
342
return
333
343
}
334
344
335
- func (l * Listener ) read (handler PacketHandler ) {
345
+ func http1StartHint (pckt * tcp.Packet ) (isRequest , isResponse bool ) {
346
+ if proto .HasRequestTitle (pckt .Payload ) {
347
+ return true , false
348
+ }
349
+
350
+ if proto .HasResponseTitle (pckt .Payload ) {
351
+ return false , true
352
+ }
353
+
354
+ // No request or response detected
355
+ return false , false
356
+ }
357
+
358
+ func http1EndHint (m * tcp.Message ) bool {
359
+ if m .MissingChunk () {
360
+ return false
361
+ }
362
+
363
+ return proto .HasFullPayload (m , m .PacketData ()... )
364
+ }
365
+
366
+ func (l * Listener ) read () {
336
367
l .Lock ()
337
368
defer l .Unlock ()
338
369
for key , handle := range l .Handles {
339
370
go func (key string , hndl packetHandle ) {
371
+ runtime .LockOSThread ()
372
+
340
373
defer l .closeHandles (key )
341
374
linkSize := 14
342
375
linkType := int (layers .LinkTypeEthernet )
@@ -351,6 +384,13 @@ func (l *Listener) read(handler PacketHandler) {
351
384
}
352
385
}
353
386
387
+ messageParser := tcp .NewMessageParser (l .messages , l .ports , hndl .ips , l .expiry , l .allowIncomplete )
388
+
389
+ if l .protocol == tcp .ProtocolHTTP {
390
+ messageParser .Start = http1StartHint
391
+ messageParser .End = http1EndHint
392
+ }
393
+
354
394
timer := time .NewTicker (1 * time .Second )
355
395
356
396
for {
@@ -371,23 +411,12 @@ func (l *Listener) read(handler PacketHandler) {
371
411
ci .Timestamp = time .Now ()
372
412
}
373
413
374
- pckt , err := tcp .ParsePacket (data , linkType , linkSize , & ci , false )
375
-
376
- if err == nil {
377
- for _ , p := range l .ports {
378
- if pckt .DstPort == p {
379
- for _ , ip := range hndl .ips {
380
- if pckt .DstIP .Equal (ip ) {
381
- pckt .Direction = tcp .DirIncoming
382
- break
383
- }
384
- }
385
- break
386
- }
387
- }
388
-
389
- handler (pckt )
390
- }
414
+ messageParser .PacketHandler (& tcp.PcapPacket {
415
+ Data : data ,
416
+ LType : linkType ,
417
+ LTypeLen : linkSize ,
418
+ Ci : & ci ,
419
+ })
391
420
continue
392
421
}
393
422
if enext , ok := err .(pcap.NextError ); ok && enext == pcap .NextErrorTimeoutExpired {
@@ -413,6 +442,10 @@ func (l *Listener) read(handler PacketHandler) {
413
442
close (l .Reading )
414
443
}
415
444
445
+ func (l * Listener ) Messages () chan * tcp.Message {
446
+ return l .messages
447
+ }
448
+
416
449
func (l * Listener ) closeHandles (key string ) {
417
450
l .Lock ()
418
451
defer l .Unlock ()
0 commit comments