2 local show_usage = require "util.prosodyctl".show_usage; |
2 local show_usage = require "util.prosodyctl".show_usage; |
3 local show_warning = require "util.prosodyctl".show_warning; |
3 local show_warning = require "util.prosodyctl".show_warning; |
4 local is_prosody_running = require "util.prosodyctl".isrunning; |
4 local is_prosody_running = require "util.prosodyctl".isrunning; |
5 local dependencies = require "util.dependencies"; |
5 local dependencies = require "util.dependencies"; |
6 local socket = require "socket"; |
6 local socket = require "socket"; |
|
7 local socket_url = require "socket.url"; |
7 local jid_split = require "util.jid".prepped_split; |
8 local jid_split = require "util.jid".prepped_split; |
8 local modulemanager = require "core.modulemanager"; |
9 local modulemanager = require "core.modulemanager"; |
|
10 local async = require "util.async"; |
|
11 local httputil = require "util.http"; |
9 |
12 |
10 local function check_ojn(check_type, target_host) |
13 local function check_ojn(check_type, target_host) |
11 local http = require "net.http"; -- .new({}); |
14 local http = require "net.http"; -- .new({}); |
12 local urlencode = require "util.http".urlencode; |
|
13 local json = require "util.json"; |
15 local json = require "util.json"; |
14 |
16 |
15 local response, err = async.wait_for(http.request( |
17 local response, err = async.wait_for(http.request( |
16 ("https://observe.jabber.network/api/v1/check/%s"):format(urlencode(check_type)), |
18 ("https://observe.jabber.network/api/v1/check/%s"):format(httputil.urlencode(check_type)), |
17 { |
19 { |
18 method="POST", |
20 method="POST", |
19 headers={["Accept"] = "application/json"; ["Content-Type"] = "application/json"}, |
21 headers={["Accept"] = "application/json"; ["Content-Type"] = "application/json"}, |
20 body=json.encode({target=target_host}), |
22 body=json.encode({target=target_host}), |
21 })); |
23 })); |
33 return false, ("Failed to parse API JSON: %s"):format(err) |
35 return false, ("Failed to parse API JSON: %s"):format(err) |
34 end |
36 end |
35 |
37 |
36 local success = decoded_body["success"]; |
38 local success = decoded_body["success"]; |
37 return success == true, nil; |
39 return success == true, nil; |
|
40 end |
|
41 |
|
42 local function check_probe(base_url, probe_module, target) |
|
43 local http = require "net.http"; -- .new({}); |
|
44 local params = httputil.formencode({ module = probe_module; target = target }) |
|
45 local response, err = async.wait_for(http.request(base_url .. "?" .. params)); |
|
46 |
|
47 if not response then return false, err; end |
|
48 |
|
49 if response.code ~= 200 then return false, ("API replied with non-200 code: %d"):format(response.code); end |
|
50 |
|
51 for line in response.body:gmatch("[^\r\n]+") do |
|
52 local probe_success = line:match("^probe_success%s+(%d+)"); |
|
53 |
|
54 if probe_success == "1" then |
|
55 return true; |
|
56 elseif probe_success == "0" then |
|
57 return false; |
|
58 end |
|
59 end |
|
60 return false, "Probe endpoint did not return a success status"; |
38 end |
61 end |
39 |
62 |
40 local function skip_bare_jid_hosts(host) |
63 local function skip_bare_jid_hosts(host) |
41 if jid_split(host) then |
64 if jid_split(host) then |
42 -- See issue #779 |
65 -- See issue #779 |
739 print("Prosody does not appear to be running, which is required for this test."); |
762 print("Prosody does not appear to be running, which is required for this test."); |
740 print("Start it and then try again."); |
763 print("Start it and then try again."); |
741 return 1; |
764 return 1; |
742 end |
765 end |
743 |
766 |
|
767 local checker = "observe.jabber.network"; |
|
768 local probe_instance; |
|
769 local probe_modules = { |
|
770 ["xmpp-client"] = "c2s_normal_auth"; |
|
771 ["xmpp-server"] = "s2s_normal"; |
|
772 ["xmpps-client"] = nil; -- TODO |
|
773 ["xmpps-server"] = nil; -- TODO |
|
774 }; |
|
775 local probe_settings = configmanager.get("*", "connectivity_probe"); |
|
776 if type(probe_settings) == "string" then |
|
777 probe_instance = probe_settings; |
|
778 elseif type(probe_settings) == "table" and type(probe_settings.url) == "string" then |
|
779 probe_instance = probe_settings.url; |
|
780 if type(probe_settings.modules) == "table" then |
|
781 probe_modules = probe_settings.modules; |
|
782 end |
|
783 elseif probe_settings ~= nil then |
|
784 print("The 'connectivity_probe' setting not understood."); |
|
785 print("Expected an URL or a table with 'url' and 'modules' fields"); |
|
786 print("See https://prosody.im/doc/prosodyctl#check for more information."); -- FIXME |
|
787 return 1; |
|
788 end |
|
789 |
|
790 local check_api; |
|
791 if probe_instance then |
|
792 local parsed_url = socket_url.parse(probe_instance); |
|
793 if not parsed_url then |
|
794 print(("'connectivity_probe' is not a valid URL: %q"):format(probe_instance)); |
|
795 print("Set it to the URL of an XMPP Blackbox Exporter instance and try again"); |
|
796 return 1; |
|
797 end |
|
798 checker = parsed_url.host; |
|
799 |
|
800 function check_api(protocol, host) |
|
801 local target = socket_url.build({scheme="xmpp",path=host}); |
|
802 local probe_module = probe_modules[protocol]; |
|
803 if not probe_module then |
|
804 return nil, "Checking protocol '"..protocol.."' is currently unsupported"; |
|
805 end |
|
806 return check_probe(probe_instance, probe_module, target); |
|
807 end |
|
808 else |
|
809 check_api = check_ojn; |
|
810 end |
|
811 |
744 for host in it.filter(skip_bare_jid_hosts, enabled_hosts()) do |
812 for host in it.filter(skip_bare_jid_hosts, enabled_hosts()) do |
745 local modules, component_module = modulemanager.get_modules_for_host(host); |
813 local modules, component_module = modulemanager.get_modules_for_host(host); |
746 if component_module then |
814 if component_module then |
747 modules:add(component_module) |
815 modules:add(component_module) |
748 end |
816 end |
749 |
817 |
750 print("Checking external connectivity for "..host.." via observe.jabber.network") |
818 print("Checking external connectivity for "..host.." via "..checker) |
751 local function check_connectivity(protocol) |
819 local function check_connectivity(protocol) |
752 local success, err = check_api(protocol, host); |
820 local success, err = check_api(protocol, host); |
753 if not success and err ~= nil then |
821 if not success and err ~= nil then |
754 print((" %s: Failed to request check at API: %s"):format(protocol, err)) |
822 print((" %s: Failed to request check at API: %s"):format(protocol, err)) |
755 elseif success then |
823 elseif success then |