Telling “refused” from “never reached”
bound: 0 alone cannot distinguish “nobody connected right now” from “no socket was ever opened”.
last_error is what separates them, and it clears the moment a bind succeeds.
A vendor will not bind
host,port,usernameandpasswordare correct.connections.transceivers,connections.transmittersorconnections.receiversis greater than zero — a vendor with all three at zero binds nothing and reports no error.- TLS settings match what the provider requires.
- Firewall allows outbound traffic to the provider.
- The provider has allow-listed your source IP, if they require it.
A customer’s bind is rejected
- The credential is
type: SMPP. An HTTP credential cannot bind, and the refusal does not say so. - The client is using the configured
systemIdandpassword. - No connection limit is exceeded:
srv.maxConnections,srv.maxConnectionsPerIP,conf.maxConnectionsPerUser.default, or the per-user limit. Since 0.9.20 the refusals are counted by reason —fireflo_smpp_bind_refused_totalon the metrics endpoint, and the Servers page shows a notice when any have happened. A customer fleet behind one NAT counts as one source IP against the per-IP limit. - If
allowedIpsis configured, the bind source IP is on it.
The listener never opened
Different from every case above: not a rejected bind, but a socket that was never created. The gateway runs normally — routing, rating, billing and vendor connections all up, systemd reportingactive — while no customer can connect.
The gateway does not exit when a listener cannot take its port. That is deliberate: one busy port
must not take a whole gateway off the air, and TLS or proxy listeners are often not configured at all.
So the evidence is in three places rather than in the exit status.
On /ops/health:
The usual cause is two gateways
Either a second instance configured on the same port, or the same instance running twice under two unit names — which is what anupdate given the wrong --service-name used to produce.
1
List every unit
systemctl list-units 'fireflo*' --all2
Compare the managed PID against the one holding the port
systemctl show <unit> -p MainPID — an orphan JVM holding the port is one systemd no longer
manages.3
Stop the service, kill the orphan by PID, start it again
By PID, never by pattern. Other JVMs may be on the host, and a pattern kill has taken out
unrelated services before.
Related
Servers
Listener settings and what each one does.
Vendors
Outbound connections, TPS and holding.
Blocking abusive clients
A customer whose connection is refused before it reaches the gateway may be blocked at the
firewall. Check this before anything else.