Compare commits

...

8 Commits

Author SHA1 Message Date
Max1Truc
cd22215520
Merge 4c0677219fc993236e85731b753bbe03be865bca into 0f37af645c5f3a0377f1650b529ed23b2e26749f 2023-10-31 23:02:49 -06:00
Caleb Maclennan
0f37af645c
Merge pull request #415 from leso-kn/feature/actions-windows 2023-10-30 22:04:00 +03:00
leso-kn
9c6195ea62
ci: Enable windows build 2023-10-27 19:31:18 +02:00
leso-kn
708e50f8e6
refactor(core): Replace check for SO_BINDTODEVICE support with platform independent version 2023-10-27 11:34:39 +02:00
leso-kn
0bc8c56043
fix(core): Disable SO_BINDTODEVICE on windows
Co-authored-by: Sewbacca <sebastian.kalus@kolabnow.com>
2023-10-27 09:59:26 +03:00
Leso_KN
f741a88b80
feat(tcp): Add 'bindtodevice' option (#408) 2023-10-23 21:27:01 +03:00
Max1Truc
4c0677219f fix(http): use CONNECT for HTTPS over HTTP proxy 2022-08-27 20:52:28 +02:00
Max1Truc
bd0f2ea49a fix(http): use the right protocol for proxies 2022-08-23 16:58:34 +02:00
5 changed files with 132 additions and 23 deletions

View File

@ -13,22 +13,27 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
luaVersion: [ "5.4", "5.3", "5.2", "5.1", "luajit", "luajit-openresty" ] luaVersion: [ "5.4", "5.3", "5.2", "5.1", "luajit", "luajit-openresty" ]
platform: [ "ubuntu-20.04", "macos-11" ] # "windows-2022" not supported by gh-actions-lua platform: [ "ubuntu-20.04", "macos-11", "windows-2022" ]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Setup msvc
uses: ilammy/msvc-dev-cmd@v1
if: ${{ !startsWith(matrix.luaVersion, 'luajit') }}
- name: Setup lua - name: Setup lua
uses: leafo/gh-actions-lua@v9 uses: leso-kn/gh-actions-lua@v11-staging
with: with:
luaVersion: ${{ matrix.luaVersion }} luaVersion: ${{ matrix.luaVersion }}
- name: Setup luarocks - name: Setup luarocks
uses: leafo/gh-actions-luarocks@v4 uses: hishamhm/gh-actions-luarocks@master
- name: Make and install - name: Make and install
run: | run: |
export DEBUG=DEBUG
luarocks make -- luasocket-scm-3.rockspec luarocks make -- luasocket-scm-3.rockspec
env:
DEBUG: DEBUG
- name: Run regression tests - name: Run regression tests
shell: bash
run: | run: |
cd test cd test
lua hello.lua lua hello.lua

View File

@ -203,8 +203,15 @@ end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
local function adjusturi(reqt) local function adjusturi(reqt)
local u = reqt local u = reqt
-- if there is a proxy, we need the full url. otherwise, just a part. local proxy
if not reqt.proxy and not _M.PROXY then if reqt.proxy then
proxy = url.parse(reqt.proxy)
end
-- We just need the path if there's no proxy,
-- or if we use https over an http proxy.
-- Otherwise, we use a full url
if not proxy or (reqt.scheme == "https" and proxy.scheme == "http") then
u = { u = {
path = socket.try(reqt.path, "invalid path 'nil'"), path = socket.try(reqt.path, "invalid path 'nil'"),
params = reqt.params, params = reqt.params,
@ -215,17 +222,7 @@ local function adjusturi(reqt)
return url.build(u) return url.build(u)
end end
local function adjustproxy(reqt) local function adjustheaders(reqt, https_connect)
local proxy = reqt.proxy or _M.PROXY
if proxy then
proxy = url.parse(proxy)
return proxy.host, proxy.port or 3128
else
return reqt.host, reqt.port
end
end
local function adjustheaders(reqt)
-- default headers -- default headers
local host = reqt.host local host = reqt.host
local port = tostring(reqt.port) local port = tostring(reqt.port)
@ -244,9 +241,8 @@ local function adjustheaders(reqt)
url.unescape(reqt.password))) url.unescape(reqt.password)))
end end
-- if we have proxy authentication information, pass it along -- if we have proxy authentication information, pass it along
local proxy = reqt.proxy or _M.PROXY if reqt.proxy and (reqt.scheme == "http" or https_connect) then
if proxy then local proxy = url.parse(reqt.proxy)
proxy = url.parse(proxy)
if proxy.user and proxy.password then if proxy.user and proxy.password then
lower["proxy-authorization"] = lower["proxy-authorization"] =
"Basic " .. (mime.b64(proxy.user .. ":" .. proxy.password)) "Basic " .. (mime.b64(proxy.user .. ":" .. proxy.password))
@ -259,6 +255,80 @@ local function adjustheaders(reqt)
return lower return lower
end end
local function reg(conn)
local mt = getmetatable(conn.sock).__index
for name, method in pairs(mt) do
if type(method) == "function" then
conn[name] = function (self, ...)
return method(self.sock, ...)
end
end
end
end
local function proxy_connect_create(params, proxy)
-- Copied and adapted from luasec's https.lua
-- in function ssl.http.tcp()
local ssl = assert(
require("ssl"), 'LuaSocket: LuaSec not found')
local https = assert(
require("ssl.https"), 'LuaSocket: LuaSec not found')
-- Force client mode
params.mode = "client"
-- 'create' function
return function ()
local conn = {}
conn.proxy_sock = _M.open(proxy.host, proxy.port, proxy.create)
local try = conn.proxy_sock.try
function conn:settimeout(...)
return self.proxy_sock.c:settimeout(https.TIMEOUT)
end
-- Wrap the underlying connection function
function conn:connect(host, port)
conn.proxy_sock:sendrequestline("CONNECT", host .. ":" .. tostring(port))
conn.proxy_sock:sendheaders(adjustheaders(proxy, true))
local code, _ = conn.proxy_sock:receivestatusline()
try(code == 200 or nil)
self.sock = try(ssl.wrap(self.proxy_sock.c, params))
self.sock:sni(host)
self.sock:settimeout(https.TIMEOUT)
try(self.sock:dohandshake())
reg(self)
return 1
end
-- Close the underlying socket
function conn:close()
conn.proxy_sock:close()
end
return conn
end
end
local function adjustproxy(reqt)
if reqt.proxy then
local proxy = url.parse(reqt.proxy)
proxy.port = proxy.port or 3128
proxy.create = SCHEMES[proxy.scheme].create(reqt)
if reqt.scheme == "https" and proxy.scheme == "http" then
local wrapped_create = proxy_connect_create(reqt, proxy)
return reqt.host, reqt.port, wrapped_create
else
return proxy.host, proxy.port, proxy.create
end
else
return reqt.host, reqt.port, reqt.create
end
end
-- default url parts -- default url parts
local default = { local default = {
path ="/" path ="/"
@ -268,6 +338,8 @@ local default = {
local function adjustrequest(reqt) local function adjustrequest(reqt)
-- parse url if provided -- parse url if provided
local nreqt = reqt.url and url.parse(reqt.url, default) or {} local nreqt = reqt.url and url.parse(reqt.url, default) or {}
-- get global proxy
nreqt.proxy = reqt.proxy or _M.PROXY
-- explicit components override url -- explicit components override url
for i,v in base.pairs(reqt) do nreqt[i] = v end for i,v in base.pairs(reqt) do nreqt[i] = v end
-- default to scheme particulars -- default to scheme particulars
@ -282,7 +354,7 @@ local function adjustrequest(reqt)
-- compute uri if user hasn't overriden -- compute uri if user hasn't overriden
nreqt.uri = reqt.uri or adjusturi(nreqt) nreqt.uri = reqt.uri or adjusturi(nreqt)
-- adjust headers in request -- adjust headers in request
nreqt.headers = adjustheaders(nreqt) nreqt.headers = adjustheaders(nreqt, false)
if nreqt.source if nreqt.source
and not nreqt.headers["content-length"] and not nreqt.headers["content-length"]
and not nreqt.headers["transfer-encoding"] and not nreqt.headers["transfer-encoding"]
@ -290,8 +362,8 @@ local function adjustrequest(reqt)
nreqt.headers["transfer-encoding"] = "chunked" nreqt.headers["transfer-encoding"] = "chunked"
end end
-- ajust host and port if there is a proxy -- adjust host, port and create if there is a proxy
nreqt.host, nreqt.port = adjustproxy(nreqt) nreqt.host, nreqt.port, nreqt.create = adjustproxy(nreqt)
return nreqt return nreqt
end end

View File

@ -54,6 +54,33 @@ int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps)
return opt->func(L, ps); return opt->func(L, ps);
} }
/*------------------------------------------------------*/
/* binds socket to network interface */
int opt_set_bindtodevice(lua_State *L, p_socket ps)
{
#ifndef SO_BINDTODEVICE
return luaL_error(L, "SO_BINDTODEVICE is not supported on this operating system");
#else
const char *dev = luaL_checkstring(L, 3);
return opt_set(L, ps, SOL_SOCKET, SO_BINDTODEVICE, (char*)dev, strlen(dev)+1);
#endif
}
int opt_get_bindtodevice(lua_State *L, p_socket ps)
{
#ifndef SO_BINDTODEVICE
return luaL_error(L, "SO_BINDTODEVICE is not supported on this operating system");
#else
char dev[IFNAMSIZ];
int len = sizeof(dev);
int err = opt_get(L, ps, SOL_SOCKET, SO_BINDTODEVICE, &dev, &len);
if (err)
return err;
lua_pushstring(L, dev);
return 1;
#endif
}
/*------------------------------------------------------*/ /*------------------------------------------------------*/
/* enables reuse of local address */ /* enables reuse of local address */
int opt_set_reuseaddr(lua_State *L, p_socket ps) int opt_set_reuseaddr(lua_State *L, p_socket ps)

View File

@ -53,6 +53,9 @@ int opt_get_tcp_keepintvl(lua_State *L, p_socket ps);
int opt_set_tcp_defer_accept(lua_State *L, p_socket ps); int opt_set_tcp_defer_accept(lua_State *L, p_socket ps);
#endif #endif
int opt_set_bindtodevice(lua_State *L, p_socket ps);
int opt_get_bindtodevice(lua_State *L, p_socket ps);
int opt_set_keepalive(lua_State *L, p_socket ps); int opt_set_keepalive(lua_State *L, p_socket ps);
int opt_get_keepalive(lua_State *L, p_socket ps); int opt_get_keepalive(lua_State *L, p_socket ps);

View File

@ -71,6 +71,7 @@ static luaL_Reg tcp_methods[] = {
/* socket option handlers */ /* socket option handlers */
static t_opt optget[] = { static t_opt optget[] = {
{"bindtodevice", opt_get_bindtodevice},
{"keepalive", opt_get_keepalive}, {"keepalive", opt_get_keepalive},
{"reuseaddr", opt_get_reuseaddr}, {"reuseaddr", opt_get_reuseaddr},
{"reuseport", opt_get_reuseport}, {"reuseport", opt_get_reuseport},
@ -92,6 +93,7 @@ static t_opt optget[] = {
}; };
static t_opt optset[] = { static t_opt optset[] = {
{"bindtodevice", opt_set_bindtodevice},
{"keepalive", opt_set_keepalive}, {"keepalive", opt_set_keepalive},
{"reuseaddr", opt_set_reuseaddr}, {"reuseaddr", opt_set_reuseaddr},
{"reuseport", opt_set_reuseport}, {"reuseport", opt_set_reuseport},