*DECK IPPSEND
USETEXT TEXTIPL
USETEXT TEXTXDR
PROC IPPSEND (SOCKID, BUFFER1, BUFLEN1, BUFFER2, BUFLEN2,
ADDRESS, SOCKSTATUS);
*CALL COPYRITE CDCNET - COPYRIGHT CONTROL DATA. 1992.
# TITLE IPPSEND - SEND DATA FROM A SOCKET #
BEGIN # IPPSEND #
#
**** IPPSEND SEND DATA FROM A SOCKET
*
* THIS PROCEDURE SENDS A BLOCK OF DATA FROM THE SOCKET *SOCKID*
* TO THE HOST AT *ADDRESS*.
*
* PROC IPPSEND
*
* ENTRY SOCKID = INTEGER VALUE OF SOCKET
* BUFFER1 = FIRST BUFFER WHICH CONTAINS THE DATA TO SEND
* BUFLEN1 = NUMBER OF BYTES IN *BUFFER1* TO SEND
* BUFFER2 = SECOND BUFFER WHICH CONTAINS THE DATA TO SEND
* BUFLEN2 = NUMBER OF BYTES IN *BUFFER2* TO SEND
* ADDRESS = 4 WORD DESTINATION IP ADDRESS ARRAY
*
* EXIT 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 THE
* APPLICATION BLOCK LIMIT HAS NOT BEEN REACHED, SET UP
* THE UDP CALL BLOCK HEADER AND COPY THE CONTENTS OF
* *BUFFER1* AND *BUFFER2* INTO THE DATA BLOCK AND SEND
* THE BLOCK TO NAM.
* IF THE APPLICATION BLOCK LIMIT HAS BEEN REACHED, CALL THE
* NAM INPUT TRAFFIC HANDLER WAITING FOR THE OUTSTANDING
* BLOCK COUNT TO FALL BELOW THE LIMIT OR FOR THE BLOCKING
* WAIT TIMER TO EXPIRE.
* IF NOT BLOCKING, CALL THE NAM INPUT TRAFFIC HANDLER
* ONCE. IF THE DATA BLOCK CAN NOT BE SENT, SET THE STATUS
* TO *FLOWCTRL* TO INDICATE THE BLOCK WAS NOT SENT.
#
#
**** PROC IPPSEND - XREF LIST
#
XREF
BEGIN
PROC IMNS; # MOVE NON-OVERLAPPING STRING #
PROC IPINITH; # NAM INPUT TRAFFIC HANDLER #
PROC NETPUT; # SEND OUTPUT BUFFER TO NETWORK #
PROC RTIME; # REAL TIME CLOCK #
PROC XDRBYTE; # CONVERT BYTES TO XDR FORMAT #
PROC XDRINT; # CONVERT INTEGERS TO XDR FORMAT #
END
#
**
#
ITEM SOCKID I; # SOCKET IDENTIFIER #
ARRAY BUFFER1 [00:00] S(1);; # OUTPUT BUFFER TO SEND #
ITEM BUFLEN1 U; # LENGTH OF DATA IN *BUFFER1* #
ARRAY BUFFER2 [00:00] S(1);; # SECOND OUTPUT BUFFER TO SEND #
ITEM BUFLEN2 U; # LENGTH OF DATA IN *BUFFER2* #
ARRAY ADDRESS [00:00] S(1);; # SOURCE ADDRESS FOR DATA #
ITEM SOCKSTATUS S:SOCKSTAT; # RETURNED SOCKET STATUS #
ITEM BUFPOS U; # OFFSET IN *OUTBUF* #
ITEM DESTBUF I; # CURRENT WRD LOCATION IN BUFFER#
ITEM DESTPOS U; # BIT OFFSET IN BUFFER WORD #
ITEM INDEX I; # LOOP COUNTER #
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 #
ITEM WRITENUM I; # NUMBER OF XDR ITEMS TO WRITE #
CONTROL EJECT;
#
**** START MAIN PROCEDURE
#
IF (ACN$ABORT [SOCKID])
THEN
BEGIN # CONNECTION ABORTED #
SOCKSTATUS = S"ABORT";
RETURN;
END
IF ACN$STATE [SOCKID] NQ S"BOUND"
THEN
BEGIN
SOCKSTATUS = SOCKSTAT"INVALIDST";
RETURN;
END
IF (ACN$OBC [SOCKID] GQ ACN$ABL [SOCKID])
THEN
BEGIN # MAXIMUM OUTSTANDING BLOCK LMT #
BLOCK = ACN$BLOCK [SOCKID]; # SET GLOBAL BLOCKING FLAG #
IF BLOCK
THEN
BEGIN # WAIT FOR FC/ACK ON CONNECTION #
WAITLOOP = ACN$WAITIME [SOCKID] / 2 + 1;
RTIME (BWT$TIME); # CURRENT TIME #
BWT$EXPIRE [0] = BWT$SECONDS [0] + ACN$WAITIME [SOCKID];
#
**** CONTINUE POLLING THE NETWORK WAITING FOR FC/ACK SUPERVISORY
* MESSAGES TO BE RECEIVED ON THE CONNECTION OR UNTIL THE WAIT TIMER
* HAS EXPIRED. THE LOOP COUNTERIS SETTO THE WAIT TIME/2 DUE TO THE
* NETWAIT TIME OF 2 SECONDS WHILE BLOCKING.
#
FOR LOOP = 0
WHILE (ACN$OBC [SOCKID] GQ ACN$ABL [SOCKID])
DO
BEGIN # WAIT FOR ACK OR EXPIRED TIME #
FOR INDEX = 1 STEP 1
WHILE (ACN$OBC [SOCKID] GQ ACN$ABL [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 (ACN$OBC [SOCKID] GQ ACN$ABL [SOCKID])
THEN
BEGIN # CHECK IF TIMED OUT #
RTIME (BWT$TIME);
IF (BWT$SECONDS [0] GQ BWT$EXPIRE [0])
THEN
BEGIN # TIMER EXPIRED #
SOCKSTATUS = S"FLOWCTRL";
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 ACK OR EXPIRED TIME #
END # WAIT FOR FC/ACK ON CONNECTION #
ELSE
BEGIN # NO ACK/NOT BLOCKING #
IPINITH; # NAM INPUT TRAFFIC HANDLER #
IF (ACN$ABORT [SOCKID])
THEN
BEGIN # CONNECTION ABORTED #
SOCKSTATUS = S"ABORT";
RETURN;
END
IF (ACN$OBC [SOCKID] GQ ACN$ABL [SOCKID])
THEN
BEGIN
SOCKSTATUS = S"FLOWCTRL";
RETURN;
END
END # NO ACK/NOT BLOCKING #
END # DATA NOT AVAILABLE #
#
**** DATA CAN BE SENT. PLACE THE UDP CALL HEADER INTO *OUTBUF*. THE
* REQUEST CONSISTS OF THE CALL TYPE, UDP VERSION, AND FOUR 32 BIT
* INTEGER ADDRESS. FOLLOWING THE ADDRESS THE CONTENTS OF *BUFFER*
* ARE MOVED INTO *OUTBUF*. IF THE BLOCK TO BE TRANSMITTED IS
* GREATER THAN *INPSIZE$* THEN AN ERROR STATUS IS RETURNED.
#
BUFPOS = 0; # INITIALIZE BUFFER POSITION #
P<IP$ADDR$REC> = LOC (ADDRESS);
UDP$HEADER [0] = DESTREQ$;
WRITENUM = 2;
XDRBYTE (OUTBUF, BUFPOS, UDP$HEAD$REC, WRITENUM, XDROPER"WRITE");
WRITENUM = 4;
XDRINT (OUTBUF, BUFPOS, IP$ADDR$REC, WRITENUM, XDROPER"WRITE");
P<ABH> = LOC (DABH); # BASE ABH POINTER #
ABHTLC [0] = BUFPOS + BUFLEN1 + BUFLEN2;# STORE LENGTH IN BYTES #
IF ((ABHTLC [0] * 2) / 15) GR INPSIZE$
THEN
BEGIN # *OUTBUF* TOO SMALL FOR DATA #
SOCKSTATUS = S"REQFAIL";
RETURN;
END # *OUTBUF* TOO SMALL FOR DATA #
IF BUFLEN1 GR 0
THEN
BEGIN
MOVEBITS = BUFLEN1 * 8;
DESTBUF = LOC (OUTBUF) + (BUFPOS * 2) / 15;
DESTPOS = XDRMODU ((BUFPOS * 8), 60);# WORD BIT OFFSET #
SCRBUF = LOC (BUFFER1);
SCRPOS = 0;
IMNS (MOVEBITS, SCRBUF, SCRPOS, DESTBUF, DESTPOS);
IF BUFLEN2 GR 0
THEN
BEGIN
SCRBUF = LOC (BUFFER2);
SCRPOS = 0;
MOVEBITS = BUFLEN2 * 8;
IMNS (MOVEBITS, SCRBUF, SCRPOS, DESTBUF, DESTPOS);
END
END
ABHADR [0] = SOCKID; # STORE CONNECTION NUMBER #
ABHABN [0] = ACN$ABN [SOCKID]; # STORE APPLICATION BLOCK NUMBER#
ACN$ABN [SOCKID] = ACN$ABN [SOCKID] + 1;
ACN$OBC [SOCKID] = ACN$OBC [SOCKID] + 1;
NETPUT (DABH, OUTBUF); # SEND THE REQUEST #
SOCKSTATUS = S"OK";
RETURN; # RETURN TO CALLER #
END # IPPSEND #
TERM