*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 = 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 = 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