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 131 |
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
# Process domain
if vals[0].symVal == "ipv4":
domain = AF_INET
else:
domain = AF_INET6
if vals[1].symVal == "stream":
sockettype = SOCK_STREAM
else:
sockettype = SOCK_DGRAM
if vals[2].symVal == "tcp":
protocol = IPPROTO_TCP
else:
protocol = IPPROTO_UDP
var socket = newSocket(domain, sockettype, protocol)
q.objType = "socket"
q.obj = socket[].addr
i.newScope("<socket>", q)
q.scope
.symbol("domain") do (i: In):
i.push q
i.push q.qVal[0].symVal.newVal
.symbol("type") do (i: In):
i.push q
i.push q.qVal[1].symVal.newVal
.symbol("protocol") do (i: In):
i.push q
i.push q.qVal[2].symVal.newVal
.symbol("close") do (i: In):
q.to(Socket).close()
.symbol("listen") do (i: In):
var port: MinValue
i.reqInt port
var socket = q.to(Socket)
socket.bindAddr(Port(port.intVal))
q.qVal.add "0.0.0.0".newSym
q.qVal.add port
q.scope
.symbol("address") do (i:In):
i.push "0.0.0.0".newVal
.symbol("port") do (i:In):
i.push port
.finalize()
socket.listen()
i.push q
.symbol("accept") do (i: In):
# Open same socket type as server
i.eval "$1 net %^socket" % [$q.qVal[0..2].newVal]
var clientVal: MinValue
i.reqObject "socket", clientVal
var client = clientVal.to(Socket)
var address = ""
q.to(Socket).acceptAddr(client, address)
clientVal.qVal.add address.newSym
i.push clientVal
.symbol("connect") do (i: In):
var q, address, port: MinValue
i.reqInt port
i.reqString address
q.to(Socket).connect(address.strVal, Port(port.intVal))
q.qVal.add address.strVal.newSym
q.qVal.add port
q.scope
.symbol("client-address") do (i:In):
i.push address.strVal.newVal
.symbol("client-port") do (i:In):
i.push port
.finalize()
i.push q
.symbol("send") do (i: In):
var s: MinValue
i.reqString s
q.to(Socket).send s.strVal
i.push q
.symbol("recv") do (i: In):
var size: MinValue
i.reqInt size
var s = ""
discard q.to(Socket).recv(s, size.intVal.int)
i.push q
i.push s.newVal
.symbol("recv-line") do (i: In):
var s = ""
q.to(Socket).readLine(s)
i.push @[q]
i.push s.newVal
.finalize()
i.push q
.finalize()
|