Annotation of Examples/DistributedObjects/remoteSpot/Thinker.m, revision 1.1.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.