Annotation of Examples/DistributedObjects/remoteSpot/Thinker.m, revision 1.1

1.1     ! root        1: 
        !             2: /* Thinker.m, the brains in the color server app */
        !             3: 
        !             4: #import "Thinker.h"
        !             5: #import "SpotView.h"
        !             6: #import "ClientRecord.h"
        !             7: #import "FullCopyList.h"
        !             8: #import <libc.h>
        !             9: #import <appkit/Panel.h>
        !            10: #import <machkit/NXNetNameServer.h>
        !            11: #import <machkit/senderIsInvalid.h>
        !            12: #import <mach/mach.h>
        !            13: #import <mach/mach_error.h>
        !            14: #import <objc/hashtable.h>
        !            15: #import <servers/netname.h>
        !            16: 
        !            17: #define REGISTERED_NAME "samsColorServer"
        !            18: #define streq !strcmp
        !            19: 
        !            20: @implementation Thinker
        !            21: 
        !            22: //////////////////////////////////////////////////////
        !            23: //             Shared server and client code
        !            24: //////////////////////////////////////////////////////
        !            25: - appDidInit:sender
        !            26: {
        !            27:        float r,g,b;
        !            28:        NXColor theColor;
        !            29: 
        !            30:        spotList = [[FullCopyList alloc] init];
        !            31: 
        !            32:        // return a proxy for the server
        !            33:        // this looks for a color server on any host.  In the real world,
        !            34:        // you would probably specify a host.
        !            35:        // this returns a local proxy to the remote "root" object
        !            36: 
        !            37:        server = [NXConnection connectToName:REGISTERED_NAME onHost:"*"];
        !            38: 
        !            39:        if (server)
        !            40:        {
        !            41:                // Become a client, already a server running
        !            42:                isServer = NO;
        !            43:                myConnection = [server connectionForProxy];
        !            44:                [myConnection registerForInvalidationNotification:self];
        !            45:                [server setProtocolForProxy:@protocol(spotServerMethods)];
        !            46:                [win setTitle:"Spot Client"];
        !            47:        }
        !            48: 
        !            49:        else
        !            50: 
        !            51:        {
        !            52:                // Become the spot server, since no server is running
        !            53:                // There is a window of vulnerability here; if 2 apps
        !            54:                // launch nearly simultaneously, both will not find servers,
        !            55:                // one will become the real server but the other will also
        !            56:                // think it's the server (but will never get clients).
        !            57:                // I should deal with this...
        !            58: 
        !            59:                isServer = YES;
        !            60: 
        !            61:                myConnection = [NXConnection registerRoot:self withName:REGISTERED_NAME];
        !            62: 
        !            63:                // printf("server: root connection is 0x%x\n", myConnection);
        !            64: 
        !            65:                [win setTitle:"Spot Server"];
        !            66:                clientList = [[List alloc] init];
        !            67: 
        !            68:                server = self;  //so this can act as its own pseudo client...
        !            69:        }
        !            70: 
        !            71:        [myConnection runFromAppKit];
        !            72: 
        !            73:        [mySpotView lateInit];
        !            74: 
        !            75:        [server addClient:self r:&r g:&g b:&b];
        !            76:        theColor = NXConvertRGBToColor(r,g,b);
        !            77:        [[win setBackgroundColor:theColor] display];
        !            78: 
        !            79:        return self;
        !            80: }
        !            81: 
        !            82: - appWillTerminate:sender
        !            83: {
        !            84:        if (isServer)
        !            85:        {
        !            86:                int     i, n = [clientList count];
        !            87: 
        !            88:                for (i = 0; i < n; i++)
        !            89:                {
        !            90:                        id theClient = [[clientList objectAt:i] client];
        !            91:                        if (theClient != self) [theClient serverTerminated];
        !            92:                }
        !            93:        }
        !            94:        else
        !            95:        {
        !            96:                [server clientTerminated:self];
        !            97:        }
        !            98:        return self;
        !            99: }
        !           100: 
        !           101: - server
        !           102: {      return server;
        !           103: }
        !           104: 
        !           105: - (BOOL)isServer
        !           106: {      return isServer;
        !           107: }
        !           108: 
        !           109: // this is sent by a connection
        !           110: - senderIsInvalid:sender
        !           111: {
        !           112:        if (isServer)
        !           113:        {
        !           114:                int     i, n = [clientList count];
        !           115: 
        !           116:                for (i = 0; i < n; i++)
        !           117:                {
        !           118:                        id theClientRecord = [clientList objectAt:i];
        !           119:                        if ([theClientRecord connection] == sender)
        !           120:                        {
        !           121:                                [self nukeClient: theClientRecord];
        !           122:                                break;
        !           123:                        }
        !           124:                }
        !           125:        }
        !           126:        else
        !           127:        {
        !           128:                [self serverTerminated];
        !           129:        }
        !           130: 
        !           131:        // now free the connection since it's no longer useful
        !           132:        // this also frees the proxies that the connection maintained
        !           133:        [sender free];
        !           134: 
        !           135:        return nil;
        !           136: }
        !           137: 
        !           138: //////////////////////////////////////////////////////
        !           139: //             Server code
        !           140: //////////////////////////////////////////////////////
        !           141: 
        !           142: // the server needs to keep a local database of clients so it can
        !           143: // message them all and associate port deaths to dead clients
        !           144: 
        !           145: - (void) addClient:remoteClient
        !           146:        r:(out float *)r
        !           147:        g:(out float *)g
        !           148:        b:(out float *)b
        !           149: {
        !           150:        id connToClient, aSpot, client;
        !           151: 
        !           152:        if (remoteClient != self)
        !           153:        {
        !           154:                [remoteClient setProtocolForProxy:@protocol(spotClientMethods)];
        !           155: 
        !           156:                connToClient = [remoteClient connectionForProxy];
        !           157:                [connToClient registerForInvalidationNotification:self];
        !           158:        }
        !           159:        else connToClient = nil;
        !           160: 
        !           161:        aSpot = [[[Spot alloc] init] addReference];
        !           162:        client = [[ClientRecord alloc] 
        !           163:                initClient:remoteClient connection:connToClient spot:aSpot];
        !           164: 
        !           165: 
        !           166: 
        !           167:        // the client list is used internally by the server, while the
        !           168:        // spot list contains some duplicate information, but must
        !           169:        // be exported.
        !           170: 
        !           171:        [clientList addObject:client];
        !           172:        [spotList addObject:aSpot];
        !           173: 
        !           174:        NXConvertColorToRGB([aSpot color], r, g, b);
        !           175: 
        !           176:        [self sendSpotListToClients];
        !           177: 
        !           178:        return;
        !           179: }
        !           180: 
        !           181: // only called in server by server
        !           182: - nukeClient: theClientRecord
        !           183: {
        !           184:        id theSpot = [theClientRecord spot];
        !           185:        [clientList removeObject:theClientRecord];
        !           186:        [spotList removeObject:theSpot];
        !           187:        [theSpot invalidate];
        !           188:        [NXApp delayedFree:theSpot];                    // so we don't kill in modal loop
        !           189:        [theClientRecord free];
        !           190:        [self sendSpotListToClients];
        !           191:        return self;
        !           192: }
        !           193: 
        !           194: - (void) clientTerminated:(in id)sender
        !           195: {
        !           196:        int     i, n = [clientList count];
        !           197:        id theClient;
        !           198: 
        !           199:        for (i = 0; i < n; i++)
        !           200:        {
        !           201:                id theClientRecord = [clientList objectAt:i];
        !           202:                theClient = [theClientRecord client];
        !           203: 
        !           204:                if (theClient == sender)
        !           205:                {
        !           206:                        [self nukeClient: theClientRecord];
        !           207:                        return;
        !           208:                }
        !           209:        }
        !           210: 
        !           211:        return;
        !           212: }
        !           213: 
        !           214: - (oneway void) sendSpotListToClients 
        !           215: {
        !           216:        int     i, n = [clientList count];
        !           217:        id theClient;
        !           218: 
        !           219:        for (i = 0; i < n; i++)
        !           220:        {
        !           221:                theClient = [[clientList objectAt:i] client];
        !           222: 
        !           223:                if (theClient != self)
        !           224:                {
        !           225:                        [theClient useSpotList:spotList];
        !           226:                }
        !           227:                else [mySpotView display];
        !           228:        }
        !           229: 
        !           230:        return;
        !           231: }
        !           232: 
        !           233: // the point is passed in view coordinates; it is interpreted in the 
        !           234: // server's view's coordinate system.  It returns a spot object if
        !           235: // possible, which creates a proxy to that object on the client side
        !           236: 
        !           237: - getSpotForPoint:(NXPoint) pnt spotLocation:(out NXPoint *)loc
        !           238: {
        !           239:        int     n = [spotList count];
        !           240:        int i;
        !           241:        
        !           242:        for (i = n-1; i >= 0; i--)
        !           243:        {
        !           244:                id      aSpot = [spotList objectAt:i];
        !           245:                NXPoint spnt = [aSpot location];
        !           246:                if (pnt.x > spnt.x && pnt.x < spnt.x + 30 &&
        !           247:                        pnt.y > spnt.y && pnt.y < spnt.y + 30)
        !           248:                {
        !           249:                        if ([aSpot doLock])
        !           250:                        {
        !           251:                                *loc = spnt;
        !           252:                                return aSpot;
        !           253:                        }
        !           254:                        return nil;
        !           255:                }
        !           256:        }
        !           257:        return nil;
        !           258: }
        !           259: 
        !           260: - (oneway void) spotDidChange
        !           261: {
        !           262:        [server sendSpotListToClients];
        !           263:        return;
        !           264: }
        !           265: 
        !           266: //////////////////////////////////////////////////////
        !           267: //             Client code
        !           268: //////////////////////////////////////////////////////
        !           269: 
        !           270: // return the clients own copy of the spotList
        !           271: - spotList
        !           272: {
        !           273:        return spotList;
        !           274: }
        !           275: 
        !           276: // don't ever send this message to the server!
        !           277: - (oneway void) useSpotList: (bycopy in id) newSpotList
        !           278: {
        !           279:        [spotList freeObjects];
        !           280:        [spotList free];
        !           281:        spotList = newSpotList;
        !           282:        [mySpotView display];
        !           283:        return;
        !           284: }
        !           285: 
        !           286: // the dying server calls this to nuke the clients
        !           287: - (oneway void) serverTerminated
        !           288: {
        !           289:        NXRunAlertPanel (NULL, "Server terminated.  Helpless client now "
        !           290:                        "terminating as well.", "Oot!", NULL, NULL);
        !           291:        [NXApp terminate:self];
        !           292: }
        !           293: 
        !           294: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.