!import "base.tri" !Local !import "io.tri" !Local -- Socket primitives for the IO driver. -- All actions return a Result tree (see lib/base.tri): -- ok value -- pair true (pair value t) -- err msg -- pair false (pair msg t) socket = pair 70 t closeSocket = sock : pair 71 sock bindSocket = sock addr port : pair 72 (pair sock (pair addr port)) listen = sock backlog : pair 73 (pair sock backlog) accept = sock : pair 74 sock connect = sock addr port : pair 75 (pair sock (pair addr port)) recv = sock maxBytes : pair 76 (pair sock maxBytes) send = sock bytes : pair 77 (pair sock bytes) getSocketName = sock : pair 78 sock -- --------------------------------------------------------------------------- -- Convenience helpers -- --------------------------------------------------------------------------- onSocket = (action errCase okCase : bind action (result : matchResult errCase okCase result)) -- Create a listening socket bound to an address and port. -- Returns ok listenSocket or err message. listenSocket = addr port backlog : bind (socket) (result : matchResult (err rest : pure (err "socket creation failed")) (sock rest : bind (bindSocket sock addr port) (bindResult : matchResult (err rest : pure (err "bind failed")) (_ rest : bind (listen sock backlog) (listenResult : matchResult (err rest : pure (err "listen failed")) (_ rest : pure (ok sock)) listenResult)) bindResult)) result) -- Accept a connection and return (clientSocket, peerAddr). -- The returned peerAddr is a string like "127.0.0.1:8080". onAccept = (sock errCase okCase : bind (accept sock) (result : matchResult errCase okCase result)) -- Receive all available bytes up to maxBytes. onRecv = (sock maxBytes errCase okCase : bind (recv sock maxBytes) (result : matchResult errCase okCase result)) -- Send bytes and return number of bytes sent. onSend = (sock bytes errCase okCase : bind (send sock bytes) (result : matchResult errCase okCase result)) -- Close a socket, ignoring errors. closeSocket_ = sock : bind (closeSocket sock) (_ : pure t)