diff --git a/Source/GSFileHandle.m b/Source/GSFileHandle.m index cc3ec34f2..56bbe97e9 100644 --- a/Source/GSFileHandle.m +++ b/Source/GSFileHandle.m @@ -366,24 +366,26 @@ static GSTcpTune *tune = nil; [self ignoreReadDescriptor]; [self ignoreWriteDescriptor]; -#if USE_ZLIB - /* - * The gzDescriptor should always be closed when we have done with it. - */ - if (gzDescriptor != 0) + if (closeOnDealloc == YES && descriptor != -1) { - gzclose(gzDescriptor); - gzDescriptor = 0; + [self closeFile]; } -#endif - if (descriptor != -1) + else { - [self setNonBlocking: wasNonBlocking]; - if (closeOnDealloc == YES) - { - close(descriptor); - descriptor = -1; - } +#if USE_ZLIB + /* + * The gzDescriptor should always be closed when we have done with it. + */ + if (gzDescriptor != 0) + { + gzclose(gzDescriptor); + gzDescriptor = 0; + } +#endif + if (descriptor != -1) + { + [self setNonBlocking: wasNonBlocking]; + } } } diff --git a/Source/GSSocketStream.m b/Source/GSSocketStream.m index fb6550def..e9479695d 100644 --- a/Source/GSSocketStream.m +++ b/Source/GSSocketStream.m @@ -476,7 +476,7 @@ static NSArray *keys = nil; { handshake = NO; active = NO; - [session disconnect]; + [session disconnect: NO]; } - (void) dealloc diff --git a/Source/GSTLS.h b/Source/GSTLS.h index 6b85e3e99..30b33327d 100644 --- a/Source/GSTLS.h +++ b/Source/GSTLS.h @@ -197,9 +197,13 @@ typedef ssize_t (*GSTLSIOW)(gnutls_transport_ptr_t, const void *, size_t); */ - (BOOL) active; -/* Disconnects and closes down the session. +/* Disconnects and closes down the session.
+ * The reusable flag specifies whether we intend to reuse the underlying + * connection.
+ * Returns YES on success, NO if the shutdown did not complete cleanly + * and the underlying connection cannot be reused. */ -- (void) disconnect; +- (BOOL) disconnect: (BOOL)reusable; /* Try to complete a handshake ... return YES if complete, NO if we need * to try again (would have to wait for the remote end).
diff --git a/Source/GSTLS.m b/Source/GSTLS.m index e45dfe6ae..c1537c443 100644 --- a/Source/GSTLS.m +++ b/Source/GSTLS.m @@ -1281,13 +1281,32 @@ static NSMutableDictionary *credentialsCache = nil; [super dealloc]; } -- (void) disconnect +- (BOOL) disconnect: (BOOL)reusable { + BOOL ok = YES; + if (YES == active || YES == handshake) { active = NO; handshake = NO; - gnutls_bye(session, GNUTLS_SHUT_RDWR); + if (NO == reusable) + { + gnutls_bye(session, GNUTLS_SHUT_WR); + } + else + { + int result; + + do + { + result = gnutls_bye(session, GNUTLS_SHUT_RDWR); + } + while (GNUTLS_E_AGAIN == result || GNUTLS_E_INTERRUPTED == result); + if (result < 0) + { + ok = NO; + } + } } if (YES == setup) { @@ -1295,11 +1314,12 @@ static NSMutableDictionary *credentialsCache = nil; gnutls_db_remove_session(session); gnutls_deinit(session); } + return ok; } - (void) finalize { - [self disconnect]; + [self disconnect: NO]; [super finalize]; } @@ -1545,7 +1565,7 @@ static NSMutableDictionary *credentialsCache = nil; ASSIGN(problem, p); NSLog(@"%@ %@", self, p); } - [self disconnect]; + [self disconnect: NO]; return YES; // Failed ... not active. } else @@ -1591,7 +1611,7 @@ static NSMutableDictionary *credentialsCache = nil; self, gnutls_strerror(ret)); NSLog(@"%@ %@", self, [self sessionInfo]); } - [self disconnect]; + [self disconnect: NO]; } } return YES; // Handshake complete diff --git a/Source/NSFileHandle.m b/Source/NSFileHandle.m index ebd2c4148..12626ab5b 100644 --- a/Source/NSFileHandle.m +++ b/Source/NSFileHandle.m @@ -985,9 +985,7 @@ GSTLSHandlePush(gnutls_transport_ptr_t handle, const void *buffer, size_t len) - (void) sslDisconnect { - // TLS may need to read data during teardown, and we need to wait for it. - [self setNonBlocking: NO]; - [session disconnect]; + [session disconnect: NO]; } - (BOOL) sslHandshakeEstablished: (BOOL*)result outgoing: (BOOL)isOutgoing