[Gd-chatter] r10936 - in trunk/libraries: layer packetizer

andreas at gwydiondylan.org andreas at gwydiondylan.org
Thu Oct 26 22:31:24 CEST 2006


Author: andreas
Date: Thu Oct 26 22:31:19 2006
New Revision: 10936

Added:
   trunk/libraries/layer/udp.dylan   (contents, props changed)
Modified:
   trunk/libraries/layer/layer.dylan
   trunk/libraries/layer/layer.hdp
   trunk/libraries/layer/tcp.dylan
   trunk/libraries/packetizer/dns.dylan
   trunk/libraries/packetizer/fields.dylan
   trunk/libraries/packetizer/module.dylan
   trunk/libraries/packetizer/protocol-definer-macro.dylan
Log:
bug: 7299

 * beginning of UDP layer
 * simple DNS query

Modified: trunk/libraries/layer/layer.dylan
==============================================================================
--- trunk/libraries/layer/layer.dylan	(original)
+++ trunk/libraries/layer/layer.dylan	Thu Oct 26 22:31:19 2006
@@ -493,13 +493,15 @@
 
 
 define function init-ethernet ()
-  let int = make(<ethernet-interface>, name: "Intel");
+  let int = make(<ethernet-interface>, name: "Xtreme");
   let ethernet-layer = make(<ethernet-layer>, ethernet-interface: int);
   let arp-handler = make(<arp-handler>);
+/*
   arp-handler.arp-table[ipv4-address("192.168.0.23")]
     := make(<advertised-arp-entry>,
             mac-address: mac-address("00:de:ad:be:ef:00"),
             ip-address: ipv4-address("192.168.0.23"));
+*/
   let ip-layer = make(<ip-layer>);
   register-route(ip-layer, make(<next-hop-route>, cidr: as(<cidr>, "0.0.0.0/0"),
                                 next-hop: ipv4-address("192.168.0.1")));
@@ -514,6 +516,7 @@
                           ip-layer: ip-layer,
                           icmp-handler: icmp-handler);
   let thr = make(<thread>, function: curry(toplevel, int));
+/*
   send(icmp-handler.ip-socket,
        ipv4-address("213.73.91.29"),
        make(<icmp-frame>,
@@ -534,6 +537,7 @@
             payload: parse-frame(<raw-frame>, as(<byte-vector>, #(#x23, #x42, #x0, #x0)))));
 
   format-out("Mac 192.168.2.1: %=\n", element(arp-handler.arp-table, ipv4-address("192.168.2.1"), default: #f));
+*/
   ip-layer;
 end;
 

Modified: trunk/libraries/layer/layer.hdp
==============================================================================
--- trunk/libraries/layer/layer.hdp	(original)
+++ trunk/libraries/layer/layer.hdp	Thu Oct 26 22:31:19 2006
@@ -4,3 +4,4 @@
 	cidr
 	layer
 	tcp
+	udp
\ No newline at end of file

Modified: trunk/libraries/layer/tcp.dylan
==============================================================================
--- trunk/libraries/layer/tcp.dylan	(original)
+++ trunk/libraries/layer/tcp.dylan	Thu Oct 26 22:31:19 2006
@@ -395,7 +395,7 @@
   process-event-locked(tcp-connection, #"close")
 end;
 
-define open generic listen-port (t :: <tcp-listener-socket>) => (res :: <integer>);
+define open generic listen-port (t :: <object>) => (res :: <integer>);
 define open generic connections (t :: <tcp-listener-socket>) => (res :: <deque>);
 define open generic listener-lock (t :: <tcp-listener-socket>) => (res :: <lock>);
 
@@ -473,27 +473,4 @@
 end;
 
 
-begin
-  let ip-layer = init-ethernet();
-  let tcp = make(<tcp-layer>, ip-layer: ip-layer, default-ip-address: ip-layer.default-ip-address);
-  let s = create-client-socket(tcp, ipv4-address("213.73.91.29"), 80);
-  write(s, "GET / HTTP/1.1\r\nHost: www.ccc.de\r\nConnection: keep-alive\r\n\r\n");
-  block(ret)
-    while (#t)
-      let res = read(s, 20, on-end-of-stream: #f);
-      //if (res)
-        //format-out("Read %s\n", map-as(<string>, curry(as, <character>), res))
-      //else
-        close(s);
-        ret();
-      //end;
-    end;
-  end;
-  let ss = create-server-socket(tcp, 23);
-  while (#t)
-    let conn = accept(ss);
-    write(conn, "fnord");
-    close(conn);
-  end;
-  sleep(1000);
-end;
+

Added: trunk/libraries/layer/udp.dylan
==============================================================================
--- (empty file)
+++ trunk/libraries/layer/udp.dylan	Thu Oct 26 22:31:19 2006
@@ -0,0 +1,74 @@
+module: layer
+
+define class <udp-layer> (<layer>)
+  constant slot ip-layer :: <ip-layer>, required-init-keyword: ip-layer:;
+  slot ip-send-socket :: <ip-socket>;
+end;
+
+define method initialize (layer :: <udp-layer>,
+                          #next next-method, #rest rest, #key, #all-keys)
+  next-method();
+  let socket = create-socket(layer.ip-layer, 17);
+  connect(socket.decapsulator, layer.demultiplexer);
+  layer.ip-send-socket := socket;
+end;
+
+define class <udp-socket> (<socket>)
+  constant slot listen-port :: <integer>, required-init-keyword: port:;
+  constant slot listen-address :: false-or(<ipv4-address>), init-keyword: address:;
+end;
+
+define method create-socket (layer :: <udp-layer>, port :: <integer>, #key address)
+ => (socket :: <udp-socket>)
+  let socket = make(<udp-socket>, port: port, address: address);
+  let template-frame = make(<udp-frame>, source-port: port);
+  socket.completer := make(<completer>, template-frame: template-frame);
+  socket.demultiplexer-output
+    := create-output-for-filter(layer.demultiplexer,
+                                format-to-string("udp.destination-port = %d", port));
+  connect(socket.demultiplexer-output, socket.decapsulator);
+  connect(socket.completer, layer.fan-in);
+  socket;
+end;
+
+define method send (socket :: <udp-socket>, destination :: <ipv4-address>, payload :: <container-frame>);
+end;                                  
+
+begin
+  let ip-layer = init-ethernet();
+  let udp = make(<udp-layer>, ip-layer: ip-layer);
+  let socket = create-socket(udp, 53);
+  connect(socket.decapsulator, make(<verbose-printer>, stream: *standard-output*));
+  send(udp.ip-send-socket, 
+       ipv4-address("141.1.1.1"),
+       make(<udp-frame>, source-port: 53, destination-port: 53,
+            payload: make(<dns-frame>,
+                          questions: vector(make(<dns-question>,
+                                                 question-type:  1, // A
+                                                 question-class: 1, // THE INTERNET
+                                                 domainname: as(<domain-name>, "www.ccc.de"))))));
+  sleep(10000);
+/*
+  let tcp = make(<tcp-layer>, ip-layer: ip-layer, default-ip-address: ip-layer.default-ip-address);
+  let s = create-client-socket(tcp, ipv4-address("213.73.91.29"), 80);
+  write(s, "GET / HTTP/1.1\r\nHost: www.ccc.de\r\nConnection: keep-alive\r\n\r\n");
+  block(ret)
+    while (#t)
+      let res = read(s, 20, on-end-of-stream: #f);
+      //if (res)
+        //format-out("Read %s\n", map-as(<string>, curry(as, <character>), res))
+      //else
+        close(s);
+        ret();
+      //end;
+    end;
+  end;
+  let ss = create-server-socket(tcp, 23);
+  while (#t)
+    let conn = accept(ss);
+    write(conn, "fnord");
+    close(conn);
+  end;
+  sleep(1000);
+*/
+end;

Modified: trunk/libraries/packetizer/dns.dylan
==============================================================================
--- trunk/libraries/packetizer/dns.dylan	(original)
+++ trunk/libraries/packetizer/dns.dylan	Thu Oct 26 22:31:19 2006
@@ -6,15 +6,15 @@
 define protocol dns-frame (container-frame)
   summary "DNS ID=%=, %= questions, %= answers",
     identifier, question-count, answer-count;
-  field identifier :: <2byte-big-endian-unsigned-integer>;
-  field query-or-response :: <1bit-unsigned-integer> = 1;
-  field opcode :: <4bit-unsigned-integer>;
-  field authoritative-answer :: <1bit-unsigned-integer>;
+  field identifier :: <2byte-big-endian-unsigned-integer> = 2342;
+  field query-or-response :: <1bit-unsigned-integer> = 0;
+  field opcode :: <4bit-unsigned-integer> = 0;
+  field authoritative-answer :: <1bit-unsigned-integer> = 0;
   field truncation :: <1bit-unsigned-integer> = 0;
   field recursion-desired :: <1bit-unsigned-integer> = 1;
   field recursion-available :: <1bit-unsigned-integer> = 0;
   field reserved :: <3bit-unsigned-integer> = 0;
-  field response-code :: <4bit-unsigned-integer>;
+  field response-code :: <4bit-unsigned-integer> = 0;
   field question-count :: <2byte-big-endian-unsigned-integer>,
     fixup: frame.questions.size;
   field answer-count :: <2byte-big-endian-unsigned-integer>,
@@ -45,8 +45,15 @@
   reduce1(method(a, b) concatenate(a, ".",  b) end, strings);
 end;
 
+define method as (class == <domain-name>, string :: <string>)
+ => (res :: <domain-name>)
+  let labels = split(string, '.');
+  labels := concatenate(labels, #(""));
+  make(<domain-name>, fragment: map(curry(as, <label>), labels));
+end;
+
 define protocol domain-name-fragment (container-frame)
-  field type-code :: <2bit-unsigned-integer>;
+  field type-code :: <2bit-unsigned-integer> = 0;
 end;
 
 define protocol label-offset (domain-name-fragment)
@@ -94,8 +101,17 @@
   res;
 end;
 
+define method as (class == <externally-delimited-string>, string :: <string>)
+ => (res :: <externally-delimited-string>)
+  let res = make(<externally-delimited-string>,
+                 data: make(<byte-sequence>, capacity: string.size));
+  copy-bytes(string, 0, res.data, 0, string.size);
+  res;
+end;
+
 define protocol label (domain-name-fragment)
-  field length :: <6bit-unsigned-integer>;
+  field length :: <6bit-unsigned-integer>,
+    fixup: frame.raw-data.frame-size.byte-offset;
   field raw-data :: <externally-delimited-string>,
     length: frame.length * 8;
 end;
@@ -105,6 +121,11 @@
   as(<string>, label.raw-data);
 end;  
 
+define method as (class == <label>, string :: <string>)
+ => (res :: <label>)
+  make(<label>, raw-data: as(<externally-delimited-string>, string))
+end;
+
 define method parse-frame (frame-type == <domain-name-fragment>,
                            packet :: <byte-sequence>,
                            #next next-method,
@@ -124,15 +145,16 @@
 define protocol dns-question (container-frame)
   field domainname :: <domain-name>;
   field question-type :: <2byte-big-endian-unsigned-integer>;
-  field question-class :: <2byte-big-endian-unsigned-integer>;
+  field question-class :: <2byte-big-endian-unsigned-integer> = 1;
 end;
 
 define protocol dns-resource-record (container-frame)
   field domainname :: <domain-name>;
   field rr-type :: <2byte-big-endian-unsigned-integer>;
-  field rr-class :: <2byte-big-endian-unsigned-integer>;
+  field rr-class :: <2byte-big-endian-unsigned-integer> = 1;
   field ttl :: <big-endian-unsigned-integer-4byte>;
-  field rdlength :: <2byte-big-endian-unsigned-integer>;
+  field rdlength :: <2byte-big-endian-unsigned-integer>,
+    fixup: frame.rdata.frame-size.byte-offset;
   variably-typed-field rdata,
     type-function: select (frame.rr-type)
                      1 => <a-host-address>;

Modified: trunk/libraries/packetizer/fields.dylan
==============================================================================
--- trunk/libraries/packetizer/fields.dylan	(original)
+++ trunk/libraries/packetizer/fields.dylan	Thu Oct 26 22:31:19 2006
@@ -105,6 +105,7 @@
 end;
 
 define abstract class <repeated-field> (<statically-typed-field>)
+  inherited slot init-value = #(), init-keyword: init-value:;
 end;
 
 define class <self-delimited-repeated-field> (<repeated-field>)

Modified: trunk/libraries/packetizer/module.dylan
==============================================================================
--- trunk/libraries/packetizer/module.dylan	(original)
+++ trunk/libraries/packetizer/module.dylan	Thu Oct 26 22:31:19 2006
@@ -20,6 +20,8 @@
     <out-of-bound-error>,
     encode-integer, decode-integer;
 
+  export <dns-frame>, <dns-question>, <domain-name>;
+
   export <udp-frame>, source-port, destination-port, length, checksum;
 
   export <tcp-frame>, sequence-number, acknowledgement-number,

Modified: trunk/libraries/packetizer/protocol-definer-macro.dylan
==============================================================================
--- trunk/libraries/packetizer/protocol-definer-macro.dylan	(original)
+++ trunk/libraries/packetizer/protocol-definer-macro.dylan	Thu Oct 26 22:31:19 2006
@@ -162,7 +162,7 @@
     => { slot ?name :: false-or(<frame>) = #f,
       init-keyword: ?#"name" }
     { repeated field ?:name ?rest:* }
-      => { slot ?name :: false-or(<stretchy-vector>) = #f,
+      => { slot ?name :: false-or(<collection>) = #f,
       init-keyword: ?#"name" }
 end;
 



More information about the chatter mailing list