Implement option to let read replies return more data than the specified reply buffer size.

This could be unsafe for some forms of client code, but it looks like the AppleShare FST always actually has a large enough buffer to hold the full amount being requested, and can deal with up to 65535 bytes being returned at once. We take advantage of this to do larger reads in a single request, which provides a noticeable performance advantage.
This commit is contained in:
Stephen Heumann 2017-04-14 22:39:18 -05:00
parent 695f2d8611
commit d4857e483f
1 changed files with 31 additions and 10 deletions

View File

@ -13,6 +13,7 @@
#include "cmdproc.h"
#include "installcmds.h"
#include "atipmapping.h"
#include "afpoptions.h"
typedef struct FPReadRec {
Word CommandCode; /* includes pad byte */
@ -188,6 +189,8 @@ static void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec) {
}
static void DoSPCommand(Session *sess, ASPCommandRec *commandRec) {
LongWord readSize;
sess->request.flags = DSI_REQUEST;
sess->request.command = DSICommand;
sess->request.requestID = htons(sess->nextRequestID++);
@ -198,7 +201,8 @@ static void DoSPCommand(Session *sess, ASPCommandRec *commandRec) {
/*
* 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.
* buffer, reduce the amount of data requested and/or assume the buffer
* is really larger than specified.
*
* 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
@ -207,24 +211,41 @@ static void DoSPCommand(Session *sess, ASPCommandRec *commandRec) {
* 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.
* However, it appears that it actually always has a buffer big enough
* for the full read amount, and it can deal with receiving up to
* 65535 bytes at once.
*
* 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.
* requested amount would be returned but then not fit in the specified
* buffer size. To deal with this, we can reduce the amount of data
* requested from the server and/or just assume we actually have a
* bigger reply buffer than specified (up to 65535 bytes). The former
* approach is safer, but allowing larger reads gives significantly
* better performance and seems to work OK with the AppleShare FST,
* so we offer options for both approaches.
*
* 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)->CommandCode == kFPRead)
{
((FPReadRec*)commandRec->cmdBlkAddr)->ReqCount =
htonl(commandRec->replyBufferLen);
readSize = ntohl(((FPReadRec*)commandRec->cmdBlkAddr)->ReqCount);
if (readSize > sess->replyBufLen) {
if (sess->atipMapping.flags & fLargeReads) {
if (readSize <= 0xFFFF) {
sess->replyBufLen = readSize;
} else {
sess->replyBufLen = 0xFFFF;
((FPReadRec*)commandRec->cmdBlkAddr)->ReqCount =
htonl(0xFFFF);
}
} else {
((FPReadRec*)commandRec->cmdBlkAddr)->ReqCount =
htonl(sess->replyBufLen);
}
}
}
/* Mask off high byte of addresses because PFI (at least) may