-- File: PressNetSender.mesa: Routines for sending a file to a printing server.
-- Last Edited: December 15, 1981 11:51 AM By: GWilliams
-- Changed CloseConnection to not do an EFTPFinishSending. If the transfer was successful, the receiving end closed the connection already and the finishsending causes the printer to botch the print.
DIRECTORY
EFTPDefs USING [eftpExternalReceiverAbort, --EFTPFinishSending,-- EFTPNotSending, eftpOK, EFTPOpenForSending, eftpOutOfSyncAbort, eftpReceiverBusyAbort, eftpRejected, EFTPSendBlock, EFTPTimeOut, EFTPTroubleSending],
PressNetDefs USING [attributesCode, imageCode, PageAttributes, PressNetErr, Printer, StingerAttributes, PrinterAttributes],
PupDefs USING [GetPupAddress, PupNameTrouble, PupPackageDestroy, PupPackageMake],
PupTypes USING[PupAddress, PupSocketID],
Storage USING [CopyString, FreeStringNil];
PressNetSender: PROGRAM
IMPORTS EFTPDefs, PupDefs, Storage
EXPORTS PressNetDefs =
BEGIN OPEN EFTPDefs, PressNetDefs, PupDefs, PupTypes, Storage;

--Pack Variables
firstScan, lastScan: CARDINAL;
pupPtr: POINTER TO PupAddress ← @sendToAddress;
sendErrorText: STRING ← NIL;
sendToAddress: PupAddress;
sendingRetries: CARDINAL ← 1;
scanLineLength: CARDINAL;
--for debugging
pageAttributes: PageAttributes ← [firstScan: 23, lastScan: 45, margin: 34, bitWc: 237];
PressSendError
: PUBLIC ERROR [err: PressNetErr, s: STRING]= CODE;
SendBuf: TYPE = MACHINE DEPENDENT RECORD
[code: CARDINAL,
pageAttributes: PageAttributes
];

--
Procs
GetPrinterAttributes: PUBLIC PROCEDURE[printer: Printer] RETURNS [pa: PrinterAttributes]=
{
RETURN[StingerAttributes];
};--
GetPrinterAttributes

PrinterReady: PUBLIC PROCEDURE [printer: Printer, retries: CARDINAL ← 1] RETURNS [goAhead: BOOLEAN ← FALSE]=
--If returns successfully, you have a connection.
--Later may return reason for no connection (i.e., printer down, not listening etc)
{pressNetErr: PressNetErr ← noError;

BEGIN

PupPackageMake[];
GetPupAddress[pupPtr, "Stinger"!
PupNameTrouble =>
{SELECT code FROM
noRoute => pressNetErr ← errorNoRoute;
noResponse => pressNetErr ← errorNoResponse;
errorFromServer => pressNetErr ← errorFromServer;
ENDCASE;
GOTO exit;};--do the GOTO to start UNWIND
];
pupPtr.socket ← PupSocketID[1, 25B];--[0, 20B] is the normal printer socket

EFTPOpenForSending[pupPtr↑, TRUE!
EFTPTroubleSending =>
{IF s # NIL THEN sendErrorText ← CopyString[s, 0];
SELECT e FROM
eftpOK => pressNetErr ← errorEftpOK;
eftpExternalReceiverAbort => pressNetErr ← errorEftpExternalReceiverAbort;
eftpReceiverBusyAbort => pressNetErr ← errorEftpReceiverBusyAbort;
eftpOutOfSyncAbort => pressNetErr ← errorEftpOutOfSyncAbort;
eftpRejected => pressNetErr ← errorEftpRejected;
ENDCASE;
GOTO exit;
};
EFTPTimeOut =>
IF (retries ← retries - 1) > 0
THEN RESUME
ELSE {pressNetErr ← errorTimedOut; GOTO exit};
];

goAhead ← TRUE;

EXITS
exit =>
BEGIN ENABLE UNWIND => IF sendErrorText # NIL THEN sendErrorText←FreeStringNil[sendErrorText];
PupPackageDestroy[];
SELECT pressNetErr FROM
errorNoRoute => ERROR PressSendError[pressNetErr, "Can’t Get there from here"];
errorNoResponse => ERROR PressSendError[pressNetErr, "Lookup Server doesn’t respond"];
errorFromServer => ERROR PressSendError[pressNetErr, "Lookup Server error."];
errorEftpOK, errorEftpExternalReceiverAbort, errorEftpReceiverBusyAbort, errorEftpOutOfSyncAbort =>
ERROR PressSendError[pressNetErr, sendErrorText];
errorEftpRejected, errorTimedOut => NULL;--simply return FALSE
ENDCASE;
END;
--of ENABLE for UNWIND
END;
}
;--PrinterReady

SetRetries:
PUBLIC PROC[n: CARDINAL]=
--this sets the retry count for all transfers after the connection is established
{
sendingRetries ← n};

SendLine: PUBLIC PROC[p: POINTER]=
BEGIN
SendBuffer[p, scanLineLength, sendingRetries, imageCode];--length in words
END;
--of SendLine

SendPageAttributes:
PUBLIC PROCEDURE[attrPt: POINTER TO PageAttributes]=
--this routine sends the page attributes to the printer.
--If goAhead returns FALSE, there was trouble with the parameters and the connection is closed.
{
sendBuf: SendBuf;
--let PressNetListener figure out all the PageG entries.

scanLineLength ← attrPt.bitWc;
firstScan ← attrPt.firstScan; lastScan ← attrPt.lastScan;
sendBuf.pageAttributes ← attrPt↑;--will this copy the whole record?
sendBuf.code ← attributesCode;

--send the info
SendBuffer[@sendBuf, SIZE[SendBuf], sendingRetries, ];--code is already in block

};
--SendPageAttributes


SendBuffer
: PROC[p: POINTER, len, timeout: CARDINAL, code: CARDINAL ← 0]=
--This routine calls SendBlock and renames all Errors for user
BEGIN
pressNetErr: PressNetErr ← noError;
BEGIN
--every buffer sent to the printer has a 1-word code at the beginning
IF code # 0 THEN
{EFTPSendBlock[@code, 2!--send the 2-byte code
EFTPTroubleSending =>
{IF s # NIL THEN sendErrorText ← CopyString[s, 0];
SELECT e FROM
eftpOK => pressNetErr ← errorEftpOK;
eftpExternalReceiverAbort => pressNetErr ← errorEftpExternalReceiverAbort;
eftpReceiverBusyAbort => pressNetErr ← errorEftpReceiverBusyAbort;
eftpOutOfSyncAbort => pressNetErr ← errorEftpOutOfSyncAbort;
eftpRejected => pressNetErr ← errorEftpRejected;
ENDCASE;
GOTO exit;
};
EFTPNotSending => {pressNetErr ← errorNotSending; GOTO exit};
EFTPTimeOut => IF (timeout ← timeout - 1) # 0
THEN RETRY
ELSE {pressNetErr ← errorTimedOut; GOTO exit};
];
};

EFTPSendBlock[p, len*2!
EFTPTroubleSending =>
{IF s # NIL THEN sendErrorText ← CopyString[s, 0];
SELECT e FROM
eftpOK => pressNetErr ← errorEftpOK;
eftpExternalReceiverAbort => pressNetErr ← errorEftpExternalReceiverAbort;
eftpReceiverBusyAbort => pressNetErr ← errorEftpReceiverBusyAbort;
eftpOutOfSyncAbort => pressNetErr ← errorEftpOutOfSyncAbort;
eftpRejected => pressNetErr ← errorEftpRejected;
ENDCASE;
GOTO exit;
};
EFTPNotSending => {pressNetErr ← errorNotSending; GOTO exit};
EFTPTimeOut => IF (timeout ← timeout - 1) # 0
THEN RETRY
ELSE {pressNetErr ← errorTimedOut; GOTO exit};
];
EXITS

exit =>
BEGIN ENABLE UNWIND => IF sendErrorText # NIL THEN sendErrorText←FreeStringNil[sendErrorText];
SELECT pressNetErr FROM
errorNoRoute => ERROR PressSendError[pressNetErr, "Can’t Get there from here"L];
errorNoResponse => ERROR PressSendError[pressNetErr, "Lookup Server doesn’t respond"L];
errorFromServer => ERROR PressSendError[pressNetErr, "Lookup Server error."L];
errorEftpOK, errorEftpExternalReceiverAbort, errorEftpReceiverBusyAbort, errorEftpOutOfSyncAbort, errorEftpRejected
=> ERROR PressSendError[pressNetErr, sendErrorText];
errorTimedOut => ERROR PressSendError[pressNetErr, "Timed out while sending data."L];
ENDCASE;
END;
--of ENABLE for UNWIND
END;
END;
--SendBuffer

CloseConnection:
PUBLIC PROC[]=
--A connection will be kept open until this routine is called. Don’t forget to call it!
{--
nRetries: CARDINAL ← 3;

--
EFTPFinishSending[!
--
EFTPNotSending => CONTINUE;
--
EFTPTimeOut => IF (nRetries ← nRetries - 1) # 0 THEN RESUME ELSE GOTO timeout;];
PupPackageDestroy[];

--EXITS
--
timeout => PupPackageDestroy[];
};
--CloseConnection

END.
-- PressNetSender.mesa
-- Last Edited: October 20, 1981 4:13 PM By: GWilliams
-- Last Edited: October 27, 1981 5:15 PM By: GWilliams
-- added totalBytesRead
-- Last Edited: November 17, 1981 3:17 PM By: GWilliams
-- Changing the thrust of the program to transmit the image information on a scan-line basis rather than by trying to send press.bits as an intact file. This decouples knowledge of press.bits from the image.
-- Last Edited: December 8, 1981 5:33 PM By: GWilliams
-- Started debugging.
-- Last Edited: December 10, 1981 11:22 AM By: GWilliams
-- in PrinterReady, now just return FALSE if I catch eftpRejected ("no such port"). This is raised if EFTP is running on another port at the printer.