diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-10-22 19:05:07 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-10-22 19:05:07 -0700 |
commit | d154c121a70e27466b43d1852ec672e2f70e1f36 (patch) | |
tree | 00bf78d1af8d46e93f5e478bfc9e7a5496557b86 | |
parent | 9a81d7460fdb16f4e77712e5381d9db8781f5ae6 (diff) | |
download | mu-d154c121a70e27466b43d1852ec672e2f70e1f36.tar.gz |
3562
Fix CI. Revert accidentally-added files.
-rw-r--r-- | 091socket.cc | 8 | ||||
-rw-r--r-- | 092socket.mu | 230 | ||||
-rw-r--r-- | html/091socket.cc.html | 8 | ||||
-rw-r--r-- | html/092socket.mu.html | 230 |
4 files changed, 214 insertions, 262 deletions
diff --git a/091socket.cc b/091socket.cc index bd3f4ed6..74626853 100644 --- a/091socket.cc +++ b/091socket.cc @@ -218,7 +218,6 @@ case _READ_FROM_SOCKET: { } :(before "End Primitive Recipe Implementations") case _READ_FROM_SOCKET: { - cerr << "$read-from-socket\n"; long long int x = static_cast<long long int>(ingredients.at(0).at(0)); socket_t* socket = reinterpret_cast<socket_t*>(x); // 1. we'd like to simply read() from the socket @@ -228,22 +227,19 @@ case _READ_FROM_SOCKET: { // 3. but poll() will block on EOF, so only use poll() on the very first // $read-from-socket on a socket if (!socket->polled) { + socket->polled = true; pollfd p; bzero(&p, sizeof(p)); p.fd = socket->fd; p.events = POLLIN | POLLHUP; - if (poll(&p, /*num pollfds*/1, /*timeout*/100/*ms*/) <= 0) { + if (poll(&p, /*num pollfds*/1, /*no timeout*/-1) <= 0) { raise << maybe(current_recipe_name()) << "error in $read-from-socket\n" << end(); products.resize(2); products.at(0).push_back(0); products.at(1).push_back(false); break; } - cerr << "poll output: " << p.revents << '\n'; - cerr << "setting socket->polled\n"; - socket->polled = true; } - cerr << "$read-from-socket " << x << " continuing\n"; int bytes = static_cast<int>(ingredients.at(1).at(0)); char* contents = new char[bytes]; bzero(contents, bytes); diff --git a/092socket.mu b/092socket.mu index 1fd2586b..6a5c427a 100644 --- a/092socket.mu +++ b/092socket.mu @@ -1,87 +1,69 @@ -# Wrappers around socket primitives that are easier to test. +# Wrappers around socket primitives that take a 'local-network' object and are +# thus easier to test. # -# To test client operations, use `assume-resources` with a filename that -# begins with a hostname. (Filenames starting with '/' are assumed to be -# local.) +# The current semantics of fake port-connections don't match UNIX socket ones, +# but we'll improve them as we learn more. + +container local-network [ + data:&:@:port-connection +] + +# Port connections represent connections to ports on localhost. +# Before passing a local-network object to network functions +# `start-reading-socket` and `start-writing-socket`, add port-connections to +# the local-network. +# +# For reading, `receive-from-socket` will check for a +# port-connection on the port parameter that's been passed in. If there's +# no port-connection for that port, it will return nothing and log an error. +# If there is a port-connection for that port, it will transmit the contents +# to the provided sink. # -# To test server operations, just run a real client against localhost. +# For writing, `start-writing-socket` returns a sink connecting the +# caller to the socket on the passed-in port. +container port-connection [ + port:num + contents:text +] -scenario example-server-test [ +def new-port-connection port:num, contents:text -> p:&:port-connection [ local-scope - # test server without a fake on a random (real) port - # that way repeatedly running the test will give ports time to timeout and - # close before reusing them - make-random-nondeterministic - port:num <- random-in-range 0/real-random-numbers, 8000, 8100 - run [ - socket:num <- $open-server-socket port - $print [server socket: ], socket, 10/newline - assert socket, [ -F - example-server-test: $open-server-socket failed] - $print [starting up server routine], 10/newline - handler-routine:number <- start-running serve-one-request socket, example-handler - ] - $print [starting to read from port ], port, 10/newline - source:&:source:char <- start-reading-from-network 0/real-resources, [localhost], [/], port - response:text <- drain source - 10:@:char/raw <- copy *response - memory-should-contain [ - 10:array:character <- [abc] - ] + load-ingredients + p:&:port-connection <- new port-connection:type + *p <- merge port, contents ] -# helper just for this scenario -def example-handler query:text -> response:text [ + +def new-fake-network -> n:&:local-network [ local-scope load-ingredients - reply [abc] + n:&:local-network <- new local-network:type + local-network-ports:&:@:port-connection <- new port-connection:type, 0 + *n <- put *n, data:offset, local-network-ports ] -#? scenario example-client-test [ -#? local-scope -#? assume-resources [ -#? [example.com/] -> [abc] -#? ] -#? run [ -#? source:&:source:char <- start-reading-from-network resources, [example.com], [/] -#? ] -#? contents:text <- drain source -#? 10:@:char/raw <- copy *contents -#? memory-should-contain [ -#? 10:address:character <- [abc] -#? ] -#? ] - -type request-handler = (recipe text -> text) - -def serve-one-request socket:num, request-handler:request-handler [ +scenario write-to-fake-socket [ local-scope - load-ingredients - session:num <- $accept socket - $print [server session socket: ], session, 10/newline - assert session, [ -F - example-server-test: $accept failed] - contents:&:source:char, sink:&:sink:char <- new-channel 30 - sink <- start-running receive-from-socket session, sink - query:text <- drain contents - response:text <- call request-handler, query - write-to-socket session, response - $close-socket session + single-port-network:&:local-network <- new-fake-network + sink:&:sink:char, writer:num/routine <- start-writing-socket single-port-network, 8080 + sink <- write sink, 120/x + close sink + wait-for-routine writer + tested-port-connections:&:@:port-connection <- get *single-port-network, data:offset + tested-port-connection:port-connection <- index *tested-port-connections, 0 + contents:text <- get tested-port-connection, contents:offset + 10:@:char/raw <- copy *contents + memory-should-contain [ + 10:array:character <- [x] + ] ] def start-reading-from-network resources:&:resources, host:text, path:text -> contents:&:source:char [ local-scope load-ingredients - $print [running start-reading-from-network], 10/newline - { - port:num, port-found?:boolean <- next-ingredient - break-if port-found? - port <- copy 80/http-port - } { break-if resources # real network - socket:num <- $open-client-socket host, port - $print [client socket: ], socket, 10/newline + socket:num <- $open-client-socket host, 80/http-port assert socket, [contents] req:text <- interpolate [GET _ HTTP/1.1], path request-socket socket, req @@ -120,72 +102,70 @@ def request-socket socket:num, s:text -> socket:num [ $write-to-socket socket, 10/lf ] -#? def start-writing-socket network:&:local-network, port:num -> sink:&:sink:char, routine-id:num [ -#? local-scope -#? load-ingredients -#? source:&:source:char, sink:&:sink:char <- new-channel 30 -#? { -#? break-if network -#? socket:num <- $open-server-socket port -#? session:num <- $accept socket -#? # TODO Create channel implementation of write-to-socket. -#? return sink, 0/routine-id -#? } -#? # fake network -#? routine-id <- start-running transmit-to-fake-socket network, port, source -#? ] +def start-writing-socket network:&:local-network, port:num -> sink:&:sink:char, routine-id:num [ + local-scope + load-ingredients + source:&:source:char, sink:&:sink:char <- new-channel 30 + { + break-if network + socket:num <- $open-server-socket port + session:num <- $accept socket + # TODO Create channel implementation of write-to-socket. + return sink, 0/routine-id + } + # fake network + routine-id <- start-running transmit-to-fake-socket network, port, source +] -#? def transmit-to-fake-socket network:&:local-network, port:num, source:&:source:char -> network:&:local-network, source:&:source:char [ -#? local-scope -#? load-ingredients -#? # compute new port connection contents -#? buf:&:buffer <- new-buffer 30 -#? { -#? c:char, done?:bool, source <- read source -#? break-unless c -#? buf <- append buf, c -#? break-if done? -#? loop -#? } -#? contents:text <- buffer-to-array buf -#? new-port-connection:&:port-connection <- new-port-connection port, contents -#? # Got the contents of the channel, time to write to fake port. -#? i:num <- copy 0 -#? port-connections:&:@:port-connection <- get *network, data:offset -#? len:num <- length *port-connections -#? { -#? done?:bool <- greater-or-equal i, len -#? break-if done? -#? current:port-connection <- index *port-connections, i -#? current-port:num <- get current, port:offset -#? ports-match?:bool <- equal current-port, port -#? i <- add i, 1 -#? loop-unless ports-match? -#? # Found an existing connection on this port, overwrite. -#? put-index *port-connections, i, *new-port-connection -#? reply -#? } -#? # Couldn't find an existing connection on this port, initialize a new one. -#? new-len:num <- add len, 1 -#? new-port-connections:&:@:port-connection <- new port-connection:type, new-len -#? put *network, data:offset, new-port-connections -#? i:num <- copy 0 -#? { -#? done?:bool <- greater-or-equal i, len -#? break-if done? -#? tmp:port-connection <- index *port-connections, i -#? put-index *new-port-connections, i, tmp -#? } -#? put-index *new-port-connections, len, *new-port-connection -#? ] +def transmit-to-fake-socket network:&:local-network, port:num, source:&:source:char -> network:&:local-network, source:&:source:char [ + local-scope + load-ingredients + # compute new port connection contents + buf:&:buffer <- new-buffer 30 + { + c:char, done?:bool, source <- read source + break-unless c + buf <- append buf, c + break-if done? + loop + } + contents:text <- buffer-to-array buf + new-port-connection:&:port-connection <- new-port-connection port, contents + # Got the contents of the channel, time to write to fake port. + i:num <- copy 0 + port-connections:&:@:port-connection <- get *network, data:offset + len:num <- length *port-connections + { + done?:bool <- greater-or-equal i, len + break-if done? + current:port-connection <- index *port-connections, i + current-port:num <- get current, port:offset + ports-match?:bool <- equal current-port, port + i <- add i, 1 + loop-unless ports-match? + # Found an existing connection on this port, overwrite. + put-index *port-connections, i, *new-port-connection + reply + } + # Couldn't find an existing connection on this port, initialize a new one. + new-len:num <- add len, 1 + new-port-connections:&:@:port-connection <- new port-connection:type, new-len + put *network, data:offset, new-port-connections + i:num <- copy 0 + { + done?:bool <- greater-or-equal i, len + break-if done? + tmp:port-connection <- index *port-connections, i + put-index *new-port-connections, i, tmp + } + put-index *new-port-connections, len, *new-port-connection +] def receive-from-socket socket:num, sink:&:sink:char -> sink:&:sink:char [ local-scope load-ingredients { - $print [read-from-socket ], socket, 10/newline req:text, eof?:bool <- $read-from-socket socket, 4096/bytes - loop-unless req bytes-read:num <- length *req i:num <- copy 0 { diff --git a/html/091socket.cc.html b/html/091socket.cc.html index a3bd7316..a81f4c79 100644 --- a/html/091socket.cc.html +++ b/html/091socket.cc.html @@ -251,7 +251,6 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> <span class="Normal">case</span> _READ_FROM_SOCKET: <span class="Delimiter">{</span> - cerr << <span class="Constant">"$read-from-socket</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span><<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>><span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> socket_t* socket = <span class="Normal">reinterpret_cast</span><socket_t*><span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Comment">// 1. we'd like to simply read() from the socket</span> @@ -261,22 +260,19 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Comment">// 3. but poll() will block on EOF, so only use poll() on the very first</span> <span class="Comment">// $read-from-socket on a socket</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!socket<span class="Delimiter">-></span>polled<span class="Delimiter">)</span> <span class="Delimiter">{</span> + socket<span class="Delimiter">-></span>polled = <span class="Constant">true</span><span class="Delimiter">;</span> pollfd p<span class="Delimiter">;</span> bzero<span class="Delimiter">(</span>&p<span class="Delimiter">,</span> <span class="Normal">sizeof</span><span class="Delimiter">(</span>p<span class="Delimiter">));</span> p<span class="Delimiter">.</span>fd = socket<span class="Delimiter">-></span>fd<span class="Delimiter">;</span> p<span class="Delimiter">.</span>events = POLLIN | POLLHUP<span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>poll<span class="Delimiter">(</span>&p<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">num pollfds</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">timeout</span><span class="Comment">*/</span><span class="Constant">100</span><span class="Comment">/*</span><span class="Comment">ms</span><span class="Comment">*/</span><span class="Delimiter">)</span> <= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>poll<span class="Delimiter">(</span>&p<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">num pollfds</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">no timeout</span><span class="Comment">*/</span>-<span class="Constant">1</span><span class="Delimiter">)</span> <= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"error in $read-from-socket</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - cerr << <span class="Constant">"poll output: "</span> << p<span class="Delimiter">.</span>revents << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> - cerr << <span class="Constant">"setting socket->polled</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> - socket<span class="Delimiter">-></span>polled = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - cerr << <span class="Constant">"$read-from-socket "</span> << x << <span class="Constant">" continuing</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> <span class="Normal">int</span> bytes = <span class="Normal">static_cast</span><<span class="Normal">int</span>><span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Normal">char</span>* contents = <span class="Normal">new</span> <span class="Normal">char</span>[bytes]<span class="Delimiter">;</span> bzero<span class="Delimiter">(</span>contents<span class="Delimiter">,</span> bytes<span class="Delimiter">);</span> diff --git a/html/092socket.mu.html b/html/092socket.mu.html index 72ffa17c..186c7c3b 100644 --- a/html/092socket.mu.html +++ b/html/092socket.mu.html @@ -33,90 +33,72 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color </head> <body> <pre id='vimCodeElement'> -<span class="Comment"># Wrappers around socket primitives that are easier to test.</span> +<span class="Comment"># Wrappers around socket primitives that take a 'local-network' object and are</span> +<span class="Comment"># thus easier to test.</span> <span class="Comment">#</span> -<span class="Comment"># To test client operations, use `assume-resources` with a filename that</span> -<span class="Comment"># begins with a hostname. (Filenames starting with '/' are assumed to be</span> -<span class="Comment"># local.)</span> +<span class="Comment"># The current semantics of fake port-connections don't match UNIX socket ones,</span> +<span class="Comment"># but we'll improve them as we learn more.</span> + +<span class="muData">container</span> local-network [ + data:&:@:port-connection +] + +<span class="Comment"># Port connections represent connections to ports on localhost.</span> +<span class="Comment"># Before passing a local-network object to network functions</span> +<span class="Comment"># `start-reading-socket` and `start-writing-socket`, add port-connections to</span> +<span class="Comment"># the local-network.</span> +<span class="Comment">#</span> +<span class="Comment"># For reading, `receive-from-socket` will check for a</span> +<span class="Comment"># port-connection on the port parameter that's been passed in. If there's</span> +<span class="Comment"># no port-connection for that port, it will return nothing and log an error.</span> +<span class="Comment"># If there is a port-connection for that port, it will transmit the contents</span> +<span class="Comment"># to the provided sink.</span> <span class="Comment">#</span> -<span class="Comment"># To test server operations, just run a real client against localhost.</span> +<span class="Comment"># For writing, `start-writing-socket` returns a sink connecting the</span> +<span class="Comment"># caller to the socket on the passed-in port.</span> +<span class="muData">container</span> port-connection [ + port:num + contents:text +] -<span class="muScenario">scenario</span> example-server-test [ +<span class="muRecipe">def</span> new-port-connection port:num, contents:text<span class="muRecipe"> -> </span>p:&:port-connection [ <span class="Constant">local-scope</span> - <span class="Comment"># test server without a fake on a random (real) port</span> - <span class="Comment"># that way repeatedly running the test will give ports time to timeout and</span> - <span class="Comment"># close before reusing them</span> - make-random-nondeterministic - port:num<span class="Special"> <- </span>random-in-range <span class="Constant">0/real-random-numbers</span>, <span class="Constant">8000</span>, <span class="Constant">8100</span> - run [ - socket:num<span class="Special"> <- </span>$open-server-socket port - $print <span class="Constant">[server socket: ]</span>, socket, <span class="Constant">10/newline</span> - assert socket, <span class="Constant">[ </span> -<span class="Constant">F - example-server-test: $open-server-socket failed]</span> - $print <span class="Constant">[starting up server routine]</span>, <span class="Constant">10/newline</span> - handler-routine:number<span class="Special"> <- </span>start-running serve-one-request socket, example-handler - ] - $print <span class="Constant">[starting to read from port ]</span>, port, <span class="Constant">10/newline</span> - source:&:source:char<span class="Special"> <- </span>start-reading-from-network <span class="Constant">0/real-resources</span>, <span class="Constant">[localhost]</span>, <span class="Constant">[/]</span>, port - response:text<span class="Special"> <- </span>drain source - <span class="Constant">10</span>:@:char/<span class="Special">raw <- </span>copy *response - memory-should-contain [ - <span class="Constant">10</span>:array:character<span class="Special"> <- </span><span class="Constant">[abc]</span> - ] + <span class="Constant">load-ingredients</span> + p:&:port-connection<span class="Special"> <- </span>new <span class="Constant">port-connection:type</span> + *p<span class="Special"> <- </span>merge port, contents ] -<span class="Comment"># helper just for this scenario</span> -<span class="muRecipe">def</span> example-handler query:text<span class="muRecipe"> -> </span>response:text [ + +<span class="muRecipe">def</span> new-fake-network<span class="muRecipe"> -> </span>n:&:local-network [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="muControl">reply</span> <span class="Constant">[abc]</span> + n:&:local-network<span class="Special"> <- </span>new <span class="Constant">local-network:type</span> + local-network-ports:&:@:port-connection<span class="Special"> <- </span>new <span class="Constant">port-connection:type</span>, <span class="Constant">0</span> + *n<span class="Special"> <- </span>put *n, <span class="Constant">data:offset</span>, local-network-ports ] -<span class="CommentedCode">#? scenario example-client-test [</span> -<span class="CommentedCode">#? local-scope</span> -<span class="CommentedCode">#? assume-resources [</span> -<span class="CommentedCode">#? [example.com/] -> [abc]</span> -<span class="CommentedCode">#? ]</span> -<span class="CommentedCode">#? run [</span> -<span class="CommentedCode">#? source:&:source:char <- start-reading-from-network resources, [example.com], [/]</span> -<span class="CommentedCode">#? ]</span> -<span class="CommentedCode">#? contents:text <- drain source</span> -<span class="CommentedCode">#? 10:@:char/raw <- copy *contents</span> -<span class="CommentedCode">#? memory-should-contain [</span> -<span class="CommentedCode">#? 10:address:character <- [abc]</span> -<span class="CommentedCode">#? ]</span> -<span class="CommentedCode">#? ]</span> - -<span class="muData">type</span> request-handler = (recipe text<span class="muRecipe"> -> </span>text) - -<span class="muRecipe">def</span> serve-one-request socket:num, request-handler:request-handler [ +<span class="muScenario">scenario</span> write-to-fake-socket [ <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - session:num<span class="Special"> <- </span>$accept socket - $print <span class="Constant">[server session socket: ]</span>, session, <span class="Constant">10/newline</span> - assert session, <span class="Constant">[ </span> -<span class="Constant">F - example-server-test: $accept failed]</span> - contents:&:source:char, sink:&:sink:char<span class="Special"> <- </span>new-channel <span class="Constant">30</span> - sink<span class="Special"> <- </span>start-running receive-from-socket session, sink - query:text<span class="Special"> <- </span>drain contents - response:text<span class="Special"> <- </span>call request-handler, query - write-to-socket session, response - $close-socket session + single-port-network:&:local-network<span class="Special"> <- </span>new-fake-network + sink:&:sink:char, writer:num/routine<span class="Special"> <- </span>start-writing-socket single-port-network, <span class="Constant">8080</span> + sink<span class="Special"> <- </span>write sink, <span class="Constant">120/x</span> + close sink + wait-for-routine writer + tested-port-connections:&:@:port-connection<span class="Special"> <- </span>get *single-port-network, <span class="Constant">data:offset</span> + tested-port-connection:port-connection<span class="Special"> <- </span>index *tested-port-connections, <span class="Constant">0</span> + contents:text<span class="Special"> <- </span>get tested-port-connection, <span class="Constant">contents:offset</span> + <span class="Constant">10</span>:@:char/<span class="Special">raw <- </span>copy *contents + memory-should-contain [ + <span class="Constant">10</span>:array:character<span class="Special"> <- </span><span class="Constant">[x]</span> + ] ] <span class="muRecipe">def</span> start-reading-from-network resources:&:resources, host:text, path:text<span class="muRecipe"> -> </span>contents:&:source:char [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - $print <span class="Constant">[running start-reading-from-network]</span>, <span class="Constant">10/newline</span> - <span class="Delimiter">{</span> - port:num, port-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="muControl">break-if</span> port-found? - port<span class="Special"> <- </span>copy <span class="Constant">80/http-port</span> - <span class="Delimiter">}</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> resources <span class="Comment"># real network</span> - socket:num<span class="Special"> <- </span>$open-client-socket host, port - $print <span class="Constant">[client socket: ]</span>, socket, <span class="Constant">10/newline</span> + socket:num<span class="Special"> <- </span>$open-client-socket host, <span class="Constant">80/http-port</span> assert socket, <span class="Constant">[contents]</span> req:text<span class="Special"> <- </span>interpolate <span class="Constant">[GET _ HTTP/1.1]</span>, path request-socket socket, req @@ -155,72 +137,70 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color $write-to-socket socket, <span class="Constant">10/lf</span> ] -<span class="CommentedCode">#? def start-writing-socket network:&:local-network, port:num -> sink:&:sink:char, routine-id:num [</span> -<span class="CommentedCode">#? local-scope</span> -<span class="CommentedCode">#? load-ingredients</span> -<span class="CommentedCode">#? source:&:source:char, sink:&:sink:char <- new-channel 30</span> -<span class="CommentedCode">#? {</span> -<span class="CommentedCode">#? break-if network</span> -<span class="CommentedCode">#? socket:num <- $open-server-socket port</span> -<span class="CommentedCode">#? session:num <- $accept socket</span> -<span class="CommentedCode">#? # TODO Create channel implementation of write-to-socket.</span> -<span class="CommentedCode">#? return sink, 0/routine-id</span> -<span class="CommentedCode">#? }</span> -<span class="CommentedCode">#? # fake network</span> -<span class="CommentedCode">#? routine-id <- start-running transmit-to-fake-socket network, port, source</span> -<span class="CommentedCode">#? ]</span> +<span class="muRecipe">def</span> start-writing-socket network:&:local-network, port:num<span class="muRecipe"> -> </span>sink:&:sink:char, routine-id:num [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + source:&:source:char, sink:&:sink:char<span class="Special"> <- </span>new-channel <span class="Constant">30</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> network + socket:num<span class="Special"> <- </span>$open-server-socket port + session:num<span class="Special"> <- </span>$accept socket + <span class="Comment"># TODO Create channel implementation of write-to-socket.</span> + <span class="muControl">return</span> sink, <span class="Constant">0/routine-id</span> + <span class="Delimiter">}</span> + <span class="Comment"># fake network</span> + routine-id<span class="Special"> <- </span>start-running transmit-to-fake-socket network, port, source +] -<span class="CommentedCode">#? def transmit-to-fake-socket network:&:local-network, port:num, source:&:source:char -> network:&:local-network, source:&:source:char [</span> -<span class="CommentedCode">#? local-scope</span> -<span class="CommentedCode">#? load-ingredients</span> -<span class="CommentedCode">#? # compute new port connection contents</span> -<span class="CommentedCode">#? buf:&:buffer <- new-buffer 30</span> -<span class="CommentedCode">#? {</span> -<span class="CommentedCode">#? c:char, done?:bool, source <- read source</span> -<span class="CommentedCode">#? break-unless c</span> -<span class="CommentedCode">#? buf <- append buf, c</span> -<span class="CommentedCode">#? break-if done?</span> -<span class="CommentedCode">#? loop</span> -<span class="CommentedCode">#? }</span> -<span class="CommentedCode">#? contents:text <- buffer-to-array buf</span> -<span class="CommentedCode">#? new-port-connection:&:port-connection <- new-port-connection port, contents</span> -<span class="CommentedCode">#? # Got the contents of the channel, time to write to fake port.</span> -<span class="CommentedCode">#? i:num <- copy 0</span> -<span class="CommentedCode">#? port-connections:&:@:port-connection <- get *network, data:offset</span> -<span class="CommentedCode">#? len:num <- length *port-connections</span> -<span class="CommentedCode">#? {</span> -<span class="CommentedCode">#? done?:bool <- greater-or-equal i, len</span> -<span class="CommentedCode">#? break-if done?</span> -<span class="CommentedCode">#? current:port-connection <- index *port-connections, i</span> -<span class="CommentedCode">#? current-port:num <- get current, port:offset</span> -<span class="CommentedCode">#? ports-match?:bool <- equal current-port, port</span> -<span class="CommentedCode">#? i <- add i, 1</span> -<span class="CommentedCode">#? loop-unless ports-match?</span> -<span class="CommentedCode">#? # Found an existing connection on this port, overwrite.</span> -<span class="CommentedCode">#? put-index *port-connections, i, *new-port-connection</span> -<span class="CommentedCode">#? reply</span> -<span class="CommentedCode">#? }</span> -<span class="CommentedCode">#? # Couldn't find an existing connection on this port, initialize a new one.</span> -<span class="CommentedCode">#? new-len:num <- add len, 1</span> -<span class="CommentedCode">#? new-port-connections:&:@:port-connection <- new port-connection:type, new-len</span> -<span class="CommentedCode">#? put *network, data:offset, new-port-connections</span> -<span class="CommentedCode">#? i:num <- copy 0</span> -<span class="CommentedCode">#? {</span> -<span class="CommentedCode">#? done?:bool <- greater-or-equal i, len</span> -<span class="CommentedCode">#? break-if done?</span> -<span class="CommentedCode">#? tmp:port-connection <- index *port-connections, i</span> -<span class="CommentedCode">#? put-index *new-port-connections, i, tmp</span> -<span class="CommentedCode">#? }</span> -<span class="CommentedCode">#? put-index *new-port-connections, len, *new-port-connection</span> -<span class="CommentedCode">#? ]</span> +<span class="muRecipe">def</span> transmit-to-fake-socket network:&:local-network, port:num, source:&:source:char<span class="muRecipe"> -> </span>network:&:local-network, source:&:source:char [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + <span class="Comment"># compute new port connection contents</span> + buf:&:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">30</span> + <span class="Delimiter">{</span> + c:char, done?:bool, source<span class="Special"> <- </span>read source + <span class="muControl">break-unless</span> c + buf<span class="Special"> <- </span>append buf, c + <span class="muControl">break-if</span> done? + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + contents:text<span class="Special"> <- </span>buffer-to-array buf + new-port-connection:&:port-connection<span class="Special"> <- </span>new-port-connection port, contents + <span class="Comment"># Got the contents of the channel, time to write to fake port.</span> + i:num<span class="Special"> <- </span>copy <span class="Constant">0</span> + port-connections:&:@:port-connection<span class="Special"> <- </span>get *network, <span class="Constant">data:offset</span> + len:num<span class="Special"> <- </span>length *port-connections + <span class="Delimiter">{</span> + done?:bool<span class="Special"> <- </span>greater-or-equal i, len + <span class="muControl">break-if</span> done? + current:port-connection<span class="Special"> <- </span>index *port-connections, i + current-port:num<span class="Special"> <- </span>get current, <span class="Constant">port:offset</span> + ports-match?:bool<span class="Special"> <- </span>equal current-port, port + i<span class="Special"> <- </span>add i, <span class="Constant">1</span> + <span class="muControl">loop-unless</span> ports-match? + <span class="Comment"># Found an existing connection on this port, overwrite.</span> + put-index *port-connections, i, *new-port-connection + <span class="muControl">reply</span> + <span class="Delimiter">}</span> + <span class="Comment"># Couldn't find an existing connection on this port, initialize a new one.</span> + new-len:num<span class="Special"> <- </span>add len, <span class="Constant">1</span> + new-port-connections:&:@:port-connection<span class="Special"> <- </span>new <span class="Constant">port-connection:type</span>, new-len + put *network, <span class="Constant">data:offset</span>, new-port-connections + i:num<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Delimiter">{</span> + done?:bool<span class="Special"> <- </span>greater-or-equal i, len + <span class="muControl">break-if</span> done? + tmp:port-connection<span class="Special"> <- </span>index *port-connections, i + put-index *new-port-connections, i, tmp + <span class="Delimiter">}</span> + put-index *new-port-connections, len, *new-port-connection +] <span class="muRecipe">def</span> receive-from-socket socket:num, sink:&:sink:char<span class="muRecipe"> -> </span>sink:&:sink:char [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> - $print <span class="Constant">[read-from-socket ]</span>, socket, <span class="Constant">10/newline</span> req:text, eof?:bool<span class="Special"> <- </span>$read-from-socket socket, <span class="Constant">4096/bytes</span> - <span class="muControl">loop-unless</span> req bytes-read:num<span class="Special"> <- </span>length *req i:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> |