AFPBridge/savenames.c
Stephen Heumann 78a300f799 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.
2017-04-21 21:09:57 -05:00

174 lines
5.0 KiB
C

#include <string.h>
#include <appletalk.h>
#include "aspinterface.h"
#include "asmglue.h"
/*
* This code is responsible for saving away the server name and zone at
* the time of an FILogin(2) call, and then writing them into the result
* records returned by FIListSessions2.
*
* This code is needed because FIListSessions2 has a bug that will cause
* these fields of its result records to contain garbage for AFP-over-TCP
* connections and in some cases also wrong values for concurrent
* AFP-over-AppleTalk sessions.
*/
#define SERVER_NAME_SIZE 32
#define ZONE_NAME_SIZE 33
typedef struct NameRec {
unsigned char serverName[SERVER_NAME_SIZE];
unsigned char zoneName[ZONE_NAME_SIZE];
} NameRec;
#define MAX_ASP_SESSION_NUM 8
#define MAX_PFI_SESSIONS 8
NameRec aspSessionNames[MAX_ASP_SESSION_NUM + 1];
NameRec dsiSessionNames[MAX_SESSIONS];
Byte aspActiveFlags[MAX_ASP_SESSION_NUM + 1] = {0};
Byte dsiActiveFlags[MAX_SESSIONS] = {0};
Byte extraActive = 0;
static unsigned char emptyStr[1] = {0};
typedef struct ListSessions2Buffer {
Byte refNum;
Byte slotDrive;
char volName[28];
Word volID;
char serverName[32];
char zoneName[33];
} ListSessions2Buffer;
/* Count number of active sessions (may overestimate) */
static unsigned int countSess(void) {
unsigned int activeCount;
unsigned int i;
activeCount = extraActive;
for (i = 0; i <= MAX_ASP_SESSION_NUM; i++) {
activeCount += aspActiveFlags[i];
}
for (i = 0; i < MAX_SESSIONS; i++) {
activeCount += aspActiveFlags[i];
}
return activeCount;
}
/*
* This is called following an FILogin or FILogin2 call, to save the names.
*/
#pragma databank 1
void SaveNames(PFILogin2Rec *commandRec) {
unsigned char *serverName, *zoneName;
unsigned int i;
unsigned int strLen;
NameRec *nameRec;
Word stateReg;
stateReg = ForceRomIn();
/*
* Don't save names for failed connections, but if we get a
* "too many sessions" error when there aren't really too many sessions,
* then change it to something more appropriate (this can happen when
* the ASP/DSI layer returns a network error).
*/
if (commandRec->result != 0 && commandRec->result != pfiLoginContErr) {
if (commandRec->result == pfiTooManySessErr
&& countSess() < MAX_PFI_SESSIONS)
{
commandRec->result = pfiUnableOpenSessErr;
}
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;
} else if (commandRec->sessRefID >= SESSION_NUM_START) {
nameRec = &dsiSessionNames[commandRec->sessRefID - SESSION_NUM_START];
dsiActiveFlags[commandRec->sessRefID - SESSION_NUM_START] = 1;
} else {
extraActive = 255;
goto ret;
}
/* Get the names (or default to empty strings if not provided) */
if (commandRec->command == pfiLogin2Command) {
serverName = commandRec->serverName;
zoneName = commandRec->zoneName;
} else {
serverName = emptyStr;
zoneName = emptyStr;
}
memset(nameRec, 0, sizeof(*nameRec));
strLen = serverName[0];
if (strLen >= SERVER_NAME_SIZE)
strLen = SERVER_NAME_SIZE - 1;
memcpy(&nameRec->serverName, serverName, strLen + 1);
nameRec->serverName[0] = strLen;
strLen = zoneName[0];
if (strLen >= ZONE_NAME_SIZE)
strLen = ZONE_NAME_SIZE - 1;
memcpy(&nameRec->zoneName, zoneName, strLen + 1);
nameRec->zoneName[0] = strLen;
ret:
RestoreStateReg(stateReg);
}
#pragma databank 0
#pragma databank 1
void InsertCorrectNames(PFIListSessions2Rec *commandRec) {
unsigned int i;
ListSessions2Buffer *resultBuf;
NameRec *nameRec;
Word stateReg;
stateReg = ForceRomIn();
if (commandRec->result != 0 && commandRec->result != pfiBufferToSmallErr)
goto ret;
resultBuf = (ListSessions2Buffer *)commandRec->bufferPtr;
for (i = 0; i < commandRec->entriesRtn; i++) {
if (resultBuf[i].refNum <= MAX_ASP_SESSION_NUM) {
nameRec = &aspSessionNames[resultBuf[i].refNum];
} else if (resultBuf[i].refNum >= SESSION_NUM_START) {
nameRec = &dsiSessionNames[resultBuf[i].refNum - SESSION_NUM_START];
} else {
continue;
}
memcpy(&resultBuf[i].serverName, nameRec, sizeof(*nameRec));
}
ret:
RestoreStateReg(stateReg);
}
#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