diff --git a/aspinterface.c b/aspinterface.c index d603498..863886b 100644 --- a/aspinterface.c +++ b/aspinterface.c @@ -10,11 +10,14 @@ #include "endian.h" #include "readtcp.h" -void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec); -void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec); -void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec); -void DoSPCommand(Session *sess, ASPCommandRec *commandRec); -void DoSPWrite(Session *sess, ASPWriteRec *commandRec); +static void CompleteCommand(Session *sess, Word result); +static void EndSession(Session *sess, Boolean callAttnRoutine); + +static void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec); +static void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec); +static void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec); +static void DoSPCommand(Session *sess, ASPCommandRec *commandRec); +static void DoSPWrite(Session *sess, ASPWriteRec *commandRec); Session sessionTbl[MAX_SESSIONS]; @@ -31,16 +34,14 @@ void DispatchASPCommand(SPCommandRec *commandRec) { break; } if (i == MAX_SESSIONS) { - commandRec->result = aspTooManySessions; - CompleteCommand(sess); + CompleteCommand(sess, aspTooManySessions); return; } sess = &sessionTbl[i]; sess->spCommandRec = commandRec; if (!StartTCPConnection(sess)) { - // Error code was set in TCPIPConnect - CompleteCommand(sess); + FlagFatalError(sess, 0); return; } sess->dsiStatus = awaitingHeader; @@ -59,8 +60,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) { // one is in progress if (commandRec->command != aspCloseSessionCommand) { if (sess->commandPending) { - commandRec->result = aspSessNumErr; - CompleteCommand(sess); + CompleteCommand(sess, aspSessNumErr); return; } sess->commandPending = TRUE; @@ -100,7 +100,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) { } } -void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec) { +static void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec) { static const Word kFPGetSrvrInfo = 15; sess->request.flags = DSI_REQUEST; sess->request.command = DSIGetStatus; @@ -110,10 +110,10 @@ void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec) { sess->replyBuf = (void*)commandRec->bufferAddr; sess->replyBufLen = commandRec->bufferLength; - SendDSIMessage(sess, &sess->request, &kFPGetSrvrInfo); + SendDSIMessage(sess, &sess->request, &kFPGetSrvrInfo, NULL); } -void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec) { +static void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec) { sess->request.flags = DSI_REQUEST; sess->request.command = DSIOpenSession; sess->request.requestID = htons(sess->nextRequestID++); @@ -122,10 +122,10 @@ void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec) { sess->replyBuf = NULL; sess->replyBufLen = 0; - SendDSIMessage(sess, &sess->request, NULL); + SendDSIMessage(sess, &sess->request, NULL, NULL); } -void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec) { +static void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec) { sess->request.flags = DSI_REQUEST; sess->request.command = DSICloseSession; sess->request.requestID = htons(sess->nextRequestID++); @@ -134,10 +134,10 @@ void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec) { sess->replyBuf = NULL; sess->replyBufLen = 0; - SendDSIMessage(sess, &sess->request, NULL); + SendDSIMessage(sess, &sess->request, NULL, NULL); } -void DoSPCommand(Session *sess, ASPCommandRec *commandRec) { +static void DoSPCommand(Session *sess, ASPCommandRec *commandRec) { sess->request.flags = DSI_REQUEST; sess->request.command = DSICommand; sess->request.requestID = htons(sess->nextRequestID++); @@ -146,13 +146,39 @@ void DoSPCommand(Session *sess, ASPCommandRec *commandRec) { sess->replyBuf = (void*)commandRec->replyBufferAddr; sess->replyBufLen = commandRec->replyBufferLen; - SendDSIMessage(sess, &sess->request, (void*)commandRec->cmdBlkAddr); + SendDSIMessage(sess, &sess->request, (void*)commandRec->cmdBlkAddr, NULL); } -void DoSPWrite(Session *sess, ASPWriteRec *commandRec) { - // TODO +static void DoSPWrite(Session *sess, ASPWriteRec *commandRec) { + sess->request.flags = DSI_REQUEST; + sess->request.command = DSIWrite; + sess->request.requestID = htons(sess->nextRequestID++); + sess->request.writeOffset = htonl(commandRec->cmdBlkLength); + sess->request.totalDataLength = + htonl(commandRec->cmdBlkLength + commandRec->writeDataLength); + sess->replyBuf = (void*)commandRec->replyBufferAddr; + sess->replyBufLen = commandRec->replyBufferLen; + + SendDSIMessage(sess, &sess->request, (void*)commandRec->cmdBlkAddr, + (void*)commandRec->writeDataAddr); } + +void FlagFatalError(Session *sess, Word errorCode) { + sess->dsiStatus = error; + if (errorCode == 0) { + // TODO deduce better error code from Marinetti errors? + errorCode = aspNetworkErr; + } + + if (sess->commandPending) { + CompleteCommand(sess, errorCode); + } + + EndSession(sess, TRUE); +} + + // Fill in any necessary data in the ASP command rec for a successful return void FinishASPCommand(Session *sess) { LongWord dataLength; @@ -181,30 +207,44 @@ void FinishASPCommand(Session *sess) { ((ASPCommandRec*)(sess->spCommandRec))->replyLength = dataLength; break; case aspWriteCommand: - // TODO + ((ASPWriteRec*)(sess->spCommandRec))->cmdResult = + sess->reply.errorCode; + ((ASPWriteRec*)(sess->spCommandRec))->replyLength = dataLength; + ((ASPWriteRec*)(sess->spCommandRec))->writtenLength = + ((ASPWriteRec*)(sess->spCommandRec))->writeDataLength; break; } complete: - CompleteCommand(sess); + CompleteCommand(sess, 0); } /* Actions to complete a command, whether successful or not */ -void CompleteCommand(Session *sess) { +static void CompleteCommand(Session *sess, Word result) { + SPCommandRec *commandRec; + + commandRec = sess->spCommandRec; + if (sess->spCommandRec->command == aspGetStatusCommand || sess->spCommandRec->command == aspCloseSessionCommand) { - EndTCPConnection(sess); - } - - // TODO call completion routine - - if (sess->spCommandRec->command == aspGetStatusCommand - || sess->spCommandRec->command == aspCloseSessionCommand) - { - memset(sess, 0, sizeof(*sess)); + EndSession(sess, FALSE); } else { sess->commandPending = FALSE; InitReadTCP(sess, DSI_HEADER_SIZE, &sess->reply); } + + commandRec->result = result; + + // TODO call completion routine +} + + +static void EndSession(Session *sess, Boolean callAttnRoutine) { + if (callAttnRoutine) { + // TODO call the attention routine to report end of session + } + + EndTCPConnection(sess); + memset(sess, 0, sizeof(*sess)); } diff --git a/aspinterface.h b/aspinterface.h index 94030d2..ec08e1b 100644 --- a/aspinterface.h +++ b/aspinterface.h @@ -16,6 +16,6 @@ extern Session sessionTbl[MAX_SESSIONS]; void DispatchASPCommand(SPCommandRec *commandRec); void FinishASPCommand(Session *sess); -void CompleteCommand(Session *sess); +void FlagFatalError(Session *sess, Word errorCode); #endif diff --git a/dsi.c b/dsi.c index ee02b2e..6c60d14 100644 --- a/dsi.c +++ b/dsi.c @@ -30,43 +30,40 @@ static DSIRequestHeader attentionReplyRec = { 0 /* reserved */ }; -void FlagFatalError(Session *sess, Word errorCode) { - sess->dsiStatus = error; - if (errorCode) { - if (sess->commandPending) { - sess->spCommandRec->result = errorCode; - } - } else { - // TODO deduce error code from Marinetti errors - } - - CompleteCommand(sess); -} - -void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload) { - Boolean hasData; - - hasData = header->totalDataLength != 0; +void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload, + void *extraPayload) { + LongWord cmdLen; + LongWord extraLen; sess->tcperr = TCPIPWriteTCP(sess->ipid, (void*)header, DSI_HEADER_SIZE, - !hasData, FALSE); + !header->totalDataLength, FALSE); sess->toolerr = toolerror(); if (sess->tcperr || sess->toolerr) { FlagFatalError(sess, 0); return; } - if (hasData) { - sess->tcperr = TCPIPWriteTCP(sess->ipid, payload, - ntohl(header->totalDataLength), - TRUE, FALSE); + if (header->writeOffset) { + cmdLen = ntohl(header->writeOffset); + extraLen = ntohl(header->totalDataLength) - cmdLen; + } else { + cmdLen = ntohl(header->totalDataLength); + extraLen = 0; + } + while (cmdLen) { + sess->tcperr = TCPIPWriteTCP(sess->ipid, payload, cmdLen, + !extraLen, FALSE); sess->toolerr = toolerror(); if (sess->tcperr || sess->toolerr) { FlagFatalError(sess, 0); return; } + + cmdLen = extraLen; + payload = extraPayload; + extraLen = 0; } } @@ -158,13 +155,13 @@ top: { if (sess->reply.command == DSIAttention) { attentionReplyRec.requestID = sess->reply.requestID; - SendDSIMessage(sess, &attentionReplyRec, NULL); + SendDSIMessage(sess, &attentionReplyRec, NULL, NULL); //TODO call attention routine. } else if (sess->reply.command == DSICloseSession) { // TODO handle close } else if (sess->reply.command == DSITickle) { tickleRequestRec.requestID = htons(sess->nextRequestID++); - SendDSIMessage(sess, &tickleRequestRec, NULL); + SendDSIMessage(sess, &tickleRequestRec, NULL, NULL); } else { FlagFatalError(sess, aspNetworkErr); return; diff --git a/dsi.h b/dsi.h index e2a5ffa..8524965 100644 --- a/dsi.h +++ b/dsi.h @@ -4,7 +4,8 @@ #include "dsiproto.h" #include "session.h" -void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload); +void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload, + void *extraPayload); void PollForData(Session *sess); #endif diff --git a/dsitest.c b/dsitest.c index 42f5fc8..973dffd 100644 --- a/dsitest.c +++ b/dsitest.c @@ -5,13 +5,32 @@ #include #include "aspinterface.h" #include "atipmapping.h" +#include "endian.h" ASPGetStatusRec getStatusRec; ASPOpenSessionRec openSessionRec; ASPCommandRec commandRec; +ASPWriteRec writeRec; ASPCloseSessionRec closeSessionRec; Byte replyBuffer[1024]; +struct FPFlushRec { + Byte CommandCode; + Byte Pad; + Word VolumeID; +} fpFlushRec; + +struct FPWriteRec { + Byte CommandCode; + Byte Flag; + Word OForkRefNum; + LongWord Offset; + LongWord ReqCount; +} fpWriteRec; + +#define kFPFlush 10 +#define kFPWrite 33 + int main(int argc, char **argv) { Boolean loadedTCP = FALSE; @@ -81,14 +100,32 @@ int main(int argc, char **argv) printf("result code = %04x\n", openSessionRec.result); if (openSessionRec.result) goto error; + + writeRec.async = AT_SYNC; + writeRec.command = aspWriteCommand; + writeRec.completionPtr = 0; + writeRec.refNum = openSessionRec.refNum; + writeRec.cmdBlkLength = sizeof(fpWriteRec); + writeRec.cmdBlkAddr = (LongWord)&fpWriteRec; + fpWriteRec.CommandCode = kFPWrite; + fpWriteRec.ReqCount = htonl(16); + writeRec.writeDataLength = 16; + writeRec.writeDataAddr = (LongWord)&openSessionRec; + writeRec.replyBufferLen = sizeof(replyBuffer); + writeRec.replyBufferAddr = (LongWord)&replyBuffer; + + printf("Sending write...\n"); + DispatchASPCommand((SPCommandRec *)&writeRec); + printf("result code = %04x, write result = %08lx\n", + writeRec.result, writeRec.cmdResult); commandRec.async = AT_SYNC; commandRec.command = aspCommandCommand; commandRec.completionPtr = 0; commandRec.refNum = openSessionRec.refNum; - // FIXME this sends meaningless garbage, not a real AFP request - commandRec.cmdBlkLength = 10; - commandRec.cmdBlkAddr = (LongWord)&openSessionRec; + commandRec.cmdBlkLength = sizeof(fpFlushRec); + commandRec.cmdBlkAddr = (LongWord)&fpFlushRec; + fpFlushRec.CommandCode = kFPFlush; commandRec.replyBufferLen = sizeof(replyBuffer); commandRec.replyBufferAddr = (LongWord)&replyBuffer; diff --git a/endian.h b/endian.h index c901a40..7008ac1 100644 --- a/endian.h +++ b/endian.h @@ -3,7 +3,10 @@ #include -/* Undefine these in case they're defined as macros */ +/* + * Undefine these in case they're defined as macros. + * (In particular, GNO has broken macro definitions for these.) + */ #undef htons #undef ntohs #undef htonl