Skip to content

Commit

Permalink
feat: Use timestamps packet was captured instead of when it was proce… (
Browse files Browse the repository at this point in the history
#75)

## Which problem is this PR solving?
We use timestamps of the client and server packets to calculate a
duration for the request - however we use the packet processed time to
do that which may skew the duration if processing is delayed or response
is processed before request.

This PR switches to using the capture timestamp instead.

- Closes #68

## Short description of the changes
- Add timestamp to the HTTP Reader struct and set it as part of the
stream process that sets the bytes for the reader to reader from
- Update the matcher store funcs to take the timestamp from the reader
instead of creating it's own

## How to verify that this has the expected result
Calculated duration fields are continued to be set, but should be more
accurate.
  • Loading branch information
MikeGoldsmith committed Aug 16, 2023
1 parent b091a33 commit 1b64737
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 6 deletions.
8 changes: 4 additions & 4 deletions assemblers/http_matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ func newRequestResponseMatcher() httpMatcher {
}
}

func (m *httpMatcher) LoadOrStoreRequest(requestID string, request *http.Request) *entry {
func (m *httpMatcher) LoadOrStoreRequest(requestID string, timestamp time.Time, request *http.Request) *entry {

// check if we already have a response for this request, if yes, return it
if e, ok := m.messages.LoadAndDelete(requestID); ok {
e.(*entry).request = request
e.(*entry).requestTimestamp = time.Now()
e.(*entry).requestTimestamp = timestamp
return e.(*entry)
}

Expand All @@ -42,12 +42,12 @@ func (m *httpMatcher) LoadOrStoreRequest(requestID string, request *http.Request
return nil
}

func (m *httpMatcher) LoadOrStoreResponse(requestID string, response *http.Response) *entry {
func (m *httpMatcher) LoadOrStoreResponse(requestID string, timestamp time.Time, response *http.Response) *entry {

// check if we already have a request for this response, if yes, return it
if e, ok := m.messages.LoadAndDelete(requestID); ok {
e.(*entry).response = response
e.(*entry).responseTimestamp = time.Now()
e.(*entry).responseTimestamp = timestamp
return e.(*entry)
}

Expand Down
6 changes: 4 additions & 2 deletions assemblers/http_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"net/http"
"sync"
"time"
)

type httpReader struct {
Expand All @@ -16,6 +17,7 @@ type httpReader struct {
bytes chan []byte
data []byte
parent *tcpStream
timestamp time.Time
}

func (h *httpReader) Read(p []byte) (int, error) {
Expand Down Expand Up @@ -44,7 +46,7 @@ func (h *httpReader) run(wg *sync.WaitGroup) {
// Error("HTTP-request", "HTTP/%s Request error: %s (%v,%+v)\n", h.ident, err, err, err)
continue
}
entry := h.parent.matcher.LoadOrStoreRequest(h.parent.ident, req)
entry := h.parent.matcher.LoadOrStoreRequest(h.parent.ident, h.timestamp, req)
if entry != nil {
// we have a match, process complete request/response pair
h.processEvent(entry)
Expand All @@ -58,7 +60,7 @@ func (h *httpReader) run(wg *sync.WaitGroup) {
continue
}

entry := h.parent.matcher.LoadOrStoreResponse(h.parent.ident, res)
entry := h.parent.matcher.LoadOrStoreResponse(h.parent.ident, h.timestamp, res)
if entry != nil {
// we have a match, process complete request/response pair
h.processEvent(entry)
Expand Down
2 changes: 2 additions & 0 deletions assemblers/tcp_stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ func (t *tcpStream) ReassembledSG(sg reassembly.ScatterGather, ac reassembly.Ass

if length > 0 {
if dir == reassembly.TCPDirClientToServer {
t.client.timestamp = ac.GetCaptureInfo().Timestamp
t.client.bytes <- data
} else {
t.server.timestamp = ac.GetCaptureInfo().Timestamp
t.server.bytes <- data
}
}
Expand Down

0 comments on commit 1b64737

Please sign in to comment.