M nex.nelua => nex.nelua +15 -3
@@ 1,14 1,26 @@
local socket = require 'socket'
-socket.listen_tcp("127.0.0.1:1900", function()
+if #arg ~= 1 then
+ print("Usage: nex.nelua <ADDRESS>")
+ print("ADDRESS may be one of:")
+ print(" `<ipv4 addr>:<port>'")
+ print(" `{<ipv6 addr>}:<port>'")
+end
+
+socket.listen_tcp(arg[1], function()
local line = socket.recv_line():gsub("\r", "")
if line:subview(1, 1) == "/" then line = line:subview(2) end
if line == "" then
- socket.send_line("Hello!\nThis is the index page!\n\nThe protocol's originator:\n=> nex://nightfall.city")
+ socket.send_line([[Hello!
+
+This is the index page, edit nex.nelua to change it.
+
+For more info, go here:
+=> nex://nightfall.city/nex/info/specification.txt]])
else
- socket.send_line("Page not Found.")
+ socket.send_line("Page not Found. Try the root.")
end
socket.end_conn()
A nps.nelua => nps.nelua +37 -0
@@ 0,0 1,37 @@
+local socket = require 'socket'
+require 'vector'
+require 'io'
+require 'arg'
+
+if #arg ~= 1 then
+ print("Usage: nps.nelua <ADDRESS>")
+ print("ADDRESS may be one of:")
+ print(" `<ipv4 addr>:<port>'")
+ print(" `{<ipv6 addr>}:<port>'")
+end
+
+socket.listen_tcp(arg[1], function()
+ local target = socket.recv_line():gsub("\r", "")
+
+ local lines: vector(string)
+ local line = socket.recv_line()
+
+ while line:gsub("\r", "") ~= "." do
+ lines:push(line)
+ line = socket.recv_line()
+ end
+
+ local ok, matches
+ if (do ok, matches = target:match("^mail/(.+)$"); in ok end) then
+ io.writef("Mail for %s:\n", matches[1])
+ for i=0,<#lines do
+ print("Mail:", lines[i])
+ end
+ else
+ socket.send("Unknown target: ")
+ socket.send_line(target)
+ socket.send_line("If you're testing this out, try editing nps.nelua!")
+ end
+
+ socket.end_conn()
+end)
M socket.nelua => socket.nelua +34 -7
@@ 82,11 82,6 @@ require 'allocators.default'
local function fakeuse(...: varargs) end
--- 192.168.2.1:2000 -> 192.168.2.1,2000
-local inet_re = '^(%d?%d?%d%.%d?%d?%d%.%d?%d?%d%.%d?%d?%d):(%d?%d?%d?%d?%d)$'
--- {::1}:2000 -> ::1,2000
-local inet6_re = '^{([^}]+)}:(%d?%d?%d?%d?%d)$'
-
local function die_errno(cond: boolean, msg: string): void
if cond then
C.perror(nilptr)
@@ 255,9 250,13 @@ function export.listen_sock(sock: cint, handler: function(): void): void
end
end
+-- 192.168.2.1:2000 -> 192.168.2.1,2000
+local inet_re = '^(%d?%d?%d%.%d?%d?%d%.%d?%d?%d%.%d?%d?%d):(%d?%d?%d?%d?%d)$'
+-- {::1}:2000 -> ::1,2000
+local inet6_re = '^{([^}]+)}:(%d?%d?%d?%d?%d)$'
function export.listen_tcp(address: string, handler: function(): void): void
- local matched, matches = string.match(address, inet_re)
- if matched then
+ 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)
@@ 285,6 284,34 @@ function export.listen_tcp(address: string, handler: function(): void): void
defer c_close(fd) end
export.listen_sock(fd, handler)
+ 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,
+ "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 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")
+
+ defer c_close(fd) end
+
+ export.listen_sock(fd, handler)
end
end