diff options
author | Stephen Malina <stephenmalina@gmail.com> | 2016-09-25 10:42:15 -0400 |
---|---|---|
committer | Stephen Malina <stephenmalina@gmail.com> | 2016-10-07 08:09:42 -0400 |
commit | d7e48920f7faf092d972ea02fc02551ba1c5bb23 (patch) | |
tree | ff2e3a01983ae2be287d0183909f2e2a7bb2289a | |
parent | 4a70fb39cc6a0f2ebe34e9b58b873e13d8221015 (diff) | |
download | mu-d7e48920f7faf092d972ea02fc02551ba1c5bb23.tar.gz |
3458
Testable network interface and write flow.
-rw-r--r-- | 092socket.mu | 116 | ||||
-rw-r--r-- | server-socket.mu | 4 |
2 files changed, 118 insertions, 2 deletions
diff --git a/092socket.mu b/092socket.mu new file mode 100644 index 00000000..60515b06 --- /dev/null +++ b/092socket.mu @@ -0,0 +1,116 @@ +# Wrappers around socket primitives that take a 'network-interface' object and +# are thus easier to test. +# 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` and `start-writing`, add port-connections to the +# local-network. +# +# For reading, `transmit-from-socket` will check for a +# port-connection on the port parameter that's been passed in. If there's +# no port-connectin for that port, it will return nothing and log. If +# there is a port-connection for that port, it will transmit the contents +# to the passed in sink. +# +# 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 +] + +def new-port-connection port:num, contents:text -> p:&:port-connection [ + local-scope + load-ingredients + p:&:port-connection <- new port-connection:type + *p <- put *p, port:offset, port + *p <- put *p, contents:offset, contents +] + +def new-fake-network -> n:&:local-network [ + local-scope + load-ingredients + 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 write-to-fake-socket [ + local-scope + 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:bool/raw <- equal contents, [x] + memory-should-contain [ + 10 <- 1 + ] +] + +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 <- $socket 8080/port + session:num <- $accept socket + # TODO Create channel implementation of write-to-socket. + routine-id <- copy 0 + return + } + # 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 +] diff --git a/server-socket.mu b/server-socket.mu index 3538b687..8a25da92 100644 --- a/server-socket.mu +++ b/server-socket.mu @@ -24,13 +24,13 @@ def main [ Content-type: text/plain SUCCESS! -] +], contents $print 10/newline, [Wrote to and closing socket...], 10/newline $close-socket session $close-socket socket ] -def write-to-socket session-socket:number, s:address:array:character [ +def write-to-socket session-socket:number, s:address:array:character, source:&:source:char [ local-scope load-ingredients len:number <- length *s |