From 909d30694281f612e8bc73bb3e5ec855f1f161a8 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Mon, 23 Sep 2024 17:24:55 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20wg=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=B0=81=E8=A3=85hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{wiregasm.js => wiregasm_load.js} | 0 public/wiregasm/worker.js | 4 +- src/views/traceManage/tshark/hooks/usePCAP.ts | 317 +++++++++++++++++ src/views/traceManage/tshark/index.vue | 321 ++---------------- 4 files changed, 338 insertions(+), 304 deletions(-) rename public/wiregasm/{wiregasm.js => wiregasm_load.js} (100%) create mode 100644 src/views/traceManage/tshark/hooks/usePCAP.ts diff --git a/public/wiregasm/wiregasm.js b/public/wiregasm/wiregasm_load.js similarity index 100% rename from public/wiregasm/wiregasm.js rename to public/wiregasm/wiregasm_load.js diff --git a/public/wiregasm/worker.js b/public/wiregasm/worker.js index e4f1c208..1d650b5a 100644 --- a/public/wiregasm/worker.js +++ b/public/wiregasm/worker.js @@ -1,7 +1,7 @@ // load the Wiregasm library importScripts( - '/wiregasm/wiregasm_new.js', - '/wiregasm/wiregasm.js' + '/wiregasm/wiregasm_new.js', // self-compilation es5 + '/wiregasm/wiregasm_load.js' // 'https://cdn.jsdelivr.net/npm/@goodtools/wiregasm/dist/wiregasm.js' ); diff --git a/src/views/traceManage/tshark/hooks/usePCAP.ts b/src/views/traceManage/tshark/hooks/usePCAP.ts new file mode 100644 index 00000000..0d40a51f --- /dev/null +++ b/src/views/traceManage/tshark/hooks/usePCAP.ts @@ -0,0 +1,317 @@ +import { onBeforeUnmount, onMounted, reactive } from 'vue'; +import { scriptUrl } from '@/assets/js/wiregasm_worker'; +import { WK, OptionsType } from '@/plugins/wk-worker'; +const wk = new WK(); + +export const NO_SELECTION = { id: '', idx: 0, start: 0, length: 0 }; + +type StateType = { + /**初始化 */ + initialized: boolean; + /**pcap信息 */ + summary: { + filename: string; + file_type: string; + file_length: number; + file_encap_type: string; + packet_count: number; + start_time: number; + stop_time: number; + elapsed_time: number; + }; + /**字段 */ + columns: string[]; + /**过滤条件 */ + filter: string; + /**过滤条件错误信息 */ + filterError: string | null; + /**当前过滤条件 */ + currentFilter: string; + /**当前选中的帧编号 */ + selectedFrame: number; + /**当前选中的帧数据 */ + selectedPacket: { tree: any[]; data_sources: any[] }; + /**pcap包帧数据 */ + packetFrameData: Map | null; + /**当前选中的帧数据-空占位 */ + selectedTreeEntry: typeof NO_SELECTION; + /**选择帧的Dump数据标签 */ + selectedDataSourceIndex: number; + /**处理完成状态 */ + finishedProcessing: boolean; + /**pcap包帧数,匹配帧数 */ + totalFrames: number; + /**pcap包帧数据 */ + packetFrames: any[]; + /**加载帧数 */ + nextPageSize: number; + /**加载页数 */ + nextPageNum: number; + /**加载下一页 */ + nextPageLoad: boolean; +}; + +export function usePCAP() { + const state = reactive({ + initialized: false, + summary: { + filename: '', + file_type: 'Wireshark/tcpdump/... - pcap', + file_length: 0, + file_encap_type: 'Ethernet', + packet_count: 0, + start_time: 0, + stop_time: 0, + elapsed_time: 0, + }, + columns: [], + filter: '', + filterError: null, + currentFilter: '', + selectedFrame: 1, + /**当前选中的帧数据 */ + selectedPacket: { tree: [], data_sources: [] }, + packetFrameData: null, // 注意:Map 需要额外处理 + selectedTreeEntry: NO_SELECTION, // NO_SELECTION 需要定义 + /**选择帧的Dump数据标签 */ + selectedDataSourceIndex: 0, + /**处理完成状态 */ + finishedProcessing: false, + totalFrames: 0, + packetFrames: [], + nextPageNum: 1, + nextPageSize: 40, + nextPageLoad: false, + }); + + // 清除帧数据和报文信息状态 + function handleStateReset() { + // 加载pcap包的数据 + state.nextPageNum = 1; + // 选择帧的数据 + state.selectedFrame = 0; + state.selectedPacket = { tree: [], data_sources: [] }; + state.packetFrameData = null; + state.selectedTreeEntry = NO_SELECTION; + state.selectedDataSourceIndex = 0; + } + + /**解析帧数据为简单结构 */ + function parseFrameData(id: string, node: Record) { + let map = new Map(); + + if (node.tree && node.tree.length > 0) { + for (let i = 0; i < node.tree.length; i++) { + const subMap = parseFrameData(`${id}-${i}`, node.tree[i]); + subMap.forEach((value, key) => { + map.set(key, value); + }); + } + } else if (node.length > 0) { + map.set(id, { + id: id, + idx: node.data_source_idx, + start: node.start, + length: node.length, + }); + } + + return map; + } + + /**帧数据点击选中 */ + function handleSelectedTreeEntry(e: any) { + console.log('fnSelectedTreeEntry', e); + state.selectedTreeEntry = e; + } + /**报文数据点击选中 */ + function handleSelectedFindSelection(src_idx: number, pos: number) { + console.log('fnSelectedFindSelection', pos); + if (state.packetFrameData == null) return; + // find the smallest one + let current = null; + for (let [k, pp] of state.packetFrameData) { + if (pp.idx !== src_idx) continue; + + if (pos >= pp.start && pos <= pp.start + pp.length) { + if ( + current != null && + state.packetFrameData.get(current).length > pp.length + ) { + current = k; + } else { + current = k; + } + } + } + if (current != null) { + state.selectedTreeEntry = state.packetFrameData.get(current); + } + } + /**包数据表点击选中 */ + function handleSelectedFrame(no: number) { + console.log('fnSelectedFrame', no, state.totalFrames); + state.selectedFrame = no; + wk.send({ type: 'select', number: state.selectedFrame }); + } + /**包数据表滚动底部加载 */ + function handleScrollBottom() { + const totalFetched = state.packetFrames.length; + console.log('fnScrollBottom', totalFetched); + if (!state.nextPageLoad && totalFetched < state.totalFrames) { + state.nextPageLoad = true; + state.nextPageNum++; + loaldFrames(state.filter, state.nextPageNum); + } + } + /**包数据表过滤 */ + function handleFilterFrames() { + console.log('fnFilterFinish', state.filter); + wk.send({ type: 'check-filter', filter: state.filter }); + } + /**包数据表加载 */ + function loaldFrames(filter: string, page: number = 1) { + if (!(state.initialized && state.finishedProcessing)) return; + const limit = state.nextPageSize; + wk.send({ + type: 'frames', + filter: filter, + skip: (page - 1) * limit, + limit: limit, + }); + } + + /**加载包文件 */ + function handleLoadFile(file: File | Blob) { + state.summary = { + filename: '', + file_type: 'Wireshark/tcpdump/... - pcap', + file_length: 0, + file_encap_type: 'Ethernet', + packet_count: 0, + start_time: 0, + stop_time: 0, + elapsed_time: 0, + }; + state.finishedProcessing = false; + + wk.send({ type: 'process', file: file }); + } + + /**本地示例文件 */ + async function handleLoadExample() { + const name = 'test_ethernet.pcap'; + const res = await fetch('/wiregasm/test_ethernet.pcap'); + const body = await res.arrayBuffer(); + + state.summary = { + filename: '', + file_type: 'Wireshark/tcpdump/... - pcap', + file_length: 0, + file_encap_type: 'Ethernet', + packet_count: 0, + start_time: 0, + stop_time: 0, + elapsed_time: 0, + }; + state.finishedProcessing = false; + + wk.send({ type: 'process-data', name: name, data: body }); + } + + /**接收数据后回调 */ + function wkMessage(res: Record) { + switch (res.type) { + case 'status': + console.info(res.status); + break; + case 'error': + console.warn(res.error); + break; + case 'init': + wk.send({ type: 'columns' }); + state.initialized = true; + break; + case 'columns': + state.columns = res.data; + break; + case 'frames': + // console.log(res.data); + const { matched, frames } = res.data; + state.totalFrames = matched; + + if (state.nextPageNum == 1) { + state.packetFrames = frames; + // 有匹配的选择第一个 + if (frames.length > 0) { + state.selectedFrame = frames[0].number; + handleSelectedFrame(state.selectedFrame); + } + } else { + state.packetFrames = state.packetFrames.concat(frames); + state.nextPageLoad = false; + } + break; + case 'selected': + state.selectedPacket = res.data; + state.packetFrameData = parseFrameData('root', res.data); + state.selectedTreeEntry = NO_SELECTION; + state.selectedDataSourceIndex = 0; + break; + case 'processed': + // setStatus(`Error: non-zero return code (${e.data.code})`); + state.finishedProcessing = true; + if (res.data.code === 0) { + state.summary = res.data.summary; + } + + // 加载数据 + handleStateReset(); + loaldFrames(state.filter); + break; + case 'filter': + const filterRes = res.data; + if (filterRes.ok) { + state.currentFilter = state.filter; + state.filterError = null; + // 加载数据 + handleStateReset(); + loaldFrames(state.filter); + } else { + state.filterError = filterRes.error; + } + break; + default: + console.warn(res); + break; + } + } + + onMounted(() => { + // 建立链接 + const options: OptionsType = { + url: scriptUrl, + onmessage: wkMessage, + onerror: (ev: any) => { + console.error(ev); + }, + }; + wk.connect(options); + }); + + onBeforeUnmount(() => { + wk.close(); + }); + + return { + state, + handleSelectedTreeEntry, + handleSelectedFindSelection, + handleSelectedFrame, + handleScrollBottom, + handleFilterFrames, + handleLoadExample, + handleLoadFile, + }; +} +export default usePCAP; diff --git a/src/views/traceManage/tshark/index.vue b/src/views/traceManage/tshark/index.vue index 3e19bca1..53bfed62 100644 --- a/src/views/traceManage/tshark/index.vue +++ b/src/views/traceManage/tshark/index.vue @@ -1,5 +1,4 @@