~emersion/soju-dev

Enable resetting a BOUNCER NETWORK port v1 APPLIED

delthas: 2
 Enable resetting a BOUNCER NETWORK port
 bouncer-networks: Add a read-only error attribute

 4 files changed, 38 insertions(+), 5 deletions(-)
With this change, can we stop sending BouncerServ NOTICEs on upstream error for
downstreams which support bouncer-networks? The downstream should now have all
of the necessary information to provide feedback to the user.
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~emersion/soju-dev/patches/30929/mbox | git am -3
Learn more about email & git

[PATCH v1 1/2] Enable resetting a BOUNCER NETWORK port Export this patch

When a client sends BOUNCER CHANGENETWORK with no value (or an empty
port value), this means it wants to reset the port value to its default
value.

Previously we considered an empty port as an actual valid, empty port
value, which would then be used to connect to the server (dial
'example.com:' (ie 'example.com:0'), which failed.
---
 downstream.go | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/downstream.go b/downstream.go
index d90de79..bef6adf 100644
--- a/downstream.go
+++ b/downstream.go
@@ -148,17 +148,17 @@ func getNetworkAttrs(network *network) irc.Tags {
}

func networkAddrFromAttrs(attrs irc.Tags) string {
	host, ok := attrs.GetTag("host")
	if !ok {
	host := string(attrs["host"])
	if host == "" {
		return ""
	}

	addr := host
	if port, ok := attrs.GetTag("port"); ok {
	if port := string(attrs["port"]); port != "" {
		addr += ":" + port
	}

	if tlsStr, ok := attrs.GetTag("tls"); ok && tlsStr == "0" {
	if tlsStr := string(attrs["tls"]); tlsStr == "0" {
		addr = "irc+insecure://" + tlsStr
	}


base-commit: 17374f209422b23b71dd63330d6806a4b4fd2ae8
-- 
2.17.1
This patch LGTM. Pushed, thanks!

[PATCH v1 2/2] bouncer-networks: Add a read-only error attribute Export this patch

This is useful for clients to display additional info abotu why a
network is disconnected.
---
 doc/ext/bouncer-networks.md |  4 ++++
 downstream.go               |  4 ++++
 user.go                     | 27 ++++++++++++++++++++++++++-
 3 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/doc/ext/bouncer-networks.md b/doc/ext/bouncer-networks.md
index cefb72d..1f55a80 100644
--- a/doc/ext/bouncer-networks.md
+++ b/doc/ext/bouncer-networks.md
@@ -242,6 +242,10 @@ Bouncers MUST recognise the following network attributes:
* `realname`: the realname to use during registration.
* `pass`: the server password (PASS) to use during registration.

Bouncers MAY recognise the following network attributes:
* `error` (read-only): a human-readable short text describing an error with the current network.
  This is typically used when the bouncer state is `disconnected` to describe the reason why the bouncer is disconnected.

TODO: more attributes

### Examples
diff --git a/downstream.go b/downstream.go
index bef6adf..01b1812 100644
--- a/downstream.go
+++ b/downstream.go
@@ -142,6 +142,10 @@ func getNetworkAttrs(network *network) irc.Tags {
		attrs["realname"] = irc.TagValue(realname)
	}

	if network.lastError != nil {
		attrs["error"] = irc.TagValue(network.lastError.Error())
	}

	fillNetworkAddrAttrs(attrs, &network.Network)

	return attrs
diff --git a/user.go b/user.go
index 29bbe85..e2fac8f 100644
--- a/user.go
+++ b/user.go
@@ -576,7 +576,10 @@ func (u *user) run() {
					dc.SendMessage(&irc.Message{
						Prefix:  dc.srv.prefix(),
						Command: "BOUNCER",
						Params:  []string{"NETWORK", netIDStr, "state=connected"},
						Params: []string{"NETWORK", netIDStr, irc.Tags{
							"state": "connected",
							"error": "",
						}.String()},
					})
				}
			})
@@ -599,6 +602,17 @@ func (u *user) run() {
				})
			}
			net.lastError = e.err
			u.forEachDownstream(func(dc *downstreamConn) {
				if dc.caps.IsEnabled("soju.im/bouncer-networks-notify") {
					dc.SendMessage(&irc.Message{
						Prefix:  dc.srv.prefix(),
						Command: "BOUNCER",
						Params: []string{"NETWORK", fmt.Sprintf("%v", net.ID), irc.Tags{
							"error": irc.TagValue(net.lastError.Error()),
						}.String()},
					})
				}
			})
		case eventUpstreamError:
			uc := e.uc

@@ -606,6 +620,17 @@ func (u *user) run() {
				sendServiceNOTICE(dc, fmt.Sprintf("disconnected from %s: %v", uc.network.GetName(), e.err))
			})
			uc.network.lastError = e.err
			u.forEachDownstream(func(dc *downstreamConn) {
				if dc.caps.IsEnabled("soju.im/bouncer-networks-notify") {
					dc.SendMessage(&irc.Message{
						Prefix:  dc.srv.prefix(),
						Command: "BOUNCER",
						Params: []string{"NETWORK", fmt.Sprintf("%v", uc.network.ID), irc.Tags{
							"error": irc.TagValue(uc.network.lastError.Error()),
						}.String()},
					})
				}
			})
		case eventUpstreamMessage:
			msg, uc := e.msg, e.uc
			if uc.isClosed() {
-- 
2.17.1
With this change, can we stop sending BouncerServ NOTICEs on upstream error for
downstreams which support bouncer-networks? The downstream should now have all
of the necessary information to provide feedback to the user.