*DECK IPPRECV
USETEXT TEXTIPL
USETEXT TEXTXDR
PROC IPPRECV (SOCKID, BUFFER, BUFLEN, ADDRESS, SOCKSTATUS);
*CALL COPYRITE CDCNET - COPYRIGHT CONTROL DATA. 1992.
# TITLE IPPRECV - RECEIVE DATA FOR SOCKET #
BEGIN # IPPRECV #
#
**** IPPRECV RECEIVE DATA FOR SOCKET
*
* THIS PROCEDURE OBTAINS A BLOCK OF DATA FOR THE SOCKET.
*
* PROC IPPRECV
*
* ENTRY SOCKID = INTEGER VALUE OF SOCKET
* BUFFER = BUFFER TO PLACE THE DATA
*
* EXIT BUFFER = BUFFER WITH RECEIVED DATA
* BUFLEN = INTEGER VALUE OF NUMBER BYTES IN BUFFER
* ADDRESS = 4 WORD SOURCE IP ADDRESS ARRAY
* SOCKSTATUS = COMPLETION STATUS
*
* METHOD IF THE SOCKET HAS BEEN ABORTED BY NAM, RETURN AN ABORT
* STATUS TO INFORM THE CALLER. IF THE SOCKET
* IS NOT CONNECTED, RETURN AN ERROR STATUS. IF DATA
* IS NOT QUEUED TO THE CONNECTION AND THE SOCKET BLOCKS,
* LOOP CALLING THE NAM INPUT HANDLER UNTIL DATA IS
* RECEIVED OR THE SPECIFIED BLOCKING TIMER HAS EXPIRED.
* IF DATA IS RECEIVED, EXTRACT THE HEADER AND VERIFY THE
* REQUEST AND UDP VERSION. PLACE THE SOURCE ADDRESS FROM
* THE HEADER INTO *ADDRESS*, AND THE REMAINDER DATA INTO
* *BUFFER*. ISSUE A LST/ON SM TO NAM SO MORE DATA CAN
* BE SENT TO THE APPLICATION.
#
#
**** PROC IPPRECV - XREF LIST
#
XREF
BEGIN
PROC IMNS; # MOVE NON-OVERLAPPING STRING #
PROC IPIAIPA; # ABORT IP APPLICATION #
PROC IPIDOSM; # DISPATCH OUTPUT SUPERVISORY MESSAGE #
PROC IPINITH; # NAM INPUT TRAFFIC HANDLER #
PROC MESSAGE; # ISSUE DAYFILE MESSAGE #
PROC RTIME; # REAL TIME CLOCK #
PROC XDRBYTE; # CONVERT BYTES TO XDR FORMAT #
PROC XDRINT; # CONVERT INTEGERS TO XDR FORMAT #
PROC XWHD; # CONVERT HEXIDECIMAL TO DISPLAY #
END
#
**
#
ITEM SOCKID I; # SOCKET IDENTIFIER #
ARRAY BUFFER [00:00] S(1);; # BUFFER TO RECEIVE DATA #
ARRAY ADDRESS [00:00] S(1);; # SOURCE ADDRESS FOR DATA #
ITEM BUFLEN U; # LENGTH OF DATA IN BUFFER #
ITEM SOCKSTATUS S:SOCKSTAT; # RETURNED SOCKET STATUS #
#
**** THIS ARRAY DEFINES THE DAYFILE MESSAGE FOR DISPLAYING AN INVALID
* MESSAGE RECEIVED.
#
ARRAY DATAMSG [00:00] S(3);
BEGIN
ITEM DATA$TEXT C(00,00,20);
ITEM DATA$ZBYTE U(02,00,60) = [0];
END
#
**** BASED ARRAY WHICH POINTS TO THE BLOCK OF DATA THAT WAS RECEIVED BY
* NAM.
#
BASED ARRAY INP$BUF [00:INPSIZE$] S(1);
BEGIN
ITEM INP$WRD U(00,00,60); # FULL WORD REFERENCE #
END
ITEM DESTBUF I; # CURRENT WRD LOCATION IN BUFFER#
ITEM DESTPOS U; # BIT OFFSET IN BUFFER WORD #
ITEM INDEX I; # LOOP COUNTER #
ITEM INPPOS U; # OFFSET IN INP$BUF BYTE #
ITEM LOOP I; # LOOP COUNTER #
ITEM MOVEBITS U; # BITS TO MOVE TO *BUFFER* #
ITEM SCRBUF U; # CURRENT LOCATION INP$BUF #
ITEM SCRPOS U; # BIT OFFSET IN INP$BUF WORD #
ITEM WAITLOOP I; # NUMBER OF WAIT CYCLES #
BASED ARRAY IPADDR [00:00] S(1);;# SOURCE ADDRESS FOR XDR CALL #
CONTROL EJECT;
#
**** START MAIN PROCEDURE
#
IF (ACN$ABORT [SOCKID])
THEN
BEGIN # CONNECTION ABORTED #
SOCKSTATUS = S"ABORT";
RETURN;
END
IF NOT ACN$CONNECT [SOCKID]
THEN
BEGIN
SOCKSTATUS = SOCKSTAT"INVALIDST";
RETURN;
END
BLOCK = ACN$BLOCK [SOCKID]; # SET GLOBAL BLOCKING FLAG #
IF NOT ACN$DATAV [SOCKID]
THEN
BEGIN # DATA NOT AVAILABLE #
IF BLOCK
THEN
BEGIN # IF BLOCKING #
WAITLOOP = ACN$WAITIME [SOCKID] / 2 + 1;
RTIME (BWT$TIME); # CURRENT TIME #
BWT$EXPIRE [0] = BWT$SECONDS [0] + ACN$WAITIME [SOCKID];
#
**** CONTINUE POLLING THE NETWORK FOR DATA UNTIL EITHER DATA IS
* IS RECEIVED ON THE CONNECTION OR UNTIL THE WAIT TIMER HAS EXPIRED.
* THE LOOP COUNTER IS SET TO THE TIME/2 DUE TO THE NETWAIT TIME OF
* 2 SECONDS WHILE BLOCKING.
#
FOR LOOP = 0
WHILE (NOT ACN$DATAV [SOCKID])
DO
BEGIN # WAIT FOR DATA OR EXPIRED TIME #
FOR INDEX = 1 STEP 1
WHILE (NOT ACN$DATAV [SOCKID]) AND
(NOT ACN$ABORT [SOCKID]) AND
(INDEX LQ WAITLOOP)
DO
BEGIN
IPINITH; # NAM INPUT TRAFFIC HANDLER #
END
IF (ACN$ABORT [SOCKID])
THEN
BEGIN # CONNECTION ABORTED #
SOCKSTATUS = S"ABORT";
RETURN;
END
IF NOT ACN$DATAV [SOCKID]
THEN
BEGIN # CHECK IF TIMED OUT #
RTIME (BWT$TIME);
IF (BWT$SECONDS [0] GQ BWT$EXPIRE [0])
THEN
BEGIN # TIMER EXPIRED #
SOCKSTATUS = S"NODATA";
RETURN;
END
ELSE
BEGIN # TIME STILL TO WAIT #
WAITLOOP = (BWT$EXPIRE [0] -
BWT$SECONDS [0]) / 2 + 1;
END
END # CHECK IF TIMED OUT #
END # WAIT FOR DATA OR EXPIRED TIME #
END # IF BLOCKING #
ELSE
BEGIN # NO DATA/NOT BLOCKING RETURN #
IPINITH; # NAM INPUT TRAFFIC HANDLER #
IF (ACN$ABORT [SOCKID])
THEN
BEGIN # CONNECTION ABORTED #
SOCKSTATUS = S"ABORT";
RETURN;
END
IF (NOT ACN$DATAV [SOCKID])
THEN
BEGIN
SOCKSTATUS = S"NODATA";
RETURN;
END
END
END # DATA NOT AVAILABLE #
P<INP$BUF> = ACN$BUFFER [SOCKID];# INITIALIZE SOURCE POINTER #
MOVEBITS = (ACN$DATALNTH [SOCKID] - UDPHEADSZ$) * 8;
#
**** DATA IS AVAILABLE. VERIFY THE FIRST TWO BYTES OF DATA INDICATE
* A VALID UDP REQUEST AND VERSION. IF IT DOES, THEN EXTRACT THE
* SOURCE ADDRESS FROM BUFFER AND PLACE IN *ADDRESS*. MOVE THE
* REMAINDER OF THE SOURCE BUFFER TO *BUFFER* WITH *IMNS*.
#
INPPOS = 0; # STARTING OFFSET IN INP$BUF #
XDRBYTE (INP$BUF, INPPOS, REC$UDP, 2, XDROPER"READ");
IF ((REC$REQ [0] NQ CALLRES$) AND
(REC$REQ [0] NQ DATAIND$)) OR
(REC$VER [0] NQ UDPVERS$) OR
(MOVEBITS LS 0)
THEN
BEGIN # INVALID DATA, ABORT APPLICATIO#
XWHD (INP$WRD [0], DATAMSG);
MESSAGE (DATAMSG, 0);
XWHD (REC$REQ, DATAMSG);
MESSAGE (DATAMSG, 0);
XWHD (REC$VER, DATAMSG);
MESSAGE (DATAMSG, 0);
IPIAIPA (NINVALID$);
RETURN;
END
P<IPADDR> = LOC (ADDRESS) + 1;
INPPOS = 3; # BEGIN EXTRACT SOURCE ADDRESS #
XDRBYTE (INP$BUF, INPPOS, ADDRESS, 1, XDROPER"READ");
XDRINT (INP$BUF, INPPOS, IPADDR, 3, XDROPER"READ");
BUFLEN = MOVEBITS / 8; # NUMBER OF BYTES IN BUFFER #
IF MOVEBITS NQ 0
THEN
BEGIN
SCRBUF = LOC (INP$BUF) + (INPPOS * 2) / 15;
DESTBUF = LOC (BUFFER);
SCRPOS = XDRMODU ((INPPOS * 8), 60);# WORD BIT OFFSET #
DESTPOS = 0;
IMNS (MOVEBITS, SCRBUF, SCRPOS, DESTBUF, DESTPOS);
END
#
**** CLEAR FLOW CONTROL ON THIS CONNECTION NOW THAT THE DATA HAS
* BEEN PROCESSED.
*
#
IF ACN$DATAV [SOCKID]
THEN
BEGIN
ACN$DATAV [SOCKID] = FALSE;
P<APSM> = LOC(OUTBUF);
SPMSG0 [0] = 0;
LSTACN [0] = SOCKID;
IPIDOSM (LSTON, LLST); # ISSUE LST/ON/R SM #
END
SOCKSTATUS = S"OK";
RETURN; # RETURN TO CALLER #
END # IPPRECV #
TERM