lib/min_net.nim
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
import net, nativesockets, strutils, critbits import ../core/types, ../core/parser, ../core/interpreter, ../core/utils # Network proc net_module*(i: In)= i.define("net") .symbol("^socket") do (i: In): var q: MinValue i.reqQuotation q # (ipv4 stream tcp) if q.qVal.len < 3 or not (q.qVal[0].isSymbol and q.qVal[1].isSymbol and q.qVal[2].isSymbol): raiseInvalid("Quotation must contain three symbols for <domain> <type> <protocol>") let vals = q.qVal if not ["ipv4", "ipv6"].contains(vals[0].symVal): raiseInvalid("Domain symbol must be 'ipv4' or 'ipv6'") if not ["stream", "dgram"].contains(vals[1].symVal): raiseInvalid("Type symbol must be 'stream' or 'dgram'") if not ["tcp", "udp"].contains(vals[2].symVal): raiseInvalid("Protocol symbol must be 'tcp' or 'udp'") var domain: Domain sockettype: SockType protocol: Protocol sDomain, sSockType, sProtocol: string # Process domain if vals[0].symVal == "ipv4": sDomain = "ipv4" domain = AF_INET else: sDomain = "ipv6" domain = AF_INET6 if vals[1].symVal == "stream": sSockType = "stream" sockettype = SOCK_STREAM else: sSockType = "dgram" sockettype = SOCK_DGRAM if vals[2].symVal == "tcp": sProtocol = "tcp" protocol = IPPROTO_TCP else: sProtocol = "udp" protocol = IPPROTO_UDP var socket = newSocket(domain, sockettype, protocol) var qs = @[ @["domain".newSym, sDomain.newVal].newVal, @["type".newSym, sSockType.newVal].newVal, @["protocol".newSym, sProtocol.newVal].newVal ].newVal qs.objType = "socket" qs.obj = socket[].addr i.newScope("<socket>", qs) var sAddress: string var sPort: BiggestInt qs.scope .symbol("close") do (i: In): qs.to(Socket).close() .symbol("listen") do (i: In): var port: MinValue i.reqInt port var socket = qs.to(Socket) sAddress = "0.0.0.0" sPort = port.intVal socket.bindAddr(Port(sPort)) qs.qVal.add @["address".newSym, sAddress.newVal].newVal qs.qVal.add @["port".newSym, sPort.newVal].newVal socket.listen() i.push qs .symbol("accept") do (i: In): # Open same socket type as server i.eval "($1 $2 $3) net %^socket" % [sDomain, sSockType, sProtocol] var clientVal: MinValue i.reqObject "socket", clientVal var client = clientVal.to(Socket) var address = "" qs.to(Socket).acceptAddr(client, address) clientVal.qVal.add address.newSym i.push clientVal .symbol("connect") do (i: In): var address, port: MinValue i.reqInt port i.reqStringLike address qs.to(Socket).connect(address.strVal, Port(port.intVal)) #var qc = @[ # @["domain".newSym, sDomain.newVal].newVal, # @["type".newSym, sSockType.newVal].newVal, # @["protocol".newSym, sProtocol.newVal].newVal #].newVal qs.qVal.add @["address".newSym, address.getString.newVal].newVal qs.qVal.add @["port".newSym, port].newVal i.push qs .symbol("send") do (i: In): echo "sending" var s: MinValue i.reqString s qs.to(Socket).send s.strVal i.push qs .symbol("recv") do (i: In): var size: MinValue i.reqInt size var s = "" discard qs.to(Socket).recv(s, size.intVal.int) i.push qs i.push s.newVal .symbol("recv-line") do (i: In): var s = "" qs.to(Socket).readLine(s) i.push @[qs] i.push s.newVal .finalize() i.push qs .finalize() |