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