Pull request: 2509 type-safety vol.2
Merge in DNS/adguard-home from 2509-type-safety-vol2 to master Updates #2509. Squashed commit of the following: commit c944e4e0a9949fc894c90b4bc1f739148a67fd9d Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Jan 21 19:36:20 2021 +0300 all: imp docs commit e8ac1815c492b0a9434596e35a48755cac2b9f3b Author: Eugene Burkov <e.burkov@adguard.com> Date: Wed Jan 20 12:38:48 2021 +0300 all: imp JSON encoding, decoding
This commit is contained in:
@@ -44,41 +44,44 @@ func addDNSAddress(dnsAddresses *[]string, addr net.IP) {
|
||||
*dnsAddresses = append(*dnsAddresses, hostport)
|
||||
}
|
||||
|
||||
// statusResponse is a response for /control/status endpoint.
|
||||
type statusResponse struct {
|
||||
DNSAddrs []string `json:"dns_addresses"`
|
||||
DNSPort int `json:"dns_port"`
|
||||
HTTPPort int `json:"http_port"`
|
||||
IsProtectionEnabled bool `json:"protection_enabled"`
|
||||
// TODO(e.burkov): Inspect if front-end doesn't requires this field as
|
||||
// openapi.yaml declares.
|
||||
IsDHCPAvailable bool `json:"dhcp_available"`
|
||||
IsRunning bool `json:"running"`
|
||||
Version string `json:"version"`
|
||||
Language string `json:"language"`
|
||||
}
|
||||
|
||||
func handleStatus(w http.ResponseWriter, _ *http.Request) {
|
||||
c := dnsforward.FilteringConfig{}
|
||||
resp := statusResponse{
|
||||
DNSAddrs: getDNSAddresses(),
|
||||
DNSPort: config.DNS.Port,
|
||||
HTTPPort: config.BindPort,
|
||||
IsRunning: isRunning(),
|
||||
Version: version.Version(),
|
||||
Language: config.Language,
|
||||
}
|
||||
|
||||
var c *dnsforward.FilteringConfig
|
||||
if Context.dnsServer != nil {
|
||||
Context.dnsServer.WriteDiskConfig(&c)
|
||||
c = &dnsforward.FilteringConfig{}
|
||||
Context.dnsServer.WriteDiskConfig(c)
|
||||
resp.IsProtectionEnabled = c.ProtectionEnabled
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"dns_addresses": getDNSAddresses(),
|
||||
"http_port": config.BindPort,
|
||||
"dns_port": config.DNS.Port,
|
||||
"running": isRunning(),
|
||||
"version": version.Version(),
|
||||
"language": config.Language,
|
||||
|
||||
"protection_enabled": c.ProtectionEnabled,
|
||||
// IsDHCPAvailable field is now false by default for Windows.
|
||||
if runtime.GOOS != "windows" {
|
||||
resp.IsDHCPAvailable = Context.dhcpServer != nil
|
||||
}
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
// Set the DHCP to false explicitly, because Context.dhcpServer
|
||||
// is probably not nil, despite the fact that there is no
|
||||
// support for DHCP on Windows in AdGuardHome.
|
||||
//
|
||||
// See also the TODO in dhcpd.Create.
|
||||
data["dhcp_available"] = false
|
||||
} else {
|
||||
data["dhcp_available"] = (Context.dhcpServer != nil)
|
||||
}
|
||||
|
||||
jsonVal, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
httpError(w, http.StatusInternalServerError, "Unable to marshal status json: %s", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, err = w.Write(jsonVal)
|
||||
err := json.NewEncoder(w).Encode(resp)
|
||||
if err != nil {
|
||||
httpError(w, http.StatusInternalServerError, "Unable to write response json: %s", err)
|
||||
return
|
||||
|
||||
@@ -21,23 +21,16 @@ import (
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
)
|
||||
|
||||
type firstRunData struct {
|
||||
WebPort int `json:"web_port"`
|
||||
DNSPort int `json:"dns_port"`
|
||||
Interfaces map[string]interface{} `json:"interfaces"`
|
||||
// getAddrsResponse is the response for /install/get_addresses endpoint.
|
||||
type getAddrsResponse struct {
|
||||
WebPort int `json:"web_port"`
|
||||
DNSPort int `json:"dns_port"`
|
||||
Interfaces map[string]*util.NetInterface `json:"interfaces"`
|
||||
}
|
||||
|
||||
type netInterfaceJSON struct {
|
||||
Name string `json:"name"`
|
||||
MTU int `json:"mtu"`
|
||||
HardwareAddr string `json:"hardware_address"`
|
||||
Addresses []net.IP `json:"ip_addresses"`
|
||||
Flags string `json:"flags"`
|
||||
}
|
||||
|
||||
// Get initial installation settings
|
||||
// handleInstallGetAddresses is the handler for /install/get_addresses endpoint.
|
||||
func (web *Web) handleInstallGetAddresses(w http.ResponseWriter, r *http.Request) {
|
||||
data := firstRunData{}
|
||||
data := getAddrsResponse{}
|
||||
data.WebPort = 80
|
||||
data.DNSPort = 53
|
||||
|
||||
@@ -47,16 +40,9 @@ func (web *Web) handleInstallGetAddresses(w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
data.Interfaces = make(map[string]interface{})
|
||||
data.Interfaces = make(map[string]*util.NetInterface)
|
||||
for _, iface := range ifaces {
|
||||
ifaceJSON := netInterfaceJSON{
|
||||
Name: iface.Name,
|
||||
MTU: iface.MTU,
|
||||
HardwareAddr: iface.HardwareAddr,
|
||||
Addresses: iface.Addresses,
|
||||
Flags: iface.Flags,
|
||||
}
|
||||
data.Interfaces[iface.Name] = ifaceJSON
|
||||
data.Interfaces[iface.Name] = iface
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -520,15 +506,15 @@ func (web *Web) handleInstallConfigureBeta(w http.ResponseWriter, r *http.Reques
|
||||
web.handleInstallConfigure(w, r)
|
||||
}
|
||||
|
||||
// firstRunDataBeta is a struct representing new client's getting addresses
|
||||
// getAddrsResponseBeta is a struct representing new client's getting addresses
|
||||
// request body. It uses array of structs instead of map.
|
||||
//
|
||||
// TODO(e.burkov): This should removed with the API v1 when the appropriate
|
||||
// functionality will appear in default firstRunData.
|
||||
type firstRunDataBeta struct {
|
||||
WebPort int `json:"web_port"`
|
||||
DNSPort int `json:"dns_port"`
|
||||
Interfaces []netInterfaceJSON `json:"interfaces"`
|
||||
type getAddrsResponseBeta struct {
|
||||
WebPort int `json:"web_port"`
|
||||
DNSPort int `json:"dns_port"`
|
||||
Interfaces []*util.NetInterface `json:"interfaces"`
|
||||
}
|
||||
|
||||
// handleInstallConfigureBeta is a substitution of /install/get_addresses
|
||||
@@ -537,7 +523,7 @@ type firstRunDataBeta struct {
|
||||
// TODO(e.burkov): This should removed with the API v1 when the appropriate
|
||||
// functionality will appear in default handleInstallGetAddresses.
|
||||
func (web *Web) handleInstallGetAddressesBeta(w http.ResponseWriter, r *http.Request) {
|
||||
data := firstRunDataBeta{}
|
||||
data := getAddrsResponseBeta{}
|
||||
data.WebPort = 80
|
||||
data.DNSPort = 53
|
||||
|
||||
@@ -547,17 +533,7 @@ func (web *Web) handleInstallGetAddressesBeta(w http.ResponseWriter, r *http.Req
|
||||
return
|
||||
}
|
||||
|
||||
data.Interfaces = make([]netInterfaceJSON, 0, len(ifaces))
|
||||
for _, iface := range ifaces {
|
||||
ifaceJSON := netInterfaceJSON{
|
||||
Name: iface.Name,
|
||||
MTU: iface.MTU,
|
||||
HardwareAddr: iface.HardwareAddr,
|
||||
Addresses: iface.Addresses,
|
||||
Flags: iface.Flags,
|
||||
}
|
||||
data.Interfaces = append(data.Interfaces, ifaceJSON)
|
||||
}
|
||||
data.Interfaces = ifaces
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err = json.NewEncoder(w).Encode(data)
|
||||
|
||||
@@ -16,10 +16,6 @@ import (
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
)
|
||||
|
||||
type getVersionJSONRequest struct {
|
||||
RecheckNow bool `json:"recheck_now"`
|
||||
}
|
||||
|
||||
// temporaryError is the interface for temporary errors from the Go standard
|
||||
// library.
|
||||
type temporaryError interface {
|
||||
@@ -29,31 +25,34 @@ type temporaryError interface {
|
||||
|
||||
// Get the latest available version from the Internet
|
||||
func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) {
|
||||
resp := &versionResponse{}
|
||||
if Context.disableUpdate {
|
||||
resp := make(map[string]interface{})
|
||||
resp["disabled"] = true
|
||||
d, _ := json.Marshal(resp)
|
||||
_, _ = w.Write(d)
|
||||
// w.Header().Set("Content-Type", "application/json")
|
||||
resp.Disabled = true
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
// TODO(e.burkov): Add error handling and deal with headers.
|
||||
return
|
||||
}
|
||||
|
||||
req := getVersionJSONRequest{}
|
||||
req := &struct {
|
||||
Recheck bool `json:"recheck_now"`
|
||||
}{}
|
||||
|
||||
var err error
|
||||
if r.ContentLength != 0 {
|
||||
err = json.NewDecoder(r.Body).Decode(&req)
|
||||
err = json.NewDecoder(r.Body).Decode(req)
|
||||
if err != nil {
|
||||
httpError(w, http.StatusBadRequest, "JSON parse: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var info updater.VersionInfo
|
||||
for i := 0; i != 3; i++ {
|
||||
func() {
|
||||
Context.controlLock.Lock()
|
||||
defer Context.controlLock.Unlock()
|
||||
|
||||
info, err = Context.updater.VersionInfo(req.RecheckNow)
|
||||
resp.VersionInfo, err = Context.updater.VersionInfo(req.Recheck)
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
@@ -76,13 +75,16 @@ func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
if err != nil {
|
||||
vcu := Context.updater.VersionCheckURL()
|
||||
// TODO(a.garipov): Figure out the purpose of %T verb.
|
||||
httpError(w, http.StatusBadGateway, "Couldn't get version check json from %s: %T %s\n", vcu, err, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
resp.confirmAutoUpdate()
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, err = w.Write(getVersionResp(info))
|
||||
err = json.NewEncoder(w).Encode(resp)
|
||||
if err != nil {
|
||||
httpError(w, http.StatusInternalServerError, "Couldn't write body: %s", err)
|
||||
}
|
||||
@@ -109,21 +111,24 @@ func handleUpdate(w http.ResponseWriter, _ *http.Request) {
|
||||
go finishUpdate()
|
||||
}
|
||||
|
||||
// Convert version.json data to our JSON response
|
||||
func getVersionResp(info updater.VersionInfo) []byte {
|
||||
ret := make(map[string]interface{})
|
||||
ret["can_autoupdate"] = false
|
||||
ret["new_version"] = info.NewVersion
|
||||
ret["announcement"] = info.Announcement
|
||||
ret["announcement_url"] = info.AnnouncementURL
|
||||
// versionResponse is the response for /control/version.json endpoint.
|
||||
type versionResponse struct {
|
||||
Disabled bool `json:"disabled"`
|
||||
updater.VersionInfo
|
||||
}
|
||||
|
||||
if info.CanAutoUpdate {
|
||||
// confirmAutoUpdate checks the real possibility of auto update.
|
||||
func (vr *versionResponse) confirmAutoUpdate() {
|
||||
if vr.CanAutoUpdate != nil && *vr.CanAutoUpdate {
|
||||
canUpdate := true
|
||||
|
||||
tlsConf := tlsConfigSettings{}
|
||||
Context.tls.WriteDiskConfig(&tlsConf)
|
||||
var tlsConf *tlsConfigSettings
|
||||
if runtime.GOOS != "windows" {
|
||||
tlsConf = &tlsConfigSettings{}
|
||||
Context.tls.WriteDiskConfig(tlsConf)
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" &&
|
||||
if tlsConf != nil &&
|
||||
((tlsConf.Enabled && (tlsConf.PortHTTPS < 1024 ||
|
||||
tlsConf.PortDNSOverTLS < 1024 ||
|
||||
tlsConf.PortDNSOverQUIC < 1024)) ||
|
||||
@@ -131,11 +136,8 @@ func getVersionResp(info updater.VersionInfo) []byte {
|
||||
config.DNS.Port < 1024) {
|
||||
canUpdate, _ = sysutil.CanBindPrivilegedPorts()
|
||||
}
|
||||
ret["can_autoupdate"] = canUpdate
|
||||
vr.CanAutoUpdate = &canUpdate
|
||||
}
|
||||
|
||||
d, _ := json.Marshal(ret)
|
||||
return d
|
||||
}
|
||||
|
||||
// Complete an update procedure
|
||||
|
||||
Reference in New Issue
Block a user