From 7d2c225d2f1f84e370252cf7dbd025927734b752 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 16 Apr 2017 00:37:57 -0500 Subject: [PATCH] Add code to close the sessions when the system is shutting down. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This only works if our init is loaded before Marinetti’s, because otherwise Marinetti’s shutdown notification procedure gets control first and shuts down the connection. --- afpbridge.c | 41 +++++++++++++++++++++++++++++++++++++++++ aspinterface.c | 37 ++++++++++++++++++++++++++----------- aspinterface.h | 1 + tcpconnection.c | 14 ++------------ 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/afpbridge.c b/afpbridge.c index 58398a8..9639fa4 100644 --- a/afpbridge.c +++ b/afpbridge.c @@ -18,6 +18,7 @@ extern Word *unloadFlagPtr; FSTInfoRecGS fstInfoRec; void pollTask(void); +void notificationProc(void); static struct RunQRec { Long reserved1; @@ -28,6 +29,17 @@ static struct RunQRec { void (*proc)(void); } runQRec; +static struct NotificationProcRec { + Long reserved1; + Word reserved2; + Word Signature; + Long Event_flags; + Long Event_code; + Byte jml; + void (*proc)(void); +} notificationProcRec; + +NotifyProcRecGS addNotifyProcRec; void setUnloadFlag(void) { if (*unloadFlagPtr == 0) @@ -83,6 +95,14 @@ int main(void) { runQRec.proc = pollTask; AddToRunQ((Pointer)&runQRec); + notificationProcRec.Signature = 0xA55A; + notificationProcRec.Event_flags = 0x20; /* shutdown */ + notificationProcRec.jml = 0x5C; + notificationProcRec.proc = notificationProc; + addNotifyProcRec.pCount = 1; + addNotifyProcRec.procPointer = (ProcPtr)¬ificationProcRec; + AddNotifyProcGS(&addNotifyProcRec); + return; error: @@ -105,3 +125,24 @@ void pollTask(void) { DecBusyFlag(); } #pragma databank 0 + + +/* + * Notification procedure called at shutdown time. + * We try to notify the servers that we're closing the connections. + * This only works if Marinetti is still active, i.e. if its own + * shutdown notification procedure hasn't run yet. + */ +#pragma databank 1 +void notificationProc(void) { + Word stateReg; + + IncBusyFlag(); + stateReg = ForceRomIn(); + + CloseAllSessions(0); + + RestoreStateReg(stateReg); + DecBusyFlag(); +} +#pragma databank 0 diff --git a/aspinterface.c b/aspinterface.c index aafd6eb..1b0c85b 100644 --- a/aspinterface.c +++ b/aspinterface.c @@ -33,11 +33,11 @@ static Byte loginBuf[100]; static const Byte afp20VersionStr[] = "\pAFPVersion 2.0"; static const Byte afp22VersionStr[] = "\pAFP2.2"; -static void EndSession(Session *sess, Boolean callAttnRoutine); +static void EndSession(Session *sess, Byte attentionCode); static void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec); -static void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec); -static void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec); +static void DoSPOpenSession(Session *sess); +static void DoSPCloseSession(Session *sess); static void DoSPCommand(Session *sess, ASPCommandRec *commandRec); static void DoSPWrite(Session *sess, ASPWriteRec *commandRec); @@ -120,10 +120,10 @@ LongWord DispatchASPCommand(SPCommandRec *commandRec) { DoSPGetStatus(sess, (ASPGetStatusRec *)commandRec); break; case aspOpenSessionCommand: - DoSPOpenSession(sess, (ASPOpenSessionRec *)commandRec); + DoSPOpenSession(sess); break; case aspCloseSessionCommand: - DoSPCloseSession(sess, (ASPCloseSessionRec *)commandRec); + DoSPCloseSession(sess); break; case aspCommandCommand: DoSPCommand(sess, (ASPCommandRec *)commandRec); @@ -171,7 +171,7 @@ static void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec) { SendDSIMessage(sess, &sess->request, &kFPGetSrvrInfo, NULL); } -static void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec) { +static void DoSPOpenSession(Session *sess) { sess->request.flags = DSI_REQUEST; sess->request.command = DSIOpenSession; sess->request.requestID = htons(sess->nextRequestID++); @@ -183,7 +183,7 @@ static void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec) { SendDSIMessage(sess, &sess->request, NULL, NULL); } -static void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec) { +static void DoSPCloseSession(Session *sess) { sess->request.flags = DSI_REQUEST; sess->request.command = DSICloseSession; sess->request.requestID = htons(sess->nextRequestID++); @@ -316,7 +316,7 @@ void FlagFatalError(Session *sess, Word errorCode) { CompleteASPCommand(sess, errorCode); } - EndSession(sess, TRUE); + EndSession(sess, aspAttenTimeout); } @@ -369,7 +369,7 @@ void CompleteASPCommand(Session *sess, Word result) { if (sess->spCommandRec->command == aspGetStatusCommand || sess->spCommandRec->command == aspCloseSessionCommand) { - EndSession(sess, FALSE); + EndSession(sess, 0); } else { sess->commandPending = FALSE; if (sess->dsiStatus != error) { @@ -386,8 +386,8 @@ void CompleteASPCommand(Session *sess, Word result) { } -static void EndSession(Session *sess, Boolean callAttnRoutine) { - if (callAttnRoutine) { +static void EndSession(Session *sess, Byte attentionCode) { + if (attentionCode != 0) { // TODO call the attention routine to report end of session } @@ -404,3 +404,18 @@ void PollAllSessions(void) { } } } + +/* Close all sessions -- used when we're shutting down */ +void CloseAllSessions(Byte attentionCode) { + unsigned int i; + Session *sess; + + for (i = 0; i < MAX_SESSIONS; i++) { + sess = &sessionTbl[i]; + if (sess->dsiStatus != unused) { + DoSPCloseSession(sess); + EndSession(sess, attentionCode); + } + } +} + diff --git a/aspinterface.h b/aspinterface.h index 3e0bd19..d980f3a 100644 --- a/aspinterface.h +++ b/aspinterface.h @@ -19,5 +19,6 @@ void CompleteASPCommand(Session *sess, Word result); void FinishASPCommand(Session *sess); void FlagFatalError(Session *sess, Word errorCode); void PollAllSessions(void); +void CloseAllSessions(Byte attentionCode); #endif diff --git a/tcpconnection.c b/tcpconnection.c index 7b9c5c8..7cdbf3e 100644 --- a/tcpconnection.c +++ b/tcpconnection.c @@ -67,19 +67,9 @@ BOOLEAN StartTCPConnection(Session *sess) { } void EndTCPConnection(Session *sess) { - srBuff mySRBuff; - LongWord initialTime; - if (sess->tcpLoggedIn) { - initialTime = GetTick(); - do { - TCPIPPoll(); - } while (TCPIPStatusTCP(sess->ipid, &mySRBuff) == tcperrOK - && !toolerror() - && mySRBuff.srState == TCPSESTABLISHED - && mySRBuff.srSndQueued > 0 - && GetTick()-initialTime < 15*60); - + TCPIPCloseTCP(sess->ipid); + TCPIPPoll(); TCPIPAbortTCP(sess->ipid); TCPIPLogout(sess->ipid); sess->tcpLoggedIn = FALSE;