eventlistener.cpp   [plain text]


#include "eventlistener.h"


namespace Security {
namespace SecurityServer {

EventListener::EventListener (CssmAllocator &standard, CssmAllocator &returning) : mClientSession (standard, returning),
																				   	mMachPortRef (NULL),
																					mRunLoopSourceRef (NULL)

{
	Initialize ();
}



EventListener::~EventListener ()
{
	if (mMachPortRef != NULL)
	{
		mach_port_t mp = CFMachPortGetPort (mMachPortRef);
		mClientSession.stopNotification (mp);
		CFRelease (mMachPortRef);
	}
	
	if (mRunLoopSourceRef != NULL)
	{
		CFRelease (mRunLoopSourceRef);
	}
}



void EventListener::Callback (CFMachPortRef port, void *msg, CFIndex size, void *info)
{
	reinterpret_cast<EventListener*>(info)->HandleCallback (port, msg, size);
}



void EventListener::Initialize ()
{
	// create a callback information structure
	CFMachPortContext context = {1, this, NULL, NULL, NULL};
	
	// create the CFMachPort
	mMachPortRef = CFMachPortCreate (NULL, Callback, &context, NULL);
	if (mMachPortRef == NULL)
	{
		return;
	}
	
    // set the buffer limit for the port
	mach_port_t mp = CFMachPortGetPort (mMachPortRef);

    mach_port_limits_t limits;
    limits.mpl_qlimit = MACH_PORT_QLIMIT_MAX;
    kern_return_t result =
        mach_port_set_attributes (mach_task_self (), mp, MACH_PORT_LIMITS_INFO,
                                  mach_port_info_t (&limits), MACH_PORT_LIMITS_INFO_COUNT);

    if (result != KERN_SUCCESS)
    {
        secdebug ("notify", "Got error %d when trying to maximize queue size", result);
    }
    
	// make a run loop source for this ref
	mRunLoopSourceRef = CFMachPortCreateRunLoopSource (NULL, mMachPortRef, NULL);
	if (mRunLoopSourceRef == NULL)
	{
		CFRelease (mMachPortRef);
		return;
	}
	
	// attach this run loop source to the main run loop
	CFRunLoopAddSource (CFRunLoopGetCurrent (), mRunLoopSourceRef, kCFRunLoopDefaultMode);
	
	// extract the actual port from the run loop, and request callbacks on that port
	mClientSession.requestNotification (mp, Listener::databaseNotifications,
											Listener::allEvents);
}



void EventListener::HandleCallback (CFMachPortRef port, void *msg, CFIndex size)
{
	// we need to parse the message and see what happened
	mClientSession.dispatchNotification (reinterpret_cast<mach_msg_header_t *>(msg), ProcessMessage, this);
}



OSStatus EventListener::ProcessMessage (Listener::Domain domain, Listener::Event event, const void *data, size_t dataLength, void *context)
{
	reinterpret_cast<EventListener*>(context)->EventReceived (domain, event, data, dataLength);
	return noErr;
}



void EventListener::RequestEvents (Listener::Domain whichDomain, Listener::EventMask whichEvents)
{
	// stop the old event request and change to the new one
	mach_port_t mp = CFMachPortGetPort (mMachPortRef);
	mClientSession.stopNotification (mp);
	mClientSession.requestNotification (mp, whichDomain, whichEvents);
}



void EventListener::EventReceived (Listener::Domain domain, Listener::Event event, const void* data, size_t dataLength)
{
}



};
};