Пример #1
0
void HTTP_Stream::parseICYStream(const UInt8 *buf, const CFIndex bufSize)
{
    HS_TRACE("Parsing an IceCast stream, received %li bytes\n", bufSize);
    
    CFIndex offset = 0;
    CFIndex bytesFound = 0;
    if (!m_icyHeadersRead) {
        HS_TRACE("ICY headers not read, reading\n");
        
        for (; offset < bufSize; offset++) {
            if (m_icyHeaderCR && buf[offset] == '\n') {
                if (bytesFound > 0) {
                    m_icyHeaderLines.push_back(createMetaDataStringWithMostReasonableEncoding(&buf[offset-bytesFound-1], bytesFound));
                    
                    bytesFound = 0;
                    
                    HS_TRACE_CFSTRING(m_icyHeaderLines[m_icyHeaderLines.size()-1]);
                    
                    continue;
                }
                
                HS_TRACE("End of ICY headers\n");
                
                m_icyHeadersRead = true;
                break;
            }
            
            if (buf[offset] == '\r') {
                m_icyHeaderCR = true;
                continue;
            } else {
                m_icyHeaderCR = false;
            }
            
            bytesFound++;
        }
    } else if (!m_icyHeadersParsed) {
        HS_TRACE("ICY headers not parsed, parsing\n");
        
        const CFStringRef icyContentTypeHeader = CFSTR("content-type:");
        const CFStringRef icyMetaDataHeader    =  CFSTR("icy-metaint:");
        const CFStringRef icyNameHeader        = CFSTR("icy-name:");

        const CFIndex icyContenTypeHeaderLength = CFStringGetLength(icyContentTypeHeader);
        const CFIndex icyMetaDataHeaderLength   = CFStringGetLength(icyMetaDataHeader);
        const CFIndex icyNameHeaderLength       = CFStringGetLength(icyNameHeader);
        
        for (std::vector<CFStringRef>::iterator h = m_icyHeaderLines.begin(); h != m_icyHeaderLines.end(); ++h) {
            CFStringRef line = *h;
            const CFIndex lineLength = CFStringGetLength(line);
            
            if (lineLength == 0) {
                continue;
            }
            
            HS_TRACE_CFSTRING(line);
            
            if (CFStringCompareWithOptions(line,
                                           icyContentTypeHeader,
                                           CFRangeMake(0, icyContenTypeHeaderLength),
                                           0) == kCFCompareEqualTo) {
                if (m_contentType) {
                    CFRelease(m_contentType), m_contentType = 0;
                }
                m_contentType = CFStringCreateWithSubstring(kCFAllocatorDefault,
                                                            line,
                                                            CFRangeMake(icyContenTypeHeaderLength, lineLength - icyContenTypeHeaderLength));
                
            }
            
            if (CFStringCompareWithOptions(line,
                                           icyMetaDataHeader,
                                           CFRangeMake(0, icyMetaDataHeaderLength),
                                           0) == kCFCompareEqualTo) {
                CFStringRef metadataInterval = CFStringCreateWithSubstring(kCFAllocatorDefault,
                                                                           line,
                                                                           CFRangeMake(icyMetaDataHeaderLength, lineLength - icyMetaDataHeaderLength));
                
                if (metadataInterval) {
                    m_icyMetaDataInterval = CFStringGetIntValue(metadataInterval);
                    
                    CFRelease(metadataInterval);
                } else {
                    m_icyMetaDataInterval = 0;
                }
            }
            
            if (CFStringCompareWithOptions(line,
                                           icyNameHeader,
                                           CFRangeMake(0, icyNameHeaderLength),
                                           0) == kCFCompareEqualTo) {
                if (m_icyName) {
                    CFRelease(m_icyName);
                }
                
                m_icyName = CFStringCreateWithSubstring(kCFAllocatorDefault,
                                                        line,
                                                        CFRangeMake(icyNameHeaderLength, lineLength - icyNameHeaderLength));
            }
        }
        
        m_icyHeadersParsed = true;
        offset++;
        
        if (m_delegate) {
            m_delegate->streamIsReadyRead();
        }
    }
    
    Stream_Configuration *config = Stream_Configuration::configuration();
    
    if (!m_icyReadBuffer) {
        m_icyReadBuffer = new UInt8[config->httpConnectionBufferSize];
    }
    
    HS_TRACE("Reading ICY stream for playback\n");
    
    UInt32 i=0;
    
    for (; offset < bufSize; offset++) {
        // is this a metadata byte?
        if (m_metaDataBytesRemaining > 0) {
            m_metaDataBytesRemaining--;
            
            if (m_metaDataBytesRemaining == 0) {
                m_dataByteReadCount = 0;
                
                if (m_delegate && !m_icyMetaData.empty()) {
                    std::map<CFStringRef,CFStringRef> metadataMap;
                    
                    CFStringRef metaData = createMetaDataStringWithMostReasonableEncoding(&m_icyMetaData[0],
                                                                                          m_icyMetaData.size());
                    
                    if (!metaData) {
                        // Metadata encoding failed, cannot parse.
                        m_icyMetaData.clear();
                        continue;
                    }
                    
                    CFArrayRef tokens = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault,
                                                                               metaData,
                                                                               CFSTR(";"));
                    
                    for (CFIndex i=0, max=CFArrayGetCount(tokens); i < max; i++) {
                        CFStringRef token = (CFStringRef) CFArrayGetValueAtIndex(tokens, i);
                        
                        CFRange foundRange;
                        
                        if (CFStringFindWithOptions(token,
                                                    CFSTR("='"),
                                                    CFRangeMake(0, CFStringGetLength(token)),
                                                    NULL,
                                                    &foundRange) == true) {
                            
                            CFRange keyRange = CFRangeMake(0, foundRange.location);
                            
                            CFStringRef metadaKey = CFStringCreateWithSubstring(kCFAllocatorDefault,
                                                                                token,
                                                                                keyRange);
                            
                            CFRange valueRange = CFRangeMake(foundRange.location + 2, CFStringGetLength(token) - keyRange.length - 3);
                            
                            CFStringRef metadaValue = CFStringCreateWithSubstring(kCFAllocatorDefault,
                                                                                  token,
                                                                                  valueRange);
                            
                            metadataMap[metadaKey] = metadaValue;
                        }
                    }
                    
                    CFRelease(tokens);
                    CFRelease(metaData);
                    
                    if (m_icyName) {
                        metadataMap[CFSTR("IcecastStationName")] = CFStringCreateCopy(kCFAllocatorDefault, m_icyName);
                    }
                    
                    m_delegate->streamMetaDataAvailable(metadataMap);
                }
                m_icyMetaData.clear();
                continue;
            }
            
            m_icyMetaData.push_back(buf[offset]);
            continue;
        }
        
        // is this the interval byte?
        if (m_icyMetaDataInterval > 0 && m_dataByteReadCount == m_icyMetaDataInterval) {
            m_metaDataBytesRemaining = buf[offset] * 16;
            
            if (m_metaDataBytesRemaining == 0) {
                m_dataByteReadCount = 0;
            }
            continue;
        }
        
        // a data byte
        m_dataByteReadCount++;
        m_icyReadBuffer[i++] = buf[offset];
    }
    
    if (m_delegate && i > 0) {
        m_delegate->streamHasBytesAvailable(m_icyReadBuffer, i);
    }
}
Пример #2
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();
    
    CFStringRef reportedNetworkError = NULL;
    
    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) {
                    
                    CFErrorRef streamError = CFReadStreamCopyError(stream);
                    
                    if (streamError) {
                        CFStringRef errorDesc = CFErrorCopyDescription(streamError);
                        
                        if (errorDesc) {
                            reportedNetworkError = CFStringCreateCopy(kCFAllocatorDefault, errorDesc);
                            
                            CFRelease(errorDesc);
                        }
                        
                        CFRelease(streamError);
                    }
                    
                    if (THIS->m_delegate) {
                        THIS->m_delegate->streamErrorOccurred(reportedNetworkError);
                        
                        if (reportedNetworkError) {
                            CFRelease(reportedNetworkError), reportedNetworkError = NULL;
                        }
                    }
                    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);
                        }
                    }
                }
            }
            
            if (reportedNetworkError) {
                CFRelease(reportedNetworkError), reportedNetworkError = NULL;
            }
            
            break;
        }
        case kCFStreamEventEndEncountered: {
            if (THIS->m_delegate) {
                THIS->m_delegate->streamEndEncountered();
            }
            break;
        }
        case kCFStreamEventErrorOccurred: {
            if (THIS->m_delegate) {
                CFStringRef reportedNetworkError = NULL;
                CFErrorRef streamError = CFReadStreamCopyError(stream);
                
                if (streamError) {
                    CFStringRef errorDesc = CFErrorCopyDescription(streamError);
                    
                    if (errorDesc) {
                        reportedNetworkError = CFStringCreateCopy(kCFAllocatorDefault, errorDesc);
                        
                        CFRelease(errorDesc);
                    }
                    
                    CFRelease(streamError);
                }
                
                THIS->m_delegate->streamErrorOccurred(reportedNetworkError);
                if (reportedNetworkError) {
                    CFRelease(reportedNetworkError);
                }
            }
            break;
        }
    }
}
Пример #3
0
void APSetHash(CFStringRef newHash)
{
    if (hash != NULL)
        CFRelease(hash);
    hash = CFStringCreateCopy(kCFAllocatorDefault, newHash);
}
Пример #4
0
void HTTP_Stream::parseHttpHeadersIfNeeded(const UInt8 *buf, const CFIndex bufSize)
{
    if (m_httpHeadersParsed) {
        return;
    }
    m_httpHeadersParsed = true;
    
    /* If the response has the "ICY 200 OK" string,
     * we are dealing with the ShoutCast protocol.
     * The HTTP headers won't be available.
     */
    if (bufSize >= 10 &&
        buf[0] == 0x49 && buf[1] == 0x43 && buf[2] == 0x59 &&
        buf[3] == 0x20 && buf[4] == 0x32 && buf[5] == 0x30 &&
        buf[6] == 0x30 && buf[7] == 0x20 && buf[8] == 0x4F &&
        buf[9] == 0x4B) {
        m_icyStream = true;
        
        HS_TRACE("Detected an IceCast stream\n");
        
        // This is an ICY stream, don't try to parse the HTTP headers
        return;
    }
    
    HS_TRACE("A regular HTTP stream\n");
    
    CFHTTPMessageRef response = (CFHTTPMessageRef)CFReadStreamCopyProperty(m_readStream, kCFStreamPropertyHTTPResponseHeader);
    if (response) {
        /*
         * If the server responded with the icy-metaint header, the response
         * body will be encoded in the ShoutCast protocol.
         */
        CFStringRef icyMetaIntString = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("icy-metaint"));
        if (icyMetaIntString) {
            m_icyStream = true;
            m_icyHeadersParsed = true;
            m_icyHeadersRead = true;
            m_icyMetaDataInterval = CFStringGetIntValue(icyMetaIntString);
            CFRelease(icyMetaIntString);
        }
        
        HS_TRACE("icy-metaint: %zu\n", m_icyMetaDataInterval);
        
        CFStringRef icyNameString = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("icy-name"));
        if (icyNameString) {
            if (m_icyName) {
                CFRelease(m_icyName);
            }
            m_icyName = icyNameString;
            
            if (m_delegate) {
                std::map<CFStringRef,CFStringRef> metadataMap;
                
                metadataMap[CFSTR("IcecastStationName")] = CFStringCreateCopy(kCFAllocatorDefault, m_icyName);
                
                m_delegate->streamMetaDataAvailable(metadataMap);
            }
        }
        
        if (m_contentType) {
            CFRelease(m_contentType);
        }
        
        m_contentType = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Type"));
        
        HS_TRACE("Content-type: ");
        HS_TRACE_CFSTRING(m_contentType);
        
        CFStringRef contentLengthString = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Length"));
        if (contentLengthString) {
            m_contentLength = CFStringGetIntValue(contentLengthString);
            
            CFRelease(contentLengthString);
        }
        
        CFRelease(response);
    }
       
    if (m_delegate) {
        m_delegate->streamIsReadyRead();
    }
}
Пример #5
0
CFStringRef APHash(void)
{
    return CFStringCreateCopy(kCFAllocatorDefault, hash);
}
Boolean
SCBondInterfaceSetLocalizedDisplayName(SCBondInterfaceRef bond, CFStringRef newName)
{
	SCNetworkInterfacePrivateRef	interfacePrivate	= (SCNetworkInterfacePrivateRef)bond;
	Boolean				ok			= TRUE;

	if (!isA_SCBondInterface(bond)) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	if ((newName != NULL) && !isA_CFString(newName)) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	// set name in the stored preferences
	if (interfacePrivate->prefs != NULL) {
		CFDictionaryRef		dict;
		CFMutableDictionaryRef	newDict;
		CFStringRef		path;

		path = CFStringCreateWithFormat(NULL,
						NULL,
						CFSTR("/%@/%@/%@"),
						kSCPrefVirtualNetworkInterfaces,
						kSCNetworkInterfaceTypeBond,
						interfacePrivate->entity_device);
		dict = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
		if (!isA_CFDictionary(dict)) {
			// if the prefs are confused
			CFRelease(path);
			_SCErrorSet(kSCStatusFailed);
			return FALSE;
		}

		newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
		if (newName != NULL) {
			CFDictionarySetValue(newDict, kSCPropUserDefinedName, newName);
		} else {
			CFDictionaryRemoveValue(newDict, kSCPropUserDefinedName);
		}
		if (!CFEqual(dict, newDict)) {
			ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
		}
		CFRelease(newDict);
		CFRelease(path);
	}

	// set name in the SCBondInterfaceRef
	if (ok) {
		if (interfacePrivate->localized_name != NULL) {
			CFRelease(interfacePrivate->localized_name);
			interfacePrivate->localized_name = NULL;
		}
		if (newName != NULL) {
			interfacePrivate->localized_name = CFStringCreateCopy(NULL, newName);
		}
	}

	return ok;
}
Пример #7
0
                         SOSErrorCreate(kSOSErrorBadSignature, error, NULL,
                                        CFSTR("Signature didn't verify for %@"), peer));
    result = true;

error_out:
    CFReleaseNull(pubKey);
    return result;
}

static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error, void (^ description_modifier)(CFMutableDictionaryRef description)) {
    SOSPeerInfoRef pi = CFTypeAllocate(SOSPeerInfo, struct __OpaqueSOSPeerInfo, allocator);
    pi->gestalt = gestalt;
    CFRetain(pi->gestalt);
    
    pi->version = SOSPeerInfoGetPeerProtocolVersion(pi);
    pi->transportType = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("KVS"));
    CFDataRef publicBytes = NULL;
    CFNumberRef versionNumber = NULL;

    SecKeyRef publicKey = SecKeyCreatePublicFromPrivate(signingKey);
    if (publicKey == NULL) {
        SOSCreateError(kSOSErrorBadKey, CFSTR("Unable to get public"), NULL, error);
        CFReleaseNull(pi);
        goto exit;
    }

    OSStatus result = SecKeyCopyPublicBytes(publicKey, &publicBytes);
    
    if (result != errSecSuccess) {
        SOSCreateError(kSOSErrorBadKey, CFSTR("Failed to export public bytes"), NULL, error);
        CFReleaseNull(pi);
Пример #8
0
static CFStringRef
copyVPNInterfaceNAP (char *interface_buf)
{
	CFStringRef       interf_key;
	CFMutableArrayRef interf_keys;
	CFDictionaryRef   dict = NULL;
	CFIndex           i;
	const void *      keys_q[128];
	void **           keys = (__typeof__(keys))keys_q;
	const void *      values_q[128];
	void **           values = (__typeof__(values))values_q;
	CFIndex           n;
	CFStringRef       vpn_if =  NULL;
	CFStringRef       result = NULL;

	if (!interface_buf) {
		return NULL;
	}

	if (gDynamicStore) {
		vpn_if = CFStringCreateWithCStringNoCopy(NULL,
												 interface_buf,
												 kCFStringEncodingASCII,
												 kCFAllocatorNull);
		if (!vpn_if) {
			// if we could not initialize interface CFString
			goto done;
		}
		
		interf_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		// get State:/Network/Interface/<vpn_if>/Airport
		interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
																   kSCDynamicStoreDomainState,
																   vpn_if,
																   kSCEntNetAirPort);
		CFArrayAppendValue(interf_keys, interf_key);
		CFRelease(interf_key);
		dict = SCDynamicStoreCopyMultiple(gDynamicStore, interf_keys, NULL);
		CFRelease(interf_keys);
		
		if (!dict) {
			// if we could not access the SCDynamicStore
			goto done;
		}
		// look for the service which matches the provided prefixes
		n = CFDictionaryGetCount(dict);
		if (n <= 0) {
			goto done;
		}
		if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
			keys   = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
			values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
		}
		CFDictionaryGetKeysAndValues(dict, (const void **)keys, (const void **)values);
		for (i=0; i < n; i++) {
			CFStringRef     s_key  = (CFStringRef)keys[i];
			CFDictionaryRef s_dict = (CFDictionaryRef)values[i];
			CFDictionaryRef i_dict = NULL;
			CFStringRef     nap;
			
			if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) {
				continue;
			}

			i_dict = CFDictionaryGetValue(s_dict, KEY_VPNNETWORKLOCATION_INTERFINFO);
			if (!isA_CFDictionary(i_dict)) {
				continue;
			}

			nap = CFDictionaryGetValue(i_dict, KEY_VPNNETWORKLOCATION_SSID);
			if (nap) {
				result = CFStringCreateCopy(NULL, nap);
				SCLog(TRUE, LOG_INFO, CFSTR("%s: found nap %@, interf %s"), __FUNCTION__, result, interface_buf);
				goto done;
			}
		}
		done :
		if (vpn_if) CFRelease(vpn_if);
		if (keys != (__typeof__(keys))keys_q) {
			CFAllocatorDeallocate(NULL, keys);
			CFAllocatorDeallocate(NULL, values);
		}
		if (dict) CFRelease(dict);
	}
	return result;
}
Пример #9
0
void
AddNeighborhoodToList(char * neighborhood, UInt32 parentID)
{
    CFStringRef tempNeighborhood = NULL;
    CFComparisonResult result = -1;
    UInt32 neighborhoodID, i;
    
    
    if (neighborhood)
    {
        tempNeighborhood = CFStringCreateWithCString(NULL, neighborhood, CFStringGetSystemEncoding());
        if (tempNeighborhood)
        {
            // Check if the item is already in our list.  If it is, "result" will be kCFCompareEqualTo.
            for (i = 0; i < kMaxNeighborhoods; i++)
            {
                if (gData[i] && gNeighborhoodInfo.parentID[i] == parentID)
                {
                    result = CFStringCompare(tempNeighborhood, gData[i], kCFCompareCaseInsensitive);
                    if (result == kCFCompareEqualTo) break;
                }
            }        
            
            if (result != kCFCompareEqualTo)
            {
                // Only add the item if the parent neighborhood is open and visible in the Data Browser.
            	if ((gNeighborhoodInfo.isNeighborhoodOpen[parentID - 1] && gNeighborhoodInfo.isNeighborhoodVisible[parentID - 1]) || parentID == 0)
            	{
                    neighborhoodID = IncrementAtomic(&gNeighborhoodInfo.neighborhoodCount); 
                    
                    if (++neighborhoodID < kMaxNeighborhoods)
                    {   
                        gNeighborhoodInfo.parentID[neighborhoodID - 1] = parentID;
                        gData[neighborhoodID - 1] = CFStringCreateCopy(NULL, tempNeighborhood);
                    
                        AddDataBrowserItems(gDataBrowserControl, parentID, 1, &neighborhoodID, kNameColumn);
                    
                        if (parentID == kDataBrowserNoItem)
                        {
                            gNeighborhoodInfo.isDefaultNeighborhood[neighborhoodID - 1] = true;
                        }
                        else
                        {
                            gNeighborhoodInfo.isDefaultNeighborhood[neighborhoodID - 1] = false;
                        }                    
                    }
                    else
                    {
                        DecrementAtomic(&gNeighborhoodInfo.neighborhoodCount);
                    }
                }
            }
            else if (result == kCFCompareEqualTo)
            {   
                if (gNeighborhoodInfo.isNeighborhoodOpen[parentID - 1] && gNeighborhoodInfo.isNeighborhoodVisible[parentID - 1])
                {
                    neighborhoodID = i + 1;
                    
                    if (gNeighborhoodInfo.isNeighborhoodVisible[i] == false)
                    {
                    	AddDataBrowserItems(gDataBrowserControl, parentID, 1, &neighborhoodID, kNameColumn);
                	
                        if (gNeighborhoodInfo.isNeighborhoodOpen[i])
                        {
                            OpenDataBrowserContainer(gDataBrowserControl, neighborhoodID);	                        
                        }
                    }
                    else
                    {
                    	if (gNeighborhoodInfo.isNeighborhoodOpen[i])
                    	{
                            CancelServicesLookup(parentID);
                            CancelNeighborhoodLookup(parentID);
                            
                            InstallEventLoopTimer(GetMainEventLoop(), 0.3, 0, gMyStartLookupTimerUPP, (void *)(neighborhoodID), NULL);
                        }
                    }
                }
            }

            CFRelease(tempNeighborhood);
        		
        	
        }
        free(neighborhood);
    }
}