[Gd-chatter] r10850 - in trunk/libraries: gui-sniffer packetizer
hannes at gwydiondylan.org
hannes at gwydiondylan.org
Fri Aug 11 18:16:22 CEST 2006
Author: hannes
Date: Fri Aug 11 18:16:20 2006
New Revision: 10850
Modified:
trunk/libraries/gui-sniffer/gui-sniffer.dylan
trunk/libraries/packetizer/module.dylan
trunk/libraries/packetizer/pcap.dylan
Log:
Bug: 7299
*cleanup redrawing
*filter needs an update/refresh of the table
*receiving packets via flow module
*open file/interface needs a reinit-gui (to set count to 0 and delete all shown packets)
*save meta information of a frame (number, timestamp (actually, duration since start of capturing))
*support for writing timestamps in pcap-files (make-unix-time gets a <day/time-duration> and generates an 8 byte unix timestamp)
Modified: trunk/libraries/gui-sniffer/gui-sniffer.dylan
==============================================================================
--- trunk/libraries/gui-sniffer/gui-sniffer.dylan (original)
+++ trunk/libraries/gui-sniffer/gui-sniffer.dylan Fri Aug 11 18:16:20 2006
@@ -53,6 +53,7 @@
define method frame-root-generator (frame :: <frame>)
list(frame);
end;
+
define method frame-print-label (frame-field :: <frame-field>)
if (~ frame-children-predicate(frame-field))
format-to-string("%s: %=", frame-field.field.field-name, frame-field.value)
@@ -79,20 +80,31 @@
format-to-string("%=", frame);
end;
-define method print-source (frame :: <ethernet-frame>)
- as(<string>, frame.source-address)
+define method print-source (frame :: <frame-with-metadata>)
+ as(<string>, frame.real-frame.source-address)
+end;
+
+define method print-destination (frame :: <frame-with-metadata>)
+ as(<string>, frame.real-frame.destination-address)
+end;
+
+define method print-protocol (frame :: <frame-with-metadata>)
+ frame.real-frame.type-code
end;
-define method print-destination (frame :: <ethernet-frame>)
- as(<string>, frame.destination-address)
+define method print-info (frame :: <frame-with-metadata>)
+ summary(frame.real-frame.payload)
end;
-define method print-protocol (frame :: <ethernet-frame>)
- frame.type-code
+define method print-number (frame :: <frame-with-metadata>)
+ frame.number;
end;
-define method print-info (frame :: <ethernet-frame>)
- summary(frame.payload)
+define method print-time (frame :: <frame-with-metadata>)
+ let (days, hours, minutes, seconds, microseconds)
+ = decode-duration(frame.receive-time);
+ let secs = (((days * 24 + hours) * 60) + minutes) * 60 + seconds;
+ secs + as(<float>, microseconds) / 1000000
end;
define method apply-filter (frame :: <gui-sniffer-frame>)
@@ -104,15 +116,32 @@
frame.filter-expression := #f
end;
if (old ~= frame.filter-expression)
- refresh-packet-table(frame);
+ filter-packet-table(frame);
+ end;
+end;
+
+define method filter-packet-table (frame :: <gui-sniffer-frame>)
+ let shown-packets
+ = if (frame.filter-expression)
+ choose-by(rcurry(matches?, frame.filter-expression),
+ map(real-frame, frame.network-frames),
+ frame.network-frames)
+ else
+ frame.network-frames
+ end;
+ unless (shown-packets = gadget-items(frame.packet-table))
+ gadget-items(frame.packet-table) := shown-packets;
+ show-packet(frame);
end;
end;
define method show-packet (frame :: <gui-sniffer-frame>)
let packet = frame.packet-table.gadget-value;
+ if (packet) packet := real-frame(packet) end;
show-packet-tree(frame, packet);
show-packet-hex-dump(frame, packet);
end;
+
define method show-packet-tree (frame :: <gui-sniffer-frame>, packet)
frame.packet-tree-view.tree-control-roots
:= if (packet)
@@ -141,15 +170,16 @@
end;
define variable *count* :: <integer> = 0;
-define method counter (frame :: <object>)
+define method counter ()
*count* := *count* + 1;
*count*;
end;
define frame <gui-sniffer-frame> (<simple-frame>, <filter>)
- slot network-frames = make(<stretchy-vector>);
+ slot network-frames :: <stretchy-vector> = make(<stretchy-vector>);
slot filter-expression = #f;
slot ethernet-interface = #f;
+ slot started-capturing-at :: <date> = current-date();
pane filter-field (frame)
make(<text-field>,
@@ -164,8 +194,13 @@
pane packet-table (frame)
make(<table-control>,
- headings: #("No", "Source", "Destination", "Protocol", "Info"),
- generators: list(counter, print-source, print-destination, print-protocol, print-info),
+ headings: #("No", "Time", "Source", "Destination", "Protocol", "Info"),
+ generators: list(print-number,
+ print-time,
+ print-source,
+ print-destination,
+ print-protocol,
+ print-info),
items: #[],
value-changed-callback: method(x) show-packet(frame) end);
@@ -218,15 +253,13 @@
define method open-pcap-file (frame :: <gui-sniffer-frame>)
let file = choose-file(frame: frame, direction: #"input");
if (file)
- frame.network-frames := make(<stretchy-vector>);
- refresh-packet-table(frame);
+ reinit-gui(frame);
let file-stream = make(<file-stream>, locator: file, direction: #"input");
let pcap-reader = make(<pcap-file-reader>, stream: file-stream);
connect(pcap-reader, frame);
toplevel(pcap-reader);
gadget-label(frame.sniffer-status-bar) := concatenate("Opened ", file);
close(file-stream);
- refresh-packet-table(frame);
end;
end;
@@ -239,7 +272,15 @@
if-exists: #"replace");
let pcap-writer = make(<pcap-file-writer>, stream: file-stream);
connect(frame, pcap-writer);
- do(curry(push-data, frame.the-output), frame.network-frames);
+ do(curry(push-data, frame.the-output),
+ map(method(x)
+ make(<pcap-packet>,
+ timestamp: make-unix-time(x.receive-time),
+ //XXX: should be absolute time since 1.1.1970, but
+ //getting integer overflows, so use relative time since
+ //packet capturing for now
+ payload: x.real-frame)
+ end, frame.network-frames));
//XXX: disconnect in flow graph, but disconnect is NYI
gadget-label(frame.sniffer-status-bar) := concatenate("Wrote ", file);
close(file-stream);
@@ -253,10 +294,10 @@
name: interface-name,
promiscious?: promiscious?);
connect(interface, frame);
- frame.network-frames := make(<stretchy-vector>);
- refresh-packet-table(frame);
+ reinit-gui(frame);
make(<thread>, function: curry(toplevel, interface));
frame.ethernet-interface := interface;
+ frame.started-capturing-at := current-date();
gadget-label(frame.sniffer-status-bar) := concatenate("Capturing ", interface-name);
end;
end;
@@ -288,30 +329,30 @@
end;
end;
-define method refresh-packet-table (frame :: <gui-sniffer-frame>)
- let shown-packets = if (frame.filter-expression)
- choose(rcurry(matches?, frame.filter-expression),
- frame.network-frames)
- else
- frame.network-frames
- end;
+define method reinit-gui (frame :: <gui-sniffer-frame>)
*count* := 0;
- if (shown-packets = gadget-items(frame.packet-table))
- update-gadget(frame.packet-table)
- else
- gadget-items(frame.packet-table) := shown-packets;
- show-packet(frame);
- end;
+ frame.network-frames := make(<stretchy-vector>);
+ gadget-items(frame.packet-table) := frame.network-frames;
+ show-packet(frame);
+end;
+
+define class <frame-with-metadata> (<object>)
+ constant slot real-frame :: <ethernet-frame>, required-init-keyword: frame:;
+ constant slot number :: <integer> = counter();
+ slot receive-time :: <day/time-duration>, required-init-keyword: receive-time:;
end;
define method push-data-aux (input :: <push-input>,
node :: <gui-sniffer-frame>,
frame :: <frame>)
- add!(node.network-frames, frame);
+ let duration = current-date() - node.started-capturing-at;
+ let frame-with-meta = make(<frame-with-metadata>, frame: frame, receive-time: duration);
+ add!(node.network-frames, frame-with-meta);
if (~ node.filter-expression | matches?(frame, node.filter-expression))
- add-item(node.packet-table, make-item(node.packet-table, frame))
+ add-item(node.packet-table, make-item(node.packet-table, frame-with-meta))
end;
end;
+
begin
let gui-sniffer = make(<gui-sniffer-frame>);
start-frame(gui-sniffer);
Modified: trunk/libraries/packetizer/module.dylan
==============================================================================
--- trunk/libraries/packetizer/module.dylan (original)
+++ trunk/libraries/packetizer/module.dylan Fri Aug 11 18:16:20 2006
@@ -34,7 +34,7 @@
<repeated-field>;
export <pcap-file>, <pcap-file-header>, <pcap-packet>, header, packets,
- $DLT-EN10MB, $DLT-PRISM-HEADER;
+ $DLT-EN10MB, $DLT-PRISM-HEADER, make-unix-time;
export <icmp-frame>, code, type, checksum;
Modified: trunk/libraries/packetizer/pcap.dylan
==============================================================================
--- trunk/libraries/packetizer/pcap.dylan (original)
+++ trunk/libraries/packetizer/pcap.dylan Fri Aug 11 18:16:20 2006
@@ -27,10 +27,14 @@
define function get-seconds () => (seconds :: <collection>)
let (year, month, day, hours, minutes, seconds,
day-of-week, time-zone-offset) = decode-date(current-date());
+ int-to-byte-vector(seconds);
+end;
+
+define function int-to-byte-vector (int :: <integer>) => (res :: <byte-vector>)
let res = make(<byte-vector>, size: 4);
for (ele in res,
i from 0)
- res[i] := logand(#xff, ash(seconds, - i * 8));
+ res[i] := logand(#xff, ash(int, - i * 8));
end;
res;
end;
@@ -42,6 +46,15 @@
= little-endian-unsigned-integer-4byte(#(#x00, #x00, #x00, #x00));
end;
+define method make-unix-time (dur :: <day/time-duration>)
+ => (res :: <unix-time-value>)
+ let (days, hours, minutes, seconds, microseconds) = decode-duration(dur);
+ let secs = (((days * 24 + hours) * 60) + minutes) * 60 + seconds;
+ make(<unix-time-value>,
+ seconds: little-endian-unsigned-integer-4byte(int-to-byte-vector(secs)),
+ microseconds: little-endian-unsigned-integer-4byte(int-to-byte-vector(microseconds)));
+end;
+
define protocol pcap-packet (header-frame)
field timestamp :: <unix-time-value> = make(<unix-time-value>);
field capture-length :: <3byte-little-endian-unsigned-integer>,
More information about the chatter
mailing list