Greg
On
12/08/2019 17:26, Greg Troxel wrote:
...snip
My mosquitto configuration file (/etc/mosquitto/mosquitto.conf) is the
default installed version. On top of this, I have a local config file
in /etc/mosquitto/conf.d that contains the following:
allow_anonymous false
connection_messages true
log_dest syslog
log_type error
log_type warning
password_file /etc/mosquitto/passwd
socket_domain ipv4
'A'
A major source of difficulty for me is how mosquitto does listener
configuration. A listener in other configs would be configured as a
stanza that has the listener and the things that control it scoped
somehow.
Yes. I have looked longingly at HiveMQ's use of XML configuration
files :-)
mosquitto sort of has the listener directive and then the
things that follow modify that listener, until the next listener. And
if you have modifier statement before the first new listener, it makes
the default listener be active and then modifies it. I think this is
basically a bug, but I realize it is hard to change.
This is the critical piece of information! Thank, Greg! :-)
This works fine as verified with mosquitto_sub/pub, plus 'netstat
-tlpn' lists an LISTEN port associated with the mosquitto process.
The key point is to see if this is bound to *.1883 or 127.0.0.1.1883.
The normal listen binds to INADDR_ANY, which is represented 0.0.0.0, and
matches all addresses.
Great call! My only mosquitto listener was 0.0.0.0:1883. Don't know
how I missed that! :-[
This also clarifies for me how mosquitto handles the default
listener. I was imagining some crazy process of seeking out all
available interfaces and creating a listener for each... but I was
overlooking the wildcard IP address.
From my reading of the docs & what I *want* to achieve, I would have
thought that the following should work for me:
listener 1883 localhost
listener 1883 192.168.0.1
In fact, this now works! See below...
...snip
EADDRINUSE means that a call to bind() failed, and that can be because
it tried to bind INADDR_ANY first and then a specific address, or
because there were two binds to INADDR_ANY. Perhaps use some kind of
ktrace/strace/ktruss type program to see what happens.
This appears to produce weird behaviour. When mosquitto has a
default listener 'bound' to 0.0.0.0 and you attempt to bind the same
IP address it seems to report an error and then trashes the listener
you already had leaving with no listeners at all :-\
...snip
You're overlooking how hard it is to configure listeners in mosquitto,
and how much you have to be careful to avoid the implicit one. :-(
Yep. Avoiding the default listener is key!
So look hard at the default config, and perhaps get rid of it, and
perhaps ask where it came from and why each line is as it is.
Working through the default conf file, this does not cause any
problems.
...snip
The problem was my adding a "socket_domain ipv4" directive in my
local conf file. That starts the default listener (not obvious
that it should, but it does). The ultimate error is, IMO, bizarre.
It appears that having inadvertently started the default listener
bound to 0.0.0.0 (i.e. everything), in attempting to bind a second
listener to a specific address (such as localhost), mosquitto
seems to determine that localhost is a subset of 0.0.0.0 and fails
with an "address already in use" error. This is not a very helpful
diagnostic, IMO! To make matters worse, the default listener gets
trashed in the process and you end up with nothing!
So. In summary. Problem now solved! Greg's advice to avoid
starting the default listener is critical. Given that,
listener 1883 localhost
listener 1883 192.168.0.1
does the business... as I thought it should! :-)
The corollary: Is mosquitto's hidden invocation of the default
listener by innocuous-looking directives really the best approach?
This looks to me like a side-effect waiting to bite you. Could
starting the default listener be made explicit? Or indeed removed
altogether? An explicit "listener 1883 0.0.0.0" directive would
seem to do the same job but has the advantage of making it obvious
what is happening?
Thanks,
Peter