diff --git a/aspinterface.c b/aspinterface.c index 19915eb..b52b03d 100644 --- a/aspinterface.c +++ b/aspinterface.c @@ -12,7 +12,17 @@ #include "asmglue.h" #include "cmdproc.h" -static void CompleteCommand(Session *sess, Word result); +typedef struct FPReadRec { + Word CommandCode; /* includes pad byte */ + Word OForkRefNum; + LongWord Offset; + LongWord ReqCount; + Byte NewLineMask; + Byte NewLineChar; +} FPReadRec; + +#define kFPRead 27 + static void EndSession(Session *sess, Boolean callAttnRoutine); static void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec); @@ -40,7 +50,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) { break; } if (i == MAX_SESSIONS) { - CompleteCommand(sess, aspTooManySessions); + CompleteASPCommand(sess, aspTooManySessions); goto ret; } sess = &sessionTbl[i]; @@ -67,7 +77,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) { // one is in progress if (commandRec->command != aspCloseSessionCommand) { if (sess->commandPending) { - CompleteCommand(sess, aspSessNumErr); + CompleteASPCommand(sess, aspSessNumErr); goto ret; } sess->commandPending = TRUE; @@ -157,6 +167,37 @@ static void DoSPCommand(Session *sess, ASPCommandRec *commandRec) { sess->replyBuf = (void*)(commandRec->replyBufferAddr & 0x00FFFFFF); sess->replyBufLen = commandRec->replyBufferLen; + /* + * If the client is requesting to read more data than will fit in its + * buffer, change the request to ask for only the amount that will fit. + * + * This is necessary because ASP request and reply bodies are limited + * to a "quantum size" of 4624 bytes. Even if more data than that is + * requested, only that amount will be returned in a single reply. + * If the full read count requested is larger, it simply serves as a + * hint about the total amount that will be read across a series of + * FPRead requests. The AppleShare FST relies on this behavior and + * only specifies a buffer size of 4624 bytes for such requests. + * + * DSI does not have this "quantum size" limitation, so the full + * requested amount would be returned but then not fit in the buffer. + * To avoid this, we modify the request to ask only for the amount of + * data that will fit in the buffer. This removes the function of + * hinting about the total read size, but should work OK in practice. + * + * A similar issue could arise with FPEnumerate requests, but it + * actually doesn't in the case of the requests generated by the + * AppleShare FST, so we don't try to address them for now. + */ + if (commandRec->cmdBlkLength == sizeof(FPReadRec) + && ((FPReadRec*)commandRec->cmdBlkAddr)->CommandCode == kFPRead + && ntohl(((FPReadRec*)commandRec->cmdBlkAddr)->ReqCount) + > commandRec->replyBufferLen) + { + ((FPReadRec*)commandRec->cmdBlkAddr)->ReqCount = + htonl(commandRec->replyBufferLen); + } + /* Mask off high byte of addresses because PFI (at least) may * put junk in them, and this can cause Marinetti errors. */ SendDSIMessage(sess, &sess->request, @@ -187,7 +228,7 @@ void FlagFatalError(Session *sess, Word errorCode) { } if (sess->commandPending) { - CompleteCommand(sess, errorCode); + CompleteASPCommand(sess, errorCode); } EndSession(sess, TRUE); @@ -231,11 +272,11 @@ void FinishASPCommand(Session *sess) { } complete: - CompleteCommand(sess, 0); + CompleteASPCommand(sess, 0); } /* Actions to complete a command, whether successful or not */ -static void CompleteCommand(Session *sess, Word result) { +void CompleteASPCommand(Session *sess, Word result) { SPCommandRec *commandRec; commandRec = sess->spCommandRec; diff --git a/aspinterface.h b/aspinterface.h index e6f1212..ce3cfb1 100644 --- a/aspinterface.h +++ b/aspinterface.h @@ -15,6 +15,7 @@ extern Session sessionTbl[MAX_SESSIONS]; void DispatchASPCommand(SPCommandRec *commandRec); +void CompleteASPCommand(Session *sess, Word result); void FinishASPCommand(Session *sess); void FlagFatalError(Session *sess, Word errorCode); void PollAllSessions(void); diff --git a/dsi.c b/dsi.c index 7531cdc..983a6a7 100644 --- a/dsi.c +++ b/dsi.c @@ -142,12 +142,11 @@ top: // Maybe we should do something with them? FinishASPCommand(sess); } else { - sess->spCommandRec->result = aspSizeErr; + CompleteASPCommand(sess, aspBufErr); } + } else { + FinishASPCommand(sess); } - - // TODO correct logic for all cases - FinishASPCommand(sess); return; } //Handle a request from the server