-- File: PressNetSender.mesa: Routines for sending a file to a printing server.
-- Last February 8, 1982 1:59 PM By: GWilliams
-- Can now talk to Platemaker.

DIRECTORY
EFTPDefs USING [EFTPAbortCode, EFTPFinishSending, EFTPNotSending, EFTPOpenForSending, EFTPSendBlock, EFTPTimeOut, EFTPTroubleSending],
PressNetDefs USING [attributesCode, DLP1Attributes, imageCode, PageAttributes, PressNetErr, Printer, StingerAttributes, PrinterAttributes],
PupDefs USING [GetPupAddress, PupNameTrouble, PupPackageDestroy, PupPackageMake],
PupStream USING [NameLookupErrorCode],
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;

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]=
{
SELECT printer FROM
Stinger => RETURN[StingerAttributes];
DLP1 => RETURN[DLP1Attributes];
ENDCASE;
};--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;
deviceString: STRING;
stingerString: STRING ← "Stinger";
dLP1String: STRING ← "Platemaker";

SELECT printer FROM
Stinger => deviceString ← stingerString;
DLP1 => deviceString ← dLP1String;
ENDCASE;

BEGIN

PupPackageMake[];
GetPupAddress[pupPtr, deviceString!
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: LONG 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: LONG 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];
PupPackageDestroy[];
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 ← 5;

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.
-- 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.
-- Last Edited: 23-Dec-81 14:54:33 By: GWilliams
-- SendLine now takes a long pointer.
-- Last Edited: 4-Jan-82 18:16:42 By: GWilliams
-- Call PupPackageDestroy before raising any error from SendBlock.