@@ -41,6 +41,7 @@ unsafe internal class UnityTlsContext : MobileTlsContext
41
41
MonoTlsConnectionInfo connectioninfo ;
42
42
bool isAuthenticated = false ;
43
43
bool hasContext = false ;
44
+ bool closedGraceful = false ;
44
45
45
46
// Memory-buffer
46
47
byte [ ] writeBuffer ;
@@ -196,7 +197,9 @@ public override (int ret, bool wantMore) Read (byte[] buffer, int offset, int co
196
197
return ( 0 , false ) ; // According to Apple and Btls implementation this is how we should handle gracefully closed connections.
197
198
198
199
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
+ }
200
203
return ( 0 , false ) ;
201
204
}
202
205
}
@@ -387,17 +390,28 @@ private size_t ReadCallback (byte* buffer, size_t bufferLen, UnityTls.unitytls_e
387
390
388
391
bool wouldBlock ;
389
392
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.
394
395
if ( numBytesRead < 0 ) {
395
396
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
+ }
397
411
}
398
412
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 ;
401
415
} catch ( Exception ex ) { // handle all exceptions and store them for later since we don't want to let them go through native code.
402
416
UnityTls . NativeInterface . unitytls_errorstate_raise_error ( errorState , UnityTls . unitytls_error_code . UNITYTLS_USER_UNKNOWN_ERROR ) ;
403
417
if ( lastException == null )
0 commit comments