AFPBridge/savenames.c
Stephen Heumann 74e32c7d3f Work around issue where PFI gives an inappropriate "too many sessions" error.
It does this when the ASP layer gives a network error. To work around it, we count the number of sessions (possibly overestimating) and convert the error to "unable to open session" if PFI has not reached its session limit (8).
2017-04-19 21:56:37 -05:00

157 lines
4.5 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->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