# provide a standard epoll-based tcp/ip server < { ==err _ 0 lt { err ?? } rep } "+??" deffd { ==err ==actions _ 0 lt { actions err ??? } rep } "+???" deffd { < sys .linux "+" via +epoll "++" via sys .asm "+!" via net .tcp "+:" via < { 1 } /running deffst { 1000000 } /interval deffst { "unconfigured accept (of epollServer)" die } /accept deffst { "unconfigured port (of epollServer)" die } /port deffst { 1 -01 +setsockopt .reuseAddr +??io.net.setsockopt -- } /reuseAddr deffst { -- } /afterListen deffst { = }' /set deffst { scope keys }' /setters deffst { =*install setters { _ { set }_ -01 install }" each } /installSetters deffst > _ ==settings "::" via { deffst }' ::installSetters < > ==:noHandler { ::port { ==s s ::reuseAddr s +FGETFL 0 +fcntl +??io.net.fcntl.get +ONONBLOCK bor ==flags s +FSETFL flags +fcntl +??io.net.fcntl.set -- } +:listenOptFd _ ::afterListen ==listenFd [ ] ==allEventHandlers { ==fd ==handler { allEventHandlers len fd le }' { allEventHandlers [ noHandler ] cat =allEventHandlers } loop handler fd allEventHandlers =[] } /protectGC deffst { ==fd noHandler fd allEventHandlers =[] } /unprotectGC deffst < { listenFd +accept ==fd fd 0 lt { +errno +EAGAIN neq { ??io.net.accept } rep } { noHandler ==eventHandler ++EPOLLIN ++EPOLLERR bor ==initialFlags 0 ==closed < { closed not { epoll ++EPOLLCTLDEL fd 0 0 ++ctl +??io.net.epoll -- fd +close +??io.net.close -- fd unprotectGC 1 =closed } rep } /close deffst { ==count closed { "" } { count str .alloc ==buf fd buf count +read |close < { 0 } ; =*close > +???io.net.con.read buf str .inplacePrefix } ? * } /read deff { ==buf closed { buf len } { fd buf _ len +write |close < =*close > +???io.net.con.write } ? * } /write deff { ==flags closed not { eventHandler +!rawAddress noHandler +!rawAddress eq { flags =initialFlags } { epoll ++EPOLLCTLMOD fd flags eventHandler +!rawAddress ++ctl +??io.net.epoll -- } ? * } rep } /ctl deffst > ::accept =eventHandler epoll ++EPOLLCTLADD fd initialFlags eventHandler +!rawAddress ++ctl +??io.net.epoll -- eventHandler fd protectGC } ? * } =*in { "unexpected output capability on listening socket" die } =*out { ??io.net } =*err > ==listenFdEventHandler listenFdEventHandler listenFd protectGC ++create +??io.net.epoll ==epoll epoll ++EPOLLCTLADD listenFd ++EPOLLIN listenFdEventHandler +!rawAddress ++ctl +??io.net.epoll -- { ::running } { epoll 16 ::interval ++wait +??io.net.wait -- { _ .data +!rawObject ":" via .events _ ++EPOLLIN band not not { :in } rep _ ++EPOLLOUT band not not { :out } rep ++EPOLLERR band not not { :err } rep } each } loop } /run deffst > } /epollServer net .alg .deff { < net .alg .epollServer "^" via < { "unconfigured accept (of bufferedEpollServer)" die } /accept deffst { 1048576 } /outputBufferLimit deffst { = }' /set deffst { scope keys }' /setters deffst { _ ^settings .installSetters =*install setters { _ { set }_ -01 install }" each } /installSetters deffst > _ ==settings "::" via { deffst }' ::installSetters sys .linux .epoll "++" via { ":" via "" ==inBuffer "" ==outBuffer 0 ==finished < { outBuffer -01 cat _ =outBuffer len ::outputBufferLimit gt { |close < =*close { ::outputBufferLimit 2 mul outputBufferLimit } =*increase > ???limit.io.out } rep ++EPOLLOUT ++EPOLLIN ++EPOLLERR bor bor :ctl } =*write { :close } =*close { 1 =finished } =*finish > ::accept ":::" via < { 4096 :read _ len { inBuffer -01 cat :::in =inBuffer } { -- :::end } ? * } =*in { outBuffer _ :write -01 str .postfix _ =outBuffer len _ { ++EPOLLOUT } { 0 } ? * ++EPOLLIN ++EPOLLERR bor bor :ctl not finished and { :close } rep } =*out { :::err } =*err > } ^accept { ^run } /run deffst > } /bufferedEpollServer net .alg .deff > -- # vim: syn=elymas