fix(multiplayer): bind to 0.0.0.0 instead of 127.0.0.1.

This commit is contained in:
huanghongxun
2021-09-27 12:38:43 +08:00
parent 3515ce1034
commit 35f2d89a23
11 changed files with 170 additions and 12 deletions

View File

@@ -57,7 +57,7 @@ public class LocalServerBroadcaster implements Runnable {
byte[] data = String.format("[MOTD]%s[/MOTD][AD]%d[/AD]", i18n("multiplayer.session.name.motd", session.getName()), port).getBytes(StandardCharsets.UTF_8);
DatagramPacket packet = new DatagramPacket(data, 0, data.length, broadcastAddress, 4445);
socket.send(packet);
LOG.fine("Broadcast server 127.0.0.1:" + port);
LOG.fine("Broadcast server 0.0.0.0:" + port);
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to send motd packet", e);
}

View File

@@ -79,7 +79,7 @@ public class LocalServerDetector extends Thread {
}
String response = new String(packet.getData(), packet.getOffset(), packet.getLength(), StandardCharsets.UTF_8);
LOG.fine("Local server broadcast message: " + response);
LOG.fine("Local server " + packet.getAddress() + ":" + packet.getPort() + " broadcast message: " + response);
onDetectedLanServer.fireEvent(new DetectedLanServerEvent(this, PingResponse.parsePingResponse(response)));
break;
}

View File

@@ -59,7 +59,7 @@ import static org.jackhuang.hmcl.util.Logging.LOG;
*/
public final class MultiplayerManager {
private static final String CATO_DOWNLOAD_URL = "https://files.huangyuhui.net/maven/";
static final String CATO_VERSION = "1.0.8";
static final String CATO_VERSION = "1.0.9";
private static final String CATO_PATH = getCatoPath();
private MultiplayerManager() {
@@ -96,8 +96,8 @@ public final class MultiplayerManager {
String[] commands = new String[]{exe.toString(),
"--token", StringUtils.isBlank(token) ? "new" : token,
"--id", peer,
"--local", String.format("127.0.0.1:%d", localPort),
"--remote", String.format("127.0.0.1:%d", remotePort),
"--local", String.format("0.0.0.0:%d", localPort),
"--remote", String.format("0.0.0.0:%d", remotePort),
"--mode", "relay"};
Process process;
try {
@@ -130,7 +130,7 @@ public final class MultiplayerManager {
client.onConnected().register(connectedEvent -> {
try {
int port = findAvailablePort();
writer.write(String.format("net add %s 127.0.0.1:%d 127.0.0.1:%d p2p\n", peer, port, connectedEvent.getPort()));
writer.write(String.format("net add %s 0.0.0.0:%d 0.0.0.0:%d p2p\n", peer, port, connectedEvent.getPort()));
future.complete(session);
} catch (IOException e) {
future.completeExceptionally(e);
@@ -154,7 +154,7 @@ public final class MultiplayerManager {
String[] commands = new String[]{exe.toString(),
"--token", StringUtils.isBlank(token) ? "new" : token,
"--allows", String.format("127.0.0.1:%d,127.0.0.1:%d", port, server.getPort()),
"--allows", String.format("0.0.0.0:%d/0.0.0.0:%d", port, server.getPort()),
"--mode", "relay"};
Process process = new ProcessBuilder()
.command(commands)

View File

@@ -17,9 +17,11 @@
*/
package org.jackhuang.hmcl.ui.multiplayer;
import com.jfoenix.controls.JFXButton;
import de.javawi.jstun.test.DiscoveryInfo;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SkinBase;
@@ -172,16 +174,22 @@ public class MultiplayerPageSkin extends SkinBase<MultiplayerPage> {
masterPane.getChildren().setAll(label);
}
VBox slavePane = new VBox(8);
BorderPane slavePane = new BorderPane();
{
HintPane slaveHintPane = new HintPane();
slaveHintPane.setText(i18n("multiplayer.state.slave.hint"));
slavePane.setTop(slaveHintPane);
Label label = new Label();
label.textProperty().bind(Bindings.createStringBinding(() ->
i18n("multiplayer.state.slave", control.getSession() == null ? "" : control.getSession().getName(), control.getPort()),
i18n("multiplayer.state.slave", control.getSession() == null ? "" : control.getSession().getName(), "0.0.0.0:" + control.getPort()),
control.sessionProperty(), control.portProperty()));
slavePane.getChildren().setAll(slaveHintPane, label);
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
slavePane.setCenter(label);
JFXButton copyButton = new JFXButton(i18n("multiplayer.state.slave.copy"));
copyButton.setOnAction(e -> FXUtils.copyText("0.0.0.0:" + control.getPort()));
slavePane.setRight(copyButton);
}
FXUtils.onChangeAndOperate(getSkinnable().multiplayerStateProperty(), state -> {

View File

@@ -643,6 +643,7 @@ multiplayer.state.disconnected=Not created/entered a multiplayer session
multiplayer.state.disconnected.hint=Someone should create a multiplayer session, and others join the session to play the game together.
multiplayer.state.master=Created room: %1$s, port: %2$d
multiplayer.state.slave=Joined room: %1$s, address: %2$s
multiplayer.state.slave.copy=Copy address
multiplayer.state.slave.hint=After joining multiplayer room, you should get to multiplayer page in Minecraft and connect to the "HMCL Multiplayer Session" server, or manually add a server with address shown below.
datapack=Datapacks

View File

@@ -641,7 +641,8 @@ multiplayer.state.connecting=連接中
multiplayer.state.disconnected=未創建/加入房間
multiplayer.state.disconnected.hint=多人聯機功能需要先有一位玩家創建房間後,其他玩家加入房間後繼續遊戲。
multiplayer.state.master=你已創建房間:%1$s埠號 %2$d
multiplayer.state.slave=你已加入房間: %1$s址為 %2$s
multiplayer.state.slave=你已加入房間: %1$s址為 %2$s
multiplayer.state.slave.copy=拷貝位址
multiplayer.state.slave.hint=加入房間後,你需要在 Minecraft 的多人遊戲頁面選擇 HMCL 多人聯機房間伺服器,或者手動添加下方的地址的伺服器。
datapack=資料包

View File

@@ -642,6 +642,7 @@ multiplayer.state.disconnected=未创建/加入房间
multiplayer.state.disconnected.hint=多人联机功能需要先有一位玩家创建房间后,其他玩家加入房间后继续游戏。
multiplayer.state.master=你已创建房间:%1$s端口号 %2$d
multiplayer.state.slave=你已加入房间: %1$s地址为 %2$s
multiplayer.state.slave.copy=拷贝地址
multiplayer.state.slave.hint=加入房间后,你需要在 Minecraft 的多人游戏页面选择 HMCL 多人联机房间服务器,或者手动添加下方的地址的服务器。
datapack=数据包

View File

@@ -0,0 +1,69 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.multiplayer;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class LocalServerBroadcastTest {
@Test
@Ignore("for manually testing")
public void test() {
int port = 12345;
DatagramSocket socket;
InetAddress broadcastAddress;
try {
socket = new DatagramSocket();
broadcastAddress = InetAddress.getByName("224.0.2.60");
} catch (IOException e) {
e.printStackTrace();
return;
}
while (true) {
try {
byte[] data = String.format("[MOTD]%s[/MOTD][AD]%d[/AD]", i18n("multiplayer.session.name.motd", "Test server"), port).getBytes(StandardCharsets.UTF_8);
DatagramPacket packet = new DatagramPacket(data, 0, data.length, broadcastAddress, 4445);
socket.send(packet);
System.out.println("Broadcast server 127.0.0.1:" + port);
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(1500);
} catch (InterruptedException ignored) {
return;
}
}
}
@Test
@Ignore
public void printLocalAddress() throws IOException {
DatagramSocket socket = new DatagramSocket(new InetSocketAddress((InetAddress) null, 4444));
System.out.println(socket.getLocalAddress());
}
}

View File

@@ -0,0 +1,49 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.multiplayer;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.Logging;
import org.junit.Ignore;
import org.junit.Test;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
public class LocalServerDetectorTest {
@Test
@Ignore("for manually testing")
public void test() {
try {
for (NetworkInterface networkInterface : Lang.toIterable(NetworkInterface.getNetworkInterfaces())) {
System.out.println(networkInterface.getName());
for (InetAddress address : Lang.toIterable(networkInterface.getInetAddresses())) {
System.out.println(address);
}
}
} catch (SocketException e) {
e.printStackTrace();
}
Logging.initForTest();
LocalServerDetector detector = new LocalServerDetector(3);
detector.run();
}
}

View File

@@ -330,6 +330,25 @@ public final class Lang {
return optional.map(Stream::of).orElseGet(Stream::empty);
}
public static <T> Iterable<T> toIterable(Enumeration<T> enumeration) {
if (enumeration == null) {
throw new NullPointerException();
}
return () -> new Iterator<T>() {
public boolean hasNext() {
return enumeration.hasMoreElements();
}
public T next() {
return enumeration.nextElement();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public static <T> Iterable<T> toIterable(Stream<T> stream) {
return stream::iterator;
}

View File

@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -72,6 +72,16 @@ public final class Logging {
LOG.addHandler(streamHandler);
}
public static void initForTest() {
LOG.setLevel(Level.ALL);
LOG.setUseParentHandlers(false);
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setFormatter(DefaultFormatter.INSTANCE);
consoleHandler.setLevel(Level.FINER);
LOG.addHandler(consoleHandler);
}
public static byte[] getRawLogs() {
return storedLogs.toByteArray();
}