コード例 #1
0
/*****************************************************************************
* CreateBrowser
* -
* This method returns a NetBrowserInfo that is looking for a type of
* service in a domain. If no browser exists, it will create one and return it.
*****************************************************************************/
NetBrowserInfo* CreateBrowser(BonjourUserEventsPlugin* plugin, CFStringRef type, CFStringRef domain)
{
    CFIndex i;
    CFIndex count = CFDictionaryGetCount(plugin->_browsers);
    NetBrowserInfo* browser = NULL;
    CFDictionaryRef* dicts = malloc(count * sizeof(CFDictionaryRef));
    NetBrowserInfo** browsers = malloc(count * sizeof(NetBrowserInfo*));

    // Fetch the values of the browser dictionary
    CFDictionaryGetKeysAndValues(plugin->_browsers, (const void**)browsers, (const void**)dicts);


    // Loop thru the browsers list and see if we can find a matching one.
    for (i = 0; i < count; ++i)
    {
        CFDictionaryRef browserDict = dicts[i];

        CFStringRef browserType = CFDictionaryGetValue(browserDict, sServiceTypeKey);
        CFStringRef browserDomain = CFDictionaryGetValue(browserDict, sServiceDomainKey);

        // If we have a matching browser, break
        if ((CFStringCompare(browserType, type, kCFCompareCaseInsensitive) == kCFCompareEqualTo) &&
            (CFStringCompare(browserDomain, domain, kCFCompareCaseInsensitive) == kCFCompareEqualTo))
        {
            asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: found a duplicate browser\n", sPluginIdentifier, __FUNCTION__);
            browser = browsers[i];
            NetBrowserInfoRetain(NULL, browser);
            break;
        }
    }

    // No match found, lets create one!
    if (!browser)
    {

        browser = NetBrowserInfoCreate(type, domain, plugin);

        if (!browser)
        {
            fprintf(stderr, "%s:%s failed to search for %s.%s", sPluginIdentifier, __FUNCTION__, CStringFromCFString(type), CStringFromCFString(domain));
            free(dicts);
            free(browsers);
            return NULL;
        }

        // Service browser created, lets add this to ourselves to the dictionary.
        CFMutableDictionaryRef browserDict = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

        CFDictionarySetValue(browserDict, sServiceTypeKey, type);
        CFDictionarySetValue(browserDict, sServiceDomainKey, domain);

        // Add the dictionary to the browsers dictionary.
        CFDictionarySetValue(plugin->_browsers, browser, browserDict);

        NetBrowserInfoRelease(NULL, browser);

        // Release Memory
        CFRelease(browserDict);
    }

    free(dicts);
    free(browsers);

    return browser;
}
コード例 #2
0
/*****************************************************************************
 * AddEventToPlugin
 * - 
 * This method is invoked when launchd wishes the plugin to setup a launch 
 * event matching the parameters in the dictionary.
 *****************************************************************************/
void AddEventToPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken, CFDictionaryRef eventParameters)
{
	CFStringRef		domain = CFDictionaryGetValue(eventParameters, sServiceDomainKey);
	CFStringRef		type = CFDictionaryGetValue(eventParameters, sServiceTypeKey);
	CFStringRef		name = CFDictionaryGetValue(eventParameters, sServiceNameKey);
	CFBooleanRef	cfOnAdd = CFDictionaryGetValue(eventParameters, sOnServiceAddKey);
	CFBooleanRef	cfOnRemove = CFDictionaryGetValue(eventParameters, sOnServiceRemoveKey);
	CFBooleanRef    cfWhileSericeExists = CFDictionaryGetValue(eventParameters, sWhileServiceExistsKey);
	
	Boolean			onAdd = false;
	Boolean			onRemove = false;
	Boolean			whileExists = false;
	
	if (cfOnAdd && CFGetTypeID(cfOnRemove) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnAdd))
		onAdd = true;
	
	if (cfOnRemove && CFGetTypeID(cfOnRemove) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnRemove))
		onRemove = true;
	
	if (cfWhileSericeExists && CFGetTypeID(cfWhileSericeExists) == CFBooleanGetTypeID() && CFBooleanGetValue(cfWhileSericeExists))
		whileExists = true;
	
	// A type is required. If none is specified, BAIL
	if (!type || CFGetTypeID(type) != CFStringGetTypeID()) 
	{
		fprintf(stderr, "%s, a LaunchEvent is missing a service type.\n", sPluginIdentifier);
		return;
	}
	
	// If we aren't suppose to launch on services appearing or disappearing, this service does nothing. Ignore.
	if ((!onAdd && !onRemove && !whileExists) || (onAdd && onRemove && whileExists))
	{
		fprintf(stderr, "%s, a LaunchEvent is missing both onAdd/onRemove/existance or has both.\n", sPluginIdentifier);
		return;
	}

	// If no domain is specified, assume local.
	if (!domain)
	{
		domain = CFSTR("local"); 
	}
	else if (CFGetTypeID(domain) != CFStringGetTypeID() ) // If the domain is not a string, fai;
	{
		fprintf(stderr, "%s, a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier);
		return;
	}

	
	// If we have a name filter, but it's not a string. This event it broken, bail.
	if (name && CFGetTypeID(name) != CFStringGetTypeID())
	{
		fprintf(stderr, "%s, a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier);
		return;
	}
	
	// Get us a browser
	NetBrowserInfo* browser = CreateBrowserForTypeAndDomain(plugin, type, domain);
	
	if (!browser)
	{
		fprintf(stderr, "%s, a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier);
		return;
	}
	
	// Create Event Dictionary
	CFMutableDictionaryRef eventDictionary = CFDictionaryCreateMutable(NULL, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
	
	
	CFDictionarySetValue(eventDictionary, sLaunchdTokenKey, launchdToken);
	
	if (name)
		CFDictionarySetValue(eventDictionary, sServiceNameKey, name);
	
	// Add to the correct dictionary.
	if (onAdd)
		AddEventDictionary(eventDictionary, plugin->_onAddEvents, browser);
	
	if (onRemove)
		AddEventDictionary(eventDictionary, plugin->_onRemoveEvents, browser);
	
	if (whileExists)
		AddEventDictionary(eventDictionary, plugin->_whileServiceExist, browser);
	
	// Add Token Mapping
	CFDictionarySetValue(plugin->_tokenToBrowserMap, launchdToken, browser);
	
	// Release Memory
	CFRelease(eventDictionary);
	NetBrowserInfoRelease(NULL, browser);
	
}
コード例 #3
0
/*****************************************************************************
* RemoveEventFromPlugin
* -
* This method is invoked when launchd wishes the plugin to setup a launch
* event matching the parameters in the dictionary.
*****************************************************************************/
void RemoveEventFromPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken)
{
    NetBrowserInfo* browser = (NetBrowserInfo*)CFDictionaryGetValue(plugin->_tokenToBrowserMap, launchdToken);
    Boolean othersUsingBrowser = false;

    if (!browser)
    {
        long long value = 0;
        CFNumberGetValue(launchdToken, kCFNumberLongLongType, &value);
        fprintf(stderr, "%s:%s Launchd asked us to remove a token we did not register! ==Token:%lld== \n", sPluginIdentifier, __FUNCTION__, value);
        return;
    }

    CFMutableArrayRef onAddEvents = (CFMutableArrayRef)CFDictionaryGetValue(plugin->_onAddEvents, browser);
    CFMutableArrayRef onRemoveEvents = (CFMutableArrayRef)CFDictionaryGetValue(plugin->_onRemoveEvents, browser);

    if (onAddEvents)
    {
        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Calling RemoveEventFromArray for OnAddEvents", sPluginIdentifier, __FUNCTION__);
        RemoveEventFromArray(onAddEvents, launchdToken);

        // Is the array now empty, clean up
        if (CFArrayGetCount(onAddEvents) == 0)
        {
            asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Removing the browser from AddEvents", sPluginIdentifier, __FUNCTION__);
            CFDictionaryRemoveValue(plugin->_onAddEvents, browser);
        }
    }

    if (onRemoveEvents)
    {
        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Calling RemoveEventFromArray for OnRemoveEvents", sPluginIdentifier, __FUNCTION__);
        RemoveEventFromArray(onRemoveEvents, launchdToken);

        // Is the array now empty, clean up
        if (CFArrayGetCount(onRemoveEvents) == 0)
        {
            asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Removing the browser from RemoveEvents", sPluginIdentifier, __FUNCTION__);
            CFDictionaryRemoveValue(plugin->_onRemoveEvents, browser);
        }
    }

    // Remove ourselves from the token dictionary.
    CFDictionaryRemoveValue(plugin->_tokenToBrowserMap, launchdToken);

    // Check to see if anyone else is using this browser.
    CFIndex i;
    CFIndex count = CFDictionaryGetCount(plugin->_tokenToBrowserMap);
    NetBrowserInfo** browsers = malloc(count * sizeof(NetBrowserInfo*));

    // Fetch the values of the token dictionary
    CFDictionaryGetKeysAndValues(plugin->_tokenToBrowserMap, NULL, (const void**)browsers);

    for (i = 0; i < count; ++i)
    {
        if (NetBrowserInfoEqual(browsers[i], browser))
        {
            othersUsingBrowser = true;
            break;
        }
    }

    // If no one else is useing our browser, clean up!
    if (!othersUsingBrowser)
    {
        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Removing browser %p from _browsers", sPluginIdentifier, __FUNCTION__, browser);
        CFDictionaryRemoveValue(plugin->_browsers, browser); // This triggers release and dealloc of the browser
    }
    else
    {
        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Decrementing browsers %p count", sPluginIdentifier, __FUNCTION__, browser);
        // Decrement my reference count (it was incremented when it was added to _browsers in CreateBrowser)
        NetBrowserInfoRelease(NULL, browser);
    }

    free(browsers);
}