Previously, our "duplicate key in server block" logic was flawed because
it did not account for the site's bind address. We defer this check to
when the listener addresses have been assigned, but before we commit
a server block to its listener.
Also refined how network address parsing and joining works, which was
necessary for a less convoluted fix.
* fix OOM issue caught by fuzzing
* use ParsedAddress as the struct name for the result of ParseNetworkAddress
* simplify code using the ParsedAddress type
* minor cleanups
This PR enables the use of placeholders in an upstream's Dial address.
A Dial address must represent precisely one socket after replacements.
See also #998 and #1639.