Skip to content

Commit 06d923d

Browse files
committed
Move some locks so that login states don't become desync'd during logout and ping timer events
1 parent db92333 commit 06d923d

File tree

1 file changed

+53
-47
lines changed

1 file changed

+53
-47
lines changed

Shoko.Server/Providers/AniDB/UDP/AniDBUDPConnectionHandler.cs

Lines changed: 53 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -227,70 +227,73 @@ private void LogoutTimerElapsed(object? sender, ElapsedEventArgs e)
227227
/// <returns></returns>
228228
public async Task<string> Send(string command, bool needsUnicode = true)
229229
{
230-
// Steps:
231-
// 1. Check Ban state and throw if Banned
232-
// 2. Check Login State and Login if needed
233-
// 3. Actually Call AniDB
234-
235-
// Check Ban State
236-
// Ideally, this will never happen, as we stop the queue and attempt a graceful rollback of the command
237-
if (IsBanned)
230+
try
238231
{
239-
throw new AniDBBannedException
232+
await _socketHandlerLock.WaitAsync();
233+
// Steps:
234+
// 1. Check Ban state and throw if Banned
235+
// 2. Check Login State and Login if needed
236+
// 3. Actually Call AniDB
237+
238+
// Check Ban State
239+
// Ideally, this will never happen, as we stop the queue and attempt a graceful rollback of the command
240+
if (IsBanned)
240241
{
241-
BanType = UpdateType.UDPBan,
242-
BanExpires = BanTime?.AddHours(BanTimerResetLength)
243-
};
244-
}
245-
// TODO Low Priority: We need to handle Login Attempt Decay, so that we can try again if it's not just a bad user/pass
246-
// It wasn't handled before, and it's not caused serious problems
242+
throw new AniDBBannedException
243+
{
244+
BanType = UpdateType.UDPBan, BanExpires = BanTime?.AddHours(BanTimerResetLength)
245+
};
246+
}
247+
// TODO Low Priority: We need to handle Login Attempt Decay, so that we can try again if it's not just a bad user/pass
248+
// It wasn't handled before, and it's not caused serious problems
247249

248-
// login doesn't use this method, so this check won't interfere with it
249-
// if we got here, and it's invalid session, then it already failed to re-log
250-
if (IsInvalidSession)
251-
{
252-
throw new NotLoggedInException();
253-
}
250+
// login doesn't use this method, so this check won't interfere with it
251+
// if we got here, and it's invalid session, then it already failed to re-log
252+
if (IsInvalidSession)
253+
{
254+
throw new NotLoggedInException();
255+
}
254256

255-
// Check Login State
256-
if (!await Login())
257+
// Check Login State
258+
if (!await Login())
259+
{
260+
throw new LoginFailedException();
261+
}
262+
263+
// Actually Call AniDB
264+
return await SendInternal(command, needsUnicode);
265+
}
266+
finally
257267
{
258-
throw new LoginFailedException();
268+
_socketHandlerLock.Release();
259269
}
260-
261-
// Actually Call AniDB
262-
return await SendDirectly(command, needsUnicode);
263270
}
264271

265-
public Task<string> SendDirectly(string command, bool needsUnicode = true, bool isPing = false, bool isLogout = false)
272+
public async Task<string> SendDirectly(string command, bool needsUnicode = true, bool isPing = false, bool isLogout = false)
266273
{
267274
try
268275
{
269-
// we want to reset the logout timer anyway
270-
if (!isLogout && !isPing)
271-
{
272-
_pingTimer?.Stop();
273-
_logoutTimer?.Stop();
274-
}
275-
276-
return SendInternal(command, needsUnicode, isPing);
276+
await _socketHandlerLock.WaitAsync();
277+
return await SendInternal(command, needsUnicode, isPing);
277278
}
278279
finally
279280
{
280-
if (!isLogout && !isPing)
281-
{
282-
_pingTimer?.Start();
283-
_logoutTimer?.Start();
284-
}
281+
_socketHandlerLock.Release();
285282
}
286283
}
287284

288-
private async Task<string> SendInternal(string command, bool needsUnicode = true, bool isPing = false)
285+
private async Task<string> SendInternal(string command, bool needsUnicode = true, bool isPing = false, bool isLogout = false)
289286
{
287+
ObjectDisposedException.ThrowIf(_socketHandler is not { IsConnected: true }, "The connection was closed by shoko");
288+
290289
try
291290
{
292-
await _socketHandlerLock.WaitAsync();
293-
ObjectDisposedException.ThrowIf(_socketHandler is not { IsConnected: true }, "The connection was closed by shoko");
291+
// we want to reset the logout timer anyway
292+
if (!isLogout && !isPing)
293+
{
294+
_pingTimer?.Stop();
295+
_logoutTimer?.Stop();
296+
}
294297

295298
// 1. Call AniDB
296299
// 2. Decode the response, converting Unicode and decompressing, as needed
@@ -325,8 +328,7 @@ private async Task<string> SendInternal(string command, bool needsUnicode = true
325328
IsBanned = true;
326329
throw new AniDBBannedException
327330
{
328-
BanType = UpdateType.UDPBan,
329-
BanExpires = BanTime?.AddHours(BanTimerResetLength)
331+
BanType = UpdateType.UDPBan, BanExpires = BanTime?.AddHours(BanTimerResetLength)
330332
};
331333
}
332334

@@ -350,7 +352,11 @@ private async Task<string> SendInternal(string command, bool needsUnicode = true
350352
}
351353
finally
352354
{
353-
_socketHandlerLock.Release();
355+
if (!isLogout && !isPing)
356+
{
357+
_pingTimer?.Start();
358+
_logoutTimer?.Start();
359+
}
354360
}
355361
}
356362

0 commit comments

Comments
 (0)