Skip to content
Open
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
10 changes: 5 additions & 5 deletions .github/workflows/dotnet-core.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: .NET Core
name: .NET

on:
push:
Expand All @@ -15,13 +15,13 @@ jobs:
working-directory: ./src/Atlasd

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init --recursive
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 3.1.301
dotnet-version: '10.0.x'
- name: Install dependencies
run: dotnet restore
working-directory: ${{env.working-directory}}
Expand Down
2 changes: 1 addition & 1 deletion src/Atlasd/Atlasd.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Description>Atlas is cross-platform software that emulates Classic Battle.net in a compatible model for Diablo, StarCraft, and WarCraft.</Description>
<Copyright>© 2020-2021 Carl Bennett &lt;carl@carlbennett.me&gt;</Copyright>
<Company>BNETDocs</Company>
Expand Down
16 changes: 12 additions & 4 deletions src/Atlasd/Battlenet/BinaryReader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using Atlasd.Battlenet.Exceptions;
using System.IO;
using System.Text;

namespace Atlasd.Battlenet
Expand All @@ -17,7 +18,7 @@ public long GetNextNull()
{
long lastPosition = BaseStream.Position;

while (BaseStream.CanRead)
while (BaseStream.Position < BaseStream.Length)
{
if (ReadByte() == 0)
{
Expand All @@ -27,6 +28,7 @@ public long GetNextNull()
}
}

BaseStream.Position = lastPosition;
return -1;
}
}
Expand All @@ -35,7 +37,13 @@ public byte[] ReadByteString()
{
lock (_lock)
{
var size = GetNextNull() - BaseStream.Position;
var nullPos = GetNextNull();
if (nullPos < 0)
{
throw new GameProtocolViolationException(null,
$"Truncated string field at stream position {BaseStream.Position}: missing null terminator");
}
var size = nullPos - BaseStream.Position;
return ReadBytes((int)size)[..^1];
}
}
Expand All @@ -46,7 +54,7 @@ public override string ReadString()
{
string str = "";
char chr;
while ((int)(chr = ReadChar()) != 0)
while (BaseStream.Position < BaseStream.Length && (int)(chr = ReadChar()) != 0)
str += chr;
return str;
}
Expand Down
5 changes: 4 additions & 1 deletion src/Atlasd/Battlenet/Channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,10 @@ public void Close()

public void Designate(GameState designator, GameState heir)
{
DesignatedHeirs[designator] = heir;
lock (DesignatedHeirs)
{
DesignatedHeirs[designator] = heir;
}
}

public bool DisbandInto(Channel destination)
Expand Down
365 changes: 195 additions & 170 deletions src/Atlasd/Battlenet/ClientState.cs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/Atlasd/Battlenet/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public ShutdownEvent(string adminMessage, bool cancelled, DateTime eventDate, Ti
public static ConcurrentDictionary<byte[], Clan> ActiveClans;
public static ConcurrentDictionary<Socket, ClientState> ActiveClientStates;
public static List<GameAd> ActiveGameAds;
public static readonly object ActiveGameAdsLock = new object();
public static ConcurrentDictionary<string, GameState> ActiveGameStates;
public static IPAddress DefaultAddress { get; private set; }
public static int DefaultPort { get; private set; }
Expand Down
15 changes: 13 additions & 2 deletions src/Atlasd/Battlenet/Friend.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,20 @@ public void Sync(GameState source)
return;
}

lock (source)
// Enforce consistent lock ordering to prevent ABBA deadlock.
// Always lock the object with the lower RuntimeHelpers hash first.
var first = source;
var second = target;
if (System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(source) >
System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(target))
{
lock (target)
first = target;
second = source;
}

lock (first)
{
lock (second)
{
var admin = source.HasAdmin();
var mutual = false;
Expand Down
57 changes: 30 additions & 27 deletions src/Atlasd/Battlenet/Protocols/Game/GameState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public enum LogonTypes : UInt32
NLS = 2,
};

private bool IsDisposing = false;
private volatile bool IsDisposing = false;

public ClientState Client { get; protected set; }

Expand Down Expand Up @@ -125,38 +125,41 @@ public static bool CanStatstringUpdate(Product.ProductCode code)

public void Close()
{
// Remove this GameState from ActiveChannel
if (ActiveChannel != null)
lock (this)
{
ActiveChannel.RemoveUser(this); // will change this.ActiveChannel to null.
}
// Remove this GameState from ActiveChannel
if (ActiveChannel != null)
{
ActiveChannel.RemoveUser(this); // will change this.ActiveChannel to null.
}

// Notify clan members
if (ActiveClan != null)
{
ActiveClan.WriteStatusChange(this, false); // offline
}
// Notify clan members
if (ActiveClan != null)
{
ActiveClan.WriteStatusChange(this, false); // offline
}

// Update keys of ActiveAccount
if (ActiveAccount != null)
{
ActiveAccount.Set(Account.LastLogoffKey, DateTime.Now);
// Update keys of ActiveAccount
if (ActiveAccount != null)
{
ActiveAccount.Set(Account.LastLogoffKey, DateTime.Now);

var timeLogged = (UInt32)ActiveAccount.Get(Account.TimeLoggedKey);
var diff = DateTime.Now - ConnectedTimestamp;
timeLogged += (UInt32)Math.Round(diff.TotalSeconds);
ActiveAccount.Set(Account.TimeLoggedKey, timeLogged);
}
var timeLogged = (UInt32)ActiveAccount.Get(Account.TimeLoggedKey);
var diff = DateTime.Now - ConnectedTimestamp;
timeLogged += (UInt32)Math.Round(diff.TotalSeconds);
ActiveAccount.Set(Account.TimeLoggedKey, timeLogged);
}

// Remove this OnlineName from ActiveAccounts and ActiveGameStates
if (!string.IsNullOrEmpty(OnlineName))
{
Battlenet.Common.ActiveAccounts.TryRemove(OnlineName, out _);
Battlenet.Common.ActiveGameStates.TryRemove(OnlineName, out _);
}
// Remove this OnlineName from ActiveAccounts and ActiveGameStates
if (!string.IsNullOrEmpty(OnlineName))
{
Battlenet.Common.ActiveAccounts.TryRemove(OnlineName, out _);
Battlenet.Common.ActiveGameStates.TryRemove(OnlineName, out _);
}

// Remove this GameAd
if (GameAd != null && GameAd.RemoveClient(this)) GameAd = null;
// Remove this GameAd
if (GameAd != null && GameAd.RemoveClient(this)) GameAd = null;
}
}

public void Dispose() /* part of IDisposable */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public override bool Invoke(MessageContext context)
{
var gameAd = gameState.GameAd;
if (gameAd.RemoveClient(gameState)) gameState.GameAd = null;
if (gameAd.Clients.Count == 0) lock (Battlenet.Common.ActiveGameAds) Battlenet.Common.ActiveGameAds.Remove(gameAd);
if (gameAd.Clients.Count == 0) lock (Battlenet.Common.ActiveGameAdsLock) Battlenet.Common.ActiveGameAds.Remove(gameAd);
}

if (gameState.ActiveChannel == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public override bool Invoke(MessageContext context)

var gameAds = new List<GameAd>();

lock (Battlenet.Common.ActiveGameAds)
lock (Battlenet.Common.ActiveGameAdsLock)
{
IList<GameAd> toDelete = new List<GameAd>();
foreach (var gameAd in Battlenet.Common.ActiveGameAds)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public override bool Invoke(MessageContext context)
if (gameState.ActiveChannel != null)
gameState.ActiveChannel.RemoveUser(gameState);

lock (Battlenet.Common.ActiveGameAds)
lock (Battlenet.Common.ActiveGameAdsLock)
{
foreach (var gameAd in Battlenet.Common.ActiveGameAds)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public override bool Invoke(MessageContext context)
Statuses status = Statuses.Failed;
GameAd gameAd = null;

lock (Battlenet.Common.ActiveGameAds)
lock (Battlenet.Common.ActiveGameAdsLock)
{
foreach (GameAd _ad in Battlenet.Common.ActiveGameAds)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public override bool Invoke(MessageContext context)
Statuses status = Statuses.Failed;
GameAd gameAd = null;

lock (Battlenet.Common.ActiveGameAds)
lock (Battlenet.Common.ActiveGameAdsLock)
{
foreach (GameAd _ad in Battlenet.Common.ActiveGameAds)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public override bool Invoke(MessageContext context)
Statuses status = Statuses.Error;
GameAd gameAd = null;

lock (Battlenet.Common.ActiveGameAds)
lock (Battlenet.Common.ActiveGameAdsLock)
{
foreach (GameAd _ad in Battlenet.Common.ActiveGameAds)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public override bool Invoke(MessageContext context)
if (!gameAdOwner)
Logging.WriteLine(Logging.LogLevel.Info, Logging.LogType.Client_Game, context.Client.RemoteEndPoint, $"{MessageName(Id)} was received but they are not the owner of the game advertisement");
else
Battlenet.Common.ActiveGameAds.Remove(gs.GameAd);
lock (Battlenet.Common.ActiveGameAdsLock) Battlenet.Common.ActiveGameAds.Remove(gs.GameAd);

return true;
}
Expand Down
1 change: 0 additions & 1 deletion src/Atlasd/Battlenet/Protocols/HTTP/HttpListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ public void Start() /* part of IListener */
{
ExclusiveAddressUse = true,
NoDelay = Daemon.Common.TcpNoDelay,
UseOnlyOverlappedIO = true,
};
Socket.Bind(LocalEndPoint);
Socket.Listen(-1);
Expand Down
1 change: 0 additions & 1 deletion src/Atlasd/Battlenet/ServerSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ public void SetLocalEndPoint(IPEndPoint localEndPoint)
{
ExclusiveAddressUse = true,
NoDelay = Daemon.Common.TcpNoDelay,
UseOnlyOverlappedIO = true,
};
}

Expand Down
2 changes: 1 addition & 1 deletion vendor/MBNCSUtil
Loading