all repos — min @ 638cb7ac58499c87dcd1a0d232e68bb831f90a48

A small but practical concatenative programming language.

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()