diff --git a/src/main/java/in/dragonbra/javasteam/steam/CMClient.java b/src/main/java/in/dragonbra/javasteam/steam/CMClient.java
index aa778935..f45f97d2 100644
--- a/src/main/java/in/dragonbra/javasteam/steam/CMClient.java
+++ b/src/main/java/in/dragonbra/javasteam/steam/CMClient.java
@@ -28,6 +28,7 @@
import in.dragonbra.javasteam.util.log.LogManager;
import in.dragonbra.javasteam.util.log.Logger;
import in.dragonbra.javasteam.util.stream.BinaryReader;
+import org.jetbrains.annotations.Nullable;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -51,10 +52,13 @@ public abstract class CMClient {
private long sessionToken;
+ @Nullable
private Integer cellID;
+ @Nullable
private Integer sessionID;
+ @Nullable
private SteamID steamID;
private IDebugNetworkListener debugNetworkListener;
@@ -64,6 +68,7 @@ public abstract class CMClient {
// connection lock around the setup and tear down of the connection task
private final Object connectionLock = new Object();
+ @Nullable
private Connection connection;
private final ScheduledFunction heartBeatFunc;
@@ -166,6 +171,12 @@ public void connect(ServerRecord cmServer) {
cmServer = getServers().getNextServerCandidate(configuration.getProtocolTypes());
}
+ if (cmServer == null) {
+ logger.error("No CM servers available to connect to");
+ onClientDisconnected(false);
+ return;
+ }
+
connection = createConnection(cmServer.getProtocolTypes());
connection.getNetMsgReceived().addEventHandler(netMsgReceived);
connection.getConnected().addEventHandler(connected);
@@ -412,7 +423,12 @@ private void handleLogOnResponse(IPacketMsg packetMsg) {
heartBeatFunc.setDelay(logonResp.getBody().getLegacyOutOfGameHeartbeatSeconds() * 1000L);
heartBeatFunc.start();
} else if (logonResponse == EResult.TryAnotherCM || logonResponse == EResult.ServiceUnavailable) {
- getServers().tryMark(connection.getCurrentEndPoint(), connection.getProtocolTypes(), ServerQuality.BAD);
+ var connection = this.connection;
+ if (connection != null) {
+ getServers().tryMark(connection.getCurrentEndPoint(), connection.getProtocolTypes(), ServerQuality.BAD);
+ } else {
+ logger.error("Connection was null trying to mark endpoint bad.");
+ }
}
}
@@ -431,7 +447,12 @@ private void handleLoggedOff(IPacketMsg packetMsg) {
logger.debug("handleLoggedOff got " + logoffResult);
if (logoffResult == EResult.TryAnotherCM || logoffResult == EResult.ServiceUnavailable) {
- getServers().tryMark(connection.getCurrentEndPoint(), connection.getProtocolTypes(), ServerQuality.BAD);
+ var connection = this.connection;
+ if (connection != null) {
+ getServers().tryMark(connection.getCurrentEndPoint(), connection.getProtocolTypes(), ServerQuality.BAD);
+ } else {
+ logger.error("Connection was null trying to mark endpoint bad.");
+ }
}
} else {
logger.debug("handleLoggedOff got unexpected response: " + packetMsg.getMsgType());
@@ -467,18 +488,26 @@ public SmartCMServerList getServers() {
/**
* Returns the local IP of this client.
*
- * @return The local IP.
+ * @return The local IP or null if no connection is available.
*/
- public InetAddress getLocalIP() {
+ public @Nullable InetAddress getLocalIP() {
+ var connection = this.connection;
+ if (connection == null) {
+ return null;
+ }
return connection.getLocalIP();
}
/**
* Returns the current endpoint this client is connected to.
*
- * @return The current endpoint.
+ * @return The current endpoint or null if no connection is available.
*/
- public InetSocketAddress getCurrentEndpoint() {
+ public @Nullable InetSocketAddress getCurrentEndpoint() {
+ var connection = this.connection;
+ if (connection == null) {
+ return null;
+ }
return connection.getCurrentEndPoint();
}
@@ -522,7 +551,7 @@ public long getSessionToken() {
* @return the Steam recommended Cell ID of this client. This value is assigned after a logon attempt has succeeded.
* This value will be null if the client is logged off of Steam.
*/
- public Integer getCellID() {
+ public @Nullable Integer getCellID() {
return cellID;
}
@@ -532,7 +561,7 @@ public Integer getCellID() {
*
* @return The session ID.
*/
- public Integer getSessionID() {
+ public @Nullable Integer getSessionID() {
return sessionID;
}
@@ -542,7 +571,7 @@ public Integer getSessionID() {
*
* @return The SteamID.
*/
- public SteamID getSteamID() {
+ public @Nullable SteamID getSteamID() {
return steamID;
}
diff --git a/src/main/java/in/dragonbra/javasteam/steam/discovery/SmartCMServerList.kt b/src/main/java/in/dragonbra/javasteam/steam/discovery/SmartCMServerList.kt
index 9c8df9d7..f6d46ed9 100644
--- a/src/main/java/in/dragonbra/javasteam/steam/discovery/SmartCMServerList.kt
+++ b/src/main/java/in/dragonbra/javasteam/steam/discovery/SmartCMServerList.kt
@@ -193,11 +193,11 @@ class SmartCMServerList(private val configuration: SteamConfiguration) {
}
}
- fun tryMark(endPoint: InetSocketAddress?, protocolTypes: ProtocolTypes, quality: ServerQuality): Boolean =
- tryMark(endPoint, EnumSet.of(protocolTypes), quality)
+ fun tryMark(endPoint: InetSocketAddress?, protocolTypes: ProtocolTypes?, quality: ServerQuality): Boolean =
+ tryMark(endPoint, protocolTypes?.let { EnumSet.of(it) }, quality)
- fun tryMark(endPoint: InetSocketAddress?, protocolTypes: EnumSet, quality: ServerQuality): Boolean {
- if (endPoint == null) {
+ fun tryMark(endPoint: InetSocketAddress?, protocolTypes: EnumSet?, quality: ServerQuality): Boolean {
+ if (endPoint == null || protocolTypes == null) {
logger.error("Couldn't mark an endpoint ${quality.name}, skipping it")
return false
}
diff --git a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamcloud/SteamCloud.kt b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamcloud/SteamCloud.kt
index 4b45d60e..c33bee9f 100644
--- a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamcloud/SteamCloud.kt
+++ b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamcloud/SteamCloud.kt
@@ -238,7 +238,7 @@ class SteamCloud : ClientMsgHandler() {
timestamp: Date,
filename: String,
platformsToSync: Int = UInt.MAX_VALUE.toInt(),
- cellId: Int = client.cellID,
+ cellId: Int = client.cellID!!,
canEncrypt: Boolean = true,
isSharedFile: Boolean = false,
deprecatedRealm: Int? = null,
@@ -492,7 +492,7 @@ class SteamCloud : ClientMsgHandler() {
bytesExpected: Long,
bytesActual: Long,
durationMs: Int,
- cellId: Int = client.cellID,
+ cellId: Int = client.cellID!!,
proxied: Boolean,
ipv6Local: Boolean,
ipv6Remote: Boolean,
diff --git a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriends.kt b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriends.kt
index fe7c555b..b6c70e84 100644
--- a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriends.kt
+++ b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriends.kt
@@ -422,10 +422,13 @@ class SteamFriends : ClientMsgHandler() {
body.steamIdChat = chatID
body.type = EChatInfoType.StateChange
+ // SteamID can be null if not connected - will be ultimately ignored in Client.Send.
+ val localSteamID = client.steamID?.convertToUInt64() ?: SteamID().convertToUInt64()
+
try {
- writeLong(client.steamID.convertToUInt64()) // ChatterActedOn
+ writeLong(localSteamID) // ChatterActedOn
writeInt(EChatMemberStateChange.Left.code()) // StateChange
- writeLong(client.steamID.convertToUInt64()) // ChatterActedBy
+ writeLong(localSteamID) // ChatterActedBy
} catch (e: IOException) {
logger.debug(e)
}
@@ -473,7 +476,7 @@ class SteamFriends : ClientMsgHandler() {
body.steamIdInvited = steamIdUser.convertToUInt64()
// steamclient also sends the steamid of the user that did the invitation
// we'll mimic that behavior
- body.steamIdPatron = client.steamID.convertToUInt64()
+ body.steamIdPatron = client.steamID?.convertToUInt64() ?: SteamID().convertToUInt64()
}.also(client::send)
}
diff --git a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/cache/FriendCache.kt b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/cache/FriendCache.kt
index d03a510a..0f5d6d1f 100644
--- a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/cache/FriendCache.kt
+++ b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/cache/FriendCache.kt
@@ -62,5 +62,5 @@ class AccountCache {
fun getUser(steamId: SteamID): User = if (isLocalUser(steamId)) localUser else users.getAccount(steamId)
- fun isLocalUser(steamId: SteamID): Boolean = localUser.steamID == steamId
+ fun isLocalUser(steamId: SteamID?): Boolean = localUser.steamID == steamId
}
diff --git a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamgameserver/SteamGameServer.kt b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamgameserver/SteamGameServer.kt
index af829db7..40760c45 100644
--- a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamgameserver/SteamGameServer.kt
+++ b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamgameserver/SteamGameServer.kt
@@ -52,7 +52,7 @@ class SteamGameServer : ClientMsgHandler() {
logon.protoHeader.clientSessionid = 0
logon.protoHeader.steamid = gsId.convertToUInt64()
- val localIp: CMsgIPAddress = NetHelpers.getMsgIPAddress(client.localIP)
+ val localIp: CMsgIPAddress = NetHelpers.getMsgIPAddress(client.localIP!!)
logon.body.obfuscatedPrivateIp = NetHelpers.obfuscatePrivateIP(localIp)
logon.body.protocolVersion = MsgClientLogon.CurrentProtocol
@@ -87,7 +87,7 @@ class SteamGameServer : ClientMsgHandler() {
logon.protoHeader.clientSessionid = 0
logon.protoHeader.steamid = gsId.convertToUInt64()
- val localIp: CMsgIPAddress = NetHelpers.getMsgIPAddress(client.localIP)
+ val localIp: CMsgIPAddress = NetHelpers.getMsgIPAddress(client.localIP!!)
logon.body.obfuscatedPrivateIp = NetHelpers.obfuscatePrivateIP(localIp)
logon.body.protocolVersion = MsgClientLogon.CurrentProtocol
diff --git a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/SteamUser.kt b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/SteamUser.kt
index d14e7031..1162ee73 100644
--- a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/SteamUser.kt
+++ b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/SteamUser.kt
@@ -34,7 +34,7 @@ import `in`.dragonbra.javasteam.util.NetHelpers
*/
class SteamUser : ClientMsgHandler() {
- val steamID: SteamID
+ val steamID: SteamID?
get() = client.steamID
/**