Initial version, with test program.
It can currently send a GetStatus request and get a response.
This commit is contained in:
commit
b5c3a29f37
|
@ -0,0 +1,11 @@
|
||||||
|
CFLAGS = -i -w
|
||||||
|
|
||||||
|
OBJS = dsitest.o aspinterface.o dsi.o readtcp.o endian.o tcpconnection.o atipmapping.o
|
||||||
|
PROG = dsitest
|
||||||
|
|
||||||
|
$(PROG): $(OBJS)
|
||||||
|
occ $(CFLAGS) -o $@ $(OBJS)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(RM) $(OBJS) $(PROG)
|
|
@ -0,0 +1,179 @@
|
||||||
|
#pragma noroot
|
||||||
|
|
||||||
|
#include <AppleTalk.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "session.h"
|
||||||
|
#include "aspinterface.h"
|
||||||
|
#include "dsi.h"
|
||||||
|
#include "tcpconnection.h"
|
||||||
|
#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);
|
||||||
|
void CompleteCommand(Session *sess);
|
||||||
|
|
||||||
|
|
||||||
|
Session sessionTbl[MAX_SESSIONS];
|
||||||
|
|
||||||
|
void DispatchASPCommand(SPCommandRec *commandRec) {
|
||||||
|
Session *sess;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (commandRec->command == aspGetStatusCommand
|
||||||
|
|| commandRec->command==aspOpenSessionCommand)
|
||||||
|
{
|
||||||
|
for (i = 0; i < MAX_SESSIONS; i++) {
|
||||||
|
if (sessionTbl[i].dsiStatus == unused)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == MAX_SESSIONS) {
|
||||||
|
commandRec->result = aspTooManySessions;
|
||||||
|
CompleteCommand(sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sess = &sessionTbl[i];
|
||||||
|
sess->spCommandRec = commandRec;
|
||||||
|
|
||||||
|
if (!StartTCPConnection(sess)) {
|
||||||
|
// Error code was set in TCPIPConnect
|
||||||
|
CompleteCommand(sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sess->dsiStatus = awaitingHeader;
|
||||||
|
InitReadTCP(sess, DSI_HEADER_SIZE, &sess->reply);
|
||||||
|
} else {
|
||||||
|
if (commandRec->refNum < SESSION_NUM_START) {
|
||||||
|
// TODO call original AppleTalk routine (or do it earlier)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i = commandRec->refNum - SESSION_NUM_START;
|
||||||
|
sess = &sessionTbl[i];
|
||||||
|
sess->spCommandRec = commandRec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO properly handle all cases of getting a command while
|
||||||
|
// one is in progress
|
||||||
|
if (commandRec->command != aspCloseSessionCommand) {
|
||||||
|
if (sess->commandStatus != noCommand) {
|
||||||
|
commandRec->result = aspSessNumErr;
|
||||||
|
CompleteCommand(sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sess->commandStatus = commandPending;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (commandRec->command) {
|
||||||
|
case aspGetStatusCommand:
|
||||||
|
DoSPGetStatus(sess, (ASPGetStatusRec *)commandRec);
|
||||||
|
break;
|
||||||
|
case aspOpenSessionCommand:
|
||||||
|
DoSPOpenSession(sess, (ASPOpenSessionRec *)commandRec);
|
||||||
|
break;
|
||||||
|
case aspCloseSessionCommand:
|
||||||
|
DoSPCloseSession(sess, (ASPCloseSessionRec *)commandRec);
|
||||||
|
break;
|
||||||
|
case aspCommandCommand:
|
||||||
|
DoSPCommand(sess, (ASPCommandRec *)commandRec);
|
||||||
|
break;
|
||||||
|
case aspWriteCommand:
|
||||||
|
DoSPWrite(sess, (ASPWriteRec *)commandRec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandRec->async & AT_ASYNC) {
|
||||||
|
if (sess->commandStatus == commandDone) {
|
||||||
|
CompleteCommand(sess);
|
||||||
|
} else {
|
||||||
|
commandRec->result = aspBusyErr; // indicate call in process
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we're here, the call is synchronous -- we must complete it
|
||||||
|
|
||||||
|
while (sess->commandStatus != commandDone) {
|
||||||
|
PollForData(sess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec) {
|
||||||
|
sess->request.flags = DSI_REQUEST;
|
||||||
|
sess->request.command = DSIGetStatus;
|
||||||
|
sess->request.requestID = htons(sess->nextRequestID++);
|
||||||
|
sess->request.writeOffset = 0;
|
||||||
|
sess->request.totalDataLength = 0;
|
||||||
|
sess->replyBuf = (void*)commandRec->bufferAddr;
|
||||||
|
sess->replyBufLen = commandRec->bufferLength;
|
||||||
|
|
||||||
|
SendDSIMessage(sess, &sess->request, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSPCommand(Session *sess, ASPCommandRec *commandRec) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSPWrite(Session *sess, ASPWriteRec *commandRec) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in any necessary data in the ASP command rec for a successful return
|
||||||
|
void FinishASPCommand(Session *sess) {
|
||||||
|
LongWord dataLength;
|
||||||
|
|
||||||
|
dataLength = ntohl(sess->reply.totalDataLength);
|
||||||
|
if (dataLength > 0xFFFF) {
|
||||||
|
// The IIgs ASP interfaces can't represent lengths over 64k.
|
||||||
|
// This should be detected as an error earlier, but let's make sure.
|
||||||
|
sess->spCommandRec->result = aspSizeErr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(sess->spCommandRec->command) {
|
||||||
|
case aspGetStatusCommand:
|
||||||
|
((ASPGetStatusRec*)(sess->spCommandRec))->dataLength = dataLength;
|
||||||
|
break;
|
||||||
|
case aspOpenSessionCommand:
|
||||||
|
// TODO set session ref num
|
||||||
|
break;
|
||||||
|
case aspCloseSessionCommand:
|
||||||
|
((ASPCloseSessionRec*)(sess->spCommandRec))->refNum =
|
||||||
|
(sess - &sessionTbl[0]) + SESSION_NUM_START;
|
||||||
|
break;
|
||||||
|
case aspCommandCommand:
|
||||||
|
((ASPCommandRec*)(sess->spCommandRec))->cmdResult =
|
||||||
|
sess->reply.errorCode;
|
||||||
|
((ASPCommandRec*)(sess->spCommandRec))->replyLength = dataLength;
|
||||||
|
break;
|
||||||
|
case aspWriteCommand:
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompleteCommand(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actions to complete a command, whether successful or not */
|
||||||
|
void CompleteCommand(Session *sess) {
|
||||||
|
if (sess->spCommandRec->command == aspGetStatusCommand
|
||||||
|
|| sess->spCommandRec->command == aspCloseSessionCommand)
|
||||||
|
{
|
||||||
|
EndTCPConnection(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO call completion routine
|
||||||
|
|
||||||
|
memset(sess, 0, sizeof(*sess));
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef ASPINTERFACE_H
|
||||||
|
#define ASPINTERFACE_H
|
||||||
|
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
|
/* async flag values */
|
||||||
|
#define AT_SYNC 0
|
||||||
|
#define AT_ASYNC 0x80
|
||||||
|
|
||||||
|
#define aspBusyErr 0x07FF /* temp result code for async call in process */
|
||||||
|
|
||||||
|
#define SESSION_NUM_START 0xF8
|
||||||
|
#define MAX_SESSIONS (256 - SESSION_NUM_START)
|
||||||
|
|
||||||
|
extern Session sessionTbl[MAX_SESSIONS];
|
||||||
|
|
||||||
|
void FinishASPCommand(Session *sess);
|
||||||
|
void DispatchASPCommand(SPCommandRec *commandRec);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma noroot
|
||||||
|
|
||||||
|
struct ATIPMapping atipMapping;
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef ATIPMAPPING_H
|
||||||
|
#define ATIPMAPPING_H
|
||||||
|
|
||||||
|
typedef struct ATIPMapping {
|
||||||
|
/* AppleTalk address/socket */
|
||||||
|
Word networkNumber; /* in network byte order */
|
||||||
|
Byte node;
|
||||||
|
Byte socket;
|
||||||
|
|
||||||
|
/* IP address/port */
|
||||||
|
LongWord ipAddr;
|
||||||
|
Word port;
|
||||||
|
} ATIPMapping;
|
||||||
|
|
||||||
|
extern struct ATIPMapping atipMapping;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,182 @@
|
||||||
|
#pragma noroot
|
||||||
|
|
||||||
|
#include <AppleTalk.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <orca.h>
|
||||||
|
#include <tcpip.h>
|
||||||
|
#include "dsiproto.h"
|
||||||
|
#include "session.h"
|
||||||
|
#include "readtcp.h"
|
||||||
|
#include "dsi.h"
|
||||||
|
#include "endian.h"
|
||||||
|
#include "aspinterface.h"
|
||||||
|
|
||||||
|
static DSIRequestHeader tickleRequestRec = {
|
||||||
|
DSI_REQUEST, /* flags */
|
||||||
|
DSITickle, /* command */
|
||||||
|
0, /* requestID - set later */
|
||||||
|
0, /* writeOffset */
|
||||||
|
0, /* totalDataLength */
|
||||||
|
0 /* reserved */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Actually a reply, but use DSIRequestHeader type so we can send it. */
|
||||||
|
static DSIRequestHeader attentionReplyRec = {
|
||||||
|
DSI_REPLY, /* flags */
|
||||||
|
DSIAttention, /* command */
|
||||||
|
0, /* requestID - set later */
|
||||||
|
0, /* errorCode */
|
||||||
|
0, /* totalDataLength */
|
||||||
|
0 /* reserved */
|
||||||
|
};
|
||||||
|
|
||||||
|
void FlagFatalError(Session *sess, Word errorCode) {
|
||||||
|
sess->dsiStatus = error;
|
||||||
|
if (errorCode) {
|
||||||
|
if (sess->commandStatus == commandPending) {
|
||||||
|
sess->spCommandRec->result = errorCode;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO deduce error code from Marinetti errors
|
||||||
|
}
|
||||||
|
// TODO close TCP connection, anything else?
|
||||||
|
|
||||||
|
// call completion routing if needed
|
||||||
|
|
||||||
|
sess->commandStatus = commandDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload) {
|
||||||
|
Boolean hasData;
|
||||||
|
|
||||||
|
hasData = header->totalDataLength != 0;
|
||||||
|
|
||||||
|
sess->tcperr = TCPIPWriteTCP(sess->ipid, (void*)header,
|
||||||
|
DSI_HEADER_SIZE,
|
||||||
|
!hasData, 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);
|
||||||
|
sess->toolerr = toolerror();
|
||||||
|
if (sess->tcperr || sess->toolerr) {
|
||||||
|
FlagFatalError(sess, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PollForData(Session *sess) {
|
||||||
|
ReadStatus rs;
|
||||||
|
LongWord dataLength;
|
||||||
|
|
||||||
|
if (sess->dsiStatus != awaitingHeader && sess->dsiStatus != awaitingPayload)
|
||||||
|
return;
|
||||||
|
|
||||||
|
top:
|
||||||
|
rs = TryReadTCP(sess);
|
||||||
|
if (rs != rsDone) {
|
||||||
|
if (rs == rsError) FlagFatalError(sess, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here, we successfully read something.
|
||||||
|
|
||||||
|
if (sess->dsiStatus == awaitingHeader) {
|
||||||
|
if (sess->reply.totalDataLength != 0) {
|
||||||
|
dataLength = ntohl(sess->reply.totalDataLength);
|
||||||
|
|
||||||
|
if (sess->commandStatus == commandPending
|
||||||
|
&& sess->reply.flags == DSI_REPLY
|
||||||
|
&& sess->reply.requestID == sess->request.requestID
|
||||||
|
&& sess->reply.command == sess->request.command)
|
||||||
|
{
|
||||||
|
if (dataLength <= sess->replyBufLen) {
|
||||||
|
InitReadTCP(sess, dataLength, sess->replyBuf);
|
||||||
|
sess->dsiStatus = awaitingPayload;
|
||||||
|
goto top;
|
||||||
|
} else {
|
||||||
|
// handle data too long
|
||||||
|
sess->junkBuf = malloc(dataLength);
|
||||||
|
if (sess->junkBuf == NULL) {
|
||||||
|
FlagFatalError(sess, atMemoryErr);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
InitReadTCP(sess, dataLength, sess->junkBuf);
|
||||||
|
sess->dsiStatus = awaitingPayload;
|
||||||
|
goto top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sess->reply.flags == DSI_REQUEST
|
||||||
|
&& sess->reply.command == DSIAttention
|
||||||
|
&& dataLength <= DSI_ATTENTION_QUANTUM)
|
||||||
|
{
|
||||||
|
InitReadTCP(sess, DSI_ATTENTION_QUANTUM, &sess->attentionCode);
|
||||||
|
sess->dsiStatus = awaitingPayload;
|
||||||
|
goto top;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FlagFatalError(sess, aspSizeErr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here, we got a full message.
|
||||||
|
|
||||||
|
// Handle a command that is now done, if any.
|
||||||
|
if (sess->commandStatus == commandPending
|
||||||
|
&& sess->reply.flags == DSI_REPLY
|
||||||
|
&& sess->reply.requestID == sess->request.requestID
|
||||||
|
&& sess->reply.command == sess->request.command)
|
||||||
|
{
|
||||||
|
if (sess->junkBuf != NULL) {
|
||||||
|
free(sess->junkBuf);
|
||||||
|
sess->junkBuf = NULL;
|
||||||
|
if (sess->reply.command == DSIOpenSession) {
|
||||||
|
// We ignore the DSIOpenSession options for now.
|
||||||
|
// Maybe we should do something with them?
|
||||||
|
FinishASPCommand(sess);
|
||||||
|
} else {
|
||||||
|
sess->spCommandRec->result = aspSizeErr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO correct logic for all cases
|
||||||
|
FinishASPCommand(sess);
|
||||||
|
sess->commandStatus = commandDone;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Handle a request from the server
|
||||||
|
else if (sess->reply.flags == DSI_REQUEST)
|
||||||
|
{
|
||||||
|
if (sess->reply.command == DSIAttention) {
|
||||||
|
attentionReplyRec.requestID = sess->reply.requestID;
|
||||||
|
SendDSIMessage(sess, &attentionReplyRec, 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);
|
||||||
|
} else {
|
||||||
|
FlagFatalError(sess, aspNetworkErr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FlagFatalError(sess, aspNetworkErr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef DSI_H
|
||||||
|
#define DSI_H
|
||||||
|
|
||||||
|
#include "dsiproto.h"
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
|
void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload);
|
||||||
|
void PollForData(Session *sess);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef DSIPROTO_H
|
||||||
|
#define DSIPROTO_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef struct DSIRequestHeader {
|
||||||
|
Byte flags;
|
||||||
|
Byte command;
|
||||||
|
Word requestID;
|
||||||
|
LongWord writeOffset;
|
||||||
|
LongWord totalDataLength;
|
||||||
|
LongWord reserved;
|
||||||
|
} DSIRequestHeader;
|
||||||
|
|
||||||
|
typedef struct DSIReplyHeader {
|
||||||
|
Byte flags;
|
||||||
|
Byte command;
|
||||||
|
Word requestID;
|
||||||
|
LongWord errorCode;
|
||||||
|
LongWord totalDataLength;
|
||||||
|
LongWord reserved;
|
||||||
|
} DSIReplyHeader;
|
||||||
|
|
||||||
|
#define DSI_HEADER_SIZE 16
|
||||||
|
|
||||||
|
/* flags values */
|
||||||
|
#define DSI_REQUEST 0
|
||||||
|
#define DSI_REPLY 1
|
||||||
|
|
||||||
|
/* DSI command codes */
|
||||||
|
#define DSICloseSession 1
|
||||||
|
#define DSICommand 2
|
||||||
|
#define DSIGetStatus 3
|
||||||
|
#define DSIOpenSession 4
|
||||||
|
#define DSITickle 5
|
||||||
|
#define DSIWrite 6
|
||||||
|
#define DSIAttention 8
|
||||||
|
|
||||||
|
/* The attention quantum supported by this implementation */
|
||||||
|
#define DSI_ATTENTION_QUANTUM 2
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,72 @@
|
||||||
|
#include <AppleTalk.h>
|
||||||
|
#include <locator.h>
|
||||||
|
#include <tcpip.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <orca.h>
|
||||||
|
#include "aspinterface.h"
|
||||||
|
#include "atipmapping.h"
|
||||||
|
|
||||||
|
ASPGetStatusRec commandRec;
|
||||||
|
Byte replyBuffer[1024];
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
Boolean loadedTCP = FALSE;
|
||||||
|
Boolean startedTCP = FALSE;
|
||||||
|
cvtRec myCvtRec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
TLStartUp();
|
||||||
|
if (!TCPIPStatus()) {
|
||||||
|
LoadOneTool(54, 0x0300); /* load Marinetti 3.0+ */
|
||||||
|
if (toolerror())
|
||||||
|
goto error;
|
||||||
|
loadedTCP = TRUE;
|
||||||
|
TCPIPStartUp();
|
||||||
|
if (toolerror())
|
||||||
|
goto error;
|
||||||
|
startedTCP = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
atipMapping.networkNumber = 0xFFFF;
|
||||||
|
atipMapping.node = 0xFF;
|
||||||
|
atipMapping.socket = 0xFF;
|
||||||
|
|
||||||
|
TCPIPConvertIPCToHex(&myCvtRec, argv[1]);
|
||||||
|
atipMapping.ipAddr = myCvtRec.cvtIPAddress;
|
||||||
|
atipMapping.port = 548;
|
||||||
|
|
||||||
|
// Do the call
|
||||||
|
commandRec.async = AT_SYNC;
|
||||||
|
commandRec.command = aspGetStatusCommand;
|
||||||
|
commandRec.completionPtr = 0;
|
||||||
|
commandRec.slsNet = atipMapping.networkNumber;
|
||||||
|
commandRec.slsNode = atipMapping.node;
|
||||||
|
commandRec.slsSocket = atipMapping.socket;
|
||||||
|
commandRec.bufferLength = sizeof(replyBuffer);
|
||||||
|
commandRec.bufferAddr = (LongWord)&replyBuffer;
|
||||||
|
|
||||||
|
DispatchASPCommand((SPCommandRec *)&commandRec);
|
||||||
|
|
||||||
|
for (i=0; i<commandRec.dataLength;i++) {
|
||||||
|
printf("%02x ", replyBuffer[i]);
|
||||||
|
if ((i+1)%16 == 0) printf("\n");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
for (i=0; i<commandRec.dataLength;i++) {
|
||||||
|
if (replyBuffer[i] >= ' ' && replyBuffer[i] <= 126)
|
||||||
|
printf("%c", replyBuffer[i]);
|
||||||
|
else
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (startedTCP)
|
||||||
|
TCPIPShutDown();
|
||||||
|
if (loadedTCP)
|
||||||
|
UnloadOneTool(54);
|
||||||
|
TLShutDown();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
case on
|
||||||
|
|
||||||
|
htons start
|
||||||
|
ntohs entry
|
||||||
|
ply
|
||||||
|
phb
|
||||||
|
plx
|
||||||
|
pla
|
||||||
|
xba
|
||||||
|
phx
|
||||||
|
plb
|
||||||
|
phy
|
||||||
|
rtl
|
||||||
|
end
|
||||||
|
|
||||||
|
htonl start
|
||||||
|
ntohl entry
|
||||||
|
lda 4,s
|
||||||
|
xba
|
||||||
|
tax
|
||||||
|
lda 6,s
|
||||||
|
xba
|
||||||
|
tay
|
||||||
|
phb
|
||||||
|
pla
|
||||||
|
sta 3,s
|
||||||
|
pla
|
||||||
|
sta 3,s
|
||||||
|
plb
|
||||||
|
tya
|
||||||
|
rtl
|
||||||
|
end
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef ENDIAN_H
|
||||||
|
#define ENDIAN_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
/* Undefine these in case they're defined as macros */
|
||||||
|
#undef htons
|
||||||
|
#undef ntohs
|
||||||
|
#undef htonl
|
||||||
|
#undef ntohl
|
||||||
|
|
||||||
|
Word htons(Word);
|
||||||
|
Word ntohs(Word);
|
||||||
|
LongWord htonl(LongWord);
|
||||||
|
LongWord ntohl(LongWord);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "endian.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("%lx\n", htonl(0x12345678));
|
||||||
|
printf("%x\n", htons(0xabcd));
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma noroot
|
||||||
|
|
||||||
|
#include "readtcp.h"
|
||||||
|
#include "session.h"
|
||||||
|
#include <tcpip.h>
|
||||||
|
#include <orca.h>
|
||||||
|
|
||||||
|
#define buffTypePointer 0x0000 /* For TCPIPReadTCP() */
|
||||||
|
#define buffTypeHandle 0x0001
|
||||||
|
#define buffTypeNewHandle 0x0002
|
||||||
|
|
||||||
|
void InitReadTCP(Session *sess, LongWord readCount, void *readPtr) {
|
||||||
|
sess->readCount = readCount;
|
||||||
|
sess->readPtr = readPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReadStatus TryReadTCP(Session *sess) {
|
||||||
|
rrBuff rrBuff;
|
||||||
|
|
||||||
|
TCPIPPoll();
|
||||||
|
sess->tcperr = TCPIPReadTCP(sess->ipid, buffTypePointer, (Ref)sess->readPtr,
|
||||||
|
sess->readCount, &rrBuff);
|
||||||
|
sess->toolerr = toolerror();
|
||||||
|
if (sess->tcperr || sess->toolerr) {
|
||||||
|
sess->dsiStatus = error;
|
||||||
|
return rsError;
|
||||||
|
}
|
||||||
|
|
||||||
|
sess->readCount -= rrBuff.rrBuffCount;
|
||||||
|
sess->readPtr += rrBuff.rrBuffCount;
|
||||||
|
|
||||||
|
if (sess->readCount == 0) {
|
||||||
|
return rsDone;
|
||||||
|
} else {
|
||||||
|
return rsWaiting;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef READTCP_H
|
||||||
|
#define READTCP_H
|
||||||
|
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
|
typedef enum ReadStatus {
|
||||||
|
rsDone,
|
||||||
|
rsWaiting,
|
||||||
|
rsError
|
||||||
|
} ReadStatus;
|
||||||
|
|
||||||
|
void InitReadTCP(Session *sess, LongWord readCount, void *readPtr);
|
||||||
|
ReadStatus TryReadTCP(Session *sess);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef SESSION_H
|
||||||
|
#define SESSION_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include "dsiproto.h"
|
||||||
|
|
||||||
|
/* Common portion of records for the various SP... commands */
|
||||||
|
typedef struct SPCommandRec {
|
||||||
|
Byte async;
|
||||||
|
Byte command;
|
||||||
|
Word result;
|
||||||
|
/* Below are in records for several ASP commands, but not all. */
|
||||||
|
LongWord completionPtr;
|
||||||
|
Byte refNum;
|
||||||
|
} SPCommandRec;
|
||||||
|
|
||||||
|
typedef enum DSISessionStatus {
|
||||||
|
unused = 0,
|
||||||
|
awaitingHeader,
|
||||||
|
awaitingPayload,
|
||||||
|
error
|
||||||
|
} DSISessionStatus;
|
||||||
|
|
||||||
|
typedef enum CommandStatus {
|
||||||
|
noCommand = 0,
|
||||||
|
commandPending,
|
||||||
|
commandDone
|
||||||
|
} CommandStatus;
|
||||||
|
|
||||||
|
typedef struct Session {
|
||||||
|
/* Marinetti TCP connection status */
|
||||||
|
Word ipid;
|
||||||
|
Boolean tcpLoggedIn;
|
||||||
|
|
||||||
|
DSISessionStatus dsiStatus;
|
||||||
|
|
||||||
|
/* Information on command currently being processed, if any. */
|
||||||
|
CommandStatus commandStatus;
|
||||||
|
SPCommandRec *spCommandRec;
|
||||||
|
DSIRequestHeader request;
|
||||||
|
|
||||||
|
DSIReplyHeader reply;
|
||||||
|
|
||||||
|
Word nextRequestID;
|
||||||
|
|
||||||
|
/* Buffer to hold reply payload data */
|
||||||
|
void *replyBuf;
|
||||||
|
Word replyBufLen;
|
||||||
|
|
||||||
|
/* Buffer to hold unusable payload data that doesn't fit in replyBuf */
|
||||||
|
void *junkBuf;
|
||||||
|
|
||||||
|
/* ReadTCP status */
|
||||||
|
LongWord readCount;
|
||||||
|
Byte *readPtr;
|
||||||
|
|
||||||
|
/* Set by DSIAttention */
|
||||||
|
Word attentionCode;
|
||||||
|
|
||||||
|
/* Marinetti error codes, both the tcperr* value and any tool error */
|
||||||
|
Word tcperr;
|
||||||
|
Word toolerr;
|
||||||
|
} Session;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,78 @@
|
||||||
|
#pragma noroot
|
||||||
|
|
||||||
|
#include <tcpip.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <AppleTalk.h>
|
||||||
|
#include <orca.h>
|
||||||
|
#include "atipmapping.h"
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
|
/* Make a TCP connection to the address mapped to the specified AT address.
|
||||||
|
* sess->spCommandRec should be an SPGetStatus or SPOpenSession command.
|
||||||
|
*
|
||||||
|
* On success, returns TRUE and sets sess->ipid.
|
||||||
|
* On failure, returns FALSE and sets commandRec->result to an error code.
|
||||||
|
*/
|
||||||
|
BOOLEAN StartTCPConnection(Session *sess) {
|
||||||
|
Word tcperr;
|
||||||
|
ASPOpenSessionRec *commandRec;
|
||||||
|
srBuff mySRBuff;
|
||||||
|
|
||||||
|
commandRec = (ASPOpenSessionRec *)sess->spCommandRec;
|
||||||
|
|
||||||
|
if (commandRec->slsNet != atipMapping.networkNumber
|
||||||
|
|| commandRec->slsNode != atipMapping.node
|
||||||
|
|| commandRec->slsSocket != atipMapping.socket)
|
||||||
|
{
|
||||||
|
commandRec->result = aspNetworkErr;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TCPIPGetConnectStatus() == FALSE) {
|
||||||
|
TCPIPConnect(NULL);
|
||||||
|
if (toolerror()) {
|
||||||
|
commandRec->result = aspNetworkErr;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sess->ipid =
|
||||||
|
TCPIPLogin(userid(), atipMapping.ipAddr, atipMapping.port, 0, 0x40);
|
||||||
|
if (toolerror()) {
|
||||||
|
commandRec->result = aspNetworkErr;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcperr = TCPIPOpenTCP(sess->ipid);
|
||||||
|
if (toolerror()) {
|
||||||
|
TCPIPLogout(sess->ipid);
|
||||||
|
commandRec->result = aspNetworkErr;
|
||||||
|
return FALSE;
|
||||||
|
} else if (tcperr != tcperrOK) {
|
||||||
|
TCPIPLogout(sess->ipid);
|
||||||
|
commandRec->result = aspNoRespErr;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
TCPIPPoll();
|
||||||
|
TCPIPStatusTCP(sess->ipid, &mySRBuff);
|
||||||
|
} while (mySRBuff.srState == TCPSSYNSENT);
|
||||||
|
if (mySRBuff.srState != TCPSESTABLISHED) {
|
||||||
|
TCPIPAbortTCP(sess->ipid);
|
||||||
|
TCPIPLogout(sess->ipid);
|
||||||
|
commandRec->result = aspNoRespErr;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sess->tcpLoggedIn = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndTCPConnection(Session *sess) {
|
||||||
|
if (sess->tcpLoggedIn) {
|
||||||
|
TCPIPAbortTCP(sess->ipid);
|
||||||
|
TCPIPLogout(sess->ipid);
|
||||||
|
sess->tcpLoggedIn = FALSE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef TCPCONNECTION_H
|
||||||
|
#define TCPCONNECTION_H
|
||||||
|
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
|
BOOLEAN StartTCPConnection(Session *sess);
|
||||||
|
void EndTCPConnection(Session *sess);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue