home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
telex1.sit
/
Telexƒ
/
Listen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-04
|
7KB
|
218 lines
/* ====================================== *\
** == AppleTalk Teletype == **
** == Listener code == **
** == (INIT) == **
** == Copyright ⌐ Gamma Software, 1990 == **
\* ====================================== */
/*
The AppleTalk cycle:
.. -> GetRequest(mySocket)
|
| ioCompletion
V
ReqCompleted -> InsertMessage -> SendResponse(mySocket)
|
| ioCompletion
V
RespCompleted -> GetRequest(mySocket)
The life cycle of one element:
InsertMessage -> (look for not-busy element) ->
-> busy=TRUE -> NMInstall(theElem)
|
| ioCompletion
V
NoteCompleted -> NMRemove(theElem) -> busy=FALSE
The structure of Telex messages:
+----------------------------+-----------------------------+
| Telex text (Pascal string) | Sender Name (Pascal String) |
+----------------------------+-----------------------------+
*/
#include "TelexDef"
static void ReqCompleted(void); /* AppleTalk cycle: Req received */
static void RespCompleted(void); /* AppleTalk cycle: Resp sent */
static void Check(int); /* Check OS return codes */
static void StartReq(Storage*); /* Initiating routine */
static short InsertMessage(Storage*);/* Insert a telex into NM queue */
static pascal void NoteCompleted(NoteBuf*);/* Telex is shown: remove it */
#ifdef THINK_C
static void* GetA0(void);
# define SaveD3() asm{\
MOVE.L D3,-(A7)\
}
# define RestD3() asm {\
MOVE.L (A7)+,D3\
}
#else
static void* GetA0 (void) = 0x2008; /* MOVE.L A0,D0 */
static void SaveD3(void) = 0x2F03; /* MOVE.L D3,-(A7) */
static void RestD3(void) = 0x261F; /* MOVE.L (A7)+,D3 */
#endif
/*
* Start of the "GetRequest"
* This routine MUST BE THE FIRST in the code resource if MPW is used:
* it is started from the INIT-code
* (Think adds its own starter code into the resource header)
*/
void main(Storage* theData) {
StartReq(theData);
}
/*
* The routine starts the GetRequest call.
* It's called from the Init at startup time and after SendResponse call
* Requests are received into the buffer in the Storage structure
*/
void StartReq(Storage* theData) {
theData->ReqBlock.ATPioCompletion = (ProcPtr) ReqCompleted;
theData->ReqBlock.ATPcsCode = tATPGetRequest;
theData->ReqBlock.ATPatpSocket = theData->ReqSocket;
theData->ReqBlock.ATPreqPointer = theData->ReqBuff;
theData->ReqBlock.ATPreqLength = sizeof(theData->ReqBuff);
Check(PGetRequest(&theData->ReqBlock,TRUE)); /* start async GetRequest */
}
/*
* End of the "GetRequest" operation:
* insert message in "Notification" queue, start "Response"
*/
static void ReqCompleted() {
Storage* theData;
SaveD3(); /* some compilers don't save it */
theData = (Storage*)GetA0(); /* A0 = ATblock address = Storage*/
if(theData->ReqBlock.ATPioResult == 0) { /* we received a nice request */
theData->ReqBlock.ATPioResult = 2; /* mark the recv block as "free" */
theData->RespWord=InsertMessage(theData);/* insert received telex into NM */
/* now prepare data for the Response */
theData->BDSArray[0].buffSize = sizeof(theData->RespWord);
theData->BDSArray[0].buffPtr = (Ptr) &theData->RespWord;
theData->RespBlock.ATPioCompletion = (ProcPtr)RespCompleted;
theData->RespBlock.ATPatpSocket = theData->ReqSocket;
theData->RespBlock.ATPcsCode = tATPSdRsp;
theData->RespBlock.ATPatpFlags = atpXOvalue;
theData->RespBlock.ATPaddrBlock = theData->ReqBlock.ATPaddrBlock;
theData->RespBlock.ATPbdsPointer = (Ptr) theData->BDSArray;
theData->RespBlock.ATPnumOfBuffs = 1;
theData->RespBlock.ATPbdsSize = 1;
theData->RespBlock.ATPtransID = theData->ReqBlock.ATPtransID;
Check(PSendResponse(&theData->RespBlock,TRUE)); /* start async Response */
} else { /* GetRequest operation failed */
StartReq(theData); /* -> restart the GetRequest */
}
RestD3(); /* since not all compilers do it */
}
/*
* Completion of the "Response" operation:
* start next "GetRequest" operation
*/
static void RespCompleted() {
Storage* theData; /* A0 = addr of respBlock */
SaveD3(); /* again, save D3 reg */
theData = (Storage*)((char*)GetA0()-sizeof(ATPParamBlock));
theData->RespBlock.ATPioResult = 2; /* response block is free */
StartReq(theData); /* start new GetRequest */
RestD3(); /* again, restore D3 reg */
}
/*
* Insert the telex message received into the "Notification" queue
*/
static short InsertMessage(Storage* theData) {
short i = Nnotes;
short error = -1;
/* Look for "Free" element among NoteBlocks*/
while(--i>=0 && theData->NoteBlocks[i].busy);
if(i>=0) { /* "free" element found */
NoteBuf* theNote = &theData->NoteBlocks[i];
unchar* theMess = theNote->mess;
unchar* theBody = (unchar*)theData->ReqBuff;
unchar* theUser = theBody+ *theBody +1; /* address of the Sender name */
int shift = 1;
int j = 0;
/* Copy Telex Header from the Storage into the Element */
while(shift<MaxMessSize-1 && j < *theData->MessHeader) {
theMess[shift++] = theData->MessHeader[++j];
}
theMess[shift++] = ' '; /* a space after the header */
/* Copy User Name from the message into the Element*/
j = 0;
if(theUser + *theUser < theBody+theData->ReqBlock.ATPreqLength) {
while(shift<MaxMessSize && j < *theUser) {
theMess[shift++] = theUser[++j];
}
}
/* Write the separator */
if(shift<MaxMessSize-2) { /* if there is enough space, draw */
theMess[shift++] = ':'; /* the separator:the semicolon sign*/
theMess[shift++] = 0x0D; /* and the Return (New Line) sign */
}
/* Copy Telex body from the Message buffer into the Element */
j=0;
while(shift<MaxMessSize && j<*theBody) {
theMess[shift++] = theBody[++j];
}
*theMess = (unchar) (shift-1); /* store the output string length */
theNote->busy = TRUE; /* Mark the Element as "busy" and */
theNote->q.nmResp = (ProcPtr)NoteCompleted; /* insert it into the NM queue*/
if(NMInstall((QElemPtr) &theNote->q) == 0) error = 0;
}
return(error);
}
/*
* Completion of the "Notification" request:
* remove from the NM queue, mark "Free"
*/
static pascal void NoteCompleted(NoteBuf* theNote) {
NMRemove((QElemPtr) &theNote->q);
theNote->busy = FALSE;
}
/*
* Check OS return codes: if non-zero, Beep: we can't do anything else here
*/
static void Check(int retcode) {
if(retcode != 0) SysBeep(1);
}
#ifdef THINK_C
static void* GetA0 () {asm{
MOVE.L A0,D0
}}
#endif