diff --git a/aspinterface.c b/aspinterface.c index cd6b50a..2244838 100644 --- a/aspinterface.c +++ b/aspinterface.c @@ -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