INHUVUT1 ; cmi/flag/maw - DGH,FRW 05 Oct 1999 15:29 Generic TCP/IP socket utilities ; [ 05/14/2002 1:26 PM ]
;;3.01;BHL IHS Interfaces with GIS;**1**;JUN 01, 2002
;COPYRIGHT 1991-2000 SAIC
;Called from tag lines in INHUVUT
;
Q
INIT(INBPN,INIP) ; Intialize parameters
;INPUT:
; INBPN=background process
; INIP=variable to contain parameters. Pass By Reference.
;OUTPUT:
; INIP will be returned as an array of parameters
; INIP("OTRY")=number of times to try and open socket
; INIP("OHNG")=pause between attempts to open socket (seconds
; INIP("DTRY")=number of times to try to open socket following
; consecutive remote end disconnects (firewalls can
; give false open)
; INIP("DHNG")=pause between attempts to open socket following
; remote end disconnect (firewalls can give false open)
; INIP("RTO")=receive timeout
; INIP("STO")=send timeout
; INIP("RTRY")=number of times to retry read from other system)
; INIP("RHNG")=hang between read attempts
; INIP("EOL")=end of line character(s)
; INIP("INIT")=initialization string to send
; INIP("ACK")=acknowledge to initialization string
; INIP("THNG")=Transmitter hang time if nothing on queue
; INIP("STRY")=number of times to retry send
; INIP("SHNG")=hang time between send retries
; INIP("SMAX")=maximum # of msgs that multi-threaded transceiver can
; have in-flight at any point in time
; INIP("TMAX")=remote system timeout
; # of seconds to wait for remote system to communicate
; before connection is closed
; Input: DUZ - (opt) USER IEN
; INIP("NOSOM")=No S.O.M. required (for apcots. This will go away)
; INIP("CRYPT")=encryption flag (default=0)
; INIP("DESKEY")=DES Key for encryption (default=null)
; INIP("SOM")=start of message (default=null)
; INIP("EOM")=end of message (default=null)
;
N STR,STR7,STR10
S STR=$G(^INTHPC(INBPN,1)),STR7=$G(^INTHPC(INBPN,7))
S STR10=$G(^INTHPC(INBPN,10))
S INIP("OTRY")=$S($L($P(STR,U)):$P(STR,U),1:10)
S INIP("OHNG")=$S($L($P(STR,U,2)):$P(STR,U,2),1:15)
S INIP("DTRY")=$S($L($P(STR,U,15)):$P(STR,U,15),1:10)
S INIP("DHNG")=$S($L($P(STR,U,18)):$P(STR,U,18),1:0)
S INIP("RTO")=$S($L($P(STR,U,3)):$P(STR,U,3),1:15)
S INIP("STO")=$S($L($P(STR,U,4)):$P(STR,U,4),1:60)
S INIP("RTRY")=$S($L($P(STR,U,5)):$P(STR,U,5),1:5)
S INIP("RHNG")=$S($L($P(STR,U,6)):$P(STR,U,6),1:1)
S INIP("EOL")=$$ASCII($S($P(STR,U,7):$P(STR,U,7),1:13))
;cmi/maw 10/5/2001 for x12
I $P($G(^INTHL7M(INBPNM,0)),U,12)="X12" S INIP("EOL")=""
S INIP("INIT")=$S($P(STR,U,8):$$ASCII($P(STR,U,8)),1:"")
S INIP("ACK")=$$ASCII($S($P(STR,U,9):$P(STR,U,9),1:""))
S INIP("THNG")=$S($L($P(STR,U,10)):$P(STR,U,10),1:10)
S INIP("STRY")=$S($L($P(STR,U,11)):$P(STR,U,11),1:10)
S INIP("SHNG")=$S($L($P(STR,U,12)):$P(STR,U,12),1:1)
S INIP("NOSOM")=$P(STR,U,13)
S INIP("SMAX")=$S($L($P(STR,U,14)):$P(STR,U,14),1:15)
S INIP("CRYPT")=$S($P(STR10,U,1):$P(STR10,U,1),1:0)
S INIP("DESKEY")=$S($L($P(STR10,U,2)):$P(STR10,U,2),1:"")
S INIP("SOM")=$$ASCII($S($P(STR,U,16):$P(STR,U,16),1:11))
S INIP("EOM")=$$ASCII($S($P(STR,U,17):$P(STR,U,17),1:28))
I $G(DUZ)>1 S INIP("TMAX")=$$DTIME^INHULOG(DUZ)
S:$P(STR7,U,5)>+$G(INIP("TMAX")) INIP("TMAX")=$P(STR7,U,5)
Q
;
ASCII(X) ;Converts a string into an ASCII string
;INPUT:
; X is string in format "13,14,15"
;OUTPUT
; format $C(13)_$C(14)_$C(15)
Q:'X ""
I X'["," Q $C(+X)
N ASC,I
S ASC="" F I=1:1:$L(X,",") S ASC=ASC_$C($P(X,",",I))
Q ASC
;
INRHB(INBPN,MESS,LAST) ;Updates background process file
;format is ^INRHB("RUN",INBPN)=$H^MESSage^$H time of last success
;INPUT:
; INBPN=Background process file number
; MESS=message text
; LAST = 1 to set $H time in third piece, 2 to kill third piece
; 0 or null to leave at previous value
;RETURNS
; 1 if background job should continue to run
; 0 if it should be shut down
;
L +^INRHB("RUN",INBPN):0
I '$D(^INRHB("RUN",INBPN)) L -^INRHB("RUN",INBPN) Q 0
S $P(^INRHB("RUN",INBPN),U,1,2)=$H_U_$G(MESS)
I $G(LAST) S $P(^INRHB("RUN",INBPN),U,3)=$S(LAST=1:$H,1:"")
L -^INRHB("RUN",INBPN)
Q 1
;
PARSE ;Parse INREC array (raw message) into ING array (HL7 segments).
;PARSE tag moved to INHUVUT1 because routine size is too large
;Array format =
; INV(1) if line terminated by $c(13), or is first line of many in seg
; INV(1,1), INV(1,2)... for overflow nodes until terminated
N DSC,LIN,REM,EOS,X,X1,SEGS
S (LN,DSC)=0,LIN=1,REM=""
;$O through all lines of "raw" array
F S LN=$O(@INREC@(LN)) Q:'LN D
.Q:@INREC@(LN)=""
.S INLIN=@INREC@(LN)
.;break each raw line into 240 chacter pieces
.F S X1=$E(INLIN,1,240),INLIN=$E(INLIN,241,999) Q:'$L(X1) D
..F S X=$$SEG(.X1,.EOS) D Q:'$L(X1)
...I $L(X) D R2 Q
...;If EOS was first character in line, X will have no length,
...;but the next parsed value of X will be start of new segmnt
...S LIN=LIN+1,DSC=0
Q
;
SEG(X1,EOS) ;Parse line X1 into HL7 segments.
;INPUT:
;--X1 (PBR) = string which may contain embedded EOS characters
;--EOS (PBR)= flag to indicate if EOS characters are present
;OUTPUT:
;--X1 (PBR) = remainder of string (if any) following EOS character
;--value returned is string preceeding EOS character
;
I X1'[INIP("EOL") S X=X1,EOS=0,X1="" Q X
S X=$P(X1,INIP("EOL")),X1=$P(X1,INIP("EOL"),2,99),EOS=1 Q X
;
R2 ;Set received lines into variable or global with format
N LEN
;INV(LIN)=segment string
;INV(LIN,DSC)=overflow of string if segment exceeds 240 characters
;INPUT:
;--X = string to be stored
;--LIN = line number into which X is to be stored.
;--DSC = descendent into which X is to be stored
; If X is not the start of a segment (DSC=0), attempt to concatenate
; X to the last INV(LIN) or INV(LIN,DSC) to length of 240, place
; remainder of X in the next DSC.
;OUTPUT:
;--new values of LIN and DSC
;
;First, check memory, roll out to global if needed.
I $S<INSMIN D
.Q:INV["^"
.K ^UTILITY("INV",$J)
.M ^UTILITY("INV",$J)=@INV K @INV S INV="^UTILITY(""INV"","_$J_")"
;IF DSC>0, store into descendent level.
I DSC D
.;if it doesn't already exist, create it.
.I '$D(@INV@(LIN,DSC)) S @INV@(LIN,DSC)=X Q
.;otherwise concatenate it to previous value
.I $L((@INV@(LIN,DSC))_X)<240 S @INV@(LIN,DSC)=@INV@(LIN,DSC)_X Q
.S LEN=240-$L(@INV@(LIN))
.S @INV@(LIN,DSC)=@INV@(LIN,DSC)_$E(X,1,LEN)
.S DSC=DSC+1,@INV@(LIN,DSC)=$E(X,LEN+1,999)
;IF DSC is 0, store into top level.
I 'DSC D
.;if it doesn't already exist, create it.
.I '$D(@INV@(LIN)) S @INV@(LIN)=X Q
.;otherwise concatenate it to previous value
.I $L((@INV@(LIN))_X)<240 S @INV@(LIN)=@INV@(LIN)_X Q
.S LEN=240-$L(@INV@(LIN))
.S @INV@(LIN)=@INV@(LIN)_$E(X,1,LEN),DSC=1,@INV@(LIN,DSC)=$E(X,LEN+1,999)
;If end of segment flag, increment LINe count and set DSC back to 0
I EOS S LIN=LIN+1,DSC=0
Q
;
RCVSTR(INV,INCHNL,INIP,INERR,INMEM) ;Read socket
;This reads a single string from a socket. It is the companion
;routine to SENDSTR^INHUVUT, and is used for initializaton
;and response to initialization. These two tags differ from
;the SEND and RECEIVE tags in that there is no start-of-message.
;The should, however, be an end-of-message. The initialization
;string should be contained in a single socket read, but this
;function allows for multipe reads up to the EOM.
;
;INPUT
; INV=Location to store message, pass by reference
; INCHNL=socket
; INIP=array of parameters, PBR
; INERR=error array, PBR
;OUTPUT
;0=ok, 1=no response at all, 2=failure in middle of receive
;3=remote system disconnected
; Note: the check for remote system disconnect is based on a string
; match from utility routine %INET. If that utility is changed, this
; must also be changed.
;
N NULLREAD,NORESP,RTO,AP,APDONE,API,APREC,X,REM,INSMIN,REC,INERRREC
S RTO=INIP("RTO"),INSMIN=$S($P($G(^INRHSITE(1,0)),U,14):$P(^(0),U,14),1:2500)
; load socket input into INREC (or into ^UTILITY("INREC")
S (APDONE,APREC,AP)="",(NULLREAD,NORESP)=0,INREC="REC"
K @INREC
S (APDONE,APREC,AP)="",(NULLREAD,NORESP)=0,INREC="REC"
F D Q:APDONE!NORESP
.D RECV^%INET(.APREC,.INCHNL,RTO,1)
.;D RECV^%INET(.APREC,.INCHNL,RTO,1,$G(INBPN)) ;maw cache
.;check for remote disconnect
.I $G(APREC(0))["Remote end disconnect" S APDONE=3 Q
.I APREC=""!(APREC[INIP("EOM")) S APDONE=1
.;Remove message framing characters from packet
.S APREC=$TR(APREC,INIP("SOM")_INIP("EOM"))
.;Check for no response from remote system after NNN tries
.I '$L(APREC) D Q
..D WAIT^INHUVUT2(INBPN,INIP("RHNG"),"Reading socket",.NORESP) Q:NORESP
..S NULLREAD=NULLREAD+1 S:NULLREAD>INIP("RTRY") NORESP=1
.I $S<INSMIN D
..Q:INREC["^"
..K ^UTILITY("INREC",$J)
..M ^UTILITY("INREC",$J)=@INREC K @INREC S INREC="^UTILITY(""INREC"","_$J_")"
.S AP=AP+1,@INREC@(AP)=APREC
;If remote end disconnected
I APDONE=3 S INERR=$G(APREC(0)) Q APDONE
;If No message was received
I 'AP S INERR="No message received from remote system on receiver "_$P(^INTHPC(INBPN,0),U) Q 1
;If remote system timed-out log error
I NORESP S INERR="Remote system on "_$P(^INTHPC(INBPN,0),U)_" timed out during transmission of message "_$P($G(@INREC@(1)),$G(INDELIM),10) Q 2
D PARSE^INHUVUT1
K @INREC
Q 0
;
INHUVUT1 ; cmi/flag/maw - DGH,FRW 05 Oct 1999 15:29 Generic TCP/IP socket utilities ; [ 05/14/2002 1:26 PM ]
+1 ;;3.01;BHL IHS Interfaces with GIS;**1**;JUN 01, 2002
+2 ;COPYRIGHT 1991-2000 SAIC
+3 ;Called from tag lines in INHUVUT
+4 ;
+5 QUIT
INIT(INBPN,INIP) ; Intialize parameters
+1 ;INPUT:
+2 ; INBPN=background process
+3 ; INIP=variable to contain parameters. Pass By Reference.
+4 ;OUTPUT:
+5 ; INIP will be returned as an array of parameters
+6 ; INIP("OTRY")=number of times to try and open socket
+7 ; INIP("OHNG")=pause between attempts to open socket (seconds
+8 ; INIP("DTRY")=number of times to try to open socket following
+9 ; consecutive remote end disconnects (firewalls can
+10 ; give false open)
+11 ; INIP("DHNG")=pause between attempts to open socket following
+12 ; remote end disconnect (firewalls can give false open)
+13 ; INIP("RTO")=receive timeout
+14 ; INIP("STO")=send timeout
+15 ; INIP("RTRY")=number of times to retry read from other system)
+16 ; INIP("RHNG")=hang between read attempts
+17 ; INIP("EOL")=end of line character(s)
+18 ; INIP("INIT")=initialization string to send
+19 ; INIP("ACK")=acknowledge to initialization string
+20 ; INIP("THNG")=Transmitter hang time if nothing on queue
+21 ; INIP("STRY")=number of times to retry send
+22 ; INIP("SHNG")=hang time between send retries
+23 ; INIP("SMAX")=maximum # of msgs that multi-threaded transceiver can
+24 ; have in-flight at any point in time
+25 ; INIP("TMAX")=remote system timeout
+26 ; # of seconds to wait for remote system to communicate
+27 ; before connection is closed
+28 ; Input: DUZ - (opt) USER IEN
+29 ; INIP("NOSOM")=No S.O.M. required (for apcots. This will go away)
+30 ; INIP("CRYPT")=encryption flag (default=0)
+31 ; INIP("DESKEY")=DES Key for encryption (default=null)
+32 ; INIP("SOM")=start of message (default=null)
+33 ; INIP("EOM")=end of message (default=null)
+34 ;
+35 NEW STR,STR7,STR10
+36 SET STR=$GET(^INTHPC(INBPN,1))
SET STR7=$GET(^INTHPC(INBPN,7))
+37 SET STR10=$GET(^INTHPC(INBPN,10))
+38 SET INIP("OTRY")=$SELECT($LENGTH($PIECE(STR,U)):$PIECE(STR,U),1:10)
+39 SET INIP("OHNG")=$SELECT($LENGTH($PIECE(STR,U,2)):$PIECE(STR,U,2),1:15)
+40 SET INIP("DTRY")=$SELECT($LENGTH($PIECE(STR,U,15)):$PIECE(STR,U,15),1:10)
+41 SET INIP("DHNG")=$SELECT($LENGTH($PIECE(STR,U,18)):$PIECE(STR,U,18),1:0)
+42 SET INIP("RTO")=$SELECT($LENGTH($PIECE(STR,U,3)):$PIECE(STR,U,3),1:15)
+43 SET INIP("STO")=$SELECT($LENGTH($PIECE(STR,U,4)):$PIECE(STR,U,4),1:60)
+44 SET INIP("RTRY")=$SELECT($LENGTH($PIECE(STR,U,5)):$PIECE(STR,U,5),1:5)
+45 SET INIP("RHNG")=$SELECT($LENGTH($PIECE(STR,U,6)):$PIECE(STR,U,6),1:1)
+46 SET INIP("EOL")=$$ASCII($SELECT($PIECE(STR,U,7):$PIECE(STR,U,7),1:13))
+47 ;cmi/maw 10/5/2001 for x12
+48 IF $PIECE($GET(^INTHL7M(INBPNM,0)),U,12)="X12"
SET INIP("EOL")=""
+49 SET INIP("INIT")=$SELECT($PIECE(STR,U,8):$$ASCII($PIECE(STR,U,8)),1:"")
+50 SET INIP("ACK")=$$ASCII($SELECT($PIECE(STR,U,9):$PIECE(STR,U,9),1:""))
+51 SET INIP("THNG")=$SELECT($LENGTH($PIECE(STR,U,10)):$PIECE(STR,U,10),1:10)
+52 SET INIP("STRY")=$SELECT($LENGTH($PIECE(STR,U,11)):$PIECE(STR,U,11),1:10)
+53 SET INIP("SHNG")=$SELECT($LENGTH($PIECE(STR,U,12)):$PIECE(STR,U,12),1:1)
+54 SET INIP("NOSOM")=$PIECE(STR,U,13)
+55 SET INIP("SMAX")=$SELECT($LENGTH($PIECE(STR,U,14)):$PIECE(STR,U,14),1:15)
+56 SET INIP("CRYPT")=$SELECT($PIECE(STR10,U,1):$PIECE(STR10,U,1),1:0)
+57 SET INIP("DESKEY")=$SELECT($LENGTH($PIECE(STR10,U,2)):$PIECE(STR10,U,2),1:"")
+58 SET INIP("SOM")=$$ASCII($SELECT($PIECE(STR,U,16):$PIECE(STR,U,16),1:11))
+59 SET INIP("EOM")=$$ASCII($SELECT($PIECE(STR,U,17):$PIECE(STR,U,17),1:28))
+60 IF $GET(DUZ)>1
SET INIP("TMAX")=$$DTIME^INHULOG(DUZ)
+61 IF $PIECE(STR7,U,5)>+$GET(INIP("TMAX"))
SET INIP("TMAX")=$PIECE(STR7,U,5)
+62 QUIT
+63 ;
ASCII(X) ;Converts a string into an ASCII string
+1 ;INPUT:
+2 ; X is string in format "13,14,15"
+3 ;OUTPUT
+4 ; format $C(13)_$C(14)_$C(15)
+5 IF 'X
QUIT ""
+6 IF X'[","
QUIT $CHAR(+X)
+7 NEW ASC,I
+8 SET ASC=""
FOR I=1:1:$LENGTH(X,",")
SET ASC=ASC_$CHAR($PIECE(X,",",I))
+9 QUIT ASC
+10 ;
INRHB(INBPN,MESS,LAST) ;Updates background process file
+1 ;format is ^INRHB("RUN",INBPN)=$H^MESSage^$H time of last success
+2 ;INPUT:
+3 ; INBPN=Background process file number
+4 ; MESS=message text
+5 ; LAST = 1 to set $H time in third piece, 2 to kill third piece
+6 ; 0 or null to leave at previous value
+7 ;RETURNS
+8 ; 1 if background job should continue to run
+9 ; 0 if it should be shut down
+10 ;
+11 LOCK +^INRHB("RUN",INBPN):0
+12 IF '$DATA(^INRHB("RUN",INBPN))
LOCK -^INRHB("RUN",INBPN)
QUIT 0
+13 SET $PIECE(^INRHB("RUN",INBPN),U,1,2)=$HOROLOG_U_$GET(MESS)
+14 IF $GET(LAST)
SET $PIECE(^INRHB("RUN",INBPN),U,3)=$SELECT(LAST=1:$HOROLOG,1:"")
+15 LOCK -^INRHB("RUN",INBPN)
+16 QUIT 1
+17 ;
PARSE ;Parse INREC array (raw message) into ING array (HL7 segments).
+1 ;PARSE tag moved to INHUVUT1 because routine size is too large
+2 ;Array format =
+3 ; INV(1) if line terminated by $c(13), or is first line of many in seg
+4 ; INV(1,1), INV(1,2)... for overflow nodes until terminated
+5 NEW DSC,LIN,REM,EOS,X,X1,SEGS
+6 SET (LN,DSC)=0
SET LIN=1
SET REM=""
+7 ;$O through all lines of "raw" array
+8 FOR
SET LN=$ORDER(@INREC@(LN))
IF 'LN
QUIT
Begin DoDot:1
+9 IF @INREC@(LN)=""
QUIT
+10 SET INLIN=@INREC@(LN)
+11 ;break each raw line into 240 chacter pieces
+12 FOR
SET X1=$EXTRACT(INLIN,1,240)
SET INLIN=$EXTRACT(INLIN,241,999)
IF '$LENGTH(X1)
QUIT
Begin DoDot:2
+13 FOR
SET X=$$SEG(.X1,.EOS)
Begin DoDot:3
+14 IF $LENGTH(X)
DO R2
QUIT
+15 ;If EOS was first character in line, X will have no length,
+16 ;but the next parsed value of X will be start of new segmnt
+17 SET LIN=LIN+1
SET DSC=0
End DoDot:3
IF '$LENGTH(X1)
QUIT
End DoDot:2
End DoDot:1
+18 QUIT
+19 ;
SEG(X1,EOS) ;Parse line X1 into HL7 segments.
+1 ;INPUT:
+2 ;--X1 (PBR) = string which may contain embedded EOS characters
+3 ;--EOS (PBR)= flag to indicate if EOS characters are present
+4 ;OUTPUT:
+5 ;--X1 (PBR) = remainder of string (if any) following EOS character
+6 ;--value returned is string preceeding EOS character
+7 ;
+8 IF X1'[INIP("EOL")
SET X=X1
SET EOS=0
SET X1=""
QUIT X
+9 SET X=$PIECE(X1,INIP("EOL"))
SET X1=$PIECE(X1,INIP("EOL"),2,99)
SET EOS=1
QUIT X
+10 ;
R2 ;Set received lines into variable or global with format
+1 NEW LEN
+2 ;INV(LIN)=segment string
+3 ;INV(LIN,DSC)=overflow of string if segment exceeds 240 characters
+4 ;INPUT:
+5 ;--X = string to be stored
+6 ;--LIN = line number into which X is to be stored.
+7 ;--DSC = descendent into which X is to be stored
+8 ; If X is not the start of a segment (DSC=0), attempt to concatenate
+9 ; X to the last INV(LIN) or INV(LIN,DSC) to length of 240, place
+10 ; remainder of X in the next DSC.
+11 ;OUTPUT:
+12 ;--new values of LIN and DSC
+13 ;
+14 ;First, check memory, roll out to global if needed.
+15 IF $STORAGE<INSMIN
Begin DoDot:1
+16 IF INV["^"
QUIT
+17 KILL ^UTILITY("INV",$JOB)
+18 MERGE ^UTILITY("INV",$JOB)=@INV
KILL @INV
SET INV="^UTILITY(""INV"","_$JOB_")"
End DoDot:1
+19 ;IF DSC>0, store into descendent level.
+20 IF DSC
Begin DoDot:1
+21 ;if it doesn't already exist, create it.
+22 IF '$DATA(@INV@(LIN,DSC))
SET @INV@(LIN,DSC)=X
QUIT
+23 ;otherwise concatenate it to previous value
+24 IF $LENGTH((@INV@(LIN,DSC))_X)<240
SET @INV@(LIN,DSC)=@INV@(LIN,DSC)_X
QUIT
+25 SET LEN=240-$LENGTH(@INV@(LIN))
+26 SET @INV@(LIN,DSC)=@INV@(LIN,DSC)_$EXTRACT(X,1,LEN)
+27 SET DSC=DSC+1
SET @INV@(LIN,DSC)=$EXTRACT(X,LEN+1,999)
End DoDot:1
+28 ;IF DSC is 0, store into top level.
+29 IF 'DSC
Begin DoDot:1
+30 ;if it doesn't already exist, create it.
+31 IF '$DATA(@INV@(LIN))
SET @INV@(LIN)=X
QUIT
+32 ;otherwise concatenate it to previous value
+33 IF $LENGTH((@INV@(LIN))_X)<240
SET @INV@(LIN)=@INV@(LIN)_X
QUIT
+34 SET LEN=240-$LENGTH(@INV@(LIN))
+35 SET @INV@(LIN)=@INV@(LIN)_$EXTRACT(X,1,LEN)
SET DSC=1
SET @INV@(LIN,DSC)=$EXTRACT(X,LEN+1,999)
End DoDot:1
+36 ;If end of segment flag, increment LINe count and set DSC back to 0
+37 IF EOS
SET LIN=LIN+1
SET DSC=0
+38 QUIT
+39 ;
RCVSTR(INV,INCHNL,INIP,INERR,INMEM) ;Read socket
+1 ;This reads a single string from a socket. It is the companion
+2 ;routine to SENDSTR^INHUVUT, and is used for initializaton
+3 ;and response to initialization. These two tags differ from
+4 ;the SEND and RECEIVE tags in that there is no start-of-message.
+5 ;The should, however, be an end-of-message. The initialization
+6 ;string should be contained in a single socket read, but this
+7 ;function allows for multipe reads up to the EOM.
+8 ;
+9 ;INPUT
+10 ; INV=Location to store message, pass by reference
+11 ; INCHNL=socket
+12 ; INIP=array of parameters, PBR
+13 ; INERR=error array, PBR
+14 ;OUTPUT
+15 ;0=ok, 1=no response at all, 2=failure in middle of receive
+16 ;3=remote system disconnected
+17 ; Note: the check for remote system disconnect is based on a string
+18 ; match from utility routine %INET. If that utility is changed, this
+19 ; must also be changed.
+20 ;
+21 NEW NULLREAD,NORESP,RTO,AP,APDONE,API,APREC,X,REM,INSMIN,REC,INERRREC
+22 SET RTO=INIP("RTO")
SET INSMIN=$SELECT($PIECE($GET(^INRHSITE(1,0)),U,14):$PIECE(^(0),U,14),1:2500)
+23 ; load socket input into INREC (or into ^UTILITY("INREC")
+24 SET (APDONE,APREC,AP)=""
SET (NULLREAD,NORESP)=0
SET INREC="REC"
+25 KILL @INREC
+26 SET (APDONE,APREC,AP)=""
SET (NULLREAD,NORESP)=0
SET INREC="REC"
+27 FOR
Begin DoDot:1
+28 DO RECV^%INET(.APREC,.INCHNL,RTO,1)
+29 ;D RECV^%INET(.APREC,.INCHNL,RTO,1,$G(INBPN)) ;maw cache
+30 ;check for remote disconnect
+31 IF $GET(APREC(0))["Remote end disconnect"
SET APDONE=3
QUIT
+32 IF APREC=""!(APREC[INIP("EOM"))
SET APDONE=1
+33 ;Remove message framing characters from packet
+34 SET APREC=$TRANSLATE(APREC,INIP("SOM")_INIP("EOM"))
+35 ;Check for no response from remote system after NNN tries
+36 IF '$LENGTH(APREC)
Begin DoDot:2
+37 DO WAIT^INHUVUT2(INBPN,INIP("RHNG"),"Reading socket",.NORESP)
IF NORESP
QUIT
+38 SET NULLREAD=NULLREAD+1
IF NULLREAD>INIP("RTRY")
SET NORESP=1
End DoDot:2
QUIT
+39 IF $STORAGE<INSMIN
Begin DoDot:2
+40 IF INREC["^"
QUIT
+41 KILL ^UTILITY("INREC",$JOB)
+42 MERGE ^UTILITY("INREC",$JOB)=@INREC
KILL @INREC
SET INREC="^UTILITY(""INREC"","_$JOB_")"
End DoDot:2
+43 SET AP=AP+1
SET @INREC@(AP)=APREC
End DoDot:1
IF APDONE!NORESP
QUIT
+44 ;If remote end disconnected
+45 IF APDONE=3
SET INERR=$GET(APREC(0))
QUIT APDONE
+46 ;If No message was received
+47 IF 'AP
SET INERR="No message received from remote system on receiver "_$PIECE(^INTHPC(INBPN,0),U)
QUIT 1
+48 ;If remote system timed-out log error
+49 IF NORESP
SET INERR="Remote system on "_$PIECE(^INTHPC(INBPN,0),U)_" timed out during transmission of message "_$PIECE($GET(@INREC@(1)),$GET(INDELIM),10)
QUIT 2
+50 DO PARSE^INHUVUT1
+51 KILL @INREC
+52 QUIT 0
+53 ;