aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrahflow <drahflow@gmx.de>2014-12-28 21:01:38 +0100
committerDrahflow <drahflow@gmx.de>2014-12-28 21:01:38 +0100
commit33465b6d99903674b365cce8c036cd42b4d6645e (patch)
tree812ad1adc0f92b60ca9804841803df0f278500ff
parente177bf86db97d618ad06509534319a79fbe9fb0f (diff)
Documented the server stuff
-rw-r--r--doc/server.md112
-rw-r--r--doc/tutorial.md1
2 files changed, 113 insertions, 0 deletions
diff --git a/doc/server.md b/doc/server.md
new file mode 100644
index 0000000..4d4f6df
--- /dev/null
+++ b/doc/server.md
@@ -0,0 +1,112 @@
+Server Algorithms
+=================
+
+As a convenience for coding TCP/IP network servers some algorithms
+are provided.
+
+All these server templates work by first creating an object, then
+configuring it via various setters, most importantly setting the
+event handler for new connections and finally starting the event
+loop. So far, all event loops are based on the epoll(7) facility.
+
+net .alg .epollServer
+---------------------
+
+ net .alg .epollServer "+" via
+ { 8000 } +port
+ { ":" via
+ # : provides methods to communicate with the new connection
+ # :read, :write, :close, :ctl (as in EPOLL_CTL)
+
+ "Welcome to server\n" :write
+
+ <
+ { 4096 :read _ dump "" eq { :close } rep } =*in
+ { "Did't :ctl for outgoing data" die } =*out
+ { "Error" die } =*err
+ >
+ } +accept
+ +run
+
+`net .alg .epollServer` creates a new server, on which the following options
+can be set, and `accept` and `port` must be set before starting the server.
+
+`port`: Takes a function which returns the port number to bind.
+
+`accept`: Takes a function which takes a scope containing capabilities
+to communicate over the newly accepted connection and returns a scope
+which provides functions to call on `in`coming data, `out`going kernel
+buffer space and `err`ors in the connection.
+
+The capabilities of the connection are `read` which takes the maximal number of
+bytes to read and returns a string of the actually read bytes or the empty string
+if the connection ended. The member `write` takes a string and writes it to the
+connection - returning the number of bytes written. `close` immediately closes
+the connection and `ctl` takes a new set of flags `bor`'ed together from
+`sys .linux .epoll .EPOLLIN`, `.EPOLLOUT`, and `.EPOLLERR` respectively.
+
+`interval`: Takes a function which provides the number of microseconds to sleep
+during the next epoll_wait(2) syscall.
+
+ net .alg .epollServer "+" via { 1000 } +interval
+ # server will abort epoll_wait after 1ms
+
+`reuseAddr`: Takes a function which takes a socket file descriptor and performs
+whatever shenanigans it deems appropriate before the socket is passed to bind(2).
+The default for this option applies SO_REUSEADDR, hence the separate option, if you
+whish to disable it set `reuseAddr` to `{ -- }`, i.e. just discard the socket descriptor.
+
+ net .alg .epollServer "+" via { -- } +reuseAddr
+ # server will not set SO_REUSEADDR
+
+FIXME: There should be a general option setting option as well (and only the default-active
+ones should be available for disabling)
+
+
+net .alg .bufferedEpollServer (what you actually want to use)
+-------------------------------------------------------------
+
+Just as `net .alg .epollServer` and actually based on it, but provides buffering for all
+in- and output so you don't have to track the number of bytes read and written and can
+instead handle stuff on a higher level. To this end, `accept` works slightly different.
+
+The capabilities `write`, `read`, `close` are provided as in `net .alg .epollServer`,
+where `close` still immediately closes the connection, whereas the new capability
+`finish` will first write the remaining output buffer bytes before actually closing
+the connection.
+
+The members of the `accept` returned scope are `in`, `err`, and `end`. The `in`
+handler gets the current input buffer and is expected to return whatever can not
+yet be handled (i.e. pars whatever prefix you like and return the rest), `err` is
+called when an error occurs on the connection and `end` is called when the remote
+end closes the connection.
+
+`net .alg .bufferedEpollServer` takes the same options as `net .alg .epollServer`
+and additionally provides `outputBufferLimit` which takes a function which
+returns the maximum number of output buffer bytes you are willing to keep
+around for slow reading clients.
+
+ net .alg .bufferedEpollServer "+" via { 16 } +outputBufferLimit
+ # server will raise an error if output buffer grows above 16 bytes
+
+
+net .alg .httpServer
+--------------------
+
+This is not yet a full featured HTTP server, but works a little bit.
+It is based on `net .alg .bufferedEpollServer` and takes the same options.
+However, you are not supposed to provide an `accept`, but instead
+call `request` to provide a function which handles the requests.
+
+ net .alg .httpServer "+" via
+ { 8080 } +port
+ { ":" via
+ # available methods are :ok, :fail, :close, :write, :finish
+ # additional members are :headers, :method, :url, :args
+ :headers keys dump
+ :method dump
+ :url dump
+ :args keys dump
+ "<html><body>O hi!</body></html>" "text/html" :ok
+ } +request
+ +run
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 9d160e0..336cbde 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -168,4 +168,5 @@ Recommended reading order
* container.md - containers other than arrays
* sys.md - some interfaces to the operating system
* err.md - error handling
+* server.md - ready-made TCP/IP server templates
* ffi.md - foreign function interface