[Gd-chatter] r11531 - in trunk/libraries: gui-sniffer layer packetizer
andreas at gwydiondylan.org
andreas at gwydiondylan.org
Sun Dec 9 21:46:24 CET 2007
Author: andreas
Date: Sun Dec 9 21:46:22 2007
New Revision: 11531
Modified:
trunk/libraries/gui-sniffer/commands.dylan
trunk/libraries/gui-sniffer/main.dylan
trunk/libraries/layer/layer.dylan
trunk/libraries/layer/module.dylan
trunk/libraries/layer/tcp.dylan
trunk/libraries/layer/udp.dylan
trunk/libraries/packetizer/filter-parser.dylan
trunk/libraries/packetizer/module.dylan
Log:
job: 7299
Increased flexibility in socket creation: arbitrary filter and completer
parameters can be specified. This allows for a more compact "ping"
implementation.
Modified: trunk/libraries/gui-sniffer/commands.dylan
==============================================================================
--- trunk/libraries/gui-sniffer/commands.dylan (original)
+++ trunk/libraries/gui-sniffer/commands.dylan Sun Dec 9 21:46:22 2007
@@ -63,18 +63,15 @@
define method do-execute-command (context :: <nnv-context>, command :: <ping-command>)
let target = command.%target;
let stream = context.context-server.server-output-stream;
- let demux-output = create-output-for-filter(context.nnv-context.ip-layer.demultiplexer,
- format-to-string("(icmp) & (ipv4.source-address = %s)",
- target));
+ let socket = create-filter-socket(context.nnv-context.ip-layer,
+ list(protocol: 1, source-address: target),
+ #());
let response-handler = make(<closure-node>,
- closure: method(packet)
+ closure: method(packet :: <icmp-frame>)
format(stream, "Host %s is alive\n", target);
- //refresh-output(context);
- //disconnect(demux-output, response-handler);
- remove-output(context.nnv-context.ip-layer.demultiplexer,
- demux-output);
+ close-socket(socket);
end);
- connect(demux-output, response-handler);
+ connect(socket, response-handler);
let icmp = icmp-frame(code: 0, icmp-type: 8,
payload: read-frame(<raw-frame>, "123412341234123412341234123412341234123412341234"));
send(context.nnv-context.ip-layer, target, icmp);
Modified: trunk/libraries/gui-sniffer/main.dylan
==============================================================================
--- trunk/libraries/gui-sniffer/main.dylan (original)
+++ trunk/libraries/gui-sniffer/main.dylan Sun Dec 9 21:46:22 2007
@@ -19,3 +19,4 @@
main()
+
Modified: trunk/libraries/layer/layer.dylan
==============================================================================
--- trunk/libraries/layer/layer.dylan (original)
+++ trunk/libraries/layer/layer.dylan Sun Dec 9 21:46:22 2007
@@ -44,6 +44,9 @@
define open generic demultiplexer (object :: <layer>) => (res :: <demultiplexer>);
define open generic sockets (object :: <layer>) => (res :: <collection>);
+// Every layer handles frames of a certain type. This g.f. returns the type.
+define open generic frame-type-for-layer (layer :: <layer>) => (frame-type :: subclass(<frame>));
+
define abstract class <layer> (<object>)
constant slot fan-in :: <fan-in> = make(<fan-in>);
constant slot fan-out :: <fan-out> = make(<fan-out>);
@@ -98,6 +101,64 @@
slot completer :: <completer>;
end;
+define class <filter-socket> (<socket>)
+end;
+
+define method connect (node :: <single-push-output-node>, socket :: <filter-socket>)
+ connect(node.the-output, socket.completer.the-input);
+end;
+
+define method connect (node :: <push-output>, socket :: <filter-socket>)
+ connect(node, socket.completer.the-input);
+end;
+
+define method disconnect (node :: <push-output>, socket :: <filter-socket>)
+ disconnect(node, socket.completer.the-input);
+end;
+
+define method disconnect (node :: <single-push-output-node>, socket :: <filter-socket>)
+ disconnect(node.the-output, socket.completer.the-input);
+end;
+
+define method connect (socket :: <filter-socket>, input :: <push-input>)
+ connect(socket.decapsulator.the-output, input);
+end;
+
+define method connect (socket :: <filter-socket>, input :: <single-push-input-node>)
+ connect(socket.decapsulator.the-output, input.the-input);
+end;
+
+define method disconnect (socket :: <filter-socket>, input :: <push-input>)
+ disconnect(socket.decapsulator.the-output, input);
+end;
+
+define method disconnect (socket :: <filter-socket>, input :: <single-push-input-node>)
+ disconnect(socket.decapsulator.the-output, input.the-input);
+end;
+
+define method create-filter-socket (layer :: <layer>,
+ filter-key-value-pairs,
+ completer-key-value-pairs)
+ => (socket :: <filter-socket>);
+ let socket = make(<filter-socket>);
+ let frame-type = frame-type-for-layer(layer);
+ let template-frame = apply(make, frame-type, completer-key-value-pairs);
+ socket.completer := make(<completer>, template-frame: template-frame);
+ socket.demultiplexer-output
+ := create-output-for-filter(layer.demultiplexer,
+ apply(build-frame-filter, frame-type, filter-key-value-pairs));
+ connect(socket.demultiplexer-output, socket.decapsulator);
+ connect(socket.completer, layer.fan-in);
+ socket;
+end;
+
+define method close-socket (socket :: <filter-socket>) => ();
+ disconnect(socket.decapsulator.the-output, socket.decapsulator.the-output.connected-input);
+ disconnect(socket.demultiplexer-output, socket.decapsulator.the-input);
+ disconnect(socket.completer.the-output, socket.completer.the-output.conected-input);
+ disconnect(socket.completer.the-input.connected-output, socket.completer.the-input);
+end;
+
define abstract class <adapter> (<object>)
end;
@@ -120,6 +181,11 @@
connect(layer.fan-out, layer.demultiplexer);
end;
+define method frame-type-for-layer (layer :: <ethernet-layer>)
+ => (type == <ethernet-frame>)
+ <ethernet-frame>
+end;
+
define open generic ethernet-type-code (object :: <ethernet-socket>) => (res :: <integer>);
define open generic listen-address (object :: <object>) => (res :: <object>);
@@ -371,6 +437,11 @@
slot raw-input;
end;
+define method frame-type-for-layer (layer :: <ip-layer>)
+ => (type == <ipv4-frame>)
+ <ipv4-frame>
+end;
+
define class <route> (<object>)
constant slot cidr :: <cidr>, required-init-keyword: cidr:;
end;
Modified: trunk/libraries/layer/module.dylan
==============================================================================
--- trunk/libraries/layer/module.dylan (original)
+++ trunk/libraries/layer/module.dylan Sun Dec 9 21:46:22 2007
@@ -10,6 +10,7 @@
use threads;
use network-flow;
use packetizer;
+ use packet-filter;
use timer;
use flow;
use network-interfaces;
@@ -45,15 +46,16 @@
init-arp-handler,
decapsulator,
create-socket,
+ create-filter-socket,
create-raw-socket,
+ close-socket,
build-ethernet-layer,
build-ip-layer,
send-socket,
send,
set-ip-address,
delete-route,
- add-next-hop-route,
- demultiplexer; // HACK: remove me!
+ add-next-hop-route;
export <udp-layer>, build-udp-layer,
<tcp-layer>;
Modified: trunk/libraries/layer/tcp.dylan
==============================================================================
--- trunk/libraries/layer/tcp.dylan (original)
+++ trunk/libraries/layer/tcp.dylan Sun Dec 9 21:46:22 2007
@@ -12,6 +12,11 @@
slot ip-send-socket :: <ip-socket>;
end;
+define method frame-type-for-layer (layer :: <tcp-layer>)
+ => (type == <tcp-frame>)
+ <tcp-frame>
+end;
+
define inline method generate-id (tcp-frame :: <tcp-frame>) => (res :: <vector>)
generate-id-aux (tcp-frame.parent.source-address,
tcp-frame.source-port,
Modified: trunk/libraries/layer/udp.dylan
==============================================================================
--- trunk/libraries/layer/udp.dylan (original)
+++ trunk/libraries/layer/udp.dylan Sun Dec 9 21:46:22 2007
@@ -13,6 +13,11 @@
layer.ip-send-socket := socket;
end;
+define method frame-type-for-layer (layer :: <udp-layer>)
+ => (type == <udp-frame>)
+ <udp-frame>
+end;
+
define class <udp-socket> (<socket>)
constant slot udp-layer :: <udp-layer>, required-init-keyword: layer:;
constant slot server-port :: <integer>, required-init-keyword: server-port:;
Modified: trunk/libraries/packetizer/filter-parser.dylan
==============================================================================
--- trunk/libraries/packetizer/filter-parser.dylan (original)
+++ trunk/libraries/packetizer/filter-parser.dylan Sun Dec 9 21:46:22 2007
@@ -137,6 +137,41 @@
format(stream, "~ (%=)", filter.expression);
end;
+define function build-field-equals-filter (frame-type :: type-union(<string>, <symbol>, subclass(<container-frame>)),
+ field-name :: type-union(<string>, <symbol>),
+ value)
+ => (filter :: <field-equals>)
+ if (instance?(frame-type, <symbol>))
+ frame-type := as(<string>, frame-type)
+ end;
+ unless (instance?(frame-type, <string>))
+ frame-type := frame-type.frame-name;
+ end;
+ if (instance?(field-name, <symbol>))
+ field-name := as(<string>, field-name)
+ end;
+ let (field, frame-name) = find-protocol-field(frame-type, field-name);
+ unless (instance?(value, high-level-type(field.type)))
+ value := read-frame(field.type, value);
+ end;
+ make(<field-equals>,
+ frame: as(<symbol>, frame-name),
+ name: as(<symbol>, field-name),
+ value: value,
+ field: field);
+end;
+
+define function build-frame-filter (frame-type :: type-union(<string>, <symbol>, subclass(<container-frame>)),
+ #rest keyword-value-pairs)
+ => (filter :: <filter-expression>)
+ let filters = make(<stretchy-vector>);
+ for(i from 0 below keyword-value-pairs.size by 2)
+ add!(filters, build-field-equals-filter(frame-type, keyword-value-pairs[i], keyword-value-pairs[i + 1]));
+ end;
+
+ reduce1(method (x, y) make(<and-expression>, left: x, right: y) end, filters);
+end;
+
define function test-filter()
format-out("%=\n",
parse-filter("(ip.source-address = 23.23.23.23) & ((tcp.source-port = 23) & (foo))"));
Modified: trunk/libraries/packetizer/module.dylan
==============================================================================
--- trunk/libraries/packetizer/module.dylan (original)
+++ trunk/libraries/packetizer/module.dylan Sun Dec 9 21:46:22 2007
@@ -161,7 +161,8 @@
<or-expression>,
<not-expression>,
matches?,
- parse-filter;
+ parse-filter,
+ build-frame-filter;
end;
More information about the chatter
mailing list