[39569] branches/gsoc08-framework/MacPorts_Framework_Release

armahg at macports.org armahg at macports.org
Sun Aug 24 22:53:02 PDT 2008


Revision: 39569
          http://trac.macosforge.org/projects/macports/changeset/39569
Author:   armahg at macports.org
Date:     2008-08-24 22:53:02 -0700 (Sun, 24 Aug 2008)
Log Message:
-----------
Removed IPC server code from MPNotifications files.

Modified Paths:
--------------
    branches/gsoc08-framework/MacPorts_Framework_Release/MPHelperTool.m
    branches/gsoc08-framework/MacPorts_Framework_Release/MPInterpreter.m
    branches/gsoc08-framework/MacPorts_Framework_Release/MPNotifications.h
    branches/gsoc08-framework/MacPorts_Framework_Release/MPNotifications.m

Modified: branches/gsoc08-framework/MacPorts_Framework_Release/MPHelperTool.m
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework_Release/MPHelperTool.m	2008-08-25 05:36:55 UTC (rev 39568)
+++ branches/gsoc08-framework/MacPorts_Framework_Release/MPHelperTool.m	2008-08-25 05:53:02 UTC (rev 39569)
@@ -495,13 +495,6 @@
 	//asl may be null
 	//aslMsg may be null
 	
-	//Set the file Descriptor here
-	NSNumber * num = (NSNumber *) (CFNumberRef) CFDictionaryGetValue(request, CFSTR(kServerFileDescriptor));
-	notificationsFileDescriptor = [num intValue];
-	asl_NSLog(asl, aslMsg, ASL_LEVEL_DEBUG, @"Setting file descriptor with value %i", notificationsFileDescriptor);
-	if (notificationsFileDescriptor > 0) {
-		hasSetFileDescriptor = YES;
-	}
 	
 	//Get the string that was passed in the request dictionary
 	NSString *  tclCmd = (NSString *) (CFStringRef)CFDictionaryGetValue(request, CFSTR(kTclStringToBeEvaluated));
@@ -693,14 +686,14 @@
 		asl_NSLog(logClient , logMsg, ASL_LEVEL_DEBUG, @"MPHelperTool: NOT calling DoShout");
 	asl_close(logClient);
 	
-    
+    // Clean up.
+    ConnectionClose(conn);
 	
 	
 	int result = BASHelperToolMain(kMPHelperCommandSet, kMPHelperCommandProcs);
 	
-	// Clean up.
-    ConnectionClose(conn);
 	
+	
 	[pool release];
 	
 	return result;

Modified: branches/gsoc08-framework/MacPorts_Framework_Release/MPInterpreter.m
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework_Release/MPInterpreter.m	2008-08-25 05:36:55 UTC (rev 39568)
+++ branches/gsoc08-framework/MacPorts_Framework_Release/MPInterpreter.m	2008-08-25 05:53:02 UTC (rev 39569)
@@ -429,18 +429,13 @@
 	NSString * interpInitPath = [[NSBundle bundleForClass:[MPInterpreter class]] 
 								 pathForResource:@"interpInit" ofType:@"tcl"];
 	
-	int serverFileDesc = [[MPNotifications sharedListener] getServerFileDescriptor];
 	
-	if (serverFileDesc < 0)
-		NSLog(@"Uninitialized file descriptor for HelperTool IPC");
 	
-	
 	request = [NSDictionary dictionaryWithObjectsAndKeys:
 			   @kMPHelperEvaluateTclCommand, @kBASCommandKey,
 			   statement, @kTclStringToBeEvaluated, 
 			   tclInterpreterPkgPath, @kTclInterpreterInitPath ,
-			   interpInitPath, @kInterpInitFilePath,
-			   [NSNumber numberWithInt:serverFileDesc], @kServerFileDescriptor, nil];
+			   interpInitPath, @kInterpInitFilePath, nil];
 	
 	assert(request != NULL);
 	

Modified: branches/gsoc08-framework/MacPorts_Framework_Release/MPNotifications.h
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework_Release/MPNotifications.h	2008-08-25 05:36:55 UTC (rev 39568)
+++ branches/gsoc08-framework/MacPorts_Framework_Release/MPNotifications.h	2008-08-25 05:53:02 UTC (rev 39569)
@@ -73,13 +73,7 @@
 #define MPALL @"MPAllNotification"
 
 
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <string.h>
 
-
 /*!
  @class MPNotifications
  @abstract A class to handle notifying Framework clients of port activity
@@ -95,10 +89,6 @@
 	NSFileHandle * readHandle;
 	
 	//BSD sockets stuff
-	NSString * serverFilePath;
-	int sd1, rc;
-	struct sockaddr_un serveraddr;
-	BOOL hasSetFileDescriptor;
 	BOOL terminateBackgroundThread;
 	
 }
@@ -143,7 +133,6 @@
 //These methods aren't for the public ... yet ...
 -(void)setPerformingTclCommand:(NSString *)string;
 -(NSString *)performingTclCommand;
--(int) getServerFileDescriptor;
 
 
 @end

Modified: branches/gsoc08-framework/MacPorts_Framework_Release/MPNotifications.m
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework_Release/MPNotifications.m	2008-08-25 05:36:55 UTC (rev 39568)
+++ branches/gsoc08-framework/MacPorts_Framework_Release/MPNotifications.m	2008-08-25 05:53:02 UTC (rev 39569)
@@ -36,1329 +36,9 @@
 
 #import "MPNotifications.h"
 
-#pragma mark MPNotifications Server Code - I
-//Things will get ugly ... before they can get beautiful ...
-/*
- File:       Server.c
- 
- Contains:   Server showing integration of CFSockets and UNIX domain sockets.
- 
- Written by: DTS
- 
- Copyright:  Copyright (c) 2005 by Apple Computer, Inc., All Rights Reserved.
- 
- Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms.  If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
- 
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software.  Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple.  Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
- 
- The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
- 
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- 
- Change History (most recent first):
- 
- $Log: Server.c,v $
- Revision 1.2  2005/05/18 13:36:39         
- Fixed various documentation/comment changes.
- 
- Revision 1.1  2005/05/17 12:19:32         
- First checked in.
- 
- 
- */
 
-/////////////////////////////////////////////////////////////////
 
-// System interfaces
 
-#include <stdlib.h>
-#include <assert.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-
-
-#include "MPHelperNotificationsCommon.h"
-#include "MPHelperNotificationsProtocol.h"
-
-/////////////////////////////////////////////////////////////////
-#pragma mark ***** Client State Management
-
-// The server maintains a ClientState structure to track the state of 
-// each client.  This state divides neatly into three groups.
-//
-// o socket -- fSockFD, fSockCF, and fRunLoopSource all represent different 
-//   aspects of the UNIX domain socket that we're using to talk to the client.
-//
-// o incoming -- fBufferedData is a buffer containing any incomplete packets that 
-//   we've received from the client.
-//
-// o outgoing -- fPendingSends and fPendingSendOffset control the packets that 
-//   are waiting to be sent to the client.  This list might get long if the 
-//   client stops listening to us.  Packets will first back up in the UNIX 
-//   domain socket's socket buffer.  Once that fills up we won't be able to 
-//   write to the socket anymore.  We respond to that by buffering the 
-//   packets on the fPendingSends list.  We also tell CFSocket to let us know 
-//   (with a kCFSocketWriteCallBack event) if space becomes available.
-//
-//   At this point one of two things will happen.  Either we'll buffer too 
-//   many packets for the client (kClientMaximumPendingSends) in which case 
-//   we'll kill the client.  Or the client will start receiving packets again, 
-//   which will start to empty the socket buffer.  CFSocket will tells about 
-//   this by sending us a kCFSocketWriteCallBack event, and we'll start 
-//   pulling packets off the fPendingSends list and writing them to the socket.
-
-enum {
-    kClientStateMagic = 'LSCM'               // for Local Server Client Magic
-};
-
-struct ClientState {
-    OSType              fMagic;             // kClientStateMagic
-    int                 fSockFD;            // UNIX domain socket to client
-    CFSocketRef         fSockCF;            // CFSocket wrapper for the above
-    CFRunLoopSourceRef  fRunLoopSource;     // runloop source for the above
-    CFMutableDataRef    fBufferedData;      // buffers data for incomplete incoming packets
-    CFMutableArrayRef   fPendingSends;      // list of packets waiting to be sent
-    size_t              fPendingSendOffset; // offset of next byte to send in first packet on list
-    Boolean             fListening;         // true if this client is a listener
-};
-typedef struct ClientState ClientState;
-
-// To prevent a deaf client from sucking down all of our memory, we limit the 
-// number of packets that we'll buffer for a given client.  If the length of 
-// fPendingSends exceeds kClientMaximumPendingSends, we'll kill the client rather 
-// than queue more data.
-
-enum {
-    kClientMaximumPendingSends = 100
-};
-
-// gClients is a set of all clients we know about.
-
-static CFMutableSetRef gClients = NULL;		// of (ClientState *)
-
-#pragma mark Misc
-
-static Boolean ClientCheckPacketSize(ClientState *client, const PacketHeader *packet, size_t requiredSize)
-// Checks that a packet that has arrived from a client is of the 
-// appropriate size.  Returns false, and prints a message, if it isn't.
-{
-    Boolean result;
-    
-    assert(client != NULL);
-    assert(packet != NULL);
-    assert(requiredSize >= sizeof(PacketHeader));
-    
-    result = true;
-    if (packet->fSize != requiredSize) {
-        fprintf(
-				stderr, 
-				"ClientCheckPacketSize: Client %p sent us a '%.4s' of the wrong size (got %" PRIu32 ", wanted %zu).\n", 
-				client, 
-				(char *) &packet->fType, 
-				packet->fSize, 
-				requiredSize
-				);
-        result = false;
-    }
-    return result;
-}
-
-static Boolean ClientCheckPacketID(ClientState *client, const PacketHeader *packet, int32_t requiredID)
-// Checks that a packet that has arrived from a client has the 
-// correct ID.  Returns false, and prints a message, if it doesn't.
-{
-    Boolean result;
-	
-    assert(client != NULL);
-    assert(packet != NULL);
-    
-    result = true;
-    if (packet->fID != requiredID) {
-        fprintf(
-				stderr, 
-				"ClientCheckPacketID: Client %p sent us a '%.4s' with the wrong ID (got %" PRId32 ", wanted %" PRId32 ").\n", 
-				client, 
-				(char *) &packet->fType, 
-				packet->fID, 
-				requiredID
-				);
-        result = false;
-    }
-    return result;
-}
-
-// Forward declarations
-
-static void ClientGotSpace(ClientState *client);
-static void ClientGotData(ClientState *client, const void *data);
-
-static void ClientEvent(
-						CFSocketRef             s, 
-						CFSocketCallBackType    type, 
-						CFDataRef               address, 
-						const void *            data, 
-						void *                  info
-)
-// This is the CFSocket event callback for client sockets.  For a description 
-// of the parameters, see the CFSocket documentation.
-//
-// This routine responds to two events, kCFSocketDataCallBack and 
-// kCFSocketWriteCallBack, dispatching them to ClientGotData and 
-// ClientGotSpace, respectively.
-{
-#pragma unused(address)
-	ClientState *	client;
-	
-    assert(s != NULL);
-	
-    client = (ClientState *) info;
-    assert(client != NULL);
-    assert(client->fMagic == kClientStateMagic);
-    
-    switch (type) {
-        case kCFSocketDataCallBack:
-            ClientGotData(client, data);
-            break;
-        case kCFSocketWriteCallBack:
-            ClientGotSpace(client);
-            break;
-        default:
-            assert(false);
-            break;
-    }
-}
-
-#pragma mark Create/Destroy
-
-static void ClientDestroy(ClientState *client);
-
-static int ClientInitialise(void)
-// Initialises the client management layer, which simply involves 
-// creating an empty gClients set.
-{
-	int err;
-	
-	err = 0;
-	gClients = CFSetCreateMutable(NULL, 0, NULL);
-	if (gClients == NULL) {
-		err = ENOMEM;
-	}
-	return err;
-}
-
-static void ClientTerminate(void)
-// Shuts down the client management layer.  This involves destroying 
-// any remaining clients and disposing of gClients.
-{
-	CFIndex             clientCount;
-	CFIndex             clientIndex;
-	ClientState **      allClients;
-	
-    if (gClients != NULL) {
-		// Can't use CFSetApplyFunction because the ClientDestroy modifies 
-		// the gClients set.
-		
-		clientCount = CFSetGetCount(gClients);
-		
-		allClients = calloc(clientCount, sizeof(ClientState *));
-		if (allClients == NULL) {
-			fprintf(stderr, "CFLocalServer: Could not clean up clients because we couldn't allocate memory.\n");
-		} else {
-			CFSetGetValues(gClients, (const void **) allClients);
-			
-			for (clientIndex = 0; clientIndex < clientCount; clientIndex++) {
-				fprintf(stderr, "CFLocalServer: Client %p killed because we're quitting.\n", allClients[clientIndex]);
-				
-				ClientDestroy( allClients[clientIndex] );
-			}
-		}
-		
-		free(allClients);
-		
-		CFRelease(gClients);
-		gClients = NULL;
-    }
-}
-
-static int ClientCreate(int clientSockFD, ClientState **clientPtr)
-// Creates a new client that communicates over clientSockFD. 
-// If clientPtr is not NULL, it returns a pointer to the 
-// client state record in *clientPtr.
-//
-// clientSockFD must be a valid file descriptor referencing a 
-// socket that's connected to the client
-// On input, if clientPtr is not NULL, *clientPtr must be NULL
-// Returns an errno-style error code
-// On success, if clientPtr is not NULL, *clientPtr will not be NULL
-// On success, clientSockFD is owned by the new client; the caller 
-// need not close it
-// On error, if clientPtr is not NULL, *clientPtr will be NULL
-// On error, clientSockFD will have been closed.
-//
-// IMPORTANT:
-// Regardless of whether this routine succeeds or fails, it assumes 
-// responsibility for clientSockFD.  The caller is never required to 
-// close it.
-{
-    int             err;
-    int             junk;
-    ClientState *   client;
-    
-    assert( (clientPtr == NULL) || (*clientPtr == NULL) );
-    
-    assert(gClients != NULL);
-    
-    // Create the client state record.
-    
-    err = 0;
-    client = (ClientState *) calloc(1, sizeof(*client));
-    if (client == NULL) {
-        err = ENOMEM;
-    }
-	
-    // Fill in the easy fields.  This also prepares us for the clean up 
-    // on failure.
-    
-    if (err == 0) {
-        client->fMagic = kClientStateMagic;
-		
-        // For clean up to work properly, we must make sure that, if 
-        // the connection record is allocated successfully, we always 
-        // set fSockFD to the incoming clientSockFD.
-		
-        client->fSockFD = clientSockFD;
-        
-        client->fBufferedData = CFDataCreateMutable(NULL, 0);
-        client->fPendingSends = CFArrayCreateMutable(NULL, 0, NULL);
-		
-        if ( (client->fBufferedData == NULL) || (client->fPendingSends == NULL) ) {
-            err = ENOMEM;
-        }
-    }
-    
-    // Make the socket non-blocking.  We need to do this because 
-    // otherwise ClientSendPending can get stuck in a write.
-    
-    if (err == 0) {
-        err = MoreUNIXSetNonBlocking(client->fSockFD);
-    }
-    
-    // Wrap the socket in a CFSocket, and create and install the run loop source.
-    
-    if (err == 0) {
-        CFSocketContext context;
-        
-        memset(&context, 0, sizeof(context));
-        context.info = client;
-        
-        client->fSockCF = CFSocketCreateWithNative(
-												   NULL, 
-												   (CFSocketNativeHandle) client->fSockFD, 
-												   kCFSocketDataCallBack + kCFSocketWriteCallBack, 
-												   ClientEvent, 
-												   &context
-												   );
-        if (client->fSockCF == NULL) {
-            err = EINVAL;
-        }
-    }
-	
-    if (err == 0) {
-        client->fRunLoopSource = CFSocketCreateRunLoopSource(NULL, client->fSockCF, 0);
-        if (client->fRunLoopSource == NULL) {
-            err = EINVAL;
-        }
-    }
-    if (err == 0) {
-        CFRunLoopAddSource( CFRunLoopGetCurrent(), client->fRunLoopSource, kCFRunLoopDefaultMode);
-        
-        assert( ! CFSetContainsValue(gClients, client) );
-        
-        // It's all good.  Record that this client exists.
-        
-        CFSetAddValue(gClients, client);
-    }
-    
-    // Clean up.
-    
-    if (err != 0) {
-        fprintf(stderr, "ClientCreate: Error %d creating client.\n", err);
-		
-        // If client is NULL, we couldn't allocate a client record, therefore 
-        // we had nowhere to record clientSockFD, therefore ClientDestroy won't 
-        // clean it up.  Thus, we have to do it ourselves.
-        
-        if (client == NULL) {
-            junk = close(clientSockFD);
-            assert(junk == 0);
-        } else {
-            ClientDestroy(client);
-        }
-        client = NULL;
-    }
-    if (clientPtr != NULL) {
-        *clientPtr = client;
-    }
-    
-    assert( (clientPtr == NULL) || ((err == 0) == (*clientPtr != NULL)) );
-	
-    return err;
-}
-
-static void ClientDestroy(ClientState *client)
-// Destroys a client.  This is called in a number of different circumstances, 
-// but these basically boil down to:
-// 
-// a) if ClientCreate fails, it's called to destroy the partially-created client, 
-// b) if some sort of communications error happens, it's called to destroy the 
-//    client,
-// c) if the client sends us a goodbye packet, this is called to destroy the client, and 
-// d) on quit, all clients are destroyed.
-{
-    int     junk;
-    
-    assert(client != NULL);
-    assert(client->fMagic == kClientStateMagic);
-	
-    // This following assert is NOT true.  If the client dies before it 
-    // gets fully started (that is, we get an error halfway through 
-    // ClientCreate), ClientDestroy is called to tidy up the mess but 
-    // the client hasn't been added into gClients yet.
-    
-    // assert( CFSetContainsValue(gClients, client) );
-    
-    // Remove the client our record of existant clients.
-    
-    CFSetRemoveValue(gClients, client);
-    
-    // Clean up the runloop source and CFSocket.
-    
-    if (client->fRunLoopSource != NULL) {
-        CFRunLoopSourceInvalidate(client->fRunLoopSource);
-        
-        CFRelease(client->fRunLoopSource);
-    }
-    if (client->fSockCF != NULL) {
-        CFSocketInvalidate(client->fSockCF);
-        
-        CFRelease(client->fSockCF);
-    }
-    
-    // Close the socket itself, but only if we don't have a corresponding 
-    // CFSocket; if a CFSocket was created, it takes over responsibility 
-    // for closing the socket.
-    
-    if ( (client->fSockFD != -1) && (client->fSockCF == NULL) ) {
-        junk = close(client->fSockFD);
-        assert(junk == 0);
-    }
-    
-    // Free any packets waiting to go out to this client.
-    
-    if (client->fPendingSends != NULL) {
-        CFIndex index;
-        CFIndex count;
-		
-        count = CFArrayGetCount(client->fPendingSends);
-        for (index = 0; index < count; index++) {
-            free( (void *) CFArrayGetValueAtIndex(client->fPendingSends, index) );
-        }
-        CFRelease(client->fPendingSends);
-    }
-    
-    // Free any buffered data from this client.
-    
-    if (client->fBufferedData != NULL) {
-        CFRelease(client->fBufferedData);
-    }
-    
-    // Free the client state record itself.
-    
-    client->fMagic = 'FRE!';
-    free(client);
-}
-
-#pragma mark Send
-
-static int ClientSendPending(ClientState *client)
-// This routine attempts to send any packets that are queued in the fSendPending 
-// array.  It is somewhat complex.  There are three possible final results.
-//
-// o It successfully sends all packets in the queue.  In this case it returns 0.
-//
-// o The write side of the socket is full (flow controlled).  In this case the 
-//   function enables the socket write callback (kCFSocketWriteCallBack, using 
-//   CFSocketEnableCallBacks) and returns 0.  When socket buffer empties a little, 
-//   CFSocket will send us the kCFSocketWriteCallBack event and we'll resume sending.
-//
-// o It fails for some other reasons (for example, the other end of the socket has 
-//   been closed, causing an EPIPE).  In this case it returns an errno-style error 
-//   indicating the failure.  The caller typically responds by destroying the client.
-//
-// This whole process is further complicated by the possibilty that the socket 
-// buffer might have enough space for half a packet.  In this case you'll get a 
-// short write, that is, write will return a positive number less than its nbytes 
-// parameter.  To handle this case we record the offset into the packet of the first 
-// byte of unwritten data.  When we go to send a packet, we always send from there. 
-// When write accepts some data, we bump the offset by that amount.  If that 
-// completes the send of the packet, we start on next packet, resetting the offset 
-// back to 0.
-{
-    int                     err;
-    Boolean                 done;
-    const PacketHeader *    thisPacket;
-    ssize_t                 bytesWritten;
-    
-    err = 0;
-    
-    // Keep going until we've sent all pending packets for this client.
-    
-    while ( (err == 0) && (CFArrayGetCount(client->fPendingSends) != 0) ) {
-        thisPacket = (const PacketHeader *) CFArrayGetValueAtIndex(client->fPendingSends, 0);
-        
-        // Try to send this packet by writing it to the socket.
-        
-        done = false;
-        do {
-            bytesWritten = write(
-								 client->fSockFD, 
-								 ((char *) thisPacket) + client->fPendingSendOffset, 
-								 thisPacket->fSize - client->fPendingSendOffset
-								 );
-            
-            if (bytesWritten > 0) {
-                // We're written some bytes.  Adjust fPendingSendOffset by 
-                // that amount and see if that completes the packet.
-                
-                client->fPendingSendOffset += bytesWritten;
-                
-                if (client->fPendingSendOffset == thisPacket->fSize) {
-                    // Packet complete.  Delete it from the head of the 
-                    // send list, reset offset back to 0, and let's go 
-                    // deal with the next packet.
-                    
-                    CFArrayRemoveValueAtIndex(client->fPendingSends, 0);
-                    free( (void *) thisPacket);
-                    client->fPendingSendOffset = 0;
-                    done = true;
-                } else {
-                    // Packet still not fully sent.  The send offset has already 
-                    // been updated, so we just loop to try again.
-                }
-            } else if (bytesWritten == -1) {
-                // We got some sort of error.
-                
-                err = errno;
-                switch (err) {
-                    case EINTR:
-                        // Interrupted.  Do nothing, so we loop and retry this 
-                        // send immediately.
-						
-                        err = 0;
-                        break;
-                    case EAGAIN:
-                        // Flow controlled.  Break out of the loop with an EAGAIN 
-                        // error; we try again when space becomes available.
-						
-                        fprintf(stderr, "ClientSendPending: Client %p write-side flow control.\n", client);
-                        
-                        // Tell the CFSocket that we now /really/ need to be told about 
-                        // write space becoming available.  Without this we'll never 
-                        // recover if the client stops accepting messages temporarily 
-                        // (which causes the socket buffer to fill up and us to get an 
-                        // EAGAIN) and then starts accepting messages again.  At that 
-                        // point the client will drain the socket buffer, but we'll never 
-                        // hear about it because CFSocket doesn't know that we care 
-                        // about write space.  With this call CFSocket knows that we 
-                        // care, and will send us an kCFSocketWriteCallBack event if 
-                        // space becomes available in the socket buffer.
-                        
-                        CFSocketEnableCallBacks(client->fSockCF, kCFSocketWriteCallBack);
-                        break;
-                    default:
-                        // Errored.  Our response is typically draconian: 
-                        // we return the error to our caller, which then kills the client 
-                        // completely.
-						
-                        fprintf(stderr, "ClientSendPending: Client %p killed because of send error (%d).\n", client, err);
-                        break;
-                }
-            } else {
-                assert(false);
-            }
-        } while ( (err == 0) && ! done );
-    }
-    
-    // As far as the caller is concerned, write-side flow control is not an error.
-    
-    if (err == EAGAIN) {
-        err = 0;
-    }
-    
-    return err;
-}
-
-static Boolean ClientSend(ClientState *client, const PacketHeader *packet)
-// Called in various places to send a packet to a client.  
-// This adds it to the send queue and then calls ClientSendPending 
-// to attempt a send.
-{
-    Boolean         result;
-    PacketHeader *  copiedPacket;
-    
-    assert(client != NULL);
-    assert(packet != NULL);
-    assert(packet->fSize >= sizeof(PacketHeader));
-	
-    // If we've buffered kClientMaximumPendingSends already, the client is 
-    // just not reading them.  To avoid us consuming all of our memory buffering 
-    // packets for a deaf client, we just kill the client.
-    
-    result = true;
-    if ( CFArrayGetCount(client->fPendingSends) >= kClientMaximumPendingSends ) {
-        fprintf(stderr, "ClientSend: Client %p killed because of too many outstanding sends.\n", client);
-        
-        result = false;
-    }
-	
-    // Copy the packet data, append that copy to the send queue, and then 
-    // give it a kick.
-    //
-    // The memory allocated here will be freed when the packet is succesfully 
-    // sent (SendPending), or the client is destroy.
-    
-    if (result) {
-        copiedPacket = (PacketHeader *) malloc(packet->fSize);
-        result = (copiedPacket != NULL);
-    }
-    if (result) {
-        memcpy(copiedPacket, packet, packet->fSize);
-        
-        CFArrayAppendValue(client->fPendingSends, copiedPacket);
-        
-        result = ( ClientSendPending(client) == 0 );
-    }
-	
-    return result;
-}
-
-static Boolean ClientSendReply(ClientState *client, const PacketHeader *request, int errNum)
-// Send an RPC reply packet to the client.  You must supply request 
-// because it forms the basis of many of the fields in the reply. 
-// You also have to supply errNum, which is an errno-style error 
-// indicating the fate of the request.
-{
-    PacketReply     response;
-	
-    assert(client  != NULL);
-    assert(request != NULL);
-	
-    InitPacketHeader(&response.fHeader, kPacketTypeReply, sizeof(response), false);
-    // Copy the ID from the request packet, overriding the fID set by InitPacketHeader.
-    response.fHeader.fID    = request->fID;
-    response.fErr = errNum;
-	
-    return ClientSend(client, &response.fHeader);
-}
-
-static void ClientGotSpace(ClientState *client)
-// This routine is called by ClientEvent when it receives the kCFSocketWriteCallBack 
-// event, indicating that there is space to write in the client's socket buffer. 
-// It calls ClientSendPending to process any packets that are waiting to be sent.  
-// In most cases this does nothing because the client send queue is empty.  However, 
-// if the client goes deaf, so the socket buffer becomes write-side flow controlled, 
-// packets can back up in the send queue.  When the client starts receiving packets 
-// again, space becomes available in the socket buffer and CFSocket sends us the 
-// kCFSocketWriteCallBack.  We respond to that by resuming our sends.
-{
-    int             err;
-	
-	assert(client != NULL);
-    
-    fprintf(stderr, "ClientGotSpace: Client %p lifted write-side flow control.\n", client);
-	
-    err = ClientSendPending(client);
-	
-	// If the sending failed for any reason (except flow control, for which 
-	// ClientSendPending mutates the EAGAIN status to a 0) we kill the client.
-	
-    if (err != 0) {
-        ClientDestroy(client);
-    }
-}
-
-#pragma mark Receive
-
-// The receive engine is based around ClientGotData, which is the routine that gets 
-// called when new data arrives, and a variety of packet handlers for processing 
-// specific types of packets and that all have the same form.
-//
-// A packet handle routine takes two parameters, the client and the packet, neither 
-// of which can be NULL, and does the work to process that packet.  This typically 
-// involves checking that the packet is valid, doing the job requested by the packet, 
-// and then, if the packet is for an RPC, sending the reply.
-//
-// If the packet handler returns false, the caller (ClientGotData) assumes that 
-// something was seriously wrong with the packet and kills the connection to the 
-// client.  A packet handler typically does this if the packet itself is malformed; 
-// if the job requested by the packet can't be done (for example, there might not 
-// be enough memory), the packet handler wouldn't return false but would, instead, 
-// send an error status back to the client in the RPC reply.
-
-static Boolean ClientGoodbye(ClientState *client, PacketGoodbye *packet)
-// A packet handler for the Goodbye packet.  See the large comment above for 
-// a discussion of the general form of a packet handler.
-//
-// A Goodbye packet is sent by the client to indicate to us that it's closing 
-// its end of the connection.
-{
-    Boolean     result;
-    
-    assert(client != NULL);
-    assert(packet != NULL);
-    
-    result = ClientCheckPacketSize(client, &packet->fHeader, sizeof(PacketGoodbye));
-    if ( result ) {
-        result = ClientCheckPacketID(client, &packet->fHeader, kPacketIDNone);
-    }
-    
-    if (result) {
-        // During reliability print all of the goodbyes proved to be too verbose, 
-        // so I've disabled it for now.
-        
-        if (false) {
-            fprintf(stderr, "%p: Goodbye (%.*s).\n", client, (int) sizeof(packet->fMessage), packet->fMessage);
-        }
-        
-        // Unlike most packet handlers, we return false on success.  This is because 
-		// the Goodbye packet tells us that the client has gone away, and thus we 
-		// need to kill the client.  It turns out that returning false does the job 
-		// without us having to write any special code.
-        
-        result = false;
-    }
-    
-    return result;
-}
-
-static Boolean ClientNOP(ClientState *client, PacketNOP *packet)
-// A packet handler for the NOP packet.  See the large comment above for 
-// a discussion of the general form of a packet handler.
-//
-// A NOP RPC does nothing; it's used to test client/server connection.
-{
-    Boolean     result;
-    
-    result = ClientCheckPacketSize(client, &packet->fHeader, sizeof(PacketNOP));
-    
-    if (result) {
-        fprintf(stderr, "%p: NOP\n", client);
-        
-        result = ClientSendReply(client, &packet->fHeader, 0);
-    }
-    
-    return result;
-}
-
-static Boolean ClientWhisper(ClientState *client, PacketWhisper *packet)
-// A packet handler for the Whisper packet.  See the large comment above for 
-// a discussion of the general form of a packet handler.
-//
-// A Whisper RPC causes the server to print the associated message.
-{
-    Boolean result;
-    
-    result = ClientCheckPacketSize(client, &packet->fHeader, sizeof(PacketWhisper));
-    if (result) {
-        fprintf(stderr, "%p: Whisper \"%.*s\"\n", client, (int) sizeof(packet->fMessage), packet->fMessage);
-		
-        result = ClientSendReply(client, &packet->fHeader, 0);
-    }
-    
-    return result;
-}
-
-static Boolean ClientShout(ClientState *client, PacketShout *packet)
-// A packet handler for the Shout packet.  See the large comment above for 
-// a discussion of the general form of a packet handler.
-//
-// A Shout packet causes the server to echo the message (in the form 
-// of a Shout packet) to every client that has registered as a listener.
-{
-    Boolean     result;
-    Boolean     sendResult;
-    
-    result = ClientCheckPacketSize(client, &packet->fHeader, sizeof(PacketShout));
-    if (result) {
-        result = ClientCheckPacketID(client, &packet->fHeader, kPacketIDNone);
-    }
-	
-	// The Shout packet is good.  Let's echo it to each listener.
-	
-    if (result) {
-        ClientState  ** allClients;
-        CFIndex         clientCount;
-        CFIndex         clientIndex;
-		
-        fprintf(stderr, "%p: Shout   \"%.*s\"\n", client, (int) sizeof(packet->fMessage), packet->fMessage);
-		
-		NSString * shout = [NSString stringWithCString:packet->fMessage encoding:NSUTF8StringEncoding];
-		NSLog(@"CLIENT SHOUT BEING CALLED (YAAAY!!) : %@" , shout);
-        
-        // We make a snapshot of the client list because clients might disappear 
-        // as we talk to them.  That is, the act of talking to the client might 
-        // cause us to notice that the client is dead.
-        
-        clientCount = CFSetGetCount(gClients);
-        
-        allClients = calloc(clientCount, sizeof(ClientState *));
-        if (allClients == NULL) {
-            fprintf(stderr, "ClientShout: Shout from %p failed because we couldn't allocate memory.\n", client);
-        } else {
-            CFSetGetValues(gClients, (const void **) allClients);
-            
-			// Iterate through the array of clients, sending the Shout packet to each.
-			
-            for (clientIndex = 0; clientIndex < clientCount; clientIndex++) {
-                ClientState *  thisClient;
-                
-                thisClient = allClients[clientIndex];
-                if (thisClient->fListening) {
-                    sendResult = ClientSend(thisClient, &packet->fHeader);
-                    
-                    // Fun fun fun.  If we're sending to ourselves, we return the result 
-                    // of the send as our function result, which, if there's a failure, 
-                    // will trigger ClientGotData to clean us up.  OTOH, if we're sending 
-                    // to another client, we're responsible for cleaning up if there's 
-                    // a failure.
-                    
-                    if (thisClient == client) {
-                        result = sendResult;
-                    } else {
-                        if ( ! sendResult ) {
-                            fprintf(stderr, "ClientShout: Shout from %p to %p failed.\n", client, thisClient);
-                            
-                            ClientDestroy(thisClient);
-                        }
-                    }
-                }
-            }
-        }
-		
-        free(allClients);
-    }
-    return result;
-}
-
-static Boolean ClientListen(ClientState *client, PacketListen *packet)
-// A packet handler for the Listen packet.  See the large comment above for 
-// a discussion of the general form of a packet handler.
-//
-// A Listen RPC tells the server that the client wants to hear about shouted 
-// messages.
-{
-    Boolean     result;
-    
-    result = ClientCheckPacketSize(client, &packet->fHeader, sizeof(PacketListen));
-    if (result) {
-        if (client->fListening) {
-            fprintf(stderr, "ClientListen: Redundant Listen from %p.\n", client);
-        } else {
-            fprintf(stderr, "%p: Listen\n", client);
-        }
-        client->fListening = true;
-        
-        result = ClientSendReply(client, &packet->fHeader, 0);
-    }
-    
-    return result;
-}
-
-static Boolean ClientQuit(ClientState *client, PacketQuit *packet)
-// A packet handler for the Quit packet.  See the large comment above for 
-// a discussion of the general form of a packet handler.
-//
-// A Quit RPC causes the server to quit.
-{
-    Boolean     result;
-    
-    result = ClientCheckPacketSize(client, &packet->fHeader, sizeof(PacketQuit));
-    if (result) {
-        fprintf(stderr, "%p: Quit\n", client);
-        
-        // Stop the main event loop.
-        
-        CFRunLoopStop( CFRunLoopGetCurrent() );
-        
-        // This reply should go out immediately.  If the client, for some reason, 
-        // is flow controlled, it may not see the response.  But really, that's 
-        // the client's fault (-:
-        
-        result = ClientSendReply(client, &packet->fHeader, 0);
-    }
-    
-    return result;
-}
-
-static void ClientGotData(ClientState *client, const void *data)
-// This routine is called by ClientEvent when it receives the kCFSocketDataCallBack 
-// event, indicating that CFSocket has read data from the socket.  The routine 
-// appends the data to the receive buffer (fBufferedData) and then looks through 
-// the receive buffer for complete packets.  For each complete packet it finds, 
-// it calls the packet handler (the various routines above) to process the packet 
-// and then it deletes the packet from the front of the receive buffer.
-// 
-// data is the data read for us by CFSocket.  It's actually a CFDataRef 
-// but, because we're being called from a generic CFSocket event handler, 
-// it's of type (const void *).  We have to do the cast here.
-{
-    CFDataRef       newData;
-	
-	assert(client != NULL);
-    
-    newData = (CFDataRef) data;
-    assert(newData != NULL);
-    assert( CFGetTypeID(newData) == CFDataGetTypeID() );
-	
-    if ( CFDataGetLength(newData) == 0 ) {
-        // A zero length data indicates the end of the data stream; the client is dead 
-		// so we just go and remove our record of it.
-        
-        fprintf(stderr, "ClientGotData: Client %p died unexpectedly.\n", client);
-        
-        ClientDestroy(client);
-    } else {
-		
-        // Append the new data to whatever data we have already buffered 
-        // (most likely nothing).
-        
-        CFDataAppendBytes(client->fBufferedData, CFDataGetBytePtr(newData), CFDataGetLength(newData));
-        
-        // Process packets until we run out of complete ones.
-        
-        do {
-            PacketHeader *  thisPacket;
-            Boolean         success;
-            
-            if ( CFDataGetLength(client->fBufferedData) < sizeof(PacketHeader) ) {
-                // Not enough data for the packet header; we're done.
-                break;
-            }
-            
-            thisPacket = (PacketHeader *) CFDataGetBytePtr(client->fBufferedData);
-            
-            if ( thisPacket->fMagic != kPacketMagic ) {
-                fprintf(stderr, "ClientGotData: Client %p sent us a packet with bad magic (%.4s).\n", client, (char *) &thisPacket->fMagic);
-                
-                ClientDestroy(client);
-                break;
-            }
-            
-            if (thisPacket->fSize > kPacketMaximumSize) {
-                fprintf(stderr, "ClientGotData: Client %p sent us a packet that's just too big (%" PRIu32 ").\n", client, thisPacket->fSize);
-                
-                ClientDestroy(client);
-                break;
-            }
-            
-            if ( CFDataGetLength(client->fBufferedData) < thisPacket->fSize ) {
-                // Not enough data for the packet body; we're done.
-                break;
-            }
-			
-			// Dispatch to the appropriate packet handler.
-            
-            switch (thisPacket->fType) {
-                case kPacketTypeGoodbye:
-                    success = ClientGoodbye(client, (PacketGoodbye *) thisPacket);
-                    break;
-                case kPacketTypeNOP:
-                    success = ClientNOP(client, (PacketNOP *) thisPacket);
-                    break;
-                case kPacketTypeWhisper:
-                    success = ClientWhisper(client, (PacketWhisper *) thisPacket);
-                    break;
-                case kPacketTypeShout:
-                    success = ClientShout(client, (PacketShout *) thisPacket);
-                    break;
-                case kPacketTypeListen:
-                    success = ClientListen(client, (PacketListen *) thisPacket);
-                    break;
-                case kPacketTypeQuit:
-                    success = ClientQuit(client, (PacketQuit *) thisPacket);
-                    break;
-                default:
-                    fprintf(stderr, "ClientGotData: Client %p sent us a packet with an unexpected type (%.4s).\n", client, (char *) &thisPacket->fType);
-                    
-                    success = false;
-                    break;                
-            }
-            if ( ! success ) {
-                ClientDestroy(client);
-                break;
-            }
-            
-            // Delete this packet from the front of our packet buffer.
-            
-            CFDataDeleteBytes(client->fBufferedData, CFRangeMake(0, thisPacket->fSize));
-            
-        } while (true);
-    }
-}
-
-/////////////////////////////////////////////////////////////////
-#pragma mark ***** Debug Infrastructure
-
-static void ClientPrintInfo(const void *value, void *context)
-// Called by PrintServerState to print the state of a particular 
-// client.  Actually passed as a callback to CFSetApplyFunction, 
-// which is why the value parameter is a (const void *) rather 
-// than a (ClientState *).  context is not used in this... context (-;
-{
-#pragma unused(context)
-    ClientState *  client;
-    static const char * kBoolToStr[2] = { "false", "true" };
-	
-    client = (ClientState *) value;
-    assert(client != NULL);
-    assert(client->fMagic == kClientStateMagic);
-    
-    fprintf(stderr, "  Client %p:\n", client);
-    fprintf(stderr, "    fSockFD            = %d\n", client->fSockFD);
-    fprintf(stderr, "    fSockCF            = %p\n", client->fSockCF);
-    fprintf(stderr, "    fRunLoopSource     = %p\n", client->fRunLoopSource);
-    fprintf(stderr, "    fBufferedData      = %p (count: %ld)\n", client->fBufferedData, CFDataGetLength(client->fBufferedData));
-    fprintf(stderr, "    fPendingSends      = %p (count: %ld)\n", client->fPendingSends, CFArrayGetCount(client->fPendingSends));
-    fprintf(stderr, "    fPendingSendOffset = %zd\n", client->fPendingSendOffset);
-    fprintf(stderr, "    fListening         = %s\n", kBoolToStr[client->fListening]);    
-}
-
-static void PrintServerState(void)
-// Called in response to a SIGINFO.  This prints a bunch of state 
-// information about the server.  Note that it is not called from a 
-// signal handler directly, rather from SignalRunLoopCallback which 
-// is a runloop callback.  So we can do all sorts of things that 
-// aren't safe in a true signal handler.
-{
-    fprintf(stderr, "CFLocalServer State\n");
-    fprintf(stderr, "-------------------\n");
-    if ( CFSetGetCount(gClients) == 0) {
-        fprintf(stderr, "Clients: none\n");
-    } else {
-        fprintf(stderr, "Clients:\n");
-        CFSetApplyFunction(gClients, ClientPrintInfo, NULL);
-    }
-    fprintf(stderr, "\n");
-	
-    DebugPrintDescriptorTable();
-}
-
-/////////////////////////////////////////////////////////////////
-#pragma mark ***** Server Framework
-
-static void ListeningSocketAcceptCallback(
-										  CFSocketRef             s, 
-										  CFSocketCallBackType    type, 
-										  CFDataRef               address, 
-										  const void *            data, 
-										  void *                  info
-)
-// This is the CFSocket event callback for the listening socket.  For a 
-// description of the parameters, see the CFSocket documentation.
-//
-// CFSocket calls this routine when it has accepted a new connection on 
-// the socket.  in this case data is a pointer to the newly created 
-// file descriptor that describes the new connection.  This routine 
-// responds by calling into the client layer to create a new client.
-{
-#pragma unused(s)
-#pragma unused(address)
-#pragma unused(info)
-    
-    assert(type == kCFSocketAcceptCallBack);
-    assert(   (int *) data  != NULL );
-    assert( (*(int *) data) != -1 );
-	
-    (void) ClientCreate( (*(int *) data), NULL );
-    
-    // If ClientCreate fails, it cleans up after itself, including 
-    // closing the newly created client socket.  It's even printed 
-    // a happy message (well, an unhappy message).  So we do nothing 
-	// on failure.
-}
-
-static void SignalRunLoopCallback(const siginfo_t *sigInfo, void *refCon)
-// This routine is called in response to a signal (SIGINT 
-// or SIGINFO).  It is not, however, a signal handler.  Rather, 
-// we orchestrate to have it called from the runloop (via 
-// the magic of InstallSignalToSocket).  It's purpose 
-// is to a) stop the server when the user types ^C (SIGINT), or 
-// b) print some information about the server (SIGINFO).
-{
-#pragma unused(sigInfo)
-#pragma unused(refCon)
-    
-    switch (sigInfo->si_signo) {
-        case SIGINFO:
-			// Respond to SIGINFO by printing some information about the server.
-			
-            PrintServerState();
-            break;
-        case SIGINT:
-			// Respond to SIGINT by stopping the server.
-			
-			// Stop the runloop.  Note that we can get a reference to the runloop by 
-			// calling CFRunLoopGetCurrent because this is called from the runloop.
-			
-			CFRunLoopStop( CFRunLoopGetCurrent() );
-			
-			// Print a bonus newline to ensure that the next command prompt isn't 
-			// printed on the same line as the echoed ^C.
-			
-			fprintf(stderr, "\n");
-            break;
-        default:
-            assert(false);
-            break;
-    }
-}
-
-static int SafeBindUnixDomainSocket(int sockFD, const char *socketPath)
-// This routine is called to safely bind the UNIX domain socket 
-// specified by sockFD to the path specificed by socketPath.  To avoid 
-// security problems, socketPath must point it to a sticky directory 
-// (such as "/var/tmp").  This allows us to create the socket with 
-// very specific permissions, without us having to worry about a malicious 
-// process switching stuff out from underneath us.
-//
-// For this test program, socketpath is "/var/tmp/com.apple.dts.CFLocalServer/Socket". 
-// The code calculates parentPath as ""/var/tmp/com.apple.dts.CFLocalServer" 
-// and grandParentPath as "/var/tmp".  Each ancestor has certain key attributes. 
-//
-// o grandParentPath must a sticky directory.  Because it's sticky, we 
-//   can create a directory within it and know that either a) we created 
-//   the directory, and no one else can mess with it because it's sticky, 
-//   or b) the directory exists, in which case we can check it's owner 
-//   and permissions and, if they are set correctly, know that no one else 
-//   can mess with it.
-//
-// o When we create the parentPath directory within grandParentPath, we set its 
-//   permissions to make it readable by everyone (so everyone can connect to our 
-//   server) but writeable only by us (so that only we can create the listening 
-//   socket).  Because parentPath is set this way, we know that no one else 
-//   can modify it to produce a security problem.
-//
-// IMPORTANT:
-// This routine is designed to protect against external attack, not against 
-// being called incorrectly.  It only does minimal checking of socketPath.  
-// For example, if one of the components of socketPath was "..", the security 
-// checking done by this routine might be invalid.  Do not pass an untrusted 
-// socketPath to this routine.
-{
-    int                 err;
-    char *              parentPath;
-    char *              grandParentPath;
-    char *              lastSlash;
-    struct stat         sb;
-    struct sockaddr_un  bindReq;
-    static const mode_t kRequiredParentMode = S_IRWXU | (S_IRGRP | S_IXGRP) | (S_IROTH | S_IXOTH); // rwxr-xr-x
-    
-    parentPath      = NULL;
-    grandParentPath = NULL;
-    
-    // sockaddr_un can only hold a very short path (it's 104 bytes long), 
-    // so we check that limit right up front.  Note the use of >= in the 
-    // check below: we fail if socketPath is exactly 104 chars long because 
-    // that would leave no space for the trailing null character.  Looking at 
-    // the kernel code, I don't think this is strictly necessary (in fact, 
-    // it seems that the kernel code will handle much longer paths than sun_path, 
-    // up to an overall sockaddr size ofSOCK_MAXADDRLEN), but I'm being 
-    // paranoid.
-    
-    err = 0;
-    if (strlen(socketPath) >= sizeof(bindReq.sun_path)) {
-        err = EINVAL;
-    }
-    
-    // Construct parentPath and grandParent path by knocking path components 
-    // off the end.
-    
-    if (err == 0) {
-        parentPath = strdup(socketPath);
-        if (parentPath == NULL) {
-            err = ENOMEM;
-        }
-    }
-    if (err == 0) {
-        lastSlash = strrchr(parentPath, '/');
-        if (lastSlash == NULL) {
-            fprintf(stderr, "SafeBindUnixDomainSocket: Can't get parent for path (%s).\n", socketPath);
-            err = EINVAL;
-        } else {
-            *lastSlash = 0;
-        }
-    }
-    if (err == 0) {
-        grandParentPath = strdup(parentPath);
-        if (grandParentPath == NULL) {
-            err = ENOMEM;
-        }
-    }
-    if (err == 0) {
-        lastSlash = strrchr(grandParentPath, '/');
-        if (lastSlash == NULL) {
-            fprintf(stderr, "SafeBindUnixDomainSocket: Can't get grandparent for path (%s).\n", socketPath);
-            err = EINVAL;
-        } else {
-            *lastSlash = 0;
-        }
-    }
-    
-    // Check that the parent directory is a sticky root-owned directory.  If the 
-    // grandparent directory is sticky, we know that any items in that directory 
-    // that are owned by us can't be substituted by anyone else (that is: deleted, 
-    // moved or renamed, and then replaced by an attacker's item).
-    
-    if (err == 0) {        
-        err = stat(grandParentPath, &sb);
-        err = MoreUNIXErrno(err);
-    }
-	
-    if ( (err == 0) && ( ! (sb.st_mode & S_ISTXT) || (sb.st_uid != 0) ) ) {
-        fprintf(stderr, "SafeBindUnixDomainSocket: Grandparent directory (%s) is not a sticky root-owned directory.\n", grandParentPath);
-        err = EINVAL;
-    }
-    
-    // Create the parent directory.  Ignore an EEXIST error because of the 
-    // next check.
-	
-    if (err == 0) {
-        err = mkdir(parentPath, kRequiredParentMode);
-        err = MoreUNIXErrno(err);
-        
-        if (err == EEXIST) {
-            err = 0;
-        }
-    }
-    
-    // Check that the parent directory is a directory, is owned by us, and 
-    // has the right mode.  This ensures that no one except us can be monkeying 
-    // with its contents.  And we know that no one can substitute a /different/ 
-    // directory underneath us because its parent (grandParentPath) is sticky.
-	
-    if (err == 0) {
-        err = stat(parentPath, &sb);
-        err = MoreUNIXErrno(err);
-    }
-    if ( (err == 0) && (sb.st_uid != geteuid()) ) {
-        fprintf(stderr, "SafeBindUnixDomainSocket: Parent (%s) is not owned by us.\n", parentPath);
-        err = EINVAL;
-    }
-    if ( (err == 0) && ! S_ISDIR(sb.st_mode) ) {
-        fprintf(stderr, "SafeBindUnixDomainSocket: Parent (%s) is not a directory.\n", parentPath);
-        err = EINVAL;
-    }
-    if ( (err == 0) && ( (sb.st_mode & ACCESSPERMS) != kRequiredParentMode ) ) {
-        fprintf(stderr, "SafeBindUnixDomainSocket: Parent (%s) has wrong permissions.\n", parentPath);
-        err = EINVAL;
-    }
-    
-    // If all is well, let's bind our socket.  This involves deleting any existing 
-    // socket and recreating our own.  We know we can do this without worrying 
-    // about substitution because only we have write access to the parent directory.
-	
-    if (err == 0) {
-        mode_t              oldUmask;
-		
-        // Temporarily set the umask to 0 (the default is 0022) so that the 
-        // socket is created rwxrwxrwx.  This allows any user to connect to 
-        // our socket.
-		
-        oldUmask = umask(0);
-		
-        // Delete any existing socket.  We delete the socket when we shut down, 
-        // but, if we quit unexpectedly, it could've been left lying around.
-        
-        (void) unlink(socketPath);
-		
-        // Bind the socket, allowing other clients to connect.
-        
-        bindReq.sun_len    = sizeof(bindReq);
-        bindReq.sun_family = AF_UNIX;
-        strcpy(bindReq.sun_path, socketPath);
-		
-        err = bind(sockFD, (struct sockaddr *) &bindReq, SUN_LEN(&bindReq));
-        err = MoreUNIXErrno(err);
-		
-        (void) umask(oldUmask);
-    }
-	
-    free(parentPath);
-    free(grandParentPath);
-    
-    return err;
-}
-
-static void PrintUsage(const char *argv0)
-// Print the program's usage.  Given that it supports no arguments whatsoever, 
-// this is pretty simple.
-{
-    const char *command;
-    
-    command = strrchr(argv0, '/');
-    if (command == NULL) {
-        command = argv0;
-    } else {
-        command += 1;
-    }
-    fprintf(stderr, "usage: %s\n", command);
-}
-
-
-#pragma mark -
- at interface MPNotifications (Private)
--(void) socketConnected:(NSNotification *)notification;
--(void) readData:(NSNotification *)notification;
--(void) notifyWithData:(NSNotification *)notification;
--(BOOL) initBSDSocket;
--(void) startServerThread;
--(void) prepareServerThread;
--(void) stopServerThread;
- at end
-
-
-
 @implementation MPNotifications
 
 
@@ -1410,29 +90,6 @@
 						[NSNumber numberWithInt:0], MPDEBUG, [NSNumber numberWithInt:0], MPALL, nil];
 		//NSLog(@"Dictionary is %@ ", [blockOptions description]);
 		
-		hasSetFileDescriptor = NO;
-		
-		if ([self initBSDSocket]) {
-			//should I be using the closeDealloc version instead? 
-			acceptHandle = [[NSFileHandle alloc] initWithFileDescriptor:sd1];
-			readHandle = [[NSFileHandle alloc] initWithFileDescriptor:sd1];
-			
-	
-			
-			//It would be nice if I could somehow add the fileHandle in the HelperTool as the sender
-			//this notification. That way I don't read stuff not intended for me.
-			//Perhaps I should post a distributed notification to indicate initiation of
-			//the asynchronous notification?
-			[[NSNotificationCenter defaultCenter] addObserver:self 
-													 selector:@selector(socketConnected:)
-														 name:NSFileHandleConnectionAcceptedNotification 
-													   object:nil];
-			
-			//Posts the notification above after accepting a connection
-			[acceptHandle acceptConnectionInBackgroundAndNotify];
-		}
-		
-		
 	}
 	return self;
 }
@@ -1481,208 +138,5 @@
 }
 
 
-#pragma mark -
-//Internal methods for IPC with helper tool
-//This method should really run in a background separate
-//thread so that it doesn't black ... I'll implement
-//that after I get the basic functionality working
-- (void) socketConnected:(NSNotification *) notification {
-	
-	[[NSNotificationCenter defaultCenter] addObserver:self 
-											 selector:@selector(readData:) 
-												 name:NSFileHandleDataAvailableNotification 
-											   object:nil];
-	
-	//Need to call this again since it is done only once in init
-	//and this is a singleton instance class
-	//acceptHandle posts the above notification
-	[acceptHandle acceptConnectionInBackgroundAndNotify];
-	
-	
-}
 
-- (void) readData:(NSNotification *) notification {
-	
-	[[NSNotificationCenter defaultCenter] addObserver:self 
-											 selector:@selector(notifyWithData:) 
-												 name:NSFileHandleReadCompletionNotification
-											   object:nil];
-	
-	//Once data is availabl we can call this method
-	//it posts the above notification on completion
-	[readHandle readInBackgroundAndNotify];
-}
-
-- (void) notifyWithData:(NSNotification *) notification {
-	NSData * inData = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem];
-	NSString * inString = [[NSString alloc] initWithData:inData 
-												encoding:NSUTF8StringEncoding];
-	//Just Log it for now
-	NSLog(@"Read in %@ from MPHelperTool", inString);
-	[inString release];
-	
-	//Once we have finished reading a stream of data and we are
-	//done logging ... we can start 
-	//[acceptHandle acceptConnectionInBackgroundAndNotify];
-}
-
--(BOOL) initBSDSocket {
-	//BSD Socket Initialization (maybe I should put this in another method ?)
-	sd1 = -1;
-	serverFilePath = @"var/run/org.macports.framework.mpnotificationsServer";
-	//serverFilePath = [[NSBundle bundleForClass:[MPNotifications class]]
-	//					  pathForResource:@"HelperToolServerFile" ofType:@"txt"];
-	sd1 = socket(AF_UNIX, SOCK_STREAM, 0);
-	if (sd1 < 0) {
-		NSLog(@"socket() failed");
-	}
-	
-	memset( &serveraddr, 0, sizeof(serveraddr));
-	serveraddr.sun_family = AF_UNIX;
-	strcpy(serveraddr.sun_path,[serverFilePath cStringUsingEncoding:NSUTF8StringEncoding] );
-	
-	rc = bind(sd1, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr));
-	if (rc < 0) {
-		NSLog(@"bind() failed");
-	}
-	else {
-		hasSetFileDescriptor = YES;
-	}
-	return hasSetFileDescriptor;
-}
-
-
--(int) getServerFileDescriptor {
-	return sd1;
-}
-
-
-#pragma mark -
-#pragma mark MPNotifications Server Code - II
-
--(void) startServerThread {
-	NSAutoreleasePool * sPool = [[NSAutoreleasePool alloc] init];
-	
-	NSLog(@"INSIDE SERVER THREAD");
-	
-	//Configure runloop
-	int         err = 0;
-    int         listenerFD;
-    CFSocketRef listenerCF;
-    Boolean     didBind;
-    
-    didBind    = false;
-    listenerFD = -1;
-    listenerCF = NULL;
-	
-	
-	
-	
-	// Ignore SIGPIPE because it's a deeply annoying concept.  If you don't ignore 
-	// SIGPIPE when writing to a UNIX domain socket whose far side has been closed 
-	// will trigger a SIGPIPE, whose default action is to terminate the program.
-    if (err == 0) {
-        fprintf(stderr, "CFLocalServer: Starting up (pid: %ld).\n", (long) getpid());
-		NSLog(@"CFLocalServer: Starting up (pid: %ld).\n", (long) getpid());
-        err = MoreUNIXIgnoreSIGPIPE();
-    }
-    
-	// Set up the signal handlers we are interested in.  In this case we redirect 
-	// SIGINT and SIGINFO to our runloop.  If either of these signals occurs, we 
-	// end up executing SignalRunLoopCallback.
-    if (err == 0) {
-        sigset_t    interestingSignals;
-        (void) sigemptyset(&interestingSignals);
-        (void) sigaddset(&interestingSignals, SIGINT);
-        (void) sigaddset(&interestingSignals, SIGINFO);
-        
-        err = InstallSignalToSocket(
-									&interestingSignals,
-									CFRunLoopGetCurrent(),
-									kCFRunLoopDefaultMode,
-									SignalRunLoopCallback,
-									NULL
-									);
-    }
-	
-	// Create the initial client set.
-    if (err == 0) {
-		err = ClientInitialise();
-		NSLog(@"Initilalizing Client");
-    }
-    
-	// Create our listening socket, bind it, and then wrap it in a CFSocket.
-    if (err == 0) {
-        listenerFD = socket(AF_UNIX, SOCK_STREAM, 0);
-        err = MoreUNIXErrno(listenerFD);
-		NSLog(@"Creating Socket");
-    }
-    if (err == 0) {
-        err = SafeBindUnixDomainSocket(listenerFD, kServerSocketPath);
-        didBind = (err == 0);
-		NSLog(@"Binding Socket %i", err);
-    }
-    if (err == 0) {
-        err = listen(listenerFD, 5);
-        err = MoreUNIXErrno(err);
-		NSLog(@"Listening Socket");
-    }
-    if (err == 0) {
-        listenerCF = CFSocketCreateWithNative(
-											  NULL, 
-											  (CFSocketNativeHandle) listenerFD, 
-											  kCFSocketAcceptCallBack, 
-											  ListeningSocketAcceptCallback, 
-											  NULL);
-		
-		NSLog(@"Creating Callbacks!");
-        if (listenerCF == NULL) {
-            err = EINVAL;
-        }
-    }
-    
-	// Schedule the listening socket on our runloop.
-	NSRunLoop * currentLoop = [NSRunLoop currentRunLoop];
-    if (err == 0) {
-        CFRunLoopSourceRef  rls;
-        
-        rls = CFSocketCreateRunLoopSource(NULL, listenerCF, 0);
-        if (rls == NULL) {
-            err = EINVAL;
-        } else {
-            CFRunLoopAddSource( [currentLoop getCFRunLoop], rls, kCFRunLoopDefaultMode);
-            NSLog(@"Adding Source to current runloop");
-			
-            // We no longer need this source, so we just release it.
-            CFRelease(rls);
-        }
-    }
-	
-	
-	double resolution = 30.0;
-	
-	//Add input sources to my run loop 
-	//terminateBackgroundThread is going to be set to NO before the privileged operation is called
-	//it will be set to YES after the privileged operation finishes execution. So I guess I need
-	//accessor methods?
-	NSThread * cThread = [NSThread currentThread];
-	NSLog(@"RUNNING RUN LOOP with thread %@" , [cThread threadDictionary]);
-	
-	do {
-		NSDate * nextDate = [NSDate dateWithTimeIntervalSinceNow:resolution];
-		[currentLoop runMode:NSDefaultRunLoopMode beforeDate:nextDate];
-		
-		//might add some code here to clean up and recreate autoreleasepool
-	}	while (terminateBackgroundThread == NO);
-	
-	[sPool release];
-}
-
--(void) prepareServerThread {
-	terminateBackgroundThread == NO;
-}
-
--(void) stopServerThread {
-	terminateBackgroundThread == YES;
-}
 @end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20080824/403ecf76/attachment-0001.html 


More information about the macports-changes mailing list