Skip to content

Commit

Permalink
Use websockets for lobby connection (#3037)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sheikah45 committed Oct 14, 2023
1 parent ef64c1d commit 201a74f
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 64 deletions.
5 changes: 3 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,9 @@ dependencies {
implementation("org.springframework:spring-websocket")

implementation("io.projectreactor.addons:reactor-extra")
implementation("io.projectreactor:reactor-tools")

def commonsVersion = "4a3facc824"
def commonsVersion = "c060e973aa54e1fa215df15c1b8bad22806d84aa"

implementation("com.github.FAForever.faf-java-commons:faf-commons-data:${commonsVersion}") {
exclude module: 'guava'
Expand Down Expand Up @@ -363,4 +364,4 @@ dependencies {
testCompileOnly("org.projectlombok:lombok")

codacy("com.github.codacy:codacy-coverage-reporter:-SNAPSHOT")
}
}
1 change: 1 addition & 0 deletions src/lombok.config
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
lombok.accessors.chain=true
config.stopBubbling=true
lombok.anyConstructor.addConstructorProperties=true
lombok.copyableAnnotations+=org.springframework.beans.factory.annotation.Qualifier
9 changes: 3 additions & 6 deletions src/main/java/com/faforever/client/api/FafApiAccessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.github.jasminb.jsonapi.exceptions.ResourceParseException;
import com.github.rutledgepaulv.qbuilders.builders.QBuilder;
import com.github.rutledgepaulv.qbuilders.conditions.Condition;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.VisibleForTesting;
Expand Down Expand Up @@ -74,6 +75,7 @@
@Slf4j
@Component
@Profile("!offline")
@RequiredArgsConstructor
public class FafApiAccessor implements InitializingBean {

@VisibleForTesting
Expand Down Expand Up @@ -119,19 +121,14 @@ public class FafApiAccessor implements InitializingBean {
private static final String JSONAPI_MEDIA_TYPE = "application/vnd.api+json;charset=utf-8";

private final ClientProperties clientProperties;
@Qualifier("apiWebClient")
private final ObjectFactory<WebClient> apiWebClientFactory;

private WebClient apiWebClient;
private Retry apiRetrySpec;

private CountDownLatch authorizedLatch = new CountDownLatch(1);

public FafApiAccessor(ClientProperties clientProperties,
@Qualifier("apiWebClient") ObjectFactory<WebClient> apiWebClientFactory) {
this.clientProperties = clientProperties;
this.apiWebClientFactory = apiWebClientFactory;
}

@Override
public void afterPropertiesSet() {
Api api = clientProperties.getApi();
Expand Down
16 changes: 10 additions & 6 deletions src/main/java/com/faforever/client/config/ClientProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class ClientProperties {
private Imgur imgur = new Imgur();
private TrueSkill trueSkill = new TrueSkill();
private Api api = new Api();
private User user = new User();
private Oauth oauth = new Oauth();
private UnitDatabase unitDatabase = new UnitDatabase();
private FAFDebugger fafDebugger = new FAFDebugger();
Expand Down Expand Up @@ -80,8 +81,7 @@ public static class Irc {

@Data
public static class Server {
private String host;
private int port;
private String url;
private int retryDelaySeconds = 30;
private int retryAttempts = 10;
}
Expand Down Expand Up @@ -148,11 +148,15 @@ public static class Api {
private int maxPageSize = 10000;
}

@Data
public static class User {
private String baseUrl;
}

public void updateFromEndpoint(ServerEndpoints serverEndpoints) {
SocketEndpoint lobby = serverEndpoints.getLobby();
if (lobby != null) {
server.setHost(lobby.getHost());
server.setPort(lobby.getPort());
UrlEndpoint user = serverEndpoints.getUser();
if (user != null) {
this.user.setBaseUrl(user.getUrl());
}

SocketEndpoint liveReplay = serverEndpoints.getLiveReplay();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,11 @@ public WebClient apiWebClient(WebClient.Builder webClientBuilder, OAuthTokenFilt
return webClientBuilder.baseUrl(clientProperties.getApi().getBaseUrl()).filter(oAuthTokenFilter).build();
}

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public WebClient userWebClient(WebClient.Builder webClientBuilder, OAuthTokenFilter oAuthTokenFilter,
ClientProperties clientProperties) {
return webClientBuilder.baseUrl(clientProperties.getUser().getBaseUrl()).filter(oAuthTokenFilter).build();
}

}
15 changes: 6 additions & 9 deletions src/main/java/com/faforever/client/login/LoginController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.faforever.client.config.ClientProperties;
import com.faforever.client.config.ClientProperties.Irc;
import com.faforever.client.config.ClientProperties.Replay;
import com.faforever.client.config.ClientProperties.Server;
import com.faforever.client.config.ClientProperties.User;
import com.faforever.client.fx.Controller;
import com.faforever.client.fx.FxApplicationThreadExecutor;
import com.faforever.client.fx.JavaFxUtil;
Expand Down Expand Up @@ -78,8 +78,7 @@ public class LoginController implements Controller<Pane> {
public Label loginErrorLabel;
public Pane loginRoot;
public GridPane serverConfigPane;
public TextField serverHostField;
public TextField serverPortField;
public TextField userUrlField;
public TextField replayServerHostField;
public TextField replayServerPortField;
public TextField ircServerHostField;
Expand Down Expand Up @@ -201,9 +200,8 @@ private void showClientOutdatedPane(String minimumVersion) {

private void populateEndpointFields() {
fxApplicationThreadExecutor.execute(() -> {
Server server = clientProperties.getServer();
serverHostField.setText(server.getHost());
serverPortField.setText(String.valueOf(server.getPort()));
User user = clientProperties.getUser();
userUrlField.setText(user.getBaseUrl());
Replay replay = clientProperties.getReplay();
replayServerHostField.setText(replay.getRemoteHost());
replayServerPortField.setText(String.valueOf(replay.getRemotePort()));
Expand Down Expand Up @@ -236,9 +234,8 @@ public void onDownloadUpdateButtonClicked() {
public CompletableFuture<Void> onLoginButtonClicked() {
initializeFuture.join();

clientProperties.getServer()
.setHost(serverHostField.getText())
.setPort(Integer.parseInt(serverPortField.getText()));
clientProperties.getUser()
.setBaseUrl(userUrlField.getText());

clientProperties.getReplay()
.setRemoteHost(replayServerHostField.getText())
Expand Down
37 changes: 23 additions & 14 deletions src/main/java/com/faforever/client/remote/FafServerAccessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

Expand Down Expand Up @@ -70,16 +73,16 @@ public class FafServerAccessor implements InitializingBean, DisposableBean {
private final EventBus eventBus;
private final ClientProperties clientProperties;
private final FafLobbyClient lobbyClient;
@Qualifier("userWebClient")
private final ObjectFactory<WebClient> userWebClientFactory;

@Override
public void afterPropertiesSet() throws Exception {
eventBus.register(this);
getEvents(IrcPasswordInfo.class)
.doOnError(throwable -> log.error("Error processing irc password", throwable))
getEvents(IrcPasswordInfo.class).doOnError(throwable -> log.error("Error processing irc password", throwable))
.retry()
.subscribe(this::onIrcPassword);
getEvents(NoticeInfo.class)
.doOnError(throwable -> log.error("Error processing notice", throwable))
getEvents(NoticeInfo.class).doOnError(throwable -> log.error("Error processing notice", throwable))
.retry()
.subscribe(this::onNotice);

Expand Down Expand Up @@ -119,16 +122,22 @@ public ReadOnlyObjectProperty<ConnectionState> connectionStateProperty() {
}

public Mono<Player> connectAndLogIn() {
Config config = new Config(tokenRetriever.getRefreshedTokenValue(), Version.getCurrentVersion(), clientProperties.getUserAgent(), clientProperties.getServer()
.getHost(), clientProperties.getServer().getPort() + 1, sessionId -> {
try {
return uidService.generate(String.valueOf(sessionId));
} catch (IOException e) {
throw new UIDException("Cannot generate UID", e, "uid.generate.error");
}
}, 1024 * 1024, false, clientProperties.getServer().getRetryAttempts(), clientProperties.getServer()
.getRetryDelaySeconds());
return lobbyClient.connectAndLogin(config);
return userWebClientFactory.getObject()
.get()
.uri("/lobby/access")
.retrieve()
.bodyToMono(LobbyAccess.class)
.map(lobbyAccess -> new Config(tokenRetriever.getRefreshedTokenValue(), Version.getCurrentVersion(), clientProperties.getUserAgent(), lobbyAccess.accessUrl(), this::tryGenerateUid, 1024 * 1024, false, clientProperties.getServer()
.getRetryAttempts(), clientProperties.getServer().getRetryDelaySeconds()))
.flatMap(lobbyClient::connectAndLogin);
}

private String tryGenerateUid(Long sessionId) {
try {
return uidService.generate(String.valueOf(sessionId));
} catch (IOException e) {
throw new UIDException("Cannot generate UID", e, "uid.generate.error");
}
}

public CompletableFuture<GameLaunchResponse> requestHostGame(NewGameInfo newGameInfo) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/faforever/client/remote/LobbyAccess.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.faforever.client.remote;

public record LobbyAccess(String accessUrl) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public static class GitHubRepo {
public static class ServerEndpoints {
private String name;
private SocketEndpoint lobby;
private UrlEndpoint lobbyWebsocket;
private UrlEndpoint user;
private SocketEndpoint irc;
private SocketEndpoint liveReplay;
private UrlEndpoint api;
Expand Down
3 changes: 1 addition & 2 deletions src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
faf-client:
server:
host: localhost
port: 8001
url: ws://localhost:8003

irc:
host: localhost
Expand Down
3 changes: 1 addition & 2 deletions src/main/resources/application-prod.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
faf-client:
server:
host: lobby.faforever.com
port: 8001
url: wss://ws.faforever.com

irc:
host: irc.faforever.com
Expand Down
3 changes: 1 addition & 2 deletions src/main/resources/application-test.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
faf-client:
server:
host: lobby.test.faforever.com
port: 8001
url: wss://lobby.test.faforever.com

irc:
host: irc.test.faforever.com
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -574,9 +574,10 @@ mapVault.ladder = Ladder maps
news.showLadderMaps = Show ladder maps
ranked1v1.showMaps = Show ladder maps
port = Port
login.userBaseUrl=User API base URL
login.serverHost = Server host
login.replayServerHost = Replay server host
login.apiBaseUrl = API base URL
login.apiBaseUrl=Game API base URL
games.showModdedGames = Show modded games
chat.userContext.copyUsername = Copy username
userInfo.idleTimeFormat = Last seen\: {0}
Expand Down
24 changes: 17 additions & 7 deletions src/main/resources/theme/login/login.fxml
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressIndicator?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="loginRoot" alignment="CENTER" spacing="20.0" styleClass="login-root" xmlns="http://javafx.com/javafx/15"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.faforever.client.login.LoginController">
<children>
Expand Down Expand Up @@ -76,9 +87,8 @@
<RowConstraints/>
</rowConstraints>
<children>
<TextField fx:id="serverHostField" promptText="%login.serverHost"/>
<TextField fx:id="serverPortField" prefColumnCount="6" promptText="%port"
GridPane.columnIndex="1"/>
<TextField fx:id="userUrlField" promptText="%login.userBaseUrl"
GridPane.columnSpan="2147483647"/>
<TextField fx:id="replayServerHostField" layoutX="10.0" layoutY="7.0"
promptText="%login.replayServerHost" GridPane.rowIndex="1"/>
<TextField fx:id="replayServerPortField" layoutX="310.0" layoutY="7.0" prefColumnCount="6"
Expand Down
Loading

0 comments on commit 201a74f

Please sign in to comment.