I have some Python code I’m trying to translate to Obj-C/Cocoa. It requires a network connection; the initialization string is sent in plaintext then the connection is secured.
Basically, it works like this:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host,port))
sock.send( ... )
sock.recv( ... )
sslSock = ssl.wrap_socket(sock)
sslSock.send( ... )
sslSock.recv( ...)
So far, I have the following. First I create the socket connection and the R/W streams:
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)HOST, PORT, &readStream, &writeStream);
inputStream = (NSInputStream *)readStream;
[inputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
outputStream = (NSOutputStream *)writeStream;
[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
When the NSStreamEventOpenCompleted is sent, I store the native socket handle:
NSSocketNativeHandle *socketHandle = [[outputStream propertyForKey:(NSString *)kCFStreamPropertySocketNativeHandle] bytes];
I handle the NSStreamEventHasBytesAvailable and NSStreamEventHasSpaceAvailable events, as appropriate. Then create two new streams from the stored socket handle, and set the SSL properties:
[inputStream close];
[outputStream close];
[inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
CFStreamCreatePairWithSocket(kCFAllocatorDefault, *socketHandle, &readStream, &writeStream);
inputStream = (NSInputStream *)readStream;
[inputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream setProperty:NSStreamSocketSecurityLevelSSLv3 forKey:NSStreamSocketSecurityLevelKey];
outputStream = (NSOutputStream *)writeStream;
[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream setProperty:NSStreamSocketSecurityLevelSSLv3 forKey:NSStreamSocketSecurityLevelKey];
[inputStream open];
[outputStream open];
And this is as far as I get. The NSStreamEventOpenCompleted event is called on both of the new streams, but NSStreamEventHasBytesAvailable and NSStreamEventHasSpaceAvailable events are never raised. Any ideas what I’m doing wrong?
Looks like my problem was two-fold.
When creating a connection via
CFStreamCreatePairWithSocketToHost, thekCFStreamPropertyShouldCloseNativeSocketproperty is set to TRUE automatically. It should be FALSE.I wasn’t setting up SSL correctly.