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