[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