Merge pull request #2390 from freifunk-gluon/v2021.1.x-backports

Backports for v2021.1.x
This commit is contained in:
David Bauer 2022-02-23 23:11:18 +01:00 committed by GitHub
commit e51836ecf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 223 additions and 119 deletions

View File

@ -10,7 +10,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Install Dependencies
run: sudo apt install lua-check
run: sudo apt-get -y update && sudo apt-get -y install lua-check
- name: Install example site
run: ln -s ./docs/site-example ./site
- name: Lint Lua code
@ -22,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Install Dependencies
run: sudo apt install shellcheck
run: sudo apt-get -y update && sudo apt-get -y install shellcheck
- name: Install example site
run: ln -s ./docs/site-example ./site
- name: Lint shell code

View File

@ -19,8 +19,9 @@ escape = '$(subst ','\'',$(1))'
GLUON_SITEDIR ?= site
$(eval $(call mkabspath,GLUON_SITEDIR))
$(GLUON_SITEDIR)/site.mk:
$(error No site configuration was found. Please check out a site configuration to $(GLUON_SITEDIR))
ifeq ($(realpath $(GLUON_SITEDIR)/site.mk),)
$(error No site configuration was found. Please check out a site configuration to $(GLUON_SITEDIR))
endif
include $(GLUON_SITEDIR)/site.mk

View File

@ -478,7 +478,7 @@ config_mode \: optional
*openlayers_url* allows to override the base URL of the
*build/ol.js* and *css/ol.css* files (the default is
``https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.2.0``).
``https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@35ffe7626ce16c372143f3c903950750075e7068/en/v5.3.0``).
It is also possible to replace the default tile layer (which is OpenStreetMap)
with a custom one using the *tile_layer* section. Only XYZ layers are supported
at this point.

View File

@ -22,7 +22,7 @@ function f:write()
uci:set("gluon-setup-mode", uci:get_first("gluon-setup-mode", "setup_mode"), "configured", true)
uci:save("gluon-setup-mode")
os.execute('gluon-reconfigure')
os.execute('exec gluon-reconfigure >/dev/null')
f.template = "wizard/reboot"
f.package = "gluon-config-mode-core"

View File

@ -69,8 +69,23 @@ void tv_subtract (struct timeval *r, const struct timeval *a, const struct timev
}
}
ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, const struct timeval *timeout) {
void resize_recvbuffer(char **recvbuffer, size_t *recvbuffer_len, size_t recvlen)
{
free(*recvbuffer);
*recvbuffer = malloc(recvlen);
if (!(*recvbuffer)) {
perror("Could not resize recvbuffer");
exit(EXIT_FAILURE);
}
*recvbuffer_len = recvlen;
}
ssize_t recvtimeout(int socket, char **recvbuffer, size_t *recvbuffer_len,
const struct timeval *timeout) {
struct timeval now, timeout_left;
ssize_t recvlen;
getclock(&now);
tv_subtract(&timeout_left, timeout, &now);
@ -79,18 +94,28 @@ ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, const st
return -1;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout_left, sizeof(timeout_left));
return recv(socket, buffer, length, flags);
recvlen = recv(socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
if (recvlen < 0)
return recvlen;
if (recvlen > *recvbuffer_len)
resize_recvbuffer(recvbuffer, recvbuffer_len, recvlen);
return recv(socket, *recvbuffer, *recvbuffer_len, 0);
}
int request(const int sock, const struct sockaddr_in6 *client_addr, const char *request, const char *sse, double timeout, unsigned int max_count) {
int request(const int sock, char **recvbuffer, size_t *recvbuffer_len,
const struct sockaddr_in6 *client_addr, const char *request,
const char *sse, double timeout, unsigned int max_count) {
ssize_t ret;
char buffer[8192];
unsigned int count = 0;
ret = sendto(sock, request, strlen(request), 0, (struct sockaddr *)client_addr, sizeof(struct sockaddr_in6));
if (ret < 0) {
perror("Error in sendto()");
free(*recvbuffer);
exit(EXIT_FAILURE);
}
@ -105,7 +130,7 @@ int request(const int sock, const struct sockaddr_in6 *client_addr, const char *
}
do {
ret = recvtimeout(sock, buffer, sizeof(buffer), 0, &tv_timeout);
ret = recvtimeout(sock, recvbuffer, recvbuffer_len, &tv_timeout);
if (ret < 0)
break;
@ -116,7 +141,7 @@ int request(const int sock, const struct sockaddr_in6 *client_addr, const char *
fputs("data: ", stdout);
}
fwrite(buffer, sizeof(char), ret, stdout);
fwrite(*recvbuffer, sizeof(char), ret, stdout);
if (sse)
fputs("\n\n", stdout);
@ -137,6 +162,8 @@ int main(int argc, char **argv) {
int sock;
struct sockaddr_in6 client_addr = {};
char *request_string = NULL;
char *recvbuffer = NULL;
size_t recvbuffer_len = 0;
sock = socket(PF_INET6, SOCK_DGRAM, 0);
@ -243,11 +270,13 @@ int main(int argc, char **argv) {
}
do {
ret = request(sock, &client_addr, request_string, sse, timeout, max_count);
ret = request(sock, &recvbuffer, &recvbuffer_len, &client_addr,
request_string, sse, timeout, max_count);
} while(loop);
if (sse)
fputs("event: eot\ndata: null\n\n", stdout);
free(recvbuffer);
return ret;
}

View File

@ -1,7 +1,11 @@
<%-
local iwinfo = require 'iwinfo'
local ubus = require 'ubus'
local unistd = require 'posix.unistd'
local util = require 'gluon.util'
local wireless = require 'gluon.wireless'
local uci = require('simple-uci').cursor()
local translations = {}
local site_i18n = i18n 'gluon-site'
@ -29,17 +33,31 @@
local mesh = get_mesh()
local function get_interfaces()
local uconn = ubus.connect()
if not uconn then
error('failed to connect to ubus')
end
local function get_interfaces(uconn)
local interfaces = util.get_mesh_devices(uconn)
ubus.close(uconn)
table.sort(interfaces)
return interfaces
end
local function get_radios()
local ret = {}
wireless.foreach_radio(uci, function(radio)
local channel = iwinfo.nl80211.channel(wireless.find_phy(radio))
if channel then
table.insert(ret, {
name = radio['.name'],
channel = channel,
})
end
end)
table.sort(ret, function(a, b)
return a.name < b.name
end)
return ret
end
local function is_wireless(iface)
while true do
local pattern = '/sys/class/net/' .. iface .. '/lower_*'
@ -52,7 +70,16 @@
return unistd.access('/sys/class/net/' .. iface .. '/wireless') ~= nil
end
local interfaces = get_interfaces()
local uconn = ubus.connect()
if not uconn then
error('failed to connect to ubus')
end
local interfaces = get_interfaces(uconn)
ubus.close(uconn)
local radios = get_radios()
local function sorted(t)
t = {unpack(t)}
@ -66,12 +93,17 @@
local function formatBits(bits)
local units = {[0]='', 'k', 'M', 'G'}
local unit = 0
local pow = math.floor(math.log(math.max(math.abs(bits), 1)) / math.log(1000))
local known_pow = math.min(pow, #units)
for i = 1, #units do
if math.abs(bits) < 1000 then
break
end
unit = i
bits = bits / 1000
end
local significand = bits/(1000^known_pow)
return string.format('%g %sbit', significand, units[known_pow])
return string.format('%g %sbit', bits, units[unit])
end
local function statistics(key, format)
@ -135,11 +167,11 @@
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.enabled then -%>
<dt><%:Bandwidth limit%></dt>
<dd>
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.egress then -%>
<%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.egress*1000) %>/s <%:upstream%><br />
<%- end %>
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.ingress then -%>
<%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.ingress*1000) %>/s <%:downstream%>
<%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.ingress*1000) %>/s <%:downstream%><br />
<%- end %>
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.egress then -%>
<%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.egress*1000) %>/s <%:upstream%>
<%- end %>
</dd>
<%- end %>
@ -190,11 +222,17 @@
<tr><th><%:Wireless 2.4 GHz%></th><td><%= statistics('clients/wifi24') %></td></tr>
<tr><th><%:Wireless 5 GHz%></th><td><%= statistics('clients/wifi5') %></td></tr>
</table>
<div id="radios" style="display: none">
<% if radios[1] then -%>
<h3><%:Radios%></h3>
<table id="radio-devices">
<table>
<% for _, radio in ipairs(radios) do -%>
<tr>
<th><%| radio.name %></th>
<td><%| translatef('Channel %u', radio.channel) %></td>
</tr>
<%- end %>
</table>
</div>
<%- end %>
<h3><%:Traffic%></h3>
<table>

File diff suppressed because one or more lines are too long

View File

@ -31,8 +31,8 @@ msgstr "Automatische Updates"
msgid "Bandwidth limit"
msgstr "Bandbreitenlimit"
msgid "Channel"
msgstr "Kanal"
msgid "Channel %u"
msgstr "Kanal %u"
msgid "Clients"
msgstr "Clients"

View File

@ -22,7 +22,7 @@ msgstr ""
msgid "Bandwidth limit"
msgstr ""
msgid "Channel"
msgid "Channel %u"
msgstr ""
msgid "Clients"

View File

@ -121,7 +121,15 @@
var neigh = iface.lookup_neigh(addr);
if (!neigh)
continue;
return 'via ' + neigh.get_hostname() + ' (' + i + ')';
var span = document.createElement('span');
span.appendChild(document.createTextNode('via '));
var a = document.createElement('a');
a.href = 'http://[' + neigh.get_addr() + ']/';
a.textContent = neigh.get_hostname();
span.appendChild(a);
span.appendChild(document.createTextNode(' (' + i + ')'));
return span;
}
return 'via ' + addr + ' (unknown iface)';
@ -208,50 +216,6 @@
});
}
function update_radios(wireless) {
function channel(frequency) {
if (frequency===2484)
return 14
if (2412<=frequency && frequency<=2472)
return (frequency-2407)/5
if (5160<=frequency && frequency<=5885)
return (frequency-5000)/5
return 'unknown'
}
var div = document.getElementById('radios');
if (!wireless) {
div.style.display = 'none';
return;
}
div.style.display = '';
var table = document.getElementById('radio-devices');
while (table.lastChild)
table.removeChild(table.lastChild);
wireless.sort(function (a, b) {
return a.phy - b.phy;
});
wireless.forEach(function (radio) {
var tr = document.createElement('tr');
var th = document.createElement('th');
th.textContent = "phy" + radio.phy;
tr.appendChild(th);
var td = document.createElement('td');
td.innerHTML = radio.frequency + " MHz<br />Channel " + channel(radio.frequency);
tr.appendChild(td);
table.appendChild(tr);
});
}
var statisticsElems = document.querySelectorAll('[data-statistics]');
add_event_source('/cgi-bin/dyn/statistics', function(data, dataPrev) {
@ -264,9 +228,16 @@
var valuePrev = resolve_key(dataPrev, stat);
var value = resolve_key(data, stat);
try {
var text = formats[format](value, valuePrev, diff);
if (text !== undefined)
elem.textContent = text;
var format_result = formats[format](value, valuePrev, diff);
switch (typeof format_result) {
case "object":
if (elem.lastChild)
elem.removeChild(elem.lastChild);
elem.appendChild(format_result);
break;
default:
elem.textContent = format_result;
}
} catch (e) {
console.error(e);
}
@ -277,11 +248,6 @@
} catch (e) {
console.error(e);
}
try {
update_radios(data.wireless);
} catch (e) {
console.error(e);
}
})
function haversine(lat1, lon1, lat2, lon2) {
@ -319,7 +285,7 @@
'resize': function(w, h) {
var lastImage;
try {
ctx.getImageData(0, 0, w, h);
lastImage = ctx.getImageData(0, 0, w, h);
} catch (e) {}
canvas.width = w;
canvas.height = h;
@ -492,6 +458,7 @@
}
var hostname = document.createElement("span");
var addr;
hostname.textContent = addr;
tdHostname.appendChild(hostname);
@ -552,13 +519,13 @@
el.classList.add("highlight");
if (signal)
signal.highlight = true;
}
};
el.onmouseleave = function () {
el.classList.remove("highlight")
el.classList.remove("highlight");
if (signal)
signal.highlight = false;
}
};
var timeout;
@ -586,7 +553,8 @@
var n = parts.length;
var groups = [];
parts.forEach(function(part, i) {
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
if (part === '') {
while (n++ <= 8)
groups.push(0);
@ -596,7 +564,7 @@
groups.push(parseInt(part, 16));
}
});
};
return groups;
}
@ -664,8 +632,11 @@
'get_hostname': function() {
return hostname.textContent;
},
'get_addr': function() {
return addr;
},
'update_nodeinfo': function(nodeinfo) {
var addr = choose_address(nodeinfo.network.addresses);
addr = choose_address(nodeinfo.network.addresses);
if (addr) {
if (hostname.nodeName.toLowerCase() === 'span') {
var oldHostname = hostname;

View File

@ -61,7 +61,7 @@ local function match(a, b, n)
end
entry({}, call(function(http, renderer)
local nodeinfo = json.parse(util.exec('exec gluon-neighbour-info -d ::1 -p 1001 -t 1 -c 1 -r nodeinfo'))
local nodeinfo = json.parse(util.exec('exec gluon-neighbour-info -d ::1 -p 1001 -t 3 -c 1 -r nodeinfo'))
local node_ip = parse_ip(http:getenv('SERVER_ADDR'))
if node_ip and (

View File

@ -44,7 +44,6 @@ $Id$
<div class="gluon-page-actions">
<input type="hidden" name="step" value="2" />
<input type="hidden" name="token" value="<%=token%>" />
<input class="gluon-button gluon-button-submit" type="submit" value="<%:Upload image%>" />
</div>
</form>

View File

@ -49,13 +49,11 @@ You may obtain a copy of the License at
<form method="post" enctype="multipart/form-data" action="<%|url(request)%>" style="display:inline">
<input type="hidden" name="step" value="3" />
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
<input type="hidden" name="token" value="<%=token%>" />
<input class="gluon-button gluon-button-submit" type="submit" value="<%:Continue%>" />
</form>
<form method="post" enctype="multipart/form-data" action="<%|url(request)%>" style="display:inline">
<input type="hidden" name="step" value="1" />
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
<input type="hidden" name="token" value="<%=token%>" />
<input class="gluon-button gluon-button-reset" type="submit" value="<%:Cancel%>" />
</form>
</div>

View File

@ -1,5 +1,4 @@
<form method="post" enctype="multipart/form-data" action="<%|url(request)%>" data-update="reset">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="<%=id%>" value="1" />
<div class="gluon-form" id="form-<%=id%>">

View File

@ -1,6 +1,7 @@
<div id="<%=id%>" class="gluon-osm-map" style="display: none"></div>
<script type="text/javascript" src="/static/gluon-web-osm.js"></script>
<script type="text/javascript">
//<![CDATA[
(function() {
var elMap = document.getElementById(<%=json(id)%>);
var wrapper = elMap.parentNode;
@ -41,4 +42,5 @@
});
});
})();
//]]>
</script>

View File

@ -4,7 +4,8 @@ local util = require "gluon.web.util"
local class = util.class
local DEFAULT_URL = 'https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.2.0'
local DEFAULT_URL =
'https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@35ffe7626ce16c372143f3c903950750075e7068/en/v5.3.0'
local M = {}

View File

@ -184,9 +184,15 @@ local function dispatch(config, http, request)
return
end
http:parse_input(node.filehandler)
local ok, err = pcall(http.parse_input, http, node.filehandler)
if not ok then
http:status(400, "Bad request")
http:prepare_content("text/plain")
http:write(err .. "\r\n")
return
end
local ok, err = pcall(node.target)
ok, err = pcall(node.target)
if not ok then
http:status(500, "Internal Server Error")
renderer.render_layout("error/500", {
@ -208,6 +214,6 @@ return function(config, http)
if not ok then
http:status(500, "Internal Server Error")
http:prepare_content("text/plain")
http:write(err)
http:write(err .. "\r\n")
end
end

View File

@ -108,16 +108,11 @@ end
-- o String value containing a chunk of the file data
-- o Boolean which indicates whether the current chunk is the last one (eof)
local function mimedecode_message_body(src, msg, filecb)
if msg and msg.env.CONTENT_TYPE then
msg.mime_boundary = msg.env.CONTENT_TYPE:match("^multipart/form%-data; boundary=(.+)$")
local mime_boundary = (msg.env.CONTENT_TYPE or ''):match("^multipart/form%-data; boundary=(.+)$")
if not mime_boundary then
error("Invalid Content-Type found")
end
if not msg.mime_boundary then
return nil, "Invalid Content-Type found"
end
local tlen = 0
local inhdr = false
local field = nil
@ -188,10 +183,10 @@ local function mimedecode_message_body(src, msg, filecb)
local spos, epos, found
repeat
spos, epos = data:find("\r\n--" .. msg.mime_boundary .. "\r\n", 1, true)
spos, epos = data:find("\r\n--" .. mime_boundary .. "\r\n", 1, true)
if not spos then
spos, epos = data:find("\r\n--" .. msg.mime_boundary .. "--\r\n", 1, true)
spos, epos = data:find("\r\n--" .. mime_boundary .. "--\r\n", 1, true)
end
@ -250,20 +245,61 @@ local function mimedecode_message_body(src, msg, filecb)
return true
end
return pump(src, snk)
assert(pump(src, snk))
end
local function check_post_origin(msg)
local default_port = '80'
local request_scheme = 'http'
if msg.env.HTTPS then
default_port = '443'
request_scheme = 'https'
end
local request_host = msg.env.HTTP_HOST
if not request_host then
error('POST request without Host header')
end
if not request_host:match(':[0-9]+$') then
request_host = request_host .. ':' .. default_port
end
local origin = msg.env.HTTP_ORIGIN
if not origin then
error('POST request without Origin header')
end
local origin_scheme, origin_host = origin:match('^([^:]*)://(.*)$')
if not origin_host then
error('POST request with invalid Origin header')
end
if not origin_host:match(':[0-9]+$') then
local origin_port
if origin_scheme == 'http' then
origin_port = '80'
elseif origin_scheme == 'https' then
origin_port = '443'
else
error('POST request with invalid Origin header')
end
origin_host = origin_host .. ':' .. origin_port
end
if request_scheme ~= origin_scheme or request_host ~= origin_host then
error('Invalid cross-origin POST')
end
end
-- This function will examine the Content-Type within the given message object
-- to select the appropriate content decoder.
-- Currently only the multipart/form-data mime type is supported.
function M.parse_message_body(src, msg, filecb)
if not (msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE) then
if msg.env.REQUEST_METHOD ~= "POST" then
return
end
if msg.env.CONTENT_TYPE:match("^multipart/form%-data") then
return mimedecode_message_body(src, msg, filecb)
end
check_post_origin(msg)
mimedecode_message_body(src, msg, filecb)
end
return M

View File

@ -0,0 +1,24 @@
From: Martin Weinelt <martin@darmstadt.freifunk.net>
Date: Tue, 8 Feb 2022 21:09:20 +0100
Subject: perl: don't build in parallel and bump release
Parallel builds cause spurious build failures with high core counts.
https://github.com/openwrt/packages/issues/8238
https://github.com/openwrt/packages/pull/17274
diff --git a/lang/perl/Makefile b/lang/perl/Makefile
index 84d256d2d8c682f18670a4cbae0a48e3333fb222..c2e5cf8e703af675dd296704597934aa9b5f7446 100644
--- a/lang/perl/Makefile
+++ b/lang/perl/Makefile
@@ -34,8 +34,8 @@ PKG_BUILD_DIR:=$(BUILD_DIR)/perl/$(PKG_NAME)-$(PKG_VERSION)
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/perl/$(PKG_NAME)-$(PKG_VERSION)
PKG_INSTALL:=1
PKG_BUILD_DEPENDS:=perl/host
-PKG_BUILD_PARALLEL:=1
-HOST_BUILD_PARALLEL:=1
+PKG_BUILD_PARALLEL:=0
+HOST_BUILD_PARALLEL:=0
# Variables used during configuration/build
HOST_PERL_PREFIX:=$(STAGING_DIR_HOSTPKG)/usr