diff options
| author | Drahflow <drahflow@gmx.de> | 2013-09-04 00:30:15 +0200 |
|---|---|---|
| committer | Drahflow <drahflow@gmx.de> | 2013-09-04 00:30:15 +0200 |
| commit | 20efe1efeb3c62b884ccc16fd77e3b4c430c3ed9 (patch) | |
| tree | f95adf63f534e734579ffca9e314ed94880ce572 | |
| parent | 17245cb03fb02ae9c6b0409c1e6bdb538322a498 (diff) | |
buffered polling tcp/ip server
| -rw-r--r-- | compiler/elymasGlobalSysAsm.ey | 13 | ||||
| -rw-r--r-- | compiler/standard.ey | 3 | ||||
| -rw-r--r-- | elymas/lib/net/alg.ey | 6 | ||||
| -rw-r--r-- | elymas/lib/net/alg/server.ey | 123 | ||||
| -rw-r--r-- | elymas/lib/sys/linux.ey | 7 | ||||
| -rw-r--r-- | elymas/lib/txt.ey | 9 | ||||
| -rw-r--r-- | elymas/loaded.ey | 2 | ||||
| -rw-r--r-- | examples/working-compiler/bufferedServer.test | 6 |
8 files changed, 164 insertions, 5 deletions
diff --git a/compiler/elymasGlobalSysAsm.ey b/compiler/elymasGlobalSysAsm.ey index 8a5499c..e9c1ad5 100644 --- a/compiler/elymasGlobalSysAsm.ey +++ b/compiler/elymasGlobalSysAsm.ey @@ -200,6 +200,19 @@ :retn ]] /eyrawAddress defv + # generate object from raw object + # 0 -> address of the object + # 0 <- object + [[ + /rbx :popqReg + + /rax :popqReg + 8 /rax :pushqMemDisp8 # push integer value + + /rbx :pushqReg + :retn + ]] /eyrawObject defv + # get raw code execution address from function object # 0 -> function object # 0 <- address of first instruction diff --git a/compiler/standard.ey b/compiler/standard.ey index f440fb0..006414e 100644 --- a/compiler/standard.ey +++ b/compiler/standard.ey @@ -12,7 +12,8 @@ } "}_" defq { - { -01 < ==o { o -01 . } > -12 deffst }" quoted { }" { * }" ? * + { -01 < ==o { o -01 . } > -12 }" quoted { }" { * }" ? * + quoted { |deffst } { deffst }" ? * }" /via defq { -1110 ; ==f =*a len _ diff --git a/elymas/lib/net/alg.ey b/elymas/lib/net/alg.ey new file mode 100644 index 0000000..7fdee8b --- /dev/null +++ b/elymas/lib/net/alg.ey @@ -0,0 +1,6 @@ +< + { =*? }' /deff deffd + { ==? }' /defv deffd +> /alg net .defv + +# vim: syn=elymas diff --git a/elymas/lib/net/alg/server.ey b/elymas/lib/net/alg/server.ey new file mode 100644 index 0000000..9935016 --- /dev/null +++ b/elymas/lib/net/alg/server.ey @@ -0,0 +1,123 @@ +# provide a standard epoll-based tcp/ip server +{ < + < + { 1 } /running deffst + { 1000000 } /interval deffst + { "unconfigured accept (of epollServer)" die } /accept deffst + { "unconfigured port (of epollServer)" die } /port deffst + + { = }' /set deffst + { scope keys }' /setters deffst + { =*install + setters { _ { set }_ -01 install }" each + } /installSetters deffst + > _ ==settings "::" via + + { -1010 deffst = }' ::installSetters # TODO: def??? should overwrite existing values + + sys .linux "+" via +epoll "++" via + net .tcp "+:" via + + < + { "noHandler .in" die } =*in + { "noHandler .out" die } =*out + { "noHandler .err" die } =*err + > ==noHandler + + < + { txt .produce .u defvst }' /add deffst # TODO: possibly do it without text conversion one day + { noHandler -01 add }' /remove deffst + > ==eventHandlers + + { + ::port +:listenFd ==listenFd + + < + { + listenFd +:acceptFd ==fd + epoll ++EPOLLCTLADD fd ++EPOLLIN ++EPOLLERR bor fd ++ctl + < + { + epoll ++EPOLLCTLDEL fd 0 0 ++ctl + fd eventHandlers .remove + fd +close + } /close deffst + { ==count + count str .alloc ==buf + fd buf count +read + _ 0 lt { "read failed" die } rep # TODO: real error handling + buf str .inplacePrefix + } /read deff + { ==buf + fd buf _ len +write + _ 0 lt { "write failed" die } rep # TODO: real error handling + } /write deff + { ==flags + epoll ++EPOLLCTLMOD fd flags fd ++ctl + } /ctl deffst + > ::accept fd eventHandlers .add + } =*in + { "unexpected output capability on listening socket" die } =*out + { "error on main server socket" die } =*err + > listenFd eventHandlers .add + + ++create ==epoll + epoll ++EPOLLCTLADD listenFd ++EPOLLIN listenFd ++ctl + + { ::running } { + epoll 16 ::interval ++wait -- # TODO: error handling + { + _ .data txt .produce .u eventHandlers -01 . ":" via # TODO: consider saving raw addresses in the epoll data instead + .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 + + { = }' /set deffst + { scope keys }' /setters deffst + { _ ^settings .installSetters =*install + setters { _ { set }_ -01 install }" each + } /installSetters deffst + > _ ==settings "::" via + + { -1010 deffst = }' ::installSetters # TODO: def??? should overwrite existing values + + sys .linux .epoll "++" via + + { ":" via "" ==inBuffer "" ==outBuffer + < + { + outBuffer -01 cat =outBuffer + ++EPOLLOUT ++EPOLLIN ++EPOLLERR bor bor :ctl + } =*write + { :close } =*close + > ::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 + } =*out + { :::err } =*err + > + } ^accept + + { ^run } /run deffst +> } /bufferedEpollServer net .alg .deff + +# vim: syn=elymas diff --git a/elymas/lib/sys/linux.ey b/elymas/lib/sys/linux.ey index 0c00fc9..f672c8d 100644 --- a/elymas/lib/sys/linux.ey +++ b/elymas/lib/sys/linux.ey @@ -359,8 +359,9 @@ # 0 -> callback data # 1 -> event mask - # 2 -> fd to add - # 3 -> epoll fd + # 2 -> fd to modify + # 3 -> what to do (i.e. EPOLLCTLADD and friends) + # 4 -> epoll fd # 0 <- raw return value { ==callbackData ==eventMask ==fd ==action ==epollFd # struct epoll_event takes 16 bytes on a x86 @@ -384,7 +385,7 @@ [ buf ret { < ->u64 ==events ->u64 ==data - > } rep -- ] + > -01 } rep -- ] ret } /wait deffd > /epoll defvd diff --git a/elymas/lib/txt.ey b/elymas/lib/txt.ey index b3bc361..847b045 100644 --- a/elymas/lib/txt.ey +++ b/elymas/lib/txt.ey @@ -2,11 +2,18 @@ < # 0 -> string # 0 <- leading digits converted to int (0, if none) - # 1 <- rest of string { "^(\\d*)" regex -- ==n [ n { 48 sub } each ] reverse 10 math .unbase } /u deffd > /consume defvd + + < + # 0 -> positive integer + # 0 <- decimal representation as string + { + [ -01 10 math .base reverse "0123456789" each ] str .fromArray + } /u deffd + > /produce defvd > /txt defvd # vim: syn=elymas diff --git a/elymas/loaded.ey b/elymas/loaded.ey index ffe59bc..6cac2a1 100644 --- a/elymas/loaded.ey +++ b/elymas/loaded.ey @@ -9,6 +9,8 @@ "lib/net/tcp.ey" "lib/net/udp.ey" "lib/net/dns.ey" + "lib/net/alg.ey" + "lib/net/alg/server.ey" ] { _ dump include }' each { "/proc/self/fd/0" include }' "loaded" sys .freeze diff --git a/examples/working-compiler/bufferedServer.test b/examples/working-compiler/bufferedServer.test new file mode 100644 index 0000000..58e47a8 --- /dev/null +++ b/examples/working-compiler/bufferedServer.test @@ -0,0 +1,6 @@ +net .alg .bufferedEpollServer "+" via + { ":" via < + { :write "" } =*in + { :close } _ =*end =*err + > } +accept + { 2001 } +port +run |
