void __CFWriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) { // Extract the context tnet_transport_t *transport = (tnet_transport_t *) clientCallBackInfo; transport_context_t *context = transport->context; /* lock context */ tsk_safeobj_lock(context); // Extract the native socket CFDataRef data = CFWriteStreamCopyProperty(stream, kCFStreamPropertySocketNativeHandle); CFSocketNativeHandle fd; CFDataGetBytes(data, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8*) &fd); CFRelease(data); transport_socket_t *sock = (transport_socket_t *) getSocket(context, fd); switch(eventType) { case kCFStreamEventOpenCompleted: { TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> kCFStreamEventOpenCompleted"); if (TNET_SOCKET_TYPE_IS_SECURE(sock->type)) { #if !TARGET_OS_IPHONE SSLContextRef sslContext = NULL; data = CFWriteStreamCopyProperty(stream, kCFStreamPropertySocketSSLContext); CFDataGetBytes(data, CFRangeMake(0, sizeof(SSLContextRef)), (UInt8*) &sslContext); CFRelease(data); // TODO: Set the client certificates #endif } break; } case kCFStreamEventEndEncountered: case kCFStreamEventErrorOccurred: { // Get the error code CFErrorRef error = CFWriteStreamCopyError(stream); CFIndex index = CFErrorGetCode(error); CFRelease(error); TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> Error %lu", index); TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, sock->fd); removeSocket(sock, context); break; } default: { // Not Implemented assert(42 == 0); break; } } /* unlock context */ tsk_safeobj_unlock(context); }
void SocketStreamHandle::writeStreamCallback(CFStreamEventType type) { switch(type) { case kCFStreamEventNone: break; case kCFStreamEventOpenCompleted: break; case kCFStreamEventHasBytesAvailable: ASSERT_NOT_REACHED(); break; case kCFStreamEventCanAcceptBytes: { // Possibly, a spurious event from CONNECT handshake. if (!CFWriteStreamCanAcceptBytes(m_writeStream.get())) return; if (m_connectingSubstate == WaitingForCredentials) break; if (m_connectingSubstate == WaitingForConnect) { m_connectingSubstate = Connected; m_state = Open; RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference. m_client->didOpen(this); break; } ASSERT(m_state == Open); ASSERT(m_connectingSubstate == Connected); sendPendingData(); break; } case kCFStreamEventErrorOccurred: { #ifndef BUILDING_ON_TIGER RetainPtr<CFErrorRef> error(AdoptCF, CFWriteStreamCopyError(m_writeStream.get())); reportErrorToClient(error.get()); #else CFStreamError error = CFWriteStreamGetError(m_writeStream.get()); m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error. #endif break; } case kCFStreamEventEndEncountered: // FIXME: Currently, we handle closing in read callback, but these can come independently (e.g. a server can stop listening, but keep sending data). break; } }
void SocketStreamHandle::writeStreamCallback(CFStreamEventType type) { switch(type) { case kCFStreamEventNone: break; case kCFStreamEventOpenCompleted: break; case kCFStreamEventHasBytesAvailable: ASSERT_NOT_REACHED(); break; case kCFStreamEventCanAcceptBytes: { // Possibly, a spurious event from CONNECT handshake. if (!CFWriteStreamCanAcceptBytes(m_writeStream.get())) return; if (m_connectingSubstate == WaitingForCredentials) break; if (m_connectingSubstate == WaitingForConnect) { m_connectingSubstate = Connected; m_state = Open; m_client->didOpenSocketStream(this); break; } ASSERT(m_state == Open); ASSERT(m_connectingSubstate == Connected); sendPendingData(); break; } case kCFStreamEventErrorOccurred: { RetainPtr<CFErrorRef> error(AdoptCF, CFWriteStreamCopyError(m_writeStream.get())); reportErrorToClient(error.get()); break; } case kCFStreamEventEndEncountered: // FIXME: Currently, we handle closing in read callback, but these can come independently (e.g. a server can stop listening, but keep sending data). break; } }