~aleteoryx/nex.nelua

d32095e087f6d7b0dee37a03808c352225a8d491 — Aleteoryx 15 days ago b12592a master
cleanup a lot

learned some undocumented bits of the lang
3 files changed, 60 insertions(+), 43 deletions(-)

M nex.nelua
M nps.nelua
M socket.nelua
M nex.nelua => nex.nelua +2 -0
@@ 1,3 1,5 @@
## pragmas.abort = 'exit'

local socket = require 'socket'
require 'arg'


M nps.nelua => nps.nelua +2 -0
@@ 1,3 1,5 @@
## pragmas.abort = 'exit'

local socket = require 'socket'
require 'vector'
require 'io'

M socket.nelua => socket.nelua +56 -43
@@ 7,10 7,6 @@

-- c imports
## cinclude '<sys/socket.h>'
local AF_INET: cint <cimport, nodecl>
local AF_INET6: cint <cimport, nodecl>
-- local AF_UNIX: cint <cimport, nodecl>

local SOCK_STREAM: cint <cimport, nodecl>
-- local SOCK_DGRAM: cint <cimport, nodecl>
-- local SOCK_RAW: cint <cimport, nodecl>


@@ 18,16 14,45 @@ local SOCK_STREAM: cint <cimport, nodecl>
local MSG_DONTWAIT: cint <cimport, nodecl>
local MSG_PEEK: cint <cimport, nodecl>

local function c_socket(domain: cint, type: cint, protocol: cint): cint <cimport 'socket', nodecl> end
local c_sa_family_t <cimport 'sa_family_t',cincomplete, nodecl> = @record{}
local AF_INET: c_sa_family_t <cimport, nodecl>
local AF_INET6: c_sa_family_t <cimport, nodecl>
local AF_UNIX: c_sa_family_t <cimport, nodecl>

local in_port_t: type = @uint16
local in_addr_t: type = @uint32
local in_addr = @record{
	s_addr: in_addr_t
}
local sockaddr_in <cimport 'struct sockaddr_in', cincomplete, nodecl> = @record{
	sin_family: c_sa_family_t,
	sin_port: in_port_t,
	sin_addr: in_addr
}

local in6_addr = @record{
	s6_addr: [16]byte
}
local sockaddr_in6 <cimport 'struct sockaddr_in6', cincomplete, nodecl> = @record{
	sin6_family: c_sa_family_t,
	sin6_port: in_port_t,
  sin6_flowinfo: uint32,
	sin6_addr: in6_addr,
	sin6_scope_id: uint32
}

local function c_socket(domain: c_sa_family_t, type: cint, protocol: cint): cint <cimport 'socket', nodecl> end
local function c_bind(fd: cint, addr: pointer <const>, len: cint): cint <cimport 'bind', nodecl> end
local function c_accept(fd: cint, address: pointer, address_len: *cint): cint <cimport 'accept', nodecl> end
local function c_listen(fd: cint, backlog: cint): cint <cimport 'listen', nodecl> end


local function c_send(fd: cint, buf: *[0]byte, len: usize, flags: cint): isize <cimport 'send', nodecl> end
local function c_recv(fd: cint, buf: *[0]byte, len: usize, flags: cint): isize <cimport 'recv', nodecl> end


## cinclude '<arpa/inet.h>'
local function c_inet_pton(af: cint, src: cstring <const>, dst: pointer): cint <cimport 'inet_pton', nodecl> end
local function c_inet_pton(af: c_sa_family_t, src: cstring <const>, dst: pointer): cint <cimport 'inet_pton', nodecl> end
local function c_htons(hostshort: uint16): uint16 <cimport 'htons'> end
local function c_ntohs(hostshort: uint16): uint16 <cimport 'ntohs'> end



@@ 80,9 105,7 @@ require 'C.stdio'
require 'allocators.default'


local function fakeuse(...: varargs) end

local function die_errno(cond: boolean, msg: string): void
local function die_errno(cond: boolean, msg: string): void <inline>
  if cond then
    C.perror(nilptr)
    error(msg)


@@ 257,29 280,22 @@ local inet6_re = '^{([^}]+)}:(%d?%d?%d?%d?%d)$'
function export.listen_tcp(address: string, conn_cap: uinteger, handler: function(): void): void
  local matched, matches
  if (do matched, matches = address:match(inet_re); in matched end) then
    local c_err: cint = 0

    local s_addr, s_port = matches:unpack(1, 2)
    local addr: uint32
    die_errno(c_inet_pton(AF_INET, (@cstring)(s_addr), &addr) <= 0,
    local addr, port = matches:unpack(1, 2)
    local p_addr: uint32
    die_errno(c_inet_pton(AF_INET, (@cstring)(addr), &p_addr) <= 0,
              "bad IPv4 address")
    local i_port = tointeger(s_port)
    assert((i_port >= 0) and (i_port < 65535), "port not within range [0,65536)")
    local port: uint16 = c_htons(i_port)
    local port = tointeger(port)
    assert((port >= 0) and (port < 65535), "port not within range [0,65536)")
    local port: uint16 = c_htons(port)

    local fd = c_socket(AF_INET, SOCK_STREAM, 0)
    die_errno(fd == -1, "couldn't open TCP socket")

    fakeuse(port)
    ##[==[ cemit [[
      struct sockaddr_in sa;
      memset(&sa, 0, sizeof(sa));
      sa.sin_family = AF_INET;
      sa.sin_port = port;
      sa.sin_addr.s_addr = addr;
      c_err = bind(fd, &sa, sizeof(sa));
    ]] ]==]
    die_errno(c_err == -1, "couldn't bind TCP socket")
    local sa: sockaddr_in
    sa.sin_family = AF_INET
    sa.sin_port = port
    sa.sin_addr.s_addr = p_addr
    die_errno(c_bind(fd, &sa, #(@sockaddr_in)) == -1, "couldn't bind TCP socket")

    defer c_close(fd) end



@@ 287,31 303,28 @@ function export.listen_tcp(address: string, conn_cap: uinteger, handler: functio
  elseif (do matched, matches = address:match(inet6_re); in matched end) then
    local c_err: cint = 0

    local s_addr, s_port = matches:unpack(1, 2)
    local addr: [16]byte
    die_errno(c_inet_pton(AF_INET6, (@cstring)(s_addr), &addr) <= 0,
    local addr, port = matches:unpack(1, 2)
    local p_addr: [16]byte
    die_errno(c_inet_pton(AF_INET6, (@cstring)(addr), &p_addr) <= 0,
              "bad IPv6 address")
    local i_port = tointeger(s_port)
    assert((i_port >= 0) and (i_port < 65535), "port not within range [0,65536)")
    local port: uint16 = c_htons(i_port)
    local port = tointeger(port)
    assert((port >= 0) and (port < 65535), "port not within range [0,65536)")
    local port: uint16 = c_htons(port)

    local fd = c_socket(AF_INET6, SOCK_STREAM, 0)
    die_errno(fd == -1, "couldn't open TCP socket")

    fakeuse(port)
    ##[==[ cemit [[
      struct sockaddr_in6 sa;
      memset(&sa, 0, sizeof(sa));
      sa.sin6_family = AF_INET6;
      sa.sin6_port = port;
      memcpy(&sa.sin6_addr.s6_addr, &addr, sizeof(addr));
      c_err = bind(fd, &sa, sizeof(sa));
    ]] ]==]
    die_errno(c_err == -1, "couldn't bind TCP socket")
    local sa: sockaddr_in6
    sa.sin6_family = AF_INET6
    sa.sin6_port = port
    sa.sin6_addr.s6_addr = p_addr
    die_errno(c_bind(fd, &sa, #(@sockaddr_in6)) == -1, "couldn't bind TCP socket")

    defer c_close(fd) end

    export.listen_sock(fd, conn_cap, handler)
  else
    error("bad addr: "..address)
  end
end