-
Notifications
You must be signed in to change notification settings - Fork 389
/
searchpktlist.go
217 lines (178 loc) · 5.93 KB
/
searchpktlist.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
// Copyright 2019-2022 Graham Clark. All rights reserved. Use of this source
// code is governed by the MIT license that can be found in the LICENSE
// file.
// Package ui contains user-interface functions and helpers for termshark.
package ui
import (
"fmt"
"github.com/gcla/gowid"
"github.com/gcla/gowid/widgets/table"
"github.com/gcla/termshark/v2/widgets/search"
)
//======================================================================
// ListResult represents a match for a search within the packet list view. This is really
// just the PSML already generated by tshark. The result is a packet number and a column;
// on a match, the packet list view will be updated to show the matched row and column.
type ListResult struct {
Column int
PacketNum int
}
func (s ListResult) PacketNumber() int {
return s.PacketNum
}
//======================================================================
// Search in the packet list view:
// 1 0.000000 10.44.10.228 8.8.4.4 DNS 77 Standard query 0x51fe A ac.duckduckgo.com
// 2 0.024306 10.44.10.228 176.103.130. DNS 77 Standard query 0x51fe A ac.duckduckgo.com
// 3 0.024875 8.8.4.4 10.44.10.228 DNS 139 Standard query response 0x51fe A ac.duckduckgo.com CNAME
// 4 0.025500 10.44.10.228 184.72.104.1 TCP 66 55408 → 443 [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 S 0
type ListSearchCallbacks struct {
*commonSearchCallbacks
*SearchStopper
samePacket bool // set to false if we have advanced beyond the current packet, so don't need to check list pos
search chan search.IntermediateResult
}
var _ search.IRequestStop = (*ListSearchCallbacks)(nil)
var _ search.ICallbacks = (*ListSearchCallbacks)(nil)
func (w *ListSearchCallbacks) Reset(app gowid.IApp) {
w.SearchStopper.Requested = false
w.ticks = 0
}
func (w *ListSearchCallbacks) StartingPosition() (interface{}, error) {
p, err := packetNumberFromCurrentTableRow()
if err != nil {
return ListResult{}, err
}
if packetListView == nil {
return ListResult{}, fmt.Errorf("No packets loaded")
}
coords, err := packetListView.FocusXY()
if err != nil {
return ListResult{}, err
}
return ListResult{
PacketNum: p.Pos,
Column: coords.Column + 1,
}, nil
}
// own goroutine
// startPacketNumber >= 1
func (w *ListSearchCallbacks) SearchPacketsFrom(ifrom interface{}, istart interface{}, term search.INeedle, app gowid.IApp) {
start := istart.(ListResult)
from := ifrom.(ListResult)
res := search.Result{}
// True if we have packets in the current batch to search (and we aren't blocked waiting for them to load)
curPacketNumber := from.PacketNum
column := from.Column
var resumeAt *ListResult
defer func() {
if resumeAt != nil {
w.search <- search.IntermediateResult{
Res: res,
ResumeAt: *resumeAt,
}
} else {
w.search <- search.IntermediateResult{
Res: res,
}
}
}()
Loop:
for {
// Map from packet number to index in pdml array
w.DoIfStopped(func() {
res.Interrupted = true
})
if res.Interrupted {
break Loop
}
Loader.PsmlLoader.Lock()
// curPacketNumber is the packet number from the pdml <packet>24</packet>. Remember there might
// be a display filter in place.
packetIndex, ok := Loader.PacketNumberMap[curPacketNumber]
if !ok {
// 1-based - packet number e.g. <packet>24</packet>
resumeAt = &ListResult{
PacketNum: curPacketNumber,
}
Loader.PsmlLoader.Unlock()
break
}
if packetIndex >= len(Loader.PsmlData()) {
panic(nil)
}
datas := Loader.PsmlData()[packetIndex]
Loader.PsmlLoader.Unlock()
if column > len(datas) {
column = len(datas)
}
for j, data := range datas[column:len(datas)] {
mpos := term.Search(data)
if mpos != -1 {
coords := ListResult{
Column: j + column,
PacketNum: curPacketNumber,
}
res.Position = coords
res.Success = true
// Terminate the search
break Loop
}
}
column = 0
w.samePacket = false
// Can this be more sophisticated?
Loader.PsmlLoader.Lock()
// 32, 44, 45, 134, 209,...
curPacketNumber, ok = Loader.PacketNumberOrder[curPacketNumber]
if !ok {
curPacketNumber = Loader.PacketNumberOrder[0]
}
Loader.PsmlLoader.Unlock()
if curPacketNumber == start.PacketNum {
break Loop
}
}
}
func (s *ListSearchCallbacks) SearchPacketsResult(res search.Result, app gowid.IApp) {
app.Run(gowid.RunFunction(func(app gowid.IApp) {
// Do this because we might be on the same listview packet, so the change callback
// won't run and adjust the lower view
//
// UPDATE - this assumes the original start position in the table is the same as
// the one now.
ClearProgressWidgetFor(app, SearchOwns)
if res.Interrupted {
return
}
if !res.Success {
OpenError("Not found.", app)
return
}
coords := res.Position.(ListResult)
trow, err := tableRowFromPacketNumber(coords.PacketNum)
if err != nil {
OpenError(fmt.Sprintf("Could not move to packet %d\n\n%v", coords.PacketNum, err), app)
return
}
packetListView.SetFocusXY(app, table.Coords{Column: coords.Column, Row: trow})
// Don't continue to jump to the end
AutoScroll = false
// Callback might not run if focus position in table is the same e.g. if we find a match
// on the same row that we started. So in that case, to expand the lower widgets, call
// setLowerWidgets explicitly - don't rely on the focus-changed callback. And I can't
// do a shortcut and call this if start == current because the starting position for the
// search may not be the same as the list-view row on display - maybe the search has
// resumed not that some extra PDML data has been loaded
setLowerWidgets(app)
// It looks better than having the found packet be at the top of the view
packetListView.GoToMiddle(app)
curPacketStructWidget.GoToMiddle(app)
curStructWidgetState = curPacketStructWidget.State()
}))
}
//======================================================================
// Local Variables:
// mode: Go
// fill-column: 110
// End: