Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
BigEasy/BigEasyPPC.c
/* |
File: BigEasyPPC.c |
Contains: xxx put contents here xxx |
Written by: xxx put writers here xxx |
Copyright: © 1992 by Apple Computer, Inc., all rights reserved. |
Change History (most recent first): |
<2> 1/7/93 dvb Compile under mpw. |
<1> 1/20/92 dvb first checked in |
*/ |
/* file: BigEasyPPC.c |
* |
* Started Mid 1991, more or less. |
* |
* A set of routines to quickly |
* access some simple uses of PPC. |
* |
*/ |
/*-------------------------- |
Protocol Notes |
--------------------------*/ |
/* |
Port creator type is always 'BigE', and the type is specified by |
the application. |
When the BrowseAndConnect is used, the PPCBrowser checks port creator and |
type to match the connecting port (and only shows those that match), and |
also attempts to connect to the port with a userdata of 'test'. The server |
port rejects the connection attempt if the userdata is 'test', and |
returns 'test' as the Reject-reason. |
*/ |
/*-------------------------- |
Inclusions |
--------------------------*/ |
#include "BigEasyPPC.h" |
#include <Errors.h> |
#include <Events.h> |
/*-------------------------- |
Constants |
--------------------------*/ |
#define kEasyPPCPortCreator 'BigE' |
enum |
/* |
* For the filterproc to work, there must |
* be an inform pending. The filterproc tests |
* this by actually connecting to the proposed |
* target, with userdata 'test'. The target sees this, |
* and ignores the connection, and posts another 'Inform' |
* just to make sure. |
*/ |
{ |
testConnection = 'test', |
realConnection = 'real' |
}; |
/*-------------------------- |
Globals |
--------------------------*/ |
Boolean gEverBrowsed = 0; /* to remember where we are in the browser */ |
LocationNameRec gTheLocation; |
PortInfoRec gThePortInfo; |
static EasyPPCSession gEasyFilterSession; /* communicate with Filter Proc */ |
/*-------------------------- |
Prototypes |
--------------------------*/ |
static short BumpStringNumber(StringPtr s); |
static void HandleSomeErrors(EasyPPCSession es,EasyPPCPollResult *pollResult); |
static void InitializeClient(EasyPPCSession es,EasyPPCClient *clientPtr); |
static EasyPPCClient *FindClient(EasyPPCSession es,long sessRefNum); |
static void RemoveClientEntry(EasyPPCSession es,EasyPPCClient *clientPtr); |
static void PollEasyPPCClient(EasyPPCSession es,EasyPPCClient *clientPtr, |
EasyPPCPollResult *pollResult); |
static EasyPPCClient *FindFreeClient(EasyPPCSession es); |
static pascal void InformCompletion(PPCParamBlockPtr pb); |
static pascal Boolean EasyBrowserFilter (LocationNamePtr location, PortInfoPtr port); |
#define MoveString(src,dst) BlockMove(src,dst,src[0]+1) |
/*-------------------------- |
Agedashi Dofu |
--------------------------*/ |
short BumpStringNumber(StringPtr s) |
/* |
* Starting from string "string" make strings "string 00" through |
* "string 99". Return false when that isn't possible. |
*/ |
{ |
unsigned char *c; |
c = s + s[0]; /* c points to very last character */ |
if(*c < '0' || *c > '9' || *(c-1) < '0' || *(c-1) > '9') /* need to append 00? */ |
{ |
s[0] += 3; |
*++c = ' '; |
*++c = '0'; |
*++c = '0'; |
} |
else |
{ |
*c += 1; |
if(*c > '9') |
{ |
*c-- = '0'; |
*c += 1; |
if(*c > '9') |
return 0; |
} |
} |
return 1; |
} |
EasyPPCSession NewEasyPPCSession(StringPtr name,OSType type) |
{ |
EasyPPCSession es; |
PPCOpenPBRec opbr; |
PPCPortRec portName; |
OSErr thisError; |
short i; |
es = (void *)NewPtr(sizeof(EasyPPCSessionRecord)); |
portName.nameScript = 0; |
MoveString(name,portName.name); |
portName.portKindSelector = ppcByCreatorAndType; |
portName.u.port.creator = kEasyPPCPortCreator; |
portName.u.port.type = type; |
opbr.ioCompletion = 0; |
opbr.serviceType = ppcServiceRealTime; |
opbr.resFlag = 0; |
opbr.portName = &portName; |
opbr.locationName = 0; |
opbr.networkVisible = 1; |
tryOpen: |
thisError = PPCOpenSync(&opbr); |
if(thisError == portNameExistsErr) |
if(BumpStringNumber(portName.name)) |
goto tryOpen; |
if(thisError) |
goto fail; |
es->portRefNum = opbr.portRefNum; |
es->type = type; |
es->serverType = type; |
thisError = GetDefaultUser(0,es->userName); |
es->waitingToWrite = 0; |
for(i = 0; i < kEasyPPCWritePacketCount; i++) |
es->wpbr[i].used = 0; |
es->connected = 0; |
for(i = 0; i < kEasyPPCClientCount; i++) |
es->client[i].used = 0; |
goto goHome; |
fail: |
DisposePtr((Ptr)es); |
es = 0; |
goHome: |
return es; |
} |
void DisposeEasyPPCSession(EasyPPCSession es) |
{ |
EasyPPCWritePB *ewpb; |
PPCClosePBRec cpbr; |
short i; |
if(es) |
{ |
cpbr.ioCompletion = 0; |
cpbr.portRefNum = es->portRefNum; |
PPCCloseSync(&cpbr); |
for(i = 0; i < kEasyPPCWritePacketCount; i++) |
{ |
ewpb = &es->wpbr[i]; |
if(ewpb->used && ewpb->buffer) |
DisposePtr(ewpb->buffer); /* easymanage */ |
} |
} |
} |
OSErr ConnectEasyPPCSession(EasyPPCSession es, |
LocationNameRec *locationName,PortInfoRec *pir,long *sessRefNum) |
{ |
PPCStartPBRec spbr; |
OSErr thisError; |
EasyPPCClient *clientPtr; |
if(!es || es->connected >= kEasyPPCClientCount) /* already enough connected */ |
{ |
thisError = -1; |
goto goHome; |
} |
spbr.ioCompletion = 0; |
spbr.portRefNum = es->portRefNum; |
spbr.serviceType = ppcServiceRealTime; |
spbr.resFlag = 0; |
spbr.portName = &pir->name; |
spbr.locationName = locationName; |
spbr.userData = 0; |
spbr.userRefNum = 0; |
thisError = PPCStartSync(&spbr); |
if(thisError == guestNotAllowedErr) |
{ |
Boolean asGuest; |
thisError = StartSecureSession(&spbr, |
(StringPtr)0x910, |
true, /* use default? */ |
false, /* don't allow guest, it didn't work */ |
&asGuest, |
"\p"); |
} |
if(!thisError) |
{ |
clientPtr = FindFreeClient(es); |
InitializeClient(es,clientPtr); |
clientPtr->userName[0] = 0; |
clientPtr->locationName = *locationName; |
clientPtr->portName = pir->name; |
clientPtr->sessRefNum = spbr.sessRefNum; |
} |
goHome: |
if(sessRefNum) |
*sessRefNum = spbr.sessRefNum; |
return thisError; |
} |
/* ---------------------------------------------------------- */ |
OSErr DisconnectEasyPPCSession(EasyPPCSession es,long sessRefNum) |
{ |
PPCEndPBRec epbr; |
OSErr thisError; |
EasyPPCClient *clientPtr; |
if(!es) |
return -1; |
clientPtr = FindClient(es,sessRefNum); |
if(!clientPtr) |
return -1; |
epbr.ioCompletion = 0; |
epbr.sessRefNum = clientPtr->sessRefNum; |
thisError = PPCEndSync(&epbr); |
RemoveClientEntry(es,clientPtr); |
HUnlock((void *)es->client); |
return thisError; |
} |
/* ---------------------------------------------------------- */ |
OSErr LetConnectEasyPPCSession(EasyPPCSession es) |
{ |
OSErr thisError; |
EasyPPCClient *clientPtr; |
/* |
* Enough connected? |
*/ |
if(!es || es->connected >= kEasyPPCClientCount) |
{ |
thisError = -1; |
goto goHome; |
} |
clientPtr = FindFreeClient(es); |
InitializeClient(es,clientPtr); |
clientPtr->sessRefNum = 0; |
clientPtr->waitingToConnect = 1; |
clientPtr->ipbr.ioCompletion = (ProcPtr)InformCompletion; |
clientPtr->ipbr.portRefNum = es->portRefNum; |
clientPtr->ipbr.autoAccept = 0; |
clientPtr->ipbr.portName = &clientPtr->portName; |
clientPtr->ipbr.locationName = &clientPtr->locationName; |
clientPtr->ipbr.userName = clientPtr->userName; |
thisError = PPCInformAsync(&clientPtr->ipbr); |
goHome: |
return thisError; |
} |
pascal void InformCompletion(PPCParamBlockPtr pb) |
/* |
* Here, we only accept the connection if |
* it's not a 'test' connection. |
* If it _is_ a test, we return 'test' as the |
* Reject-reason. |
*/ |
{ |
PPCInformPBRec *ipbr; |
PPCAcceptPBRec apbr; |
PPCRejectPBRec rpbr; |
ipbr = (PPCInformPBRec *)pb; |
if(ipbr->ioResult) /* problem? maybe the port's being closed? */ |
return; /* just quit it. */ |
if(ipbr->userData != testConnection) |
{ |
apbr.ioCompletion = 0; |
apbr.sessRefNum = ipbr->sessRefNum; |
PPCAcceptSync(&apbr); |
} |
else |
{ |
rpbr.ioCompletion = 0; |
rpbr.sessRefNum = ipbr->sessRefNum; |
rpbr.rejectInfo = testConnection; |
PPCRejectSync(&rpbr); |
PPCInformAsync(ipbr); |
} |
} |
OSErr WriteEasyPPCSession(EasyPPCSession es,long sessRefNum, |
long packetType,void *buffer,long length,Boolean easyManage) |
/* |
* If 'easyManage' is true, then BigEasyPPC makes a local copy |
* of the data, and the caller is free to forget about his copy. |
*/ |
{ |
OSErr result; |
PPCWritePBRec *wpb; |
EasyPPCWritePB *ewpb; |
short i; |
EasyPPCClient *clientPtr; |
if(!es || (es->waitingToWrite >= kEasyPPCWritePacketCount) ) |
{ |
result = 1; |
goto goHome; |
} |
clientPtr = FindClient(es,sessRefNum); |
if(!clientPtr) |
{ |
result = 1; |
goto goHome; |
} |
es->waitingToWrite ++; |
for(i = 0; i < kEasyPPCWritePacketCount; i++) |
{ |
ewpb = &es->wpbr[i]; |
if(!ewpb->used) |
goto gotOne; |
} |
result = 1; /* this should never happen! */ |
Debugger(); |
goto goHome; |
gotOne: |
ewpb->used = 1; |
if(easyManage) |
{ |
ewpb->buffer = NewPtr(length); |
if(!ewpb->buffer) |
DebugStr("\pCouldn't allocate ppc buffer copy! Whoa!"); |
BlockMove(buffer,ewpb->buffer,length); |
buffer = ewpb->buffer; |
} |
else |
ewpb->buffer = 0; |
wpb = &ewpb->wpbr; |
wpb->ioCompletion = 0; |
wpb->sessRefNum = clientPtr->sessRefNum; |
wpb->bufferLength = length; |
wpb->bufferPtr = buffer; |
wpb->more = 0; |
wpb->userData = length; |
wpb->blockCreator = 0; |
wpb->blockType = packetType; |
result = PPCWriteAsync(wpb); |
goHome: |
return result; |
} |
OSErr ReadEasyPPCSession(EasyPPCSession es,long sessRefNum,void *buffer,long length) |
{ |
OSErr result; |
EasyPPCClient *clientPtr; |
if(!es) |
{ |
result = 1; |
goto goHome; |
} |
clientPtr = FindClient(es,sessRefNum); |
if(!clientPtr || clientPtr->waitingToReadLength || clientPtr->waitingToReadData) |
{ |
result = 1; |
goto goHome; |
} |
clientPtr->waitingToReadData = 1; |
*(long *)buffer = clientPtr->tinyBuffer; |
if(clientPtr->waitingDataSize > 4) |
{ |
clientPtr->rpbr.ioCompletion = 0; |
clientPtr->rpbr.sessRefNum = clientPtr->sessRefNum; |
clientPtr->rpbr.bufferLength = length - 4; |
clientPtr->rpbr.bufferPtr = (void *) ( (long)buffer + 4 ); |
if(clientPtr->rpbr.bufferLength < 0) |
clientPtr->rpbr.bufferLength = 0; |
result = PPCReadAsync(&clientPtr->rpbr); |
} |
goHome: |
return result; |
} |
/* ---------------------------------------------------------- */ |
void PollEasyPPCClient(EasyPPCSession es,EasyPPCClient *clientPtr, |
EasyPPCPollResult *pollResult) |
{ |
/* |
* Should we start up the read process? |
*/ |
if(!clientPtr->waitingToReadLength && !clientPtr->waitingToReadData && |
clientPtr->sessRefNum) /* neither? */ |
{ |
clientPtr->waitingToReadLength = 1; |
clientPtr->rpbr.ioCompletion = 0; |
clientPtr->rpbr.sessRefNum = clientPtr->sessRefNum; |
clientPtr->rpbr.bufferLength = 4; |
clientPtr->rpbr.bufferPtr = (void *)&clientPtr->tinyBuffer; |
pollResult->error = PPCReadAsync(&clientPtr->rpbr); |
if(pollResult->error) |
{ |
pollResult->operation = 1; |
pollResult->sessRefNum = clientPtr->sessRefNum; |
pollResult->length = 0; |
pollResult->packetType = 0; |
pollResult->buffer = 0; |
goto goHome; |
} |
} |
/* |
* Received a length datum? |
*/ |
if(clientPtr->waitingToReadLength && clientPtr->rpbr.ioResult != 1) |
{ |
clientPtr->waitingToReadLength = 0; |
clientPtr->waitingDataSize = clientPtr->rpbr.userData; |
pollResult->operation = easyPPCSessionMessageWaiting; |
pollResult->error = clientPtr->rpbr.ioResult; |
pollResult->sessRefNum = clientPtr->rpbr.sessRefNum; |
pollResult->length = clientPtr->rpbr.userData; |
pollResult->packetType = clientPtr->rpbr.blockType; |
pollResult->buffer = 0; |
goto goHome; |
} |
/* |
* Received a message? |
*/ |
if(clientPtr->waitingToReadData && |
(clientPtr->waitingDataSize < 4 || clientPtr->rpbr.ioResult != 1) ) |
{ |
clientPtr->waitingToReadData = 0; |
clientPtr->waitingDataSize = 0; |
pollResult->operation = easyPPCSessionMessageRead; |
pollResult->error = clientPtr->rpbr.ioResult; |
pollResult->sessRefNum = clientPtr->rpbr.sessRefNum; |
pollResult->length = clientPtr->rpbr.userData; |
pollResult->packetType = clientPtr->rpbr.blockType; |
pollResult->buffer = clientPtr->rpbr.bufferPtr; |
if(clientPtr->rpbr.more && !pollResult->error) /* don't handle part-reads very well. */ |
Debugger(); |
goto goHome; |
} |
/* |
* Someone connect to us? |
*/ |
if(clientPtr->waitingToConnect && clientPtr->ipbr.ioResult != 1) |
{ |
if(clientPtr->ipbr.userData != testConnection) |
{ |
clientPtr->waitingToConnect = 0; |
clientPtr->sessRefNum = clientPtr->ipbr.sessRefNum; |
pollResult->operation = easyPPCSessionJustConnected; |
pollResult->error = clientPtr->ipbr.ioResult; |
pollResult->sessRefNum = clientPtr->ipbr.sessRefNum; |
pollResult->length = 0; |
pollResult->packetType = 0; |
pollResult->buffer = 0; |
goto goHome; |
} |
} |
/* |
* No activity? |
*/ |
pollResult->operation = easyPPCSessionIdle; |
pollResult->error = 0; |
pollResult->sessRefNum = 0; |
pollResult->length = 0; |
pollResult->packetType = 0; |
pollResult->buffer = 0; |
goHome: |
HandleSomeErrors(es,pollResult); |
} |
/* ---------------------------------------------------------- */ |
void PollEasyPPCSession(EasyPPCSession es,EasyPPCPollResult *pollResult) |
{ |
unsigned short i,j; |
EasyPPCWritePB *ewpb; |
PPCWritePBRec *wpb; |
EasyPPCClient *clientPtr; |
es->fairSeed++; |
if(es->fairSeed & 1) |
goto checkOutgoing; |
/* |
* Every poll, switch which |
* client gets checked first. |
*/ |
es->fairClient++; |
j = es->fairClient; |
for(i = 0; i < kEasyPPCClientCount; i++) |
{ |
clientPtr = &es->client[ (i + j) % kEasyPPCClientCount]; |
if(clientPtr->used) |
{ |
PollEasyPPCClient(es,clientPtr,pollResult); |
if(pollResult->operation != easyPPCSessionIdle) |
goto goHome; |
} |
} |
checkOutgoing: |
/* |
* Sent a message? |
*/ |
if(es->waitingToWrite) |
{ |
es->fairWrite ++; |
j = es->fairWrite + TickCount(); |
for(i = 0; i < kEasyPPCWritePacketCount; i++) |
{ |
ewpb = &es->wpbr[(i + j) % kEasyPPCWritePacketCount]; |
wpb = &ewpb->wpbr; |
if(ewpb->used && wpb->ioResult != 1) |
{ |
es->waitingToWrite --; |
ewpb->used = 0; |
pollResult->operation = easyPPCSessionMessageWritten; |
pollResult->error = wpb->ioResult; |
pollResult->sessRefNum = wpb->sessRefNum; |
pollResult->packetType = wpb->blockType; |
pollResult->length = wpb->userData; |
if(ewpb->buffer) |
{ |
DisposePtr(ewpb->buffer); /* easymanage */ |
pollResult->buffer = 0; |
} |
else |
pollResult->buffer = wpb->bufferPtr; |
goto goHome; |
} |
} |
} |
pollResult->operation = easyPPCSessionIdle; |
pollResult->error = 0; |
pollResult->sessRefNum = 0; |
pollResult->length = 0; |
pollResult->packetType = 0; |
pollResult->buffer = 0; |
goHome: |
HandleSomeErrors(es,pollResult); |
} |
void HandleSomeErrors(EasyPPCSession es,EasyPPCPollResult *pollResult) |
/* |
* Handle some types of PPC errors, and modify |
* the result accordingly. |
*/ |
{ |
EasyPPCClient *clientPtr; |
switch(pollResult->error) |
{ |
case sessClosedErr: |
case noSessionErr: |
pollResult->error = easyPPCSessionOtherPortGone; |
/* |
* There may be no client, if we're just |
* clearing out the stale outgoing-messages. |
*/ |
clientPtr = FindClient(es,pollResult->sessRefNum); |
if(clientPtr) |
RemoveClientEntry(es,clientPtr); |
break; |
default: |
if(pollResult->error < 0) |
Debugger(); |
break; |
} |
} |
/* ---------------------------------------------------------- */ |
OSErr BrowseAndConnectEasyPPCSession(EasyPPCSession es, |
StringPtr prompt, StringPtr applListLabel,long *sessRefNum, |
LocationNameRec *location,PortInfoRec *portInfo) |
{ |
OSErr thisError; |
if(es->connected >= kEasyPPCClientCount) /* enough connections? */ |
{ |
thisError = easyPPCSessionTooManyConnections; |
goto goHome; |
} |
gEasyFilterSession = es; /* great, pass arguments in global */ |
thisError = PPCBrowser(prompt, |
applListLabel, |
gEverBrowsed, |
&gTheLocation, |
&gThePortInfo, |
EasyBrowserFilter, |
0); |
gEverBrowsed = true; |
if(thisError) |
goto goHome; |
thisError = ConnectEasyPPCSession(es,&gTheLocation,&gThePortInfo,sessRefNum); |
if(location) |
*location = gTheLocation; |
if(portInfo) |
*portInfo = gThePortInfo; |
goHome: |
return thisError; |
} |
pascal Boolean EasyBrowserFilter (LocationNamePtr location, PortInfoPtr port) |
/* |
* If the port has the same type as us, and our servertype is our own type, |
* then guest access must be enabled, and a test connection is attempted. |
* |
* If the servertype is different, and we find one of that kind, then a |
* connection is attempted, but, if "guest not allowed" is returned, we |
* assume that it's okay to try, later, with the password, and allow it in |
* the browser. |
*/ |
{ |
OSErr thisError; |
if (port->name.u.port.creator == kEasyPPCPortCreator |
&& port->name.u.port.type == gEasyFilterSession->serverType) |
{ |
/* |
* Try to connect to it, to see if it's available |
*/ |
PPCStartPBRec spbr; |
PPCEndPBRec epbr; |
spbr.ioCompletion = 0; |
spbr.portRefNum = gEasyFilterSession->portRefNum; |
spbr.serviceType = ppcServiceRealTime; |
spbr.resFlag = 0; |
spbr.portName = &port->name; |
spbr.locationName = location; |
spbr.userData = testConnection; |
spbr.userRefNum = 0; |
thisError = PPCStartSync(&spbr); |
if(!thisError) /* shouldn't accept, but... */ |
{ |
epbr.ioCompletion = 0; |
epbr.sessRefNum = spbr.sessRefNum; |
PPCEndSync(&epbr); |
return false; |
} |
else if(thisError == guestNotAllowedErr) |
return true; |
else |
{ |
if(thisError == userRejectErr && spbr.rejectInfo == testConnection) |
return true; |
else |
return false; |
} |
} |
else |
return false; |
} |
/* ---------------------------------------------------------- */ |
void FindNamesEasyPPCSession(EasyPPCSession es,long sessRefNum, |
StringPtr zoneName,StringPtr macName,StringPtr portName) |
/* |
* Return the names of the Macintosh we're connected to. |
*/ |
{ |
EasyPPCClient *clientPtr; |
StringPtr s; |
clientPtr = FindClient(es,sessRefNum); |
if(clientPtr) |
{ |
if(zoneName) |
{ |
s = clientPtr->locationName.u.nbpEntity.zoneStr; |
if(s[0] && clientPtr->locationName.locationKindSelector |
== ppcNBPLocation) |
MoveString(s,zoneName); |
else |
MoveString("\p<Local>",zoneName); |
} |
if(macName) |
{ |
s = clientPtr->locationName.u.nbpEntity.objStr; |
if(s[0] && clientPtr->locationName.locationKindSelector |
== ppcNBPLocation) |
MoveString(s,macName); |
else |
MoveString("\p<This Macintosh>",macName); |
} |
if(portName) |
MoveString(clientPtr->portName.name,portName); |
} |
else |
{ |
if(zoneName) |
zoneName[0] = 0; |
if(macName) |
macName[0] = 0; |
if(portName) |
portName[0] = 0; |
} |
} |
/* ---------------------------------------------------------- */ |
void InitializeClient(EasyPPCSession es,EasyPPCClient *clientPtr) |
/* |
* Initialize just this client, as if it's |
* just sitting there. |
*/ |
{ |
#pragma unused (es) |
clientPtr->sessRefNum = 0; |
clientPtr->waitingToConnect = 0; |
clientPtr->waitingToReadData = 0; |
clientPtr->waitingToReadLength = 0; |
} |
/* ---------------------------------------------------------- */ |
EasyPPCClient *FindClient(EasyPPCSession es,long sessRefNum) |
/* |
* Do a linear search of the EasyPPCSession's |
* clients, and return a pointer to the |
* client specified. |
* |
* sessRefNum nil==0 matches to the first client. |
* So, an app that only has one connection need not remember |
* its refNum. |
* |
* If there isn't a match, return nil. |
*/ |
{ |
short i; |
EasyPPCClient *w; |
if(!es->connected) |
{ |
w = 0; |
goto goHome; |
} |
if(sessRefNum == 0) |
{ |
w = &es->client[0]; |
if(!w->sessRefNum) /* Not a good choice, if not really connected */ |
w = 0; |
goto goHome; |
} |
for(i = 0; i < kEasyPPCClientCount; i++) |
{ |
w = &es->client[i]; |
if(w->used && w->sessRefNum == sessRefNum) |
goto goHome; |
} |
w = 0; |
goHome: |
return w; |
} |
/* ---------------------------------------------------------- */ |
void RemoveClientEntry(EasyPPCSession es,EasyPPCClient *clientPtr) |
/* |
* Remove client number 'n' from the list. |
* Assume the list is locked, already. |
* Also, unmark any outgoing packets for that session. |
*/ |
{ |
/* |
* Remove any waiting outgoing packets |
*/ |
clientPtr->used = 0; |
es->connected --; |
} |
/* ---------------------------------------------------------- */ |
EasyPPCClient *FindFreeClient(EasyPPCSession es) |
{ |
short i; |
EasyPPCClient *clientPtr; |
for(i = 0; i < kEasyPPCClientCount; i++) |
{ |
clientPtr = &es->client[i]; |
if(!clientPtr->used) |
{ |
clientPtr->used = 1; |
es->connected ++; |
goto goHome; |
} |
} |
clientPtr = 0; |
Debugger(); //!!! should _never_ happen. |
goHome: |
return clientPtr; |
} |
/* ---------------------------------------------------------- */ |
void SetServerTypeEasyPPCSession(EasyPPCSession es,OSType serverType) |
{ |
es->serverType = serverType; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-19