diff --git a/ice-adapter/src/main/java/com/faforever/iceadapter/IceAdapter.java b/ice-adapter/src/main/java/com/faforever/iceadapter/IceAdapter.java index d4caace..abd6c56 100644 --- a/ice-adapter/src/main/java/com/faforever/iceadapter/IceAdapter.java +++ b/ice-adapter/src/main/java/com/faforever/iceadapter/IceAdapter.java @@ -92,7 +92,7 @@ public static void onHostGame(String mapName) { public static void onJoinGame(String remotePlayerLogin, int remotePlayerId) { log.info("onJoinGame {} {}", remotePlayerId, remotePlayerLogin); createGameSession(); - int port = gameSession.connectToPeer(remotePlayerLogin, remotePlayerId, false); + int port = gameSession.connectToPeer(remotePlayerLogin, remotePlayerId, false, 0); GPGNetServer.clientFuture.thenAccept(gpgNetClient -> { gpgNetClient.getLobbyFuture().thenRun(() -> { @@ -108,7 +108,7 @@ public static void onConnectToPeer(String remotePlayerLogin, int remotePlayerId, } log.info("onConnectToPeer {} {}, offer: {}", remotePlayerId, remotePlayerLogin, String.valueOf(offer)); - int port = gameSession.connectToPeer(remotePlayerLogin, remotePlayerId, offer); + int port = gameSession.connectToPeer(remotePlayerLogin, remotePlayerId, offer, 0); GPGNetServer.clientFuture.thenAccept(gpgNetClient -> { gpgNetClient.getLobbyFuture().thenRun(() -> { diff --git a/ice-adapter/src/main/java/com/faforever/iceadapter/debug/DebugWindowController.java b/ice-adapter/src/main/java/com/faforever/iceadapter/debug/DebugWindowController.java index a3a0699..e10906e 100644 --- a/ice-adapter/src/main/java/com/faforever/iceadapter/debug/DebugWindowController.java +++ b/ice-adapter/src/main/java/com/faforever/iceadapter/debug/DebugWindowController.java @@ -1,13 +1,17 @@ package com.faforever.iceadapter.debug; +import com.faforever.iceadapter.IceAdapter; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.HBox; +import javafx.util.Callback; import lombok.extern.slf4j.Slf4j; import org.slf4j.LoggerFactory; +import java.util.Objects; + @Slf4j public class DebugWindowController { @@ -33,6 +37,7 @@ public class DebugWindowController { public TableColumn loginColumn; public TableColumn offerColumn; public TableColumn connectedColumn; + public TableColumn buttonReconnect; public TableColumn stateColumn; public TableColumn rttColumn; public TableColumn lastColumn; @@ -51,6 +56,12 @@ public void onKillAdapterClicked(ActionEvent actionEvent) { System.exit(337); } + public void reconnectToPeer(DebugWindow.DebugPeer peer) { + if (Objects.nonNull(peer)) { + new Thread(() -> IceAdapter.gameSession.reconnectToPeer(peer.getId())).start(); + } + } + @FXML private void initialize() { if(Debug.ENABLE_DEBUG_WINDOW_LOG_TEXT_AREA) { @@ -71,6 +82,30 @@ private void initialize() { localCandColumn.setCellValueFactory(new PropertyValueFactory<>("localCandidate")); remoteCandColumn.setCellValueFactory(new PropertyValueFactory<>("remoteCandidate")); + buttonReconnect.setCellFactory(new Callback() { + @Override + public TableCell call(TableColumn param) { + return new TableCell<>() { + final Button btn = new Button("reconnect"); + + @Override + protected void updateItem(DebugWindow.DebugPeer item, boolean empty) { + super.updateItem(item, empty); + setText(null); + if (empty) { + setGraphic(null); + } else { + btn.setOnAction(event -> { + DebugWindow.DebugPeer peer = getTableRow().getItem(); + reconnectToPeer(peer); + }); + setGraphic(btn); + } + } + }; + } + }); + killAdapterButton.setOnAction(this::onKillAdapterClicked); } } diff --git a/ice-adapter/src/main/java/com/faforever/iceadapter/ice/GameSession.java b/ice-adapter/src/main/java/com/faforever/iceadapter/ice/GameSession.java index 7819e6c..82b2f38 100644 --- a/ice-adapter/src/main/java/com/faforever/iceadapter/ice/GameSession.java +++ b/ice-adapter/src/main/java/com/faforever/iceadapter/ice/GameSession.java @@ -52,8 +52,8 @@ public GameSession() { * * @return the port the ice adapter will be listening/sending for FA */ - public int connectToPeer(String remotePlayerLogin, int remotePlayerId, boolean offer) { - Peer peer = new Peer(this, remotePlayerId, remotePlayerLogin, offer); + public int connectToPeer(String remotePlayerLogin, int remotePlayerId, boolean offer, int preferredPort) { + Peer peer = new Peer(this, remotePlayerId, remotePlayerLogin, offer, preferredPort); peers.put(remotePlayerId, peer); debug().connectToPeer(remotePlayerId, remotePlayerLogin, offer); return peer.getFaSocket().getLocalPort(); @@ -72,6 +72,23 @@ public void disconnectFromPeer(int remotePlayerId) { //TODO: still attempting to ICE } + /** + * Does a manual {@link #disconnectFromPeer} and {@link #connectToPeer}. + * Uses the same port that was on the previous connection. + */ + public void reconnectToPeer(Integer remotePlayerId) { + Peer reconnectPeer = peers.get(remotePlayerId); + if (Objects.nonNull(reconnectPeer)) { + String remotePlayerLogin = reconnectPeer.getRemoteLogin(); + boolean offer = reconnectPeer.isLocalOffer(); + int port = reconnectPeer.getFaSocket() + .getLocalPort(); + + disconnectFromPeer(remotePlayerId); + connectToPeer(remotePlayerLogin, remotePlayerId, offer, port); + } + } + /** * Stops the connection to all peers and all ice agents */ diff --git a/ice-adapter/src/main/java/com/faforever/iceadapter/ice/Peer.java b/ice-adapter/src/main/java/com/faforever/iceadapter/ice/Peer.java index a4f3369..039944f 100644 --- a/ice-adapter/src/main/java/com/faforever/iceadapter/ice/Peer.java +++ b/ice-adapter/src/main/java/com/faforever/iceadapter/ice/Peer.java @@ -19,19 +19,23 @@ public class Peer { private final int remoteId; private final String remoteLogin; private final boolean localOffer;//Do we offer or are we waiting for a remote offer + private final int preferredPort; - private PeerIceModule ice = new PeerIceModule(this); + public volatile boolean closing = false; + + private final PeerIceModule ice = new PeerIceModule(this); private DatagramSocket faSocket;//Socket on which we are listening for FA / sending data to FA - public Peer(GameSession gameSession, int remoteId, String remoteLogin, boolean localOffer) { + public Peer(GameSession gameSession, int remoteId, String remoteLogin, boolean localOffer, int preferredPort) { this.gameSession = gameSession; this.remoteId = remoteId; this.remoteLogin = remoteLogin; this.localOffer = localOffer; + this.preferredPort = preferredPort; - log.debug("Peer created: {}, {}, localOffer: {}", remoteId, remoteLogin, String.valueOf(localOffer)); + log.debug("Peer created: {}, localOffer: {}, preferredPort: {}", getPeerIdentifier(), String.valueOf(localOffer), preferredPort); - initForwarding(); + initForwarding(preferredPort); if (localOffer) { new Thread(ice::initiateIce).start(); @@ -41,9 +45,9 @@ public Peer(GameSession gameSession, int remoteId, String remoteLogin, boolean l /** * Starts waiting for data from FA */ - private void initForwarding() { + private void initForwarding(int port) { try { - faSocket = new DatagramSocket(0); + faSocket = new DatagramSocket(port); } catch (SocketException e) { log.error("Could not create socket for peer: {}", getPeerIdentifier(), e); } @@ -65,8 +69,11 @@ synchronized void onIceDataReceived(byte data[], int offset, int length) { faSocket.send(packet); } catch (UnknownHostException e) { } catch (IOException e) { - log.error("Error while writing to local FA as peer (probably disconnecting from peer) " + getPeerIdentifier(), e); - return; + if (closing) { + log.debug("Ignoring error the send packet because the connection was closed {}", getPeerIdentifier()); + } else { + log.error("Error while writing to local FA as peer (probably disconnecting from peer) {}", getPeerIdentifier(), e); + } } } @@ -81,29 +88,30 @@ private void faListener() { faSocket.receive(packet); ice.onFaDataReceived(data, packet.getLength()); } catch (IOException e) { - log.debug("Error while reading from local FA as peer (probably disconnecting from peer) " + getPeerIdentifier(), e); + if (closing) { + log.debug("Ignoring error the receive packet because the connection was closed as peer {}", getPeerIdentifier()); + } else { + log.debug("Error while reading from local FA as peer (probably disconnecting from peer) {}", getPeerIdentifier(), e); + } return; } } log.debug("No longer listening for messages from FA"); } - public volatile boolean closing = false; public void close() { if(closing) { return; } - log.info("Closing peer for player {}", getRemoteId()); + log.info("Closing peer for player {}", getPeerIdentifier()); closing = true; if(faSocket != null) { faSocket.close(); } - if(ice != null) { - ice.close(); - } + ice.close(); } /** diff --git a/ice-adapter/src/main/resources/debugWindow.fxml b/ice-adapter/src/main/resources/debugWindow.fxml index 21b675c..13ae1bd 100644 --- a/ice-adapter/src/main/resources/debugWindow.fxml +++ b/ice-adapter/src/main/resources/debugWindow.fxml @@ -56,6 +56,7 @@ +