Skip to content

Commit 2cc3fa1

Browse files
committed
Adding isSecure method to check if a socket has been secured via SSL/TLS. Also fixing a bug that might occur on Mac OS X when using secure sockets, and reading data with a small fixed length.
1 parent 59c69ae commit 2cc3fa1

File tree

2 files changed

+78
-17
lines changed

2 files changed

+78
-17
lines changed

GCD/GCDAsyncSocket.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,13 @@ typedef enum GCDAsyncSocketError GCDAsyncSocketError;
397397
- (BOOL)isIPv4;
398398
- (BOOL)isIPv6;
399399

400+
/**
401+
* Returns whether or not the socket has been secured via SSL/TLS.
402+
*
403+
* See also the startTLS method.
404+
**/
405+
- (BOOL)isSecure;
406+
400407
#pragma mark Reading
401408

402409
// The readData and writeData methods won't block (they are asynchronous).

GCD/GCDAsyncSocket.m

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -820,9 +820,9 @@ - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQu
820820
{
821821
NSString *assertMsg = @"The given socketQueue parameter must not be a concurrent queue.";
822822

823-
NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), @"%@", assertMsg);
824-
NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), @"%@", assertMsg);
825-
NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), @"%@", assertMsg);
823+
NSAssert1(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), @"%@", assertMsg);
824+
NSAssert1(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), @"%@", assertMsg);
825+
NSAssert1(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), @"%@", assertMsg);
826826

827827
dispatch_retain(sq);
828828
socketQueue = sq;
@@ -3183,6 +3183,24 @@ - (BOOL)isIPv6
31833183
}
31843184
}
31853185

3186+
- (BOOL)isSecure
3187+
{
3188+
if (dispatch_get_current_queue() == socketQueue)
3189+
{
3190+
return (flags & kSocketSecure) ? YES : NO;
3191+
}
3192+
else
3193+
{
3194+
__block BOOL result;
3195+
3196+
dispatch_sync(socketQueue, ^{
3197+
result = (flags & kSocketSecure) ? YES : NO;
3198+
});
3199+
3200+
return result;
3201+
}
3202+
}
3203+
31863204
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
31873205
#pragma mark Utilities
31883206
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -3771,8 +3789,31 @@ - (void)doReadData
37713789

37723790
}
37733791
#else
3792+
37743793
estimatedBytesAvailable = socketFDBytesAvailable + [sslReadBuffer length];
3794+
3795+
if (flags & kSocketSecure)
3796+
{
3797+
// SecureTransport has an internal buffer of its own.
3798+
// When we invoke SSLRead, it in turn invokes our lower level read IO function,
3799+
// and reads data in encrypted chunks from the socket.
3800+
// If we ask for a length of data from SSLRead that doesn't fall on the border of
3801+
// one of these encrypted chunks, then the SSLRead function stores the extra
3802+
// data in its own internal buffer.
3803+
//
3804+
// The SSLGetBufferedReadSize function will tell us the size of this internal buffer.
3805+
// From the documentation:
3806+
//
3807+
// "This function does not block or cause any low-level read operations to occur."
3808+
3809+
size_t sslInternalBufSize = 0;
3810+
SSLGetBufferedReadSize(sslContext, &sslInternalBufSize);
3811+
3812+
estimatedBytesAvailable += sslInternalBufSize;
3813+
}
3814+
37753815
hasBytesAvailable = (estimatedBytesAvailable > 0);
3816+
37763817
#endif
37773818

37783819
if ((hasBytesAvailable == NO) && ([partialReadBuffer length] == 0))
@@ -4038,15 +4079,22 @@ - (void)doReadData
40384079

40394080
if (result != noErr)
40404081
{
4041-
bytesRead = 0;
4042-
40434082
if (result == errSSLWouldBlock)
40444083
waiting = YES;
40454084
else
40464085
error = [self sslError:result];
40474086

4048-
if (readIntoPartialReadBuffer)
4049-
[partialReadBuffer setLength:0];
4087+
// It's possible that bytesRead > 0, yet the result is errSSLWouldBlock.
4088+
// This happens when the SSLRead function is able to read some data,
4089+
// but not the entire amount we requested.
4090+
4091+
if (bytesRead <= 0)
4092+
{
4093+
bytesRead = 0;
4094+
4095+
if (readIntoPartialReadBuffer)
4096+
[partialReadBuffer setLength:0];
4097+
}
40504098
}
40514099

40524100
// Do not modify socketFDBytesAvailable.
@@ -5233,22 +5281,24 @@ - (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength
52335281

52345282
if (sslReadBufferLength > 0)
52355283
{
5284+
LogVerbose(@"%@: Reading from SSL pre buffer...", THIS_METHOD);
5285+
52365286
size_t bytesToCopy = (size_t)((sslReadBufferLength > totalBytesLeft) ? totalBytesLeft : sslReadBufferLength);
52375287

5238-
LogVerbose(@"Copying %u bytes from sslReadBuffer", (unsigned)bytesToCopy);
5288+
LogVerbose(@"%@: Copying %u bytes from sslReadBuffer", THIS_METHOD, (unsigned)bytesToCopy);
52395289

52405290
memcpy(buffer, [sslReadBuffer mutableBytes], bytesToCopy);
52415291

52425292
[sslReadBuffer replaceBytesInRange:NSMakeRange(0, bytesToCopy) withBytes:NULL length:0];
52435293

5244-
LogVerbose(@"sslReadBuffer.length = %lu", (unsigned long)[sslReadBuffer length]);
5294+
LogVerbose(@"%@: sslReadBuffer.length = %lu", THIS_METHOD, (unsigned long)[sslReadBuffer length]);
52455295

52465296
totalBytesLeft -= bytesToCopy;
52475297
totalBytesRead += bytesToCopy;
52485298

52495299
done = (totalBytesLeft == 0);
52505300

5251-
if (done) LogVerbose(@"SSLRead complete");
5301+
if (done) LogVerbose(@"%@: Complete", THIS_METHOD);
52525302
}
52535303

52545304
//
@@ -5257,6 +5307,8 @@ - (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength
52575307

52585308
if (!done && (socketFDBytesAvailable > 0))
52595309
{
5310+
LogVerbose(@"%@: Reading from socket...", THIS_METHOD);
5311+
52605312
int socketFD = (socket6FD == SOCKET_NULL) ? socket4FD : socket6FD;
52615313

52625314
BOOL readIntoPreBuffer;
@@ -5268,13 +5320,13 @@ - (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength
52685320
// Read all available data from socket into sslReadBuffer.
52695321
// Then copy requested amount into dataBuffer.
52705322

5323+
LogVerbose(@"%@: Reading into sslReadBuffer...", THIS_METHOD);
5324+
52715325
if ([sslReadBuffer length] < socketFDBytesAvailable)
52725326
{
52735327
[sslReadBuffer setLength:socketFDBytesAvailable];
52745328
}
52755329

5276-
LogVerbose(@"Reading into sslReadBuffer...");
5277-
52785330
readIntoPreBuffer = YES;
52795331
bytesToRead = (size_t)socketFDBytesAvailable;
52805332
buf = [sslReadBuffer mutableBytes];
@@ -5283,17 +5335,19 @@ - (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength
52835335
{
52845336
// Read available data from socket directly into dataBuffer.
52855337

5338+
LogVerbose(@"%@: Reading directly into dataBuffer...", THIS_METHOD);
5339+
52865340
readIntoPreBuffer = NO;
52875341
bytesToRead = totalBytesLeft;
52885342
buf = buffer + totalBytesRead;
52895343
}
52905344

52915345
ssize_t result = read(socketFD, buf, bytesToRead);
5292-
LogVerbose(@"read from socket = %i", (int)result);
5346+
LogVerbose(@"%@: read from socket = %i", THIS_METHOD, (int)result);
52935347

52945348
if (result < 0)
52955349
{
5296-
LogVerbose(@"read errno = %i", errno);
5350+
LogVerbose(@"%@: read errno = %i", THIS_METHOD, errno);
52975351

52985352
if (errno != EWOULDBLOCK)
52995353
{
@@ -5330,7 +5384,7 @@ - (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength
53305384
{
53315385
size_t bytesToCopy = MIN(totalBytesLeft, bytesReadFromSocket);
53325386

5333-
LogVerbose(@"Copying %u bytes from sslReadBuffer", (unsigned)bytesToCopy);
5387+
LogVerbose(@"%@: Copying %u bytes out of sslReadBuffer", THIS_METHOD, (unsigned)bytesToCopy);
53345388

53355389
memcpy(buffer + totalBytesRead, [sslReadBuffer bytes], bytesToCopy);
53365390

@@ -5340,7 +5394,7 @@ - (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength
53405394
totalBytesLeft -= bytesToCopy;
53415395
totalBytesRead += bytesToCopy;
53425396

5343-
LogVerbose(@"sslReadBuffer.length = %lu", (unsigned long)[sslReadBuffer length]);
5397+
LogVerbose(@"%@: sslReadBuffer.length = %lu", THIS_METHOD, (unsigned long)[sslReadBuffer length]);
53445398
}
53455399
else
53465400
{
@@ -5350,7 +5404,7 @@ - (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength
53505404

53515405
done = (totalBytesLeft == 0);
53525406

5353-
if (done) LogVerbose(@"SSLRead complete");
5407+
if (done) LogVerbose(@"%@: Complete", THIS_METHOD);
53545408
}
53555409
}
53565410

0 commit comments

Comments
 (0)