mirror of
https://github.com/Qortal/qortal.git
synced 2025-04-29 22:37:52 +00:00
Renamed the "bindAddress" setting to "bindAddresses". It is now an array of strings, allowing for multiple addresses to be specified in order of importance. Each address is tried in turn until one successfully binds, trying IPv6 first by default and then IPv4. This fixes an issue where the core failed to start on IPv4-only networks unless the bindAddress was manually overridden in Settings.json. This was reported in issue #25, and is also quite commonly reported by new users on Discord. It will now start correctly on both IPv4-only and IPv6-only networks, because it will automatically fall back to an IPv4 bindAddress if the IPv6 one fails to bind.
This commit is contained in:
parent
3920933fc7
commit
45a9654d5e
@ -46,6 +46,7 @@ import org.qortal.api.websocket.ChatMessagesWebSocket;
|
|||||||
import org.qortal.api.websocket.PresenceWebSocket;
|
import org.qortal.api.websocket.PresenceWebSocket;
|
||||||
import org.qortal.api.websocket.TradeBotWebSocket;
|
import org.qortal.api.websocket.TradeBotWebSocket;
|
||||||
import org.qortal.api.websocket.TradeOffersWebSocket;
|
import org.qortal.api.websocket.TradeOffersWebSocket;
|
||||||
|
import org.qortal.network.Network;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
|
||||||
public class ApiService {
|
public class ApiService {
|
||||||
@ -118,13 +119,13 @@ public class ApiService {
|
|||||||
ServerConnector portUnifiedConnector = new ServerConnector(this.server,
|
ServerConnector portUnifiedConnector = new ServerConnector(this.server,
|
||||||
new DetectorConnectionFactory(sslConnectionFactory),
|
new DetectorConnectionFactory(sslConnectionFactory),
|
||||||
httpConnectionFactory);
|
httpConnectionFactory);
|
||||||
portUnifiedConnector.setHost(Settings.getInstance().getBindAddress());
|
portUnifiedConnector.setHost(Network.getInstance().getBindAddress());
|
||||||
portUnifiedConnector.setPort(Settings.getInstance().getApiPort());
|
portUnifiedConnector.setPort(Settings.getInstance().getApiPort());
|
||||||
|
|
||||||
this.server.addConnector(portUnifiedConnector);
|
this.server.addConnector(portUnifiedConnector);
|
||||||
} else {
|
} else {
|
||||||
// Non-SSL
|
// Non-SSL
|
||||||
InetAddress bindAddr = InetAddress.getByName(Settings.getInstance().getBindAddress());
|
InetAddress bindAddr = InetAddress.getByName(Network.getInstance().getBindAddress());
|
||||||
InetSocketAddress endpoint = new InetSocketAddress(bindAddr, Settings.getInstance().getApiPort());
|
InetSocketAddress endpoint = new InetSocketAddress(bindAddr, Settings.getInstance().getApiPort());
|
||||||
this.server = new Server(endpoint);
|
this.server = new Server(endpoint);
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,8 @@ public class Network {
|
|||||||
private ServerSocketChannel serverChannel;
|
private ServerSocketChannel serverChannel;
|
||||||
private Iterator<SelectionKey> channelIterator = null;
|
private Iterator<SelectionKey> channelIterator = null;
|
||||||
|
|
||||||
|
private String bindAddress = null;
|
||||||
|
|
||||||
// volatile because value is updated inside any one of the EPC threads
|
// volatile because value is updated inside any one of the EPC threads
|
||||||
private volatile long nextConnectTaskTimestamp = 0L; // ms - try first connect once NTP syncs
|
private volatile long nextConnectTaskTimestamp = 0L; // ms - try first connect once NTP syncs
|
||||||
|
|
||||||
@ -138,9 +140,16 @@ public class Network {
|
|||||||
// Grab P2P port from settings
|
// Grab P2P port from settings
|
||||||
int listenPort = Settings.getInstance().getListenPort();
|
int listenPort = Settings.getInstance().getListenPort();
|
||||||
|
|
||||||
// Grab P2P bind address from settings
|
// Grab P2P bind addresses from settings
|
||||||
|
String[] bindAddresses = Settings.getInstance().getBindAddresses();
|
||||||
|
for (int i=0; i<bindAddresses.length; i++) {
|
||||||
|
|
||||||
|
String bindAddress = bindAddresses[i];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InetAddress bindAddr = InetAddress.getByName(Settings.getInstance().getBindAddress());
|
LOGGER.info(String.format("Binding to address %s", bindAddress));
|
||||||
|
|
||||||
|
InetAddress bindAddr = InetAddress.getByName(bindAddress);
|
||||||
InetSocketAddress endpoint = new InetSocketAddress(bindAddr, listenPort);
|
InetSocketAddress endpoint = new InetSocketAddress(bindAddr, listenPort);
|
||||||
|
|
||||||
channelSelector = Selector.open();
|
channelSelector = Selector.open();
|
||||||
@ -151,13 +160,23 @@ public class Network {
|
|||||||
serverChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
|
serverChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
|
||||||
serverChannel.bind(endpoint, LISTEN_BACKLOG);
|
serverChannel.bind(endpoint, LISTEN_BACKLOG);
|
||||||
serverChannel.register(channelSelector, SelectionKey.OP_ACCEPT);
|
serverChannel.register(channelSelector, SelectionKey.OP_ACCEPT);
|
||||||
|
|
||||||
|
this.bindAddress = bindAddress; // Store the selected address, so that it can be used by other parts of the app
|
||||||
|
break; // We don't want to bind to more than one address
|
||||||
|
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
LOGGER.error(String.format("Can't bind listen socket to address %s", Settings.getInstance().getBindAddress()));
|
LOGGER.error(String.format("Can't bind listen socket to address %s", bindAddress));
|
||||||
|
if (i == bindAddresses.length-1) { // Only throw an exception if all addresses have been tried
|
||||||
throw new IOException("Can't bind listen socket to address", e);
|
throw new IOException("Can't bind listen socket to address", e);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.error(String.format("Can't create listen socket: %s", e.getMessage()));
|
LOGGER.error(String.format("Can't create listen socket: %s", e.getMessage()));
|
||||||
|
if (i == bindAddresses.length-1) { // Only throw an exception if all addresses have been tried
|
||||||
throw new IOException("Can't create listen socket", e);
|
throw new IOException("Can't create listen socket", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Load all known peers from repository
|
// Load all known peers from repository
|
||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
@ -179,6 +198,10 @@ public class Network {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getBindAddress() {
|
||||||
|
return this.bindAddress;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] getMessageMagic() {
|
public byte[] getMessageMagic() {
|
||||||
return Settings.getInstance().isTestNet() ? TESTNET_MESSAGE_MAGIC : MAINNET_MESSAGE_MAGIC;
|
return Settings.getInstance().isTestNet() ? TESTNET_MESSAGE_MAGIC : MAINNET_MESSAGE_MAGIC;
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,10 @@ public class Settings {
|
|||||||
// General
|
// General
|
||||||
private String localeLang = Locale.getDefault().getLanguage();
|
private String localeLang = Locale.getDefault().getLanguage();
|
||||||
|
|
||||||
// Common to all networking (API/P2P)
|
// Common to all networking (API/P2P). They are tried in order until one successfully binds.
|
||||||
private String bindAddress = "::"; // Use IPv6 wildcard to listen on all local addresses
|
private String[] bindAddresses = new String[] {
|
||||||
|
"::", "0.0.0.0"
|
||||||
|
};
|
||||||
|
|
||||||
// UI servers
|
// UI servers
|
||||||
private int uiPort = 12388;
|
private int uiPort = 12388;
|
||||||
@ -376,8 +378,8 @@ public class Settings {
|
|||||||
return this.isTestNet ? TESTNET_LISTEN_PORT : MAINNET_LISTEN_PORT;
|
return this.isTestNet ? TESTNET_LISTEN_PORT : MAINNET_LISTEN_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBindAddress() {
|
public String[] getBindAddresses() {
|
||||||
return this.bindAddress;
|
return this.bindAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMinBlockchainPeers() {
|
public int getMinBlockchainPeers() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user