qserver/qserver.c

555 lines
11 KiB
C
Raw Permalink Normal View History

2018-11-22 05:00:04 +00:00
#pragma nda NDAOpen NDAClose NDAAction NDAInit 30 0xffff "--Quote Server\\H**"
2018-04-01 19:42:52 +00:00
#pragma lint -1
#pragma optimize -1
2018-11-22 05:00:04 +00:00
#include <Control.h>
2018-04-01 19:42:52 +00:00
#include <Desk.h>
#include <Event.h>
#include <Font.h>
2018-11-22 05:00:04 +00:00
#include <GSOS.h>
#include <Loader.h>
#include <Locator.h>
#include <Memory.h>
#include <QDAux.h>
#include <Quickdraw.h>
#include <Resources.h>
#include <TCPIP.h>
2018-04-01 19:42:52 +00:00
#include <TextEdit.h>
2018-11-22 05:00:04 +00:00
#include <Types.h>
#include <Window.h>
2018-04-01 19:42:52 +00:00
#include <intmath.h>
#include <misctool.h>
2018-11-22 05:00:04 +00:00
#include <stdfile.h>
2018-04-01 19:42:52 +00:00
2018-11-19 02:23:47 +00:00
#include <stdio.h>
2018-04-01 19:42:52 +00:00
#include "qserver.h"
2018-11-20 03:25:56 +00:00
unsigned NDAStartUpTools(Word memID, StartStopRecord *ssRef);
void NDAShutDownTools(StartStopRecord *ssRef);
2018-11-22 04:55:15 +00:00
typedef struct NDAResourceCookie {
Word oldPrefs;
Word oldRApp;
Word resFileID;
} NDAResourceCookie;
void NDAResourceRestore(NDAResourceCookie *cookie);
void NDAResourceShutDown(NDAResourceCookie *cookie);
Word NDAResourceStartUp(Word memID, Word access, NDAResourceCookie *cookie);
2018-04-01 19:42:52 +00:00
Handle LoadQuote(word mID, Word rfile);
Word LoadConfig(Word MemID);
void UnloadConfig(void);
void DoConfig(Word MemID);
const char *ReqName = "\pTCP/IP~kelvin~qserver~";
/*
variables
*/
WindowPtr MyWindow;
Boolean FlagTCP;
Boolean FlagQS;
2018-11-22 04:55:15 +00:00
Boolean ToolsLoaded;
2018-04-01 19:42:52 +00:00
Word MyID;
Word Ipid;
word rFile;
Handle rPath;
word rCount;
2018-11-22 05:00:04 +00:00
struct qentry {
Word ipid;
Word state;
Longword tick;
2018-04-01 19:42:52 +00:00
};
#define QSIZE 16
struct qentry queue[QSIZE];
word total;
word current;
2018-11-22 05:00:04 +00:00
void fixstats(void) {
static char stats[16];
Word i;
2018-04-01 19:42:52 +00:00
2018-11-19 02:23:47 +00:00
i = sprintf(stats + 1, "%u : %u", current, total);
2018-04-01 19:42:52 +00:00
stats[0] = i; // pascal string
SetInfoRefCon((LongWord)stats, MyWindow);
DrawInfoBar(MyWindow);
}
2018-11-22 05:00:04 +00:00
void InsertString(word length, char *cp) {
Handle handle;
TERecord **temp;
longword oldStart, oldEnd;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
handle = (Handle)GetCtlHandleFromID(MyWindow, CtrlTE);
temp = (TERecord **)handle;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
(**temp).textFlags &= (~fReadOnly);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
TEGetSelection((pointer)&oldStart, (pointer)&oldEnd, handle);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
TESetSelection((Pointer)-1, (Pointer)-1, handle);
TEInsert(teDataIsTextBlock, (Ref)cp, length, NULL, NULL, /* no style info */
handle);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
(**temp).textFlags |= fReadOnly;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
TESetSelection((Pointer)oldStart, (Pointer)oldEnd, handle);
2018-04-01 19:42:52 +00:00
}
2018-11-22 05:00:04 +00:00
enum {
STATE_NULL = 0,
STATE_ESTABLISH, // waiting to establish
STATE_QUOTE, // send the quote...
STATE_SEND, // waiting for data to send
STATE_CLOSE
2018-04-01 19:42:52 +00:00
};
2018-11-22 05:00:04 +00:00
void QServer(void) {
static srBuff srBuffer;
word delta;
int i;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
delta = false;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
TCPIPPoll();
for (i = 0; i < QSIZE; i++) {
word ipid;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
ipid = queue[i].ipid;
if (!ipid)
continue;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
TCPIPStatusTCP(ipid, &srBuffer);
if (_toolErr) {
queue[i].ipid = 0;
queue[i].state = 0;
current--;
delta = true;
continue;
}
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
if (srBuffer.srState == TCPSCLOSED) {
TCPIPLogout(ipid);
queue[i].ipid = 0;
queue[i].state = 0;
current--;
delta = true;
continue;
}
switch (queue[i].state) {
case STATE_ESTABLISH:
if (srBuffer.srState != TCPSESTABLISHED)
break;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
queue[i].state = STATE_QUOTE;
// drop through and send the quote.
case STATE_QUOTE: {
Handle h;
h = LoadQuote(MyID, rFile);
if (h) {
HLock(h);
TCPIPWriteTCP(ipid, *h, GetHandleSize(h), false, false);
DisposeHandle(h);
} else {
TCPIPWriteTCP(ipid, "Your quote here!\r\n", 18, false, false);
}
queue[i].state = STATE_SEND;
break;
2018-11-23 21:15:55 +00:00
}
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
case STATE_SEND:
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
if (srBuffer.srSndQueued == 0) {
TCPIPCloseTCP(ipid);
queue[i].state = STATE_CLOSE;
}
break;
}
}
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
// check for a new connection.
if (current < QSIZE) {
word child;
int i;
child = TCPIPAcceptTCP(Ipid, 0);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
if (!_toolErr)
for (i = 0; i < QSIZE; i++) {
if (!queue[i].ipid) {
static char buffer[16];
static char line[32];
int j;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
TCPIPStatusTCP(child, &srBuffer);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
queue[i].ipid = child;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
if (srBuffer.srState == TCPSESTABLISHED)
queue[i].state = STATE_SEND;
else
queue[i].state = STATE_ESTABLISH;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
queue[i].tick = GetTick();
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
current++;
total++;
delta = true;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
TCPIPConvertIPToASCII(srBuffer.srDestIP, buffer, 0);
2018-04-01 19:42:52 +00:00
2018-11-23 21:15:45 +00:00
j = sprintf(line, "%b:%u\r", buffer, srBuffer.srDestPort);
2018-04-01 19:45:56 +00:00
2018-11-22 05:00:04 +00:00
InsertString(j, line);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
break;
}
}
}
if (delta)
fixstats(); // statistics changed.
2018-04-01 19:42:52 +00:00
}
2018-11-22 05:00:04 +00:00
int StartServer(void) {
int i;
word oFile;
word oDepth;
static char err[256];
GSString255 *path;
total = current = 0;
if (!rPath) {
InsertString(32, "Fatal: No quote file specified.\r");
return false;
}
HLock(rPath);
path = *(GSString255 **)rPath;
rFile = OpenResourceFile(readEnable, NULL, (pointer)path);
if (_toolErr) {
/* todo */
InsertString(
sprintf(err, "Fatal: Unable to open %.*s\r", path->length, path->text),
err);
return false;
}
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
oFile = GetCurResourceFile();
SetCurResourceFile(rFile);
oDepth = SetResourceFileDepth(1);
rCount = CountResources(rTextForLETextBox2);
SetCurResourceFile(oFile);
SetResourceFileDepth(oDepth);
if (!rCount) {
/* todo */
InsertString(sprintf(err, "Fatal: Invalid quote file %.*s\r", path->length,
path->text),
err);
CloseResourceFile(rFile);
return false;
}
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
SetRandSeed(GetTick());
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
for (i = 0; i < QSIZE; i++) {
queue[i].ipid = 0;
queue[i].state = 0;
}
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
Ipid = TCPIPLogin(MyID, 0, 0, 0, 64);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
TCPIPSetSourcePort(Ipid, PORT_QOTD);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
TCPIPListenTCP(Ipid);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
FlagQS = true;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
HiliteCtlByID(inactiveHilite, MyWindow, CtrlStartQS);
HiliteCtlByID(noHilite, MyWindow, CtrlStopQS);
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
fixstats();
HUnlock(rPath);
2018-04-01 19:45:56 +00:00
2018-11-22 05:00:04 +00:00
InsertString(16, "QServer started\r");
return true;
2018-04-01 19:42:52 +00:00
}
2018-11-22 05:00:04 +00:00
int StopServer(void) {
int i;
// close any q entries
for (i = 0; i < QSIZE; i++) {
int ipid;
ipid = queue[i].ipid;
if (ipid) {
TCPIPAbortTCP(ipid);
TCPIPLogout(ipid);
queue[i].ipid = 0;
}
}
TCPIPCloseTCP(Ipid);
TCPIPLogout(Ipid);
FlagQS = false;
Ipid = 0;
HiliteCtlByID(inactiveHilite, MyWindow, CtrlStopQS);
HiliteCtlByID(noHilite, MyWindow, CtrlStartQS);
CloseResourceFile(rFile);
SetInfoRefCon((LongWord) "\pServer stopped", MyWindow);
DrawInfoBar(MyWindow);
InsertString(16, "QServer stopped\r");
return true;
}
2018-04-01 19:42:52 +00:00
// activate/inactivate controls based on Marinetti status
2018-11-22 05:00:04 +00:00
void UpdateStatus(Boolean redraw) {
2018-04-01 19:42:52 +00:00
if (FlagTCP) // TCP started
{
2018-11-22 05:00:04 +00:00
// deactivate
2018-04-01 19:42:52 +00:00
HiliteCtlByID(inactiveHilite, MyWindow, CtrlStartM);
HiliteCtlByID(inactiveHilite, MyWindow, CtrlStopQS);
// activate
HiliteCtlByID(noHilite, MyWindow, CtrlStopM);
HiliteCtlByID(noHilite, MyWindow, CtrlStartQS);
2018-11-22 05:00:04 +00:00
SetInfoRefCon((LongWord) "\pNetwork Connected", MyWindow);
} else {
// activate
2018-04-01 19:42:52 +00:00
HiliteCtlByID(noHilite, MyWindow, CtrlStartM);
// deactivate
HiliteCtlByID(inactiveHilite, MyWindow, CtrlStopM);
HiliteCtlByID(inactiveHilite, MyWindow, CtrlStartQS);
HiliteCtlByID(inactiveHilite, MyWindow, CtrlStopQS);
2018-11-22 05:00:04 +00:00
SetInfoRefCon((LongWord) "\pNetwork Disconnected", MyWindow);
2018-04-01 19:42:52 +00:00
}
2018-11-22 05:00:04 +00:00
if (redraw)
2018-04-01 19:42:52 +00:00
DrawInfoBar(MyWindow);
}
2018-11-22 05:00:04 +00:00
#pragma databank 1
2018-04-01 19:42:52 +00:00
/*
* watch for
*/
2018-11-22 05:00:04 +00:00
pascal word HandleRequest(word request, longword dataIn, longword dataOut) {
Word oldRApp;
2018-04-01 19:42:52 +00:00
oldRApp = GetCurResourceApp();
SetCurResourceApp(MyID);
2018-11-22 05:00:04 +00:00
if (request == TCPIPSaysNetworkUp) {
2018-04-01 19:42:52 +00:00
FlagTCP = true;
UpdateStatus(true);
}
2018-11-22 05:00:04 +00:00
if (request == TCPIPSaysNetworkDown) {
if (FlagQS)
StopServer();
2018-04-01 19:42:52 +00:00
FlagTCP = false;
Ipid = 0;
UpdateStatus(true);
}
SetCurResourceApp(oldRApp);
}
2018-11-22 05:00:04 +00:00
pascal void MarinettiCallback(char *str) {
if (MyWindow) {
2018-04-01 19:42:52 +00:00
SetInfoRefCon((LongWord)str, MyWindow);
DrawInfoBar(MyWindow);
}
}
2018-11-22 05:00:04 +00:00
pascal void DrawInfo(void *rect, const char *str, GrafPortPtr w) {
if (str) {
2018-04-01 19:42:52 +00:00
SetForeColor(0x00);
SetBackColor(0x0f);
2018-11-22 05:00:04 +00:00
MoveTo(8, 22);
2018-04-01 19:42:52 +00:00
DrawString(str);
}
}
2018-11-22 05:00:04 +00:00
void DrawWindow(void) { DrawControls(GetPort()); }
2018-04-01 19:42:52 +00:00
#pragma databank 0
2018-04-01 19:45:56 +00:00
2018-11-22 05:00:04 +00:00
static StartStopRecord ss = {0,
0,
0,
0,
4,
{
0x12, 0x0000, /* QD Aux */
0x17, 0x0000, /* Std File */
0x1b, 0x0000, /* Font Manager */
0x22, 0x0000, /* Text Edit */
0x36, 0x0300, /* TCP */
2018-04-01 19:45:56 +00:00
2018-11-22 05:00:04 +00:00
}
2018-04-01 19:42:52 +00:00
2018-11-20 03:25:56 +00:00
};
2018-04-01 19:45:56 +00:00
2018-11-22 04:55:15 +00:00
static NDAResourceCookie resInfo;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
GrafPortPtr NDAOpen(void) {
2018-04-01 19:42:52 +00:00
2018-11-22 04:55:15 +00:00
MyWindow = NULL;
if (!ToolsLoaded) {
if (NDAStartUpTools(MyID, &ss)) {
NDAShutDownTools(&ss);
return NULL;
}
ToolsLoaded = true;
2018-11-20 03:25:56 +00:00
}
2018-04-01 19:42:52 +00:00
// Check if Marinetti Active.
2018-04-01 19:45:56 +00:00
FlagTCP = TCPIPGetConnectStatus();
2018-04-01 19:42:52 +00:00
2018-11-22 04:55:15 +00:00
if (NDAResourceStartUp(MyID, readEnable, &resInfo)) {
LoadConfig(MyID);
2018-11-22 05:00:04 +00:00
MyWindow = NewWindow2(NULL, 0, DrawWindow, NULL, refIsResource, rQSWindow,
rWindParam1);
2018-04-01 19:42:52 +00:00
SetInfoDraw(DrawInfo, MyWindow);
UpdateStatus(false);
AcceptRequests(ReqName, MyID, &HandleRequest);
SetSysWindow(MyWindow);
ShowWindow(MyWindow);
SelectWindow(MyWindow);
}
2018-11-22 04:55:15 +00:00
NDAResourceRestore(&resInfo);
return MyWindow;
2018-04-01 19:42:52 +00:00
}
2018-11-22 05:00:04 +00:00
void NDAClose(void) {
// if running, shut down.
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
if (FlagQS)
StopServer();
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
AcceptRequests(ReqName, MyID, NULL);
CloseWindow(MyWindow);
MyWindow = NULL;
2018-11-22 04:55:15 +00:00
2018-11-22 05:00:04 +00:00
UnloadConfig();
NDAResourceShutDown(&resInfo);
2018-04-01 19:42:52 +00:00
}
2018-11-22 05:00:04 +00:00
void NDAInit(Word code) {
if (code) {
2018-04-01 19:42:52 +00:00
MyWindow = NULL;
FlagTCP = false;
FlagQS = false;
2018-11-22 04:55:15 +00:00
ToolsLoaded = false;
2018-04-01 19:42:52 +00:00
MyID = MMStartUp();
Ipid = 0;
2018-11-22 05:00:04 +00:00
} else {
2018-11-22 04:55:15 +00:00
if (ToolsLoaded)
NDAShutDownTools(&ss);
ToolsLoaded = false;
2018-04-01 19:42:52 +00:00
}
}
2018-11-22 05:00:04 +00:00
word NDAAction(void *param, int code) {
word eventCode;
static EventRecord event = {0};
static word counter = 0;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
if (code == runAction) {
if (FlagQS)
QServer();
2018-04-01 19:42:52 +00:00
return 1;
}
2018-11-22 05:00:04 +00:00
else if (code == eventAction) {
2018-04-01 19:42:52 +00:00
BlockMove((Pointer)param, (Pointer)&event, 16);
event.wmTaskMask = 0x001FFFFF;
eventCode = TaskMasterDA(0, &event);
2018-11-22 05:00:04 +00:00
switch (eventCode) {
2018-04-01 19:42:52 +00:00
case updateEvt:
BeginUpdate(MyWindow);
DrawWindow();
EndUpdate(MyWindow);
break;
case wInControl:
2018-11-22 05:00:04 +00:00
switch (event.wmTaskData4) {
2018-04-01 19:42:52 +00:00
/* start marinetti */
case CtrlStartM:
//
2018-11-22 05:00:04 +00:00
if (TCPIPGetConnectStatus()) {
2018-04-01 19:42:52 +00:00
FlagTCP = true;
UpdateStatus(true);
2018-11-22 05:00:04 +00:00
} else {
2018-04-01 19:42:52 +00:00
TCPIPConnect(MarinettiCallback);
}
break;
/* stop marinetti */
case CtrlStopM:
2018-11-22 05:00:04 +00:00
if (!TCPIPGetConnectStatus()) {
2018-04-01 19:42:52 +00:00
FlagTCP = false;
UpdateStatus(true);
2018-11-22 05:00:04 +00:00
} else {
if (FlagQS)
StopServer();
2018-04-01 19:42:52 +00:00
// if option key down, force a shutdown.
TCPIPDisconnect(event.modifiers & optionKey, MarinettiCallback);
}
break;
2018-11-22 05:00:04 +00:00
/* start the server */
case CtrlStartQS:
StartServer();
break;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
/* stop the server */
case CtrlStopQS:
StopServer();
break;
2018-04-01 19:42:52 +00:00
2018-11-22 05:00:04 +00:00
case CtrlConfig:
DoConfig(MyID);
break;
2018-04-01 19:42:52 +00:00
}
// todo - Command-A selects all.
}
2018-11-22 05:00:04 +00:00
} else if (code == copyAction) {
2018-04-01 19:42:52 +00:00
TECopy(NULL);
return 1; // yes we handled it.
}
2018-11-22 05:00:04 +00:00
return 0;
2018-04-01 19:42:52 +00:00
}