Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,30 @@ public static void main(String[] args) {
@Override
public void run() {

// // If any configuration needs to be set; such as connection protocol api key, etc., you can configure it like so.
// var configuration = SteamConfiguration.create(config -> {
// If any configuration needs to be set; such as connection protocol api key, etc., you can configure it like so.
// var config = SteamConfiguration.create(config -> {
// config.withProtocolTypes(ProtocolTypes.WEB_SOCKET);
// });
// // create our steamclient instance with custom configuration.
// steamClient = new SteamClient(configuration);

// You can also create custom connection classes if you have specific networking requirements.
// var config = SteamConfiguration.create(builder -> {
// builder.withProtocolTypes(EnumSet.of(ProtocolTypes.TCP, ProtocolTypes.UDP)); // Declare desired protocol types.
// IConnectionFactory connectionFactory = (configuration, protocol) -> {
// if (protocol.contains(ProtocolTypes.TCP)) {
// return new CustomTCPConnection();
// } else if (protocol.contains(ProtocolTypes.UDP)) {
// // We ask for TCP and UDP above, so this condition should handle UDP.
// return CustomUDPConnection();
// } else {
// // Fallback: 'thenResolve` will fallback to default connection types.
// return null;
// }
// };
// builder.withConnectionFactory(connectionFactory.thenResolve(IConnectionFactory.DEFAULT));
// });

// create our steamclient instance with custom configuration.
// steamClient = new SteamClient(config);

// create our steamclient instance using default configuration
steamClient = new SteamClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,27 @@ public abstract class Connection {
/**
* Occurs when a net message is received over the network.
*/
final Event<NetMsgEventArgs> netMsgReceived = new Event<>();
protected final Event<NetMsgEventArgs> netMsgReceived = new Event<>();

/**
* Occurs when the physical connection is established.
*/
final Event<EventArgs> connected = new Event<>();
protected final Event<EventArgs> connected = new Event<>();

/**
* Occurs when the physical connection is broken.
*/
final Event<DisconnectedEventArgs> disconnected = new Event<>();
protected final Event<DisconnectedEventArgs> disconnected = new Event<>();

void onNetMsgReceived(NetMsgEventArgs e) {
protected void onNetMsgReceived(NetMsgEventArgs e) {
netMsgReceived.handleEvent(this, e);
}

void onConnected() {
protected void onConnected() {
connected.handleEvent(this, null);
}

void onDisconnected(boolean e) {
protected void onDisconnected(boolean e) {
disconnected.handleEvent(this, new DisconnectedEventArgs(e));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package in.dragonbra.javasteam.networking.steam3;

import in.dragonbra.javasteam.steam.steamclient.configuration.SteamConfiguration;
import org.jetbrains.annotations.Nullable;

import java.util.EnumSet;
import java.util.Objects;

@FunctionalInterface
public interface IConnectionFactory {

IConnectionFactory DEFAULT = (configuration, protocol) -> {
if (protocol.contains(ProtocolTypes.WEB_SOCKET)) {
return new WebSocketConnection();
}
if (protocol.contains(ProtocolTypes.TCP)) {
return new EnvelopeEncryptedConnection(new TcpConnection(), configuration.getUniverse());
}
if (protocol.contains(ProtocolTypes.UDP)) {
return new EnvelopeEncryptedConnection(new UdpConnection(), configuration.getUniverse());
}
return null;
};

/**
* If the final method returns null, an exception will be thrown.
*/
@Nullable Connection createConnection(SteamConfiguration configuration, EnumSet<ProtocolTypes> protocol);

/**
* If this method returns null, the subConnectionFactory will be used.
*/
default IConnectionFactory thenResolve(IConnectionFactory subConnectionFactory) {
Objects.requireNonNull(subConnectionFactory);
return (configuration, protocol) -> {
Connection connection = createConnection(configuration, protocol);
if (connection == null) {
return subConnectionFactory.createConnection(configuration, protocol);
}
return connection;
};
}
}
20 changes: 10 additions & 10 deletions src/main/java/in/dragonbra/javasteam/steam/CMClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import in.dragonbra.javasteam.networking.steam3.*;
import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesBase.CMsgMulti;
import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesClientserver.CMsgClientSessionToken;
import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesClientserverLogin.CMsgClientHello;
import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesClientserverLogin.CMsgClientHeartBeat;
import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesClientserverLogin.CMsgClientHello;
import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesClientserverLogin.CMsgClientLoggedOff;
import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesClientserverLogin.CMsgClientLogonResponse;
import in.dragonbra.javasteam.steam.discovery.ServerQuality;
Expand All @@ -35,7 +35,7 @@
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.EnumSet;
import java.util.zip.GZIPInputStream;

/**
Expand Down Expand Up @@ -189,6 +189,8 @@ public void connect(ServerRecord cmServer) {
connection.getNetMsgReceived().addEventHandler(netMsgReceived);
connection.getConnected().addEventHandler(connected);
connection.getDisconnected().addEventHandler(disconnected);
logger.debug(String.format("Connecting to %s with protocol %s, and with connection impl %s",
cmServer.getEndpoint(), cmServer.getProtocolTypes(), connection.getClass().getSimpleName()));
connection.connect(cmServer.getEndpoint());
} catch (Exception e) {
logger.debug("Failed to connect to Steam network", e);
Expand Down Expand Up @@ -312,15 +314,13 @@ protected void onClientDisconnected(boolean userInitiated) {
}

private Connection createConnection(EnumSet<ProtocolTypes> protocol) {
if (protocol.contains(ProtocolTypes.WEB_SOCKET)) {
return new WebSocketConnection();
} else if (protocol.contains(ProtocolTypes.TCP)) {
return new EnvelopeEncryptedConnection(new TcpConnection(), getUniverse());
} else if (protocol.contains(ProtocolTypes.UDP)) {
return new EnvelopeEncryptedConnection(new UdpConnection(), getUniverse());
IConnectionFactory connectionFactory = configuration.getConnectionFactory();
Connection connection = connectionFactory.createConnection(configuration, protocol);
if (connection == null) {
logger.error(String.format("Connection factory returned null connection for protocols %s", protocol));
throw new IllegalArgumentException("Connection factory returned null connection.");
}

throw new IllegalArgumentException("Protocol bitmask has no supported protocols set.");
return connection;
}

public static IPacketMsg getPacketMsg(byte[] data) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package `in`.dragonbra.javasteam.steam.steamclient.configuration

import `in`.dragonbra.javasteam.enums.EClientPersonaStateFlag
import `in`.dragonbra.javasteam.enums.EUniverse
import `in`.dragonbra.javasteam.networking.steam3.IConnectionFactory
import `in`.dragonbra.javasteam.networking.steam3.ProtocolTypes
import `in`.dragonbra.javasteam.steam.contentdownloader.IManifestProvider
import `in`.dragonbra.javasteam.steam.discovery.IServerListProvider
Expand All @@ -14,6 +15,15 @@ import java.util.*
*/
@Suppress("unused")
interface ISteamConfigurationBuilder {

/**
* Configures this [SteamConfiguration] to use the provided [IConnectionFactory].
*
* @param connectionFactory The [IConnectionFactory] to use.
* @return A builder with modified configuration.
*/
fun withConnectionFactory(connectionFactory: IConnectionFactory): ISteamConfigurationBuilder

/**
* Configures this [SteamConfiguration] for a particular Steam cell.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package `in`.dragonbra.javasteam.steam.steamclient.configuration

import `in`.dragonbra.javasteam.enums.EClientPersonaStateFlag
import `in`.dragonbra.javasteam.enums.EUniverse
import `in`.dragonbra.javasteam.networking.steam3.IConnectionFactory
import `in`.dragonbra.javasteam.networking.steam3.ProtocolTypes
import `in`.dragonbra.javasteam.steam.contentdownloader.IManifestProvider
import `in`.dragonbra.javasteam.steam.discovery.IServerListProvider
Expand All @@ -19,6 +20,23 @@ import java.util.*
@Suppress("MemberVisibilityCanBePrivate")
class SteamConfiguration internal constructor(private val state: SteamConfigurationState) {

/**
* Builds the underlying [in.dragonbra.javasteam.networking.steam3.Connection] used for connecting to stream.
*
* ```java
* steamClient = new SteamClient(SteamConfiguration.create(builder -> {
* IConnectionFactory connectionFactory = (configuration, protocol) -> {
* return null;//custom connection or null to resolve fallback
* };
* builder.withConnectionFactory(
* connectionFactory.thenResolve(IConnectionFactory.DEFAULT));
* }));
* ```
*
*/
val connectionFactory: IConnectionFactory
get() = state.connectionFactory

/**
* Whether to use the Steam Directory to discover available servers.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package `in`.dragonbra.javasteam.steam.steamclient.configuration

import `in`.dragonbra.javasteam.enums.EClientPersonaStateFlag
import `in`.dragonbra.javasteam.enums.EUniverse
import `in`.dragonbra.javasteam.networking.steam3.IConnectionFactory
import `in`.dragonbra.javasteam.networking.steam3.ProtocolTypes
import `in`.dragonbra.javasteam.steam.contentdownloader.IManifestProvider
import `in`.dragonbra.javasteam.steam.contentdownloader.MemoryManifestProvider
Expand All @@ -21,6 +22,11 @@ class SteamConfigurationBuilder : ISteamConfigurationBuilder {

fun build(): SteamConfiguration = SteamConfiguration(state)

override fun withConnectionFactory(connectionFactory: IConnectionFactory): ISteamConfigurationBuilder {
state.connectionFactory = connectionFactory
return this
}

override fun withCellID(cellID: Int): ISteamConfigurationBuilder {
state.cellID = cellID
return this
Expand Down Expand Up @@ -89,6 +95,7 @@ class SteamConfigurationBuilder : ISteamConfigurationBuilder {
companion object {
@JvmStatic
fun createDefaultState(): SteamConfigurationState = SteamConfigurationState(
connectionFactory = IConnectionFactory.DEFAULT,
isAllowDirectoryFetch = true,
connectionTimeout = 5000L,
defaultPersonaStateFlags = EnumSet.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ package `in`.dragonbra.javasteam.steam.steamclient.configuration

import `in`.dragonbra.javasteam.enums.EClientPersonaStateFlag
import `in`.dragonbra.javasteam.enums.EUniverse
import `in`.dragonbra.javasteam.networking.steam3.IConnectionFactory
import `in`.dragonbra.javasteam.networking.steam3.ProtocolTypes
import `in`.dragonbra.javasteam.steam.contentdownloader.IManifestProvider
import `in`.dragonbra.javasteam.steam.discovery.IServerListProvider
import okhttp3.OkHttpClient
import java.util.EnumSet
import java.util.*

/**
* @author lngtr
* @since 2018-02-20
*/
data class SteamConfigurationState(
var connectionFactory: IConnectionFactory,
var isAllowDirectoryFetch: Boolean,
var cellID: Int,
var connectionTimeout: Long,
Expand Down