2021-07-16 16:37:38 +00:00
|
|
|
/*
|
|
|
|
* main.c
|
|
|
|
* Listener
|
|
|
|
*
|
|
|
|
* Created by Jeremy Rand on 2021-07-16.
|
|
|
|
* Copyright (c) 2021 ___ORGANIZATIONNAME___. All rights reserved.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2021-07-21 21:31:24 +00:00
|
|
|
#pragma nda NDAOpen NDAClose NDAAction NDAInit 2 0x03FF " Listener\\H**"
|
2021-07-16 16:37:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
#include <orca.h>
|
|
|
|
#include <GSOS.h>
|
|
|
|
#include <QuickDraw.h>
|
|
|
|
#include <Window.h>
|
|
|
|
#include <Desk.h>
|
|
|
|
#include <Event.h>
|
|
|
|
#include <Resources.h>
|
|
|
|
#include <MiscTool.h>
|
|
|
|
#include <Memory.h>
|
|
|
|
#include <Loader.h>
|
2021-07-20 04:14:16 +00:00
|
|
|
#include <locator.h>
|
2021-07-19 04:01:10 +00:00
|
|
|
#include <tcpip.h>
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
2021-07-19 04:01:10 +00:00
|
|
|
#include <string.h>
|
2021-07-16 16:37:38 +00:00
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
// Defines
|
|
|
|
|
|
|
|
#define LISTEN_PORT 19026
|
|
|
|
|
|
|
|
#define LISTEN_STATE_MSG 1
|
|
|
|
#define LISTEN_TEXT_MSG 2
|
2022-02-23 04:54:31 +00:00
|
|
|
#define LISTEN_SEND_MORE 3
|
2021-07-20 04:14:16 +00:00
|
|
|
|
|
|
|
#define WINDOW_CHAR_WIDTH 50
|
|
|
|
|
|
|
|
// Typedefs
|
|
|
|
|
|
|
|
typedef enum tListenState {
|
|
|
|
LISTEN_STATE_START = 0,
|
|
|
|
LISTEN_STATE_NETWORK_UNCONNECTED,
|
|
|
|
LISTEN_STATE_NETWORK_CONNECTED,
|
|
|
|
LISTEN_STATE_AWAITING_CONNECTION,
|
2021-07-20 23:05:19 +00:00
|
|
|
LISTEN_STATE_AWAITING_ESTABLISH,
|
2021-07-20 04:14:16 +00:00
|
|
|
LISTEN_STATE_AWAITING_MSG_HEADER,
|
2021-07-20 23:05:19 +00:00
|
|
|
LISTEN_STATE_AWAITING_TEXT,
|
2021-07-20 04:14:16 +00:00
|
|
|
|
|
|
|
LISTEN_STATE_ERROR,
|
|
|
|
|
|
|
|
NUM_LISTEN_STATES
|
|
|
|
} tListenState;
|
|
|
|
|
|
|
|
typedef struct tMessageHeader {
|
|
|
|
uint16_t messageType;
|
|
|
|
uint16_t messageArg;
|
|
|
|
} tMessageHeader;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct tTextList tTextList;
|
|
|
|
|
|
|
|
typedef struct tTextListHeader {
|
|
|
|
struct tTextList * next;
|
|
|
|
uint16_t size;
|
|
|
|
uint16_t position;
|
|
|
|
} tTextListHeader;
|
|
|
|
|
|
|
|
typedef struct tTextList {
|
|
|
|
tTextListHeader header;
|
|
|
|
char text[1];
|
|
|
|
} tTextList;
|
|
|
|
|
|
|
|
typedef struct tGlobals {
|
|
|
|
BOOLEAN ndaActive;
|
|
|
|
BOOLEAN tcpipStarted;
|
|
|
|
BOOLEAN networkConnected;
|
|
|
|
BOOLEAN hasListenIpid;
|
|
|
|
BOOLEAN hasConnIpid;
|
|
|
|
GrafPortPtr winPtr;
|
|
|
|
tListenState state;
|
|
|
|
Word listenIpid;
|
|
|
|
Word connIpid;
|
|
|
|
Word position;
|
|
|
|
tTextList * textListHead;
|
|
|
|
tTextList * textListTail;
|
|
|
|
tMessageHeader messageHeader;
|
|
|
|
tTextList * textTransfer;
|
|
|
|
char line1[WINDOW_CHAR_WIDTH];
|
|
|
|
char line2[WINDOW_CHAR_WIDTH];
|
|
|
|
char line3[WINDOW_CHAR_WIDTH];
|
|
|
|
} tGlobals;
|
|
|
|
|
|
|
|
typedef void (*tStateHandler)(void);
|
|
|
|
|
|
|
|
|
|
|
|
// Forward declarations
|
|
|
|
|
|
|
|
void handleStartState(void);
|
|
|
|
void handleNetworkUnconnectedState(void);
|
|
|
|
void handleNetworkConnectedState(void);
|
|
|
|
void handleAwaitingConnectionState(void);
|
2021-07-20 23:05:19 +00:00
|
|
|
void handleAwaitingEstablishState(void);
|
2021-07-20 04:14:16 +00:00
|
|
|
void handleAwaitingMsgHeaderState(void);
|
2021-07-20 23:05:19 +00:00
|
|
|
void handleAwaitingTextState(void);
|
2021-07-20 04:14:16 +00:00
|
|
|
void handleErrorState(void);
|
|
|
|
|
|
|
|
|
|
|
|
// Globals
|
|
|
|
|
|
|
|
static tGlobals * globals = NULL;
|
2021-07-16 16:37:38 +00:00
|
|
|
static unsigned int userId;
|
2021-07-20 04:14:16 +00:00
|
|
|
static tStateHandler stateHandlers[NUM_LISTEN_STATES] = {
|
|
|
|
handleStartState,
|
|
|
|
handleNetworkUnconnectedState,
|
|
|
|
handleNetworkConnectedState,
|
|
|
|
handleAwaitingConnectionState,
|
2021-07-20 23:05:19 +00:00
|
|
|
handleAwaitingEstablishState,
|
2021-07-20 04:14:16 +00:00
|
|
|
handleAwaitingMsgHeaderState,
|
2021-07-20 23:05:19 +00:00
|
|
|
handleAwaitingTextState,
|
2021-07-20 04:14:16 +00:00
|
|
|
|
|
|
|
handleErrorState,
|
|
|
|
};
|
|
|
|
static char * stateMessages[NUM_LISTEN_STATES] = {
|
|
|
|
"Starting network tools",
|
|
|
|
"Connecting to network",
|
|
|
|
"Creating listen socket",
|
|
|
|
"Waiting for connection",
|
2021-07-20 23:05:19 +00:00
|
|
|
"Establishing connection",
|
2021-07-20 04:14:16 +00:00
|
|
|
"Connected to device",
|
2021-07-20 23:05:19 +00:00
|
|
|
"Receiving text",
|
2021-07-20 04:14:16 +00:00
|
|
|
|
|
|
|
""
|
|
|
|
};
|
2021-07-16 16:37:38 +00:00
|
|
|
|
2021-07-19 04:01:10 +00:00
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
// Implementation
|
2021-07-16 16:37:38 +00:00
|
|
|
|
2022-03-15 03:48:36 +00:00
|
|
|
void delayToNextTick()
|
2021-07-16 16:37:38 +00:00
|
|
|
{
|
2022-03-15 03:48:36 +00:00
|
|
|
LongWord oldTickCounter = GetTick();
|
|
|
|
while (oldTickCounter == GetTick())
|
|
|
|
;
|
2021-07-16 16:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-15 03:48:36 +00:00
|
|
|
void closeConnection(void)
|
2021-07-20 04:14:16 +00:00
|
|
|
{
|
2022-03-15 03:48:36 +00:00
|
|
|
static srBuff srBuffer;
|
|
|
|
int counter;
|
2021-07-20 04:14:16 +00:00
|
|
|
|
2022-03-15 03:48:36 +00:00
|
|
|
if (globals->hasConnIpid) {
|
|
|
|
TCPIPCloseTCP(globals->connIpid);
|
|
|
|
for (counter = 0; counter < 20; counter++)
|
|
|
|
{
|
|
|
|
TCPIPPoll();
|
|
|
|
delayToNextTick();
|
|
|
|
TCPIPStatusTCP(globals->connIpid, &srBuffer);
|
|
|
|
if ((srBuffer.srState == TCPSCLOSED) ||
|
|
|
|
(srBuffer.srState == TCPSTIMEWAIT))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((srBuffer.srState != TCPSCLOSED) &
|
|
|
|
(srBuffer.srState != TCPSTIMEWAIT))
|
|
|
|
TCPIPAbortTCP(globals->connIpid);
|
|
|
|
TCPIPLogout(globals->connIpid);
|
2021-07-20 04:14:16 +00:00
|
|
|
}
|
2022-03-15 03:48:36 +00:00
|
|
|
globals->hasConnIpid = FALSE;
|
2021-07-20 04:14:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void teardownNetwork(void)
|
|
|
|
{
|
2022-03-15 03:48:36 +00:00
|
|
|
closeConnection();
|
2021-07-20 04:14:16 +00:00
|
|
|
|
|
|
|
if (globals->hasListenIpid) {
|
|
|
|
TCPIPCloseTCP(globals->listenIpid);
|
|
|
|
TCPIPLogout(globals->listenIpid);
|
|
|
|
}
|
|
|
|
globals->hasListenIpid = FALSE;
|
|
|
|
|
|
|
|
if (globals->networkConnected)
|
|
|
|
TCPIPDisconnect(TRUE, NULL);
|
|
|
|
globals->networkConnected = FALSE;
|
|
|
|
|
|
|
|
if (globals->tcpipStarted)
|
|
|
|
TCPIPShutDown();
|
|
|
|
globals->tcpipStarted = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-15 03:48:36 +00:00
|
|
|
void freeText(void)
|
|
|
|
{
|
|
|
|
tTextList * textList = globals->textListHead;
|
|
|
|
|
|
|
|
if (globals->textTransfer != NULL)
|
|
|
|
free(globals->textTransfer);
|
|
|
|
|
|
|
|
while (textList != NULL) {
|
|
|
|
tTextList * prev = textList;
|
|
|
|
textList = textList->header.next;
|
|
|
|
free(prev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void NDAClose(void)
|
|
|
|
{
|
|
|
|
if ((globals != NULL) &&
|
|
|
|
(globals->ndaActive)) {
|
|
|
|
CloseWindow(globals->winPtr);
|
|
|
|
globals->winPtr = NULL;
|
|
|
|
globals->ndaActive = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
teardownNetwork();
|
|
|
|
ResourceShutDown();
|
|
|
|
freeText();
|
|
|
|
memset(globals, 0, sizeof(*globals));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void freeGlobals(void)
|
|
|
|
{
|
|
|
|
freeText();
|
|
|
|
|
|
|
|
free(globals);
|
|
|
|
globals = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-16 16:37:38 +00:00
|
|
|
void NDAInit(int code)
|
|
|
|
{
|
|
|
|
/* When code is 1, this is tool startup, otherwise tool
|
|
|
|
* shutdown.
|
|
|
|
*/
|
|
|
|
if (code) {
|
|
|
|
userId = MMStartUp();
|
2021-07-20 04:14:16 +00:00
|
|
|
globals = malloc(sizeof(*globals));
|
|
|
|
memset(globals, 0, sizeof(*globals));
|
2021-07-16 16:37:38 +00:00
|
|
|
} else {
|
2021-07-20 04:14:16 +00:00
|
|
|
if ((globals != NULL) &&
|
|
|
|
(globals->ndaActive)) {
|
2021-07-16 16:37:38 +00:00
|
|
|
NDAClose();
|
2021-07-20 04:14:16 +00:00
|
|
|
teardownNetwork();
|
|
|
|
freeGlobals();
|
|
|
|
}
|
2021-07-16 16:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
void InvalidateWindow(void)
|
|
|
|
{
|
|
|
|
Rect frame;
|
|
|
|
SetPort(globals->winPtr);
|
|
|
|
GetPortRect(&frame);
|
|
|
|
frame.v2 -= frame.v1;
|
|
|
|
frame.h2 -= frame.h1;
|
|
|
|
frame.h1 = 0;
|
|
|
|
frame.v1 = 0;
|
|
|
|
InvalRect(&frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-16 16:37:38 +00:00
|
|
|
#pragma databank 1
|
|
|
|
void DrawContents(void)
|
|
|
|
{
|
2021-07-19 04:01:10 +00:00
|
|
|
Rect frame;
|
|
|
|
GetPortRect(&frame);
|
|
|
|
frame.v2 -= frame.v1;
|
|
|
|
frame.h2 -= frame.h1;
|
|
|
|
frame.h1 = 0;
|
|
|
|
frame.v1 = 0;
|
|
|
|
EraseRect(&frame);
|
|
|
|
|
2021-07-16 16:37:38 +00:00
|
|
|
PenNormal();
|
|
|
|
MoveTo(7,10);
|
2021-07-20 04:14:16 +00:00
|
|
|
DrawCString(globals->line1);
|
2021-07-19 04:01:10 +00:00
|
|
|
MoveTo(7,20);
|
2021-07-20 04:14:16 +00:00
|
|
|
DrawCString(globals->line2);
|
2021-07-19 04:01:10 +00:00
|
|
|
MoveTo(7,30);
|
2021-07-20 04:14:16 +00:00
|
|
|
DrawCString(globals->line3);
|
2021-07-16 16:37:38 +00:00
|
|
|
}
|
|
|
|
#pragma databank 0
|
|
|
|
|
|
|
|
|
|
|
|
GrafPortPtr NDAOpen(void)
|
|
|
|
{
|
|
|
|
unsigned int oldResourceApp;
|
|
|
|
LevelRecGS levelDCB;
|
|
|
|
unsigned int oldLevel;
|
|
|
|
SysPrefsRecGS prefsDCB;
|
|
|
|
unsigned int oldPrefs;
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
if (globals->ndaActive)
|
2021-07-16 16:37:38 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
levelDCB.pCount = 2;
|
|
|
|
GetLevelGS(&levelDCB);
|
|
|
|
oldLevel = levelDCB.level;
|
|
|
|
levelDCB.level = 0;
|
|
|
|
SetLevelGS(&levelDCB);
|
|
|
|
|
|
|
|
prefsDCB.pCount = 1;
|
|
|
|
GetSysPrefsGS(&prefsDCB);
|
|
|
|
oldPrefs = prefsDCB.preferences;
|
|
|
|
prefsDCB.preferences = (prefsDCB.preferences & 0x1fff) | 0x8000;
|
|
|
|
SetSysPrefsGS(&prefsDCB);
|
|
|
|
|
|
|
|
oldResourceApp = OpenResourceFileByID(readEnable, userId);
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
globals->winPtr = NewWindow2("\p Listener ", 0, DrawContents, NULL, 0x02, windowRes, rWindParam1);
|
2021-07-16 16:37:38 +00:00
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
SetSysWindow(globals->winPtr);
|
|
|
|
ShowWindow(globals->winPtr);
|
|
|
|
SelectWindow(globals->winPtr);
|
2021-07-16 16:37:38 +00:00
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
globals->ndaActive = TRUE;
|
2021-07-16 16:37:38 +00:00
|
|
|
|
|
|
|
prefsDCB.preferences = oldPrefs;
|
|
|
|
SetSysPrefsGS(&prefsDCB);
|
|
|
|
|
|
|
|
levelDCB.level = oldLevel;
|
|
|
|
SetLevelGS(&levelDCB);
|
|
|
|
|
|
|
|
SetCurResourceApp(oldResourceApp);
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
return globals->winPtr;
|
2021-07-16 16:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
void enterErrorState(char * errorString, Word errorCode)
|
|
|
|
{
|
|
|
|
strcpy(globals->line1, errorString);
|
|
|
|
sprintf(globals->line2, " Error code = $%04x", errorCode);
|
|
|
|
InvalidateWindow();
|
|
|
|
teardownNetwork();
|
|
|
|
globals->state = LISTEN_STATE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void newState(tListenState state)
|
|
|
|
{
|
|
|
|
strcpy(globals->line1, stateMessages[state]);
|
|
|
|
InvalidateWindow();
|
|
|
|
globals->state = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void handleStartState(void)
|
|
|
|
{
|
|
|
|
LoadOneTool(54, 0x200); // Load Marinetti
|
|
|
|
if (toolerror()) {
|
|
|
|
enterErrorState("Unable to load Marinetti", toolerror());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TCPIPStatus()) {
|
|
|
|
TCPIPStartUp();
|
|
|
|
if (toolerror()) {
|
|
|
|
enterErrorState("Unable to start Marinetti", toolerror());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
globals->tcpipStarted = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TCPIPGetConnectStatus()) {
|
|
|
|
newState(LISTEN_STATE_NETWORK_CONNECTED);
|
|
|
|
} else {
|
|
|
|
newState(LISTEN_STATE_NETWORK_UNCONNECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void handleNetworkUnconnectedState(void)
|
|
|
|
{
|
2021-07-20 23:05:19 +00:00
|
|
|
TCPIPPoll();
|
2021-07-20 04:14:16 +00:00
|
|
|
TCPIPConnect(NULL);
|
|
|
|
if ((!toolerror()) &&
|
|
|
|
(TCPIPGetConnectStatus())) {
|
|
|
|
globals->networkConnected = TRUE;
|
|
|
|
newState(LISTEN_STATE_NETWORK_CONNECTED);
|
|
|
|
} else {
|
|
|
|
enterErrorState("Unable to connect to network", toolerror());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void handleNetworkConnectedState(void)
|
2021-07-16 16:37:38 +00:00
|
|
|
{
|
2021-07-20 04:14:16 +00:00
|
|
|
Word error;
|
2021-07-19 04:01:10 +00:00
|
|
|
|
2021-07-20 23:05:19 +00:00
|
|
|
TCPIPPoll();
|
|
|
|
globals->listenIpid = TCPIPLogin(userId, 0, 0, 0, 64);
|
2021-07-20 04:14:16 +00:00
|
|
|
if (toolerror()) {
|
|
|
|
enterErrorState("Unable to create socket", toolerror());
|
2021-07-19 04:01:10 +00:00
|
|
|
return;
|
2021-07-20 04:14:16 +00:00
|
|
|
}
|
2021-07-19 04:01:10 +00:00
|
|
|
|
2021-07-20 23:05:19 +00:00
|
|
|
TCPIPSetSourcePort(globals->listenIpid, LISTEN_PORT);
|
|
|
|
if (toolerror()) {
|
|
|
|
enterErrorState("Unable to set port number", toolerror());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
error = TCPIPListenTCP(globals->listenIpid);
|
|
|
|
if (error != terrOK) {
|
|
|
|
TCPIPLogout(globals->listenIpid);
|
|
|
|
enterErrorState("Unable to listen on socket", error);
|
2021-07-19 04:01:10 +00:00
|
|
|
return;
|
2021-07-20 04:14:16 +00:00
|
|
|
}
|
|
|
|
globals->hasListenIpid = TRUE;
|
|
|
|
newState(LISTEN_STATE_AWAITING_CONNECTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void handleAwaitingConnectionState(void)
|
|
|
|
{
|
2021-07-20 23:05:19 +00:00
|
|
|
TCPIPPoll();
|
2021-07-20 04:14:16 +00:00
|
|
|
globals->connIpid = TCPIPAcceptTCP(globals->listenIpid, 0);
|
|
|
|
switch (toolerror()) {
|
|
|
|
case terrOK:
|
|
|
|
globals->hasConnIpid = TRUE;
|
2021-07-20 23:05:19 +00:00
|
|
|
newState(LISTEN_STATE_AWAITING_ESTABLISH);
|
2021-07-20 04:14:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case terrNOINCOMING:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
enterErrorState("Unable to accept connection", toolerror());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-20 23:05:19 +00:00
|
|
|
void handleAwaitingEstablishState(void)
|
|
|
|
{
|
|
|
|
static srBuff srBuffer;
|
|
|
|
|
|
|
|
TCPIPPoll();
|
|
|
|
|
|
|
|
TCPIPStatusTCP(globals->connIpid, &srBuffer);
|
|
|
|
if (toolerror()) {
|
|
|
|
enterErrorState("Unable to get connection state", toolerror());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (srBuffer.srState) {
|
|
|
|
case TCPSSYNSENT:
|
|
|
|
case TCPSSYNRCVD:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TCPSESTABLISHED:
|
|
|
|
newState(LISTEN_STATE_AWAITING_MSG_HEADER);
|
|
|
|
globals->position = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2022-03-16 03:22:56 +00:00
|
|
|
closeConnection();
|
|
|
|
newState(LISTEN_STATE_AWAITING_CONNECTION);
|
2021-07-20 23:05:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
void handleAwaitingMsgHeaderState(void)
|
|
|
|
{
|
2021-07-20 23:05:19 +00:00
|
|
|
static srBuff srBuffer;
|
|
|
|
static rrBuff readResponseBuf;
|
|
|
|
tTextList * textTransfer;
|
|
|
|
|
|
|
|
TCPIPPoll();
|
|
|
|
|
|
|
|
TCPIPStatusTCP(globals->connIpid, &srBuffer);
|
|
|
|
if (toolerror()) {
|
|
|
|
enterErrorState("Unable to get connection state", toolerror());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (srBuffer.srState != TCPSESTABLISHED) {
|
2022-03-15 03:48:36 +00:00
|
|
|
closeConnection();
|
2021-07-20 23:05:19 +00:00
|
|
|
newState(LISTEN_STATE_AWAITING_CONNECTION);
|
|
|
|
return;
|
|
|
|
}
|
2021-07-20 04:14:16 +00:00
|
|
|
Word error = TCPIPReadTCP(globals->connIpid, 0,
|
|
|
|
((uint32_t)(&(globals->messageHeader))) + globals->position,
|
|
|
|
sizeof(globals->messageHeader) - globals->position,
|
|
|
|
&readResponseBuf);
|
|
|
|
if (error != tcperrOK) {
|
|
|
|
enterErrorState("Unable to read from connection", error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
globals->position += readResponseBuf.rrBuffCount;
|
|
|
|
if (globals->position < sizeof(globals->messageHeader))
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (globals->messageHeader.messageType) {
|
|
|
|
case LISTEN_STATE_MSG:
|
|
|
|
if (globals->messageHeader.messageArg)
|
|
|
|
strcpy(globals->line2, " Listening...");
|
|
|
|
else
|
2021-07-20 04:17:05 +00:00
|
|
|
globals->line2[0] = '\0';
|
2021-07-20 04:14:16 +00:00
|
|
|
InvalidateWindow();
|
2021-07-20 23:05:19 +00:00
|
|
|
globals->position = 0;
|
2021-07-20 04:14:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LISTEN_TEXT_MSG:
|
2021-07-20 23:05:19 +00:00
|
|
|
textTransfer = malloc(sizeof(tTextListHeader) + globals->messageHeader.messageArg);
|
|
|
|
if (textTransfer == NULL) {
|
|
|
|
enterErrorState("Unable to get memory for text", 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
globals->textTransfer = textTransfer;
|
|
|
|
textTransfer->header.next = NULL;
|
|
|
|
textTransfer->header.size = globals->messageHeader.messageArg;
|
|
|
|
textTransfer->header.position = 0;
|
|
|
|
newState(LISTEN_STATE_AWAITING_TEXT);
|
2022-03-11 03:57:23 +00:00
|
|
|
if (FrontWindow() == globals->winPtr)
|
|
|
|
SendBehind((GrafPortPtr)toBottom, globals->winPtr);
|
2021-07-20 04:14:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
enterErrorState("Unexpected message type", globals->messageHeader.messageType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-20 23:05:19 +00:00
|
|
|
void handleAwaitingTextState(void)
|
|
|
|
{
|
|
|
|
static srBuff srBuffer;
|
|
|
|
static rrBuff readResponseBuf;
|
|
|
|
tTextList * textTransfer = globals->textTransfer;
|
|
|
|
|
|
|
|
TCPIPPoll();
|
|
|
|
|
|
|
|
TCPIPStatusTCP(globals->connIpid, &srBuffer);
|
|
|
|
if (toolerror()) {
|
|
|
|
enterErrorState("Unable to get connection state", toolerror());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (srBuffer.srState != TCPSESTABLISHED) {
|
2022-03-15 03:48:36 +00:00
|
|
|
closeConnection();
|
2021-07-20 23:05:19 +00:00
|
|
|
newState(LISTEN_STATE_AWAITING_CONNECTION);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Word error = TCPIPReadTCP(globals->connIpid, 0,
|
|
|
|
(uint32_t)(&(textTransfer->text[textTransfer->header.position])),
|
|
|
|
textTransfer->header.size - textTransfer->header.position,
|
|
|
|
&readResponseBuf);
|
|
|
|
if (error != tcperrOK) {
|
|
|
|
enterErrorState("Unable to read text from connection", error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
textTransfer->header.position += readResponseBuf.rrBuffCount;
|
|
|
|
if (textTransfer->header.position < textTransfer->header.size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (globals->textListTail != NULL) {
|
|
|
|
globals->textListTail->header.next = textTransfer;
|
|
|
|
} else {
|
|
|
|
globals->textListHead = textTransfer;
|
|
|
|
strcpy(globals->line3, " Typing...");
|
|
|
|
InvalidateWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
textTransfer->header.position = 0;
|
|
|
|
globals->textListTail = textTransfer;
|
|
|
|
globals->textTransfer = NULL;
|
|
|
|
newState(LISTEN_STATE_AWAITING_MSG_HEADER);
|
|
|
|
globals->position = 0;
|
|
|
|
}
|
2021-07-20 04:14:16 +00:00
|
|
|
|
|
|
|
void handleErrorState(void)
|
|
|
|
{
|
|
|
|
// Do nothing. Once we have entered the error state, then nothing more to do.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void runStateMachine(void)
|
|
|
|
{
|
|
|
|
stateHandlers[globals->state]();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void sendKey(void)
|
|
|
|
{
|
2022-03-15 03:48:36 +00:00
|
|
|
EventRecord eventRecord;
|
|
|
|
|
|
|
|
// If there is still a key down waiting to be processed, then don't send another one.
|
|
|
|
if (EventAvail(keyDownMask, &eventRecord))
|
|
|
|
return;
|
2021-07-19 04:01:10 +00:00
|
|
|
|
2022-03-15 03:48:36 +00:00
|
|
|
tTextList * textList = globals->textListHead;
|
2021-07-20 04:14:16 +00:00
|
|
|
PostEvent(keyDownEvt, 0x00C00000 | textList->text[textList->header.position]);
|
|
|
|
textList->header.position++;
|
|
|
|
if (textList->header.position < textList->header.size)
|
2021-07-19 04:01:10 +00:00
|
|
|
return;
|
|
|
|
|
2021-07-20 04:17:05 +00:00
|
|
|
if (textList == globals->textListTail) {
|
2021-07-20 04:14:16 +00:00
|
|
|
globals->textListTail = NULL;
|
2021-07-20 04:17:05 +00:00
|
|
|
globals->line3[0] = '\0';
|
|
|
|
InvalidateWindow();
|
|
|
|
}
|
2021-07-20 04:14:16 +00:00
|
|
|
|
|
|
|
globals->textListHead = textList->header.next;
|
|
|
|
free(textList);
|
2022-02-23 04:54:31 +00:00
|
|
|
|
|
|
|
// If there is no more text to type, let the other end know we are ready for more.
|
|
|
|
if ((globals->textListHead == NULL) &&
|
|
|
|
((globals->state == LISTEN_STATE_AWAITING_TEXT) ||
|
|
|
|
(globals->state == LISTEN_STATE_AWAITING_MSG_HEADER))) {
|
|
|
|
uint16_t msg = LISTEN_SEND_MORE;
|
|
|
|
TCPIPWriteTCP(globals->connIpid, (Pointer)&msg, sizeof(msg), FALSE, FALSE);
|
|
|
|
}
|
2021-07-16 16:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
void HandleRun(void)
|
2021-07-16 16:37:38 +00:00
|
|
|
{
|
2021-07-20 04:14:16 +00:00
|
|
|
if (globals == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
runStateMachine();
|
|
|
|
if (globals->textListHead != NULL)
|
|
|
|
sendKey();
|
2021-07-16 16:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-20 04:14:16 +00:00
|
|
|
void HandleControl(EventRecord *event)
|
2021-07-19 04:01:10 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-16 16:37:38 +00:00
|
|
|
void HandleKey(EventRecord *event)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void HandleCursor(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void HandleMenu(int menuItem)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN NDAAction(EventRecord *sysEvent, int code)
|
|
|
|
{
|
|
|
|
static EventRecord localEvent;
|
|
|
|
unsigned int eventCode;
|
|
|
|
BOOLEAN result = FALSE;
|
|
|
|
|
|
|
|
switch (code) {
|
|
|
|
case runAction:
|
|
|
|
HandleRun();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eventAction:
|
|
|
|
BlockMove((Pointer)sysEvent, (Pointer)&localEvent, 16);
|
|
|
|
localEvent.wmTaskMask = 0x001FFFFF;
|
|
|
|
eventCode = TaskMasterDA(0, &localEvent);
|
|
|
|
switch(eventCode) {
|
|
|
|
case updateEvt:
|
2021-07-20 04:14:16 +00:00
|
|
|
BeginUpdate(globals->winPtr);
|
2021-07-16 16:37:38 +00:00
|
|
|
DrawContents();
|
2021-07-20 04:14:16 +00:00
|
|
|
EndUpdate(globals->winPtr);
|
2021-07-16 16:37:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case wInControl:
|
|
|
|
HandleControl(&localEvent);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case keyDownEvt:
|
|
|
|
case autoKeyEvt:
|
|
|
|
HandleKey(&localEvent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case cursorAction:
|
|
|
|
HandleCursor();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case cutAction:
|
|
|
|
case copyAction:
|
|
|
|
case pasteAction:
|
|
|
|
case clearAction:
|
|
|
|
result = TRUE;
|
|
|
|
HandleMenu(code);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|