Skip to content

Commit abcfc1e

Browse files
authored
Merge pull request #1028 from Unity-Technologies/unity-master-fix-tls-no-graceful-close-during-read
Fixed SslStream/UnityTlsContext not reporting gracefully closed Streams on read
2 parents 70d9bef + b597755 commit abcfc1e

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

mcs/class/System/Mono.UnityTls/UnityTlsContext.cs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ unsafe internal class UnityTlsContext : MobileTlsContext
4141
MonoTlsConnectionInfo connectioninfo;
4242
bool isAuthenticated = false;
4343
bool hasContext = false;
44+
bool closedGraceful = false;
4445

4546
// Memory-buffer
4647
byte [] writeBuffer;
@@ -196,7 +197,9 @@ public override (int ret, bool wantMore) Read (byte[] buffer, int offset, int co
196197
return (0, false); // According to Apple and Btls implementation this is how we should handle gracefully closed connections.
197198

198199
default:
199-
Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to read data to TLS context");
200+
if (!closedGraceful) {
201+
Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to read data to TLS context");
202+
}
200203
return (0, false);
201204
}
202205
}
@@ -387,17 +390,28 @@ private size_t ReadCallback (byte* buffer, size_t bufferLen, UnityTls.unitytls_e
387390

388391
bool wouldBlock;
389392
int numBytesRead = Parent.InternalRead (readBuffer, 0, bufferLen, out wouldBlock);
390-
if (wouldBlock) {
391-
UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK);
392-
return 0;
393-
}
393+
394+
// Non graceful exit.
394395
if (numBytesRead < 0) {
395396
UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_READ_FAILED);
396-
return 0;
397+
} else if (numBytesRead > 0) {
398+
Marshal.Copy (readBuffer, 0, (IntPtr)buffer, bufferLen);
399+
} else { // numBytesRead == 0
400+
// careful when rearranging this: wouldBlock might be true even if stream was closed abruptly.
401+
if (wouldBlock) {
402+
UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK);
403+
}
404+
// indicates graceful exit.
405+
// UnityTls only accepts an exit as gracful, if it was closed via a special TLS protocol message.
406+
// Both .Net and MobileTlsContext have a different idea of this concept though!
407+
else {
408+
closedGraceful = true;
409+
UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_READ_FAILED);
410+
}
397411
}
398412

399-
Marshal.Copy (readBuffer, 0, (IntPtr)buffer, bufferLen);
400-
return numBytesRead;
413+
// Note that UnityTls ignores this number when raising an error.
414+
return numBytesRead;
401415
} catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code.
402416
UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_UNKNOWN_ERROR);
403417
if (lastException == null)

0 commit comments

Comments
 (0)