Skip to content

Commit

Permalink
multi: Fix rpclisten config parsing (#191)
Browse files Browse the repository at this point in the history
This updates tinywallet.config to correctly parse rpclisten from the
dcrd config file, to be used as the default URL when configuring the
dcrd connection in tinywallet.
  • Loading branch information
rstaudt2 authored Jun 18, 2020
1 parent 863fd39 commit 280dc57
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 18 deletions.
5 changes: 3 additions & 2 deletions decred/decred/util/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def readINI(path, keys):
Returns:
dict: Discovered keys and values.
"""
config = configparser.ConfigParser()
config = configparser.ConfigParser(strict=False)
# Need to add a section header since configparser doesn't handle sectionless
# INI format.
with open(path) as f:
Expand Down Expand Up @@ -214,12 +214,13 @@ def makeWebsocketURL(baseURL, path):
Turn the HTTP/HTTPS URL into a WS/WSS one.
Args:
url (str): The base URL.
baseURL (str): The base URL.
path (str): The websocket endpoint path. e.g. path of "ws" will yield
URL wss://yourhost.com/ws.
Returns:
string: the WebSocket URL.
"""
baseURL = f"wss://{baseURL}" if "//" not in baseURL else baseURL
url = urlsplit(baseURL)
scheme = "wss" if url.scheme in ("https", "wss") else "ws"
return urlunsplit((scheme, url.netloc, f"/{path}", "", ""))
19 changes: 19 additions & 0 deletions decred/tests/unit/util/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,22 @@ def testgetenv(s):
monkeypatch.setattr(os.path, "expanduser", testexpanduser)
monkeypatch.setattr(os, "getenv", testgetenv)
assert helpers.appDataDir(appName) == "."


def test_makeWebsocketURL():
"""
Tests are 3-tuples:
baseURL (str): The base URL.
path (str): The websocket endpoint path.
want (str): The expected result.
"""
tests = [
("https://localhost:19556", "ws", "wss://localhost:19556/ws"),
("http://localhost:8337", "ws1", "ws://localhost:8337/ws1"),
("ws://localhost:9999", "ws2", "ws://localhost:9999/ws2"),
("wss://localhost", "ws3", "wss://localhost/ws3"),
("localhost:1234", "ws4", "wss://localhost:1234/ws4"),
]
for baseURL, path, want in tests:
assert helpers.makeWebsocketURL(baseURL, path) == want
30 changes: 25 additions & 5 deletions tinywallet/tests/unit/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import pytest

from decred.dcr.nets import simnet
from decred.dcr.nets import DcrdPorts, simnet
from decred.util import helpers
from tinywallet import ui # noqa, for coverage.
from tinywallet.config import CmdArgs, dcrd, load
Expand Down Expand Up @@ -56,10 +56,30 @@ def mock_appDataDir(app_name):
cfg_file.write("rpcuser=username\n")
cfg = dcrd(simnet)
assert "rpc.cert" in cfg["rpccert"]
assert "localhost" in cfg["rpclisten"]

cfg_file.write("rpcuser=username\nrpclisten=listen\n")
assert "listen" in dcrd(simnet)["rpclisten"]
assert cfg["rpclisten"] == f"localhost:{DcrdPorts[simnet.Name]}"
assert not cfg["notls"]

tests = [
("rpclisten=", f"localhost:{DcrdPorts[simnet.Name]}"),
("rpclisten=0.0.0.0", f"0.0.0.0:{DcrdPorts[simnet.Name]}"),
("rpclisten=::", f"localhost:{DcrdPorts[simnet.Name]}"),
("rpclisten=:9109", "localhost:9109"),
("rpclisten=0.0.0.0:9109", "0.0.0.0:9109"),
("rpclisten=[::]:9109", "localhost:9109"),
("rpclisten=[::1]:9109", "localhost:9109"),
("rpclisten=:8337\nrpclisten=:9999", "localhost:9999"),
]
for rpclistenCfg, want in tests:
cfg_file.write(f"rpcuser=username\n{rpclistenCfg}\n")
assert dcrd(simnet)["rpclisten"] == want

tests = [
("notls=1", True),
("notls=0", False),
]
for notlsCfg, want in tests:
cfg_file.write(f"rpcuser=username\n{notlsCfg}\n")
assert dcrd(simnet)["notls"] == want


def test_load():
Expand Down
27 changes: 19 additions & 8 deletions tinywallet/tinywallet/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import logging
import os
import sys
from urllib.parse import urlparse

from appdirs import AppDirs

Expand Down Expand Up @@ -112,9 +113,9 @@ class DB:
def dcrd(netParams):
"""
Attempt to fetch the dcrd configuration settings. Values will be parsed for
'rpcuser', 'rpcpass', 'rpclisten', and 'rpccert'. The setting for 'rpcuser'
must be present in the file. If values are not found for 'rpccert' or
'rpclisten', default locations are populated.
'notls', 'rpcuser', 'rpcpass', 'rpclisten', and 'rpccert'. The setting for
'rpcuser' must be present in the file. If values are not found for 'rpccert'
or 'rpclisten', default locations are populated.
Args:
netParams (bool): The network parameters.
Expand All @@ -126,16 +127,26 @@ def dcrd(netParams):
cfgPath = os.path.join(dcrdCfgDir, "dcrd.conf")
if not os.path.isfile(cfgPath):
return {}
dcrdCfg = helpers.readINI(cfgPath, ["rpclisten", "rpcuser", "rpcpass", "rpccert"])
dcrdCfg = helpers.readINI(
cfgPath, ["notls", "rpclisten", "rpcuser", "rpcpass", "rpccert"]
)
if "rpcuser" not in dcrdCfg:
return None
if "rpccert" not in dcrdCfg:
dcrdCfg["rpccert"] = os.path.join(dcrdCfgDir, "rpc.cert")
# Tinywallet uses the protocol (scheme) of the URL for now.
rpcHost = "localhost"
rpcPort = nets.DcrdPorts[netParams.Name]
if "rpclisten" in dcrdCfg:
dcrdCfg["rpclisten"] = "https://" + dcrdCfg["rpclisten"]
else:
dcrdCfg["rpclisten"] = f"https://localhost:{nets.DcrdPorts[netParams.Name]}"
try:
rpcUrl = urlparse(f"//{dcrdCfg['rpclisten']}")
if rpcUrl.hostname:
rpcHost = rpcUrl.hostname.replace("::1", "").strip(":") or rpcHost
if rpcUrl.port:
rpcPort = rpcUrl.port
except ValueError:
pass
dcrdCfg["rpclisten"] = f"{rpcHost}:{rpcPort}"
dcrdCfg["notls"] = dcrdCfg["notls"] == "1" if "notls" in dcrdCfg else False
return dcrdCfg


Expand Down
7 changes: 4 additions & 3 deletions tinywallet/tinywallet/screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -1445,10 +1445,11 @@ def insertSpace():
grid.addWidget(Q.makeLabel("dcrd URL", 14, Q.ALIGN_LEFT), row, 0, 1, 3)
grid.addWidget(Q.makeLabel("RPC username", 14, Q.ALIGN_LEFT), row, 3)
row += 1
defaultRpclisten = f"127.0.0.1:{nets.DcrdPorts[cfg.netParams.Name]}"
host = nodeConfig.get("rpclisten", defaultRpclisten)
dcrdCfg = config.dcrd(cfg.netParams)
host = nodeConfig.get("rpclisten", dcrdCfg["rpclisten"])
scheme = "https" if not dcrdCfg["notls"] else "http"

self.rpcListen = QtWidgets.QLineEdit(f"https://{host}/")
self.rpcListen = QtWidgets.QLineEdit(f"{scheme}://{host}/")
grid.addWidget(self.rpcListen, row, 0, 1, 3)
self.rpcUser = QtWidgets.QLineEdit(nodeConfig.get("rpcuser", ""))
grid.addWidget(self.rpcUser, row, 3)
Expand Down

0 comments on commit 280dc57

Please sign in to comment.