Пример #1
0
void HTTPInputSource::HandleNetworkEvent(CFReadStreamRef stream, CFStreamEventType type)
{
	switch(type) {
		case kCFStreamEventOpenCompleted:
			mOffset = mDesiredOffset;
			break;

		case kCFStreamEventHasBytesAvailable:
			if(nullptr == mResponseHeaders) {
				CFTypeRef responseHeader = CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
				if(responseHeader) {
					mResponseHeaders = CFHTTPMessageCopyAllHeaderFields(static_cast<CFHTTPMessageRef>(const_cast<void *>(responseHeader)));
					CFRelease(responseHeader), responseHeader = nullptr;
				}				
			}
			break;
		
		case kCFStreamEventErrorOccurred:
		{
			CFErrorRef error = CFReadStreamCopyError(stream);
			if(error) {
				LOGGER_ERR("org.sbooth.AudioEngine.InputSource.HTTP", "Error: " << error);
				CFRelease(error), error = nullptr;
			}
			break;
		}

		case kCFStreamEventEndEncountered:
			mEOSReached = true;
			break;
	}
}
CFDictionaryRef download_file(int socket, CFDictionaryRef dict)
{
    UInt8 buffer[8192];
    CFIndex bytesRead;

    CFStringRef path = CFDictionaryGetValue(dict, CFSTR("Path"));
    if(path == NULL || CFGetTypeID(path) != CFStringGetTypeID())
        return NULL;
    CFMutableDictionaryRef out  = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);	

    CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, FALSE);
    CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL);
    CFRelease(fileURL);
    if(!CFReadStreamOpen(stream))
    {
        CFErrorRef error = CFReadStreamCopyError(stream);
        if (error != NULL)
        {
            CFStringRef errorDesc = CFErrorCopyDescription(error);
            CFDictionaryAddValue(out, CFSTR("Error"), errorDesc);
            CFRelease(errorDesc);
            CFRelease(error);
        }
        CFRelease(stream);
        return out;
    }
    CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);

    while(CFReadStreamHasBytesAvailable(stream))
    {
        if((bytesRead = CFReadStreamRead(stream, buffer, 8192)) <= 0)
            break;
        CFDataAppendBytes(data, buffer, bytesRead);
    }
    CFReadStreamClose(stream);
    CFRelease(stream);

    CFDictionaryAddValue(out, CFSTR("Data"), data);
    CFRelease(data);

    return out;
}
Пример #3
0
void HTTPInputSource::HandleNetworkEvent(CFReadStreamRef stream, CFStreamEventType type)
{
	switch(type) {
		case kCFStreamEventOpenCompleted:
			mOffset = mDesiredOffset;
			break;

		case kCFStreamEventHasBytesAvailable:
			if(NULL == mResponseHeaders) {
				CFTypeRef responseHeader = CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
				if(responseHeader)
					mResponseHeaders = CFHTTPMessageCopyAllHeaderFields(static_cast<CFHTTPMessageRef>(const_cast<void *>(responseHeader)));
			}
			break;
		
		case kCFStreamEventErrorOccurred:
			CFShow(CFReadStreamCopyError(stream));
			break;

		case kCFStreamEventEndEncountered:
			mEOSReached = true;
			break;
	}
}
Пример #4
0
void SocketStreamHandle::readStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable: {
        if (m_connectingSubstate == WaitingForConnect) {
            if (m_connectionType == CONNECTProxy) {
                RetainPtr<CFHTTPMessageRef> proxyResponse(AdoptCF, wkCopyCONNECTProxyResponse(m_readStream.get(), m_httpsURL.get()));
                if (proxyResponse && (407 == CFHTTPMessageGetResponseStatusCode(proxyResponse.get()))) {
                    addCONNECTCredentials(proxyResponse.get());
                    return;
                }
            }
        } else 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);
            if (m_state == Closed)
                break;
            // Fall through.
        } else if (m_state == Closed)
            break;

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        CFIndex length;
        UInt8 localBuffer[1024]; // Used if CFReadStreamGetBuffer couldn't return anything.
        const UInt8* ptr = CFReadStreamGetBuffer(m_readStream.get(), 0, &length);
        if (!ptr) {
            length = CFReadStreamRead(m_readStream.get(), localBuffer, sizeof(localBuffer));
            ptr = localBuffer;
        }

        m_client->didReceiveData(this, reinterpret_cast<const char*>(ptr), length);

        break;
    }
    case kCFStreamEventCanAcceptBytes:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventErrorOccurred: {
#ifndef BUILDING_ON_TIGER
        RetainPtr<CFErrorRef> error(AdoptCF, CFReadStreamCopyError(m_readStream.get()));
        reportErrorToClient(error.get());
#else
        CFStreamError error = CFReadStreamGetError(m_readStream.get());
        m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error.
#endif
        break;
    }
    case kCFStreamEventEndEncountered:
        platformClose();
        break;
    }
}
void __CFReadStreamClientCallBack(CFReadStreamRef 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 = CFReadStreamCopyProperty(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("__CFReadStreamClientCallBack --> kCFStreamEventOpenCompleted");
            break;
        }
        case kCFStreamEventHasBytesAvailable:
        {
            tsk_size_t len = 0;
            void *buffer = 0;
            tnet_transport_event_t* e;
            
            // Allocate a standard buffer
            len = TNET_BUFFER_SIZE;
            if (!(buffer = tsk_calloc(len, sizeof(uint8_t)))) {
                TSK_DEBUG_ERROR("TSK_CALLOC FAILED.");
                break;
            }
            
            // Process to read data
            CFIndex index = CFReadStreamRead(stream, buffer, TNET_BUFFER_SIZE);
            len = index;
            
            TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> %u bytes read", len);
            
            e = tnet_transport_event_create(event_data, transport->callback_data, sock->fd);
            e->data = buffer;
            e->size = len;
            
            TSK_RUNNABLE_ENQUEUE_OBJECT(TSK_RUNNABLE(transport), e);
            
            break;
        }
        case kCFStreamEventEndEncountered:
        case kCFStreamEventErrorOccurred:
        {
            // Get the error code
            CFErrorRef error = CFReadStreamCopyError(stream);
            CFIndex index = CFErrorGetCode(error);
            CFRelease(error);
                        
            TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> 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::readStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable: {
        if (m_connectingSubstate == WaitingForConnect) {
            if (m_connectionType == CONNECTProxy) {
                RetainPtr<CFHTTPMessageRef> proxyResponse(AdoptCF, wkCopyCONNECTProxyResponse(m_readStream.get(), m_httpsURL.get()));
                if (proxyResponse) {
                    CFIndex proxyResponseCode = CFHTTPMessageGetResponseStatusCode(proxyResponse.get());
                    switch (proxyResponseCode) {
                    case 200:
                        // Successful connection.
                        break;
                    case 407:
                        addCONNECTCredentials(proxyResponse.get());
                        return;
                    default:
                        m_client->didFailSocketStream(this, SocketStreamError(static_cast<int>(proxyResponseCode), m_url.string(), "Proxy connection could not be established"));
                        platformClose();
                        return;
                    }
                }
            }
        } else if (m_connectingSubstate == WaitingForCredentials)
            break;

        if (m_connectingSubstate == WaitingForConnect) {
            m_connectingSubstate = Connected;
            m_state = Open;
            m_client->didOpenSocketStream(this);
            if (m_state == Closed)
                break;
            // Fall through.
        } else if (m_state == Closed)
            break;

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        CFIndex length;
        UInt8 localBuffer[1024]; // Used if CFReadStreamGetBuffer couldn't return anything.
        const UInt8* ptr = CFReadStreamGetBuffer(m_readStream.get(), 0, &length);
        if (!ptr) {
            length = CFReadStreamRead(m_readStream.get(), localBuffer, sizeof(localBuffer));
            ptr = localBuffer;
        }

        m_client->didReceiveSocketStreamData(this, reinterpret_cast<const char*>(ptr), length);

        break;
    }
    case kCFStreamEventCanAcceptBytes:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventErrorOccurred: {
        RetainPtr<CFErrorRef> error(AdoptCF, CFReadStreamCopyError(m_readStream.get()));
        reportErrorToClient(error.get());
        break;
    }
    case kCFStreamEventEndEncountered:
        platformClose();
        break;
    }
}
Пример #7
0
void HTTP_Stream::readCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo)
{
    HTTP_Stream *THIS = static_cast<HTTP_Stream*>(clientCallBackInfo);
    
    Stream_Configuration *config = Stream_Configuration::configuration();
    
    switch (eventType) {
        case kCFStreamEventHasBytesAvailable: {
            if (!THIS->m_httpReadBuffer) {
                THIS->m_httpReadBuffer = new UInt8[config->httpConnectionBufferSize];
            }
            
            while (CFReadStreamHasBytesAvailable(stream)) {
                if (!THIS->m_scheduledInRunLoop) {
                    /*
                     * This is critical - though the stream has data available,
                     * do not try to feed the audio queue with data, if it has
                     * indicated that it doesn't want more data due to buffers
                     * full.
                     */
                    THIS->m_readPending = true;
                    break;
                }
                
                CFIndex bytesRead = CFReadStreamRead(stream, THIS->m_httpReadBuffer, config->httpConnectionBufferSize);
                
                if (CFReadStreamGetStatus(stream) == kCFStreamStatusError ||
                    bytesRead < 0) {
                    
#if defined (HS_DEBUG)
                    CFErrorRef streamError = CFReadStreamCopyError(stream);
                    
                    if (streamError) {
                        CFStringRef errorDesc = CFErrorCopyDescription(streamError);
                        
                        if (errorDesc) {
                            HS_TRACE_CFSTRING(errorDesc);
                            
                            CFRelease(errorDesc);
                        }
                        
                        CFRelease(streamError);
                    }
#endif /* HS_DEBUG */
                    
                    if (THIS->m_delegate) {
                        THIS->m_delegate->streamErrorOccurred();
                    }
                    break;
                }
                
                if (bytesRead > 0) {
                    HS_TRACE("Read %li bytes\n", bytesRead);
                    
                    THIS->parseHttpHeadersIfNeeded(THIS->m_httpReadBuffer, bytesRead);
                    
    #ifdef INCLUDE_ID3TAG_SUPPORT
                    if (!THIS->m_icyStream && THIS->m_id3Parser->wantData()) {
                        THIS->m_id3Parser->feedData(THIS->m_httpReadBuffer, (UInt32)bytesRead);
                    }
    #endif
                    
                    if (THIS->m_icyStream) {
                        HS_TRACE("Parsing ICY stream\n");
                        
                        THIS->parseICYStream(THIS->m_httpReadBuffer, bytesRead);
                    } else {
                        if (THIS->m_delegate) {
                            HS_TRACE("Not an ICY stream; calling the delegate back\n");
                            
                            THIS->m_delegate->streamHasBytesAvailable(THIS->m_httpReadBuffer, (UInt32)bytesRead);
                        }
                    }
                }
            }
                
            break;
        }
        case kCFStreamEventEndEncountered: {
            if (THIS->m_delegate) {
                THIS->m_delegate->streamEndEncountered();
            }
            break;
        }
        case kCFStreamEventErrorOccurred: {
            if (THIS->m_delegate) {
                THIS->m_delegate->streamErrorOccurred();
            }
            break;
        }
    }
}