From a38e2f716a3401b597304afb5dcf4e0844c2f585 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 23 Apr 2017 19:38:50 -0500 Subject: [PATCH] Detect when Marinetti has disconnected, and close all sessions at that time. Also, detect and give an error when invalid session numbers are used. --- afpbridge.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- aspinterface.c | 25 ++++++++++++++++--------- aspinterface.h | 4 ++-- dsi.c | 2 +- 4 files changed, 65 insertions(+), 13 deletions(-) diff --git a/afpbridge.c b/afpbridge.c index 007aa76..9160032 100644 --- a/afpbridge.c +++ b/afpbridge.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "installcmds.h" #include "aspinterface.h" @@ -17,6 +18,8 @@ LongWord version = 0x01006001; /* in rVersion format */ const char versionMessageString[] = "\pSTH~AFPBridge~Version~"; +const char requestNameString[] = "\pTCP/IP~STH~AFPBridge~"; + typedef struct VersionMessageRec { Word blockLen; char nameString[23]; @@ -28,6 +31,7 @@ extern void resetRoutine(void); void pollTask(void); void notificationProc(void); +static pascal Word requestProc(Word reqCode, Long dataIn, Long dataOut); static struct RunQRec { Long reserved1; @@ -51,6 +55,8 @@ static struct NotificationProcRec { #define SoftResetPtr ((LongWord *)0xE11010) extern LongWord oldSoftReset; +#define busyFlagPtr ((Byte*)0xE100FF) + #define JML 0x5C void setUnloadFlag(void) { @@ -126,6 +132,8 @@ int main(void) { addNotifyProcRec.procPointer = (ProcPtr)¬ificationProcRec; AddNotifyProcGS(&addNotifyProcRec); + AcceptRequests(requestNameString, userid(), &requestProc); + oldSoftReset = *SoftResetPtr; *SoftResetPtr = ((LongWord)&resetRoutine << 8) | JML; @@ -167,9 +175,46 @@ void notificationProc(void) { IncBusyFlag(); stateReg = ForceRomIn(); - CloseAllSessions(0); + CloseAllSessions(0, TRUE); RestoreStateReg(stateReg); DecBusyFlag(); } #pragma databank 0 + +#pragma databank 1 +void handleDisconnect(void) { + Word stateReg; + + IncBusyFlag(); + stateReg = ForceRomIn(); + + CloseAllSessions(aspAttenClosed, FALSE); + + RestoreStateReg(stateReg); + DecBusyFlag(); +} +#pragma databank 0 + +/* + * Request procedure called by Marinetti with its notifications. + * If the network has gone down, we immediately close all sessions. + * We check the busy flag to avoid doing this within our code + * (which runs with the busy flag set), although I don't think that + * can really happen with current versions of Marinetti. + */ +#pragma databank 1 +#pragma toolparms 1 +static pascal Word requestProc(Word reqCode, Long dataIn, Long dataOut) { + if (reqCode == TCPIPSaysNetworkDown) { + if (*busyFlagPtr) { + SchAddTask(&handleDisconnect); + } else { + handleDisconnect(); + } + } + + return 0; +} +#pragma toolparms 0 +#pragma databank 0 diff --git a/aspinterface.c b/aspinterface.c index 5c1e04d..4009a02 100644 --- a/aspinterface.c +++ b/aspinterface.c @@ -97,7 +97,7 @@ top: for (i = 0; i < MAX_SESSIONS; i++) { if (sessionTbl[i].dsiStatus == needsReset) - EndASPSession(&sessionTbl[i], 0); + EndASPSession(&sessionTbl[i], 0, TRUE); } for (i = 0; i < MAX_SESSIONS; i++) { if (sessionTbl[i].dsiStatus == unused) @@ -150,6 +150,11 @@ top: sess = &sessionTbl[commandRec->refNum - SESSION_NUM_START]; + if (sess->dsiStatus == unused) { + CompleteASPCommand(commandRec, aspRefErr); + goto ret; + } + if (sess->commandPending) { if (commandRec->command != aspCloseSessionCommand) { CompleteASPCommand(commandRec, aspSessNumErr); @@ -419,7 +424,7 @@ void FlagFatalError(Session *sess, Word errorCode) { CompleteCurrentASPCommand(sess, errorCode); } - EndASPSession(sess, aspAttenTimeout); + EndASPSession(sess, aspAttenTimeout, TRUE); } @@ -491,7 +496,7 @@ void CompleteCurrentASPCommand(Session *sess, Word result) { if (sess->spCommandRec->command == aspGetStatusCommand || sess->spCommandRec->command == aspCloseSessionCommand) { - EndASPSession(sess, 0); + EndASPSession(sess, 0, TRUE); } else { sess->commandPending = FALSE; if (sess->dsiStatus != error) { @@ -517,12 +522,13 @@ static void CompleteASPCommand(SPCommandRec *commandRec, Word result) { } -void EndASPSession(Session *sess, Byte attentionCode) { +void EndASPSession(Session *sess, Byte attentionCode, Boolean doLogout) { if (attentionCode != 0) { CallAttentionRoutine(sess, attentionCode, 0); } - EndTCPConnection(sess); + if (doLogout) + EndTCPConnection(sess); memset(sess, 0, sizeof(*sess)); } @@ -562,22 +568,23 @@ void PollAllSessions(void) { break; case needsReset: - EndASPSession(&sessionTbl[i], 0); + EndASPSession(&sessionTbl[i], 0, TRUE); break; } } } /* Close all sessions -- used when we're shutting down */ -void CloseAllSessions(Byte attentionCode) { +void CloseAllSessions(Byte attentionCode, Boolean doLogout) { unsigned int i; Session *sess; for (i = 0; i < MAX_SESSIONS; i++) { sess = &sessionTbl[i]; if (sess->dsiStatus != unused) { - DoSPCloseSession(sess); - EndASPSession(sess, attentionCode); + if (doLogout) + DoSPCloseSession(sess); + EndASPSession(sess, attentionCode, doLogout); } } } diff --git a/aspinterface.h b/aspinterface.h index 9f5a126..8d7bca0 100644 --- a/aspinterface.h +++ b/aspinterface.h @@ -18,10 +18,10 @@ LongWord DispatchASPCommand(SPCommandRec *commandRec); void CompleteCurrentASPCommand(Session *sess, Word result); void FinishASPCommand(Session *sess); void FlagFatalError(Session *sess, Word errorCode); -void EndASPSession(Session *sess, Byte attentionCode); +void EndASPSession(Session *sess, Byte attentionCode, Boolean doLogout); void CallAttentionRoutine(Session *sess, Byte attenType, Word atten); void PollAllSessions(void); -void CloseAllSessions(Byte attentionCode); +void CloseAllSessions(Byte attentionCode, Boolean doLogout); void ResetAllSessions(void); #endif diff --git a/dsi.c b/dsi.c index 690e94f..50bf726 100644 --- a/dsi.c +++ b/dsi.c @@ -158,7 +158,7 @@ top: SendDSIMessage(sess, &attentionReplyRec, NULL, NULL); CallAttentionRoutine(sess, aspAttenNormal, sess->attentionCode); } else if (sess->reply.command == DSICloseSession) { - EndASPSession(sess, aspAttenClosed); + EndASPSession(sess, aspAttenClosed, TRUE); return; } else if (sess->reply.command == DSITickle) { tickleRequestRec.requestID = htons(sess->nextRequestID++);