Add an option to tell the server that the GS is going to sleep after each command sent.
This tells the server to keep the session alive (typically for at least several hours) without sending or expecting tickles. This is useful in cases where our run queue procedure is not run regularly or at all, e.g. in text-mode shells. The implementation here is geared toward compatibility with Netatalk and differs from Apple's published standards in a couple ways. It may or may not work with other servers.
This commit is contained in:
parent
2cb7cc7572
commit
78a300f799
13
afpcdev.c
13
afpcdev.c
|
@ -50,6 +50,7 @@
|
|||
#define afpOverTCPOptionsItem 301
|
||||
#define useLargeReadsItem 302
|
||||
#define forceAFP22Item 303
|
||||
#define fakeSleepItem 304
|
||||
|
||||
#define fstMissingError 3000
|
||||
#define noEasyMountError 3001
|
||||
|
@ -492,6 +493,18 @@ void DoHit(long ctlID, CtlRecHndl ctlHandle)
|
|||
} else if (menuItem == forceAFP22Item) {
|
||||
flags ^= fForceAFP22;
|
||||
CheckMItem((flags & fForceAFP22) ? TRUE : FALSE, forceAFP22Item);
|
||||
|
||||
/* Fake sleep is allowed only with AFP 2.2. */
|
||||
if (flags & fForceAFP22) {
|
||||
EnableMItem(fakeSleepItem);
|
||||
} else {
|
||||
DisableMItem(fakeSleepItem);
|
||||
CheckMItem(FALSE, fakeSleepItem);
|
||||
flags &= ~fFakeSleep;
|
||||
}
|
||||
} else if (menuItem == fakeSleepItem) {
|
||||
flags ^= fFakeSleep;
|
||||
CheckMItem((flags & fFakeSleep) ? TRUE : FALSE, fakeSleepItem);
|
||||
}
|
||||
|
||||
SetCtlValue(afpOverTCPOptionsItem, ctlHandle);
|
||||
|
|
12
afpcdev.rez
12
afpcdev.rez
|
@ -97,6 +97,7 @@ resource rIcon (1) {
|
|||
#define afpOverTCPOptionsItem 301
|
||||
#define useLargeReadsItem 302
|
||||
#define forceAFP22Item 303
|
||||
#define fakeSleepItem 304
|
||||
|
||||
/*
|
||||
* Controls in the control panel window (for 640 mode or 320 mode)
|
||||
|
@ -244,7 +245,7 @@ resource rMenu (optionsMenu) {
|
|||
optionsMenu, /* menu ID */
|
||||
refIsResource*menuTitleRefShift + refIsResource*itemRefShift,
|
||||
optionsMenu, /* menu title ref (not drawn) */
|
||||
{afpOverTCPOptionsItem, useLargeReadsItem, forceAFP22Item};
|
||||
{afpOverTCPOptionsItem, useLargeReadsItem, forceAFP22Item, fakeSleepItem};
|
||||
};
|
||||
resource rPString(optionsMenu,noCrossBank) { "" };
|
||||
|
||||
|
@ -275,6 +276,15 @@ resource rMenuItem (forceAFP22Item) {
|
|||
};
|
||||
resource rPString(forceAFP22Item,noCrossBank) { "Force AFP Version 2.2" };
|
||||
|
||||
resource rMenuItem (fakeSleepItem) {
|
||||
fakeSleepItem, /* menu item ID */
|
||||
"","",
|
||||
0,
|
||||
fDisabled+refIsResource*itemTitleRefShift,
|
||||
fakeSleepItem /* menu item title ref */
|
||||
};
|
||||
resource rPString(fakeSleepItem,noCrossBank) { "Fake Sleep to Keep Alive" };
|
||||
|
||||
/*
|
||||
* Controls in the help window
|
||||
*/
|
||||
|
|
|
@ -9,5 +9,7 @@ AFPOptions afpOptions[] =
|
|||
{"AFP over TCP (LargeReads)", fLargeReads},
|
||||
{"AFP over TCP (AFP2.2)", fForceAFP22},
|
||||
{"AFP over TCP (LargeReads,AFP2.2)", fLargeReads | fForceAFP22},
|
||||
{"AFP over TCP (AFP2.2,FakeSleep)", fForceAFP22 | fFakeSleep},
|
||||
{"AFP over TCP (LR,AFP2.2,FS)", fLargeReads | fForceAFP22 | fFakeSleep},
|
||||
{0, 0}
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#define fLargeReads 0x0001
|
||||
#define fForceAFP22 0x0002
|
||||
#define fFakeSleep 0x0004
|
||||
|
||||
typedef struct AFPOptions {
|
||||
char *zoneString;
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef struct FPReadRec {
|
|||
|
||||
#define kFPRead 27
|
||||
#define kFPLogin 18
|
||||
#define kFPZzzzz 122
|
||||
|
||||
/* For forced AFP 2.2 login */
|
||||
static Byte loginBuf[100];
|
||||
|
@ -41,6 +42,7 @@ static void DoSPCommand(Session *sess, ASPCommandRec *commandRec);
|
|||
static void DoSPWrite(Session *sess, ASPWriteRec *commandRec);
|
||||
|
||||
static void CompleteASPCommand(SPCommandRec *commandRec, Word result);
|
||||
static void InitSleepRec(Session *sess, Byte sessRefNum);
|
||||
|
||||
Session sessionTbl[MAX_SESSIONS];
|
||||
|
||||
|
@ -54,6 +56,7 @@ LongWord DispatchASPCommand(SPCommandRec *commandRec) {
|
|||
|
||||
stateReg = ForceRomIn();
|
||||
|
||||
top:
|
||||
if (commandRec->command == aspGetStatusCommand
|
||||
|| commandRec->command==aspOpenSessionCommand)
|
||||
{
|
||||
|
@ -84,6 +87,7 @@ LongWord DispatchASPCommand(SPCommandRec *commandRec) {
|
|||
sess = &sessionTbl[i];
|
||||
sess->spCommandRec = commandRec;
|
||||
sess->commandPending = TRUE;
|
||||
InitSleepRec(sess, i + SESSION_NUM_START);
|
||||
|
||||
if ((i = StartTCPConnection(sess)) != 0) {
|
||||
FlagFatalError(sess, i);
|
||||
|
@ -186,7 +190,30 @@ LongWord DispatchASPCommand(SPCommandRec *commandRec) {
|
|||
}
|
||||
}
|
||||
|
||||
ret:
|
||||
ret:
|
||||
/*
|
||||
* If requested by user, we tell the server we are "going to sleep"
|
||||
* after every command we send. This avoids having the server
|
||||
* disconnect us because we can't send tickles for a while.
|
||||
*
|
||||
* This implementation is designed to work with Netatalk:
|
||||
* -Apple's docs say FPZzzzz was introduced with AFP 2.3, but Netatalk
|
||||
* supports it with AFP 2.2 and doesn't support AFP 2.3 at all.
|
||||
* -Apple's docs also say there is no reply to FPZzzzz, but Netatalk
|
||||
* send a reply with four bytes of data.
|
||||
* Netatalk includes comments indicating Apple's implementation in OS X
|
||||
* may really work more like Netatalk, but I haven't checked this.
|
||||
*/
|
||||
if ((sess->atipMapping.flags & fFakeSleep)
|
||||
&& sess->loggedIn && commandRec->result == 0
|
||||
&& (commandRec->command == aspCommandCommand
|
||||
|| commandRec->command == aspWriteCommand)
|
||||
&& commandRec != (SPCommandRec*)&sess->sleepCommandRec)
|
||||
{
|
||||
commandRec = (SPCommandRec*)&sess->sleepCommandRec;
|
||||
goto top;
|
||||
}
|
||||
|
||||
RestoreStateReg(stateReg);
|
||||
return 0;
|
||||
|
||||
|
@ -454,6 +481,19 @@ void CallAttentionRoutine(Session *sess, Byte attenType, Word atten) {
|
|||
CallCompletionRoutine((void *)(sess->attention + 1));
|
||||
}
|
||||
|
||||
static void InitSleepRec(Session *sess, Byte sessRefNum) {
|
||||
sess->sleepCommandRec.async = 0;
|
||||
sess->sleepCommandRec.command = aspCommandCommand;
|
||||
sess->sleepCommandRec.completionPtr = 0;
|
||||
sess->sleepCommandRec.refNum = sessRefNum;
|
||||
sess->sleepCommandRec.cmdBlkLength = sizeof(sess->fpZzzzzRec);
|
||||
sess->sleepCommandRec.cmdBlkAddr = (LongWord)&sess->fpZzzzzRec;
|
||||
sess->sleepCommandRec.replyBufferLen = sizeof(sess->fpZzzzzResponseRec);
|
||||
sess->sleepCommandRec.replyBufferAddr = (LongWord)&sess->fpZzzzzResponseRec;
|
||||
sess->fpZzzzzRec.CommandCode = kFPZzzzz;
|
||||
sess->fpZzzzzRec.Flag = 0;
|
||||
}
|
||||
|
||||
void PollAllSessions(void) {
|
||||
unsigned int i;
|
||||
|
||||
|
|
13
cmdproc.asm
13
cmdproc.asm
|
@ -88,6 +88,19 @@ jslOldPFIListSessions2 entry
|
|||
rtl
|
||||
end
|
||||
|
||||
pfiLoginContCmdProc start
|
||||
lda cmdRecPtr+2
|
||||
pha
|
||||
lda cmdRecPtr
|
||||
pha
|
||||
jslOldPFILoginCont entry
|
||||
jsl jslOldPFILoginCont ; to be changed
|
||||
rep #$30 ; ensure full native mode
|
||||
jsl PostLoginCont
|
||||
rtl
|
||||
end
|
||||
|
||||
|
||||
CallCompletionRoutine start
|
||||
phb
|
||||
jsl ForceLCBank2 ;use LC bank 2
|
||||
|
|
|
@ -7,6 +7,8 @@ void pfiLoginCmdProc(void);
|
|||
extern LongWord jslOldPFILogin;
|
||||
void pfiLogin2CmdProc(void);
|
||||
extern LongWord jslOldPFILogin2;
|
||||
void pfiLoginContCmdProc(void);
|
||||
extern LongWord jslOldPFILoginCont;
|
||||
void pfiListSessions2CmdProc(void);
|
||||
extern LongWord jslOldPFIListSessions2;
|
||||
void CallCompletionRoutine(void *);
|
||||
|
|
|
@ -21,6 +21,7 @@ NewCmd newCmds[] = {
|
|||
{nbpLookupNameCommand, nbpCmdProc, NULL},
|
||||
{pfiLoginCommand, pfiLoginCmdProc, &jslOldPFILogin},
|
||||
{pfiLogin2Command, pfiLogin2CmdProc, &jslOldPFILogin2},
|
||||
{pfiLoginContCommand, pfiLoginContCmdProc, &jslOldPFILoginCont},
|
||||
{pfiListSessions2Command, pfiListSessions2CmdProc, &jslOldPFIListSessions2},
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
|
17
savenames.c
17
savenames.c
|
@ -87,6 +87,10 @@ void SaveNames(PFILogin2Rec *commandRec) {
|
|||
goto ret;
|
||||
}
|
||||
|
||||
if (commandRec->result == 0 && commandRec->sessRefID >= SESSION_NUM_START) {
|
||||
sessionTbl[commandRec->sessRefID - SESSION_NUM_START].loggedIn = TRUE;
|
||||
}
|
||||
|
||||
if (commandRec->sessRefID <= MAX_ASP_SESSION_NUM) {
|
||||
nameRec = &aspSessionNames[commandRec->sessRefID];
|
||||
aspActiveFlags[commandRec->sessRefID] = 1;
|
||||
|
@ -154,3 +158,16 @@ ret:
|
|||
}
|
||||
#pragma databank 0
|
||||
|
||||
#pragma databank 1
|
||||
void PostLoginCont(PFILoginContRec *commandRec) {
|
||||
Word stateReg;
|
||||
|
||||
stateReg = ForceRomIn();
|
||||
|
||||
if (commandRec->result == 0 && commandRec->sessRefID >= SESSION_NUM_START) {
|
||||
sessionTbl[commandRec->sessRefID - SESSION_NUM_START].loggedIn = TRUE;
|
||||
}
|
||||
|
||||
RestoreStateReg(stateReg);
|
||||
}
|
||||
#pragma databank 0
|
||||
|
|
14
session.h
14
session.h
|
@ -2,6 +2,7 @@
|
|||
#define SESSION_H
|
||||
|
||||
#include <types.h>
|
||||
#include <appletalk.h>
|
||||
#include "dsiproto.h"
|
||||
#include "atipmapping.h"
|
||||
|
||||
|
@ -23,6 +24,11 @@ typedef enum DSISessionStatus {
|
|||
needsReset /* set after control-reset in P8 mode */
|
||||
} DSISessionStatus;
|
||||
|
||||
typedef struct FPZzzzzRec {
|
||||
Word CommandCode; /* includes pad byte */
|
||||
LongWord Flag;
|
||||
} FPZzzzzRec;
|
||||
|
||||
typedef struct Session {
|
||||
/* Marinetti TCP connection status */
|
||||
Word ipid;
|
||||
|
@ -62,6 +68,14 @@ typedef struct Session {
|
|||
|
||||
/* Attention routine header (followed by the routine) */
|
||||
ASPAttentionHeaderRec *attention;
|
||||
|
||||
/* Is this session successfully logged in? */
|
||||
Boolean loggedIn;
|
||||
|
||||
/* Records for sending (fake) sleep messages to server */
|
||||
ASPCommandRec sleepCommandRec;
|
||||
FPZzzzzRec fpZzzzzRec;
|
||||
Byte fpZzzzzResponseRec[4];
|
||||
} Session;
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue