Home   Package List   Routine Alphabetical List   Global Alphabetical List   FileMan Files List   FileMan Sub-Files List   Package Component Lists   Package-Namespace Mapping  
Routine: HLCSTCP1

HLCSTCP1.m

Go to the documentation of this file.
  1. HLCSTCP1 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ;09/13/2006
  1. ;;1.6;HEALTH LEVEL SEVEN;**19,43,57,64,71,133**;JUL 17,1995;Build 13
  1. ;Per VHA Directive 2004-038, this routine should not be modified.
  1. ;Receiver
  1. ;connection is initiated by sender and listener accepts connection
  1. ;and calls this routine
  1. ;
  1. N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP1"
  1. N HLMIEN,HLASTMSG
  1. D MON^HLCSTCP("Open")
  1. K ^TMP("HLCSTCP",$J,0)
  1. S HLMIEN=0,HLASTMSG=""
  1. F D Q:$$STOP^HLCSTCP I 'HLMIEN D MON^HLCSTCP("Idle") H 3
  1. . S HLMIEN=$$READ
  1. . Q:'HLMIEN
  1. . D PROCESS
  1. Q
  1. ;
  1. PROCESS ;check message and reply
  1. ;HLDP=LL in 870, update monitor, received msg.
  1. N HLTCP,HLTCPI,HLTCPO
  1. S HLTCP="",HLTCPO=HLDP,HLTCPI=+HLMIEN
  1. ;update monitor, msg. received
  1. D LLCNT^HLCSTCP(HLDP,1)
  1. D NEW^HLTP3(HLMIEN)
  1. ;update monitor, msg. processed
  1. D LLCNT^HLCSTCP(HLDP,2)
  1. Q
  1. ;
  1. READ() ;read 1 message, returns ien in 773^ien in 772 for message
  1. D MON^HLCSTCP("Reading")
  1. N HLDB,HLDT,HLDEND,HLACKWT,HLDSTRT,HLHDR,HLIND1,HLINE,HLMSG,HLRDOUT,HLRS,HLX,X
  1. ;HLDSTRT=start char., HLDEND=end char., HLRS=record seperator
  1. S HLDSTRT=$C(11),HLDEND=$C(28),HLRS=$C(13)
  1. ;HLRDOUT=exit read loop, HLINE=line count, HLIND1=ien 773^ien 772
  1. ;HLHDR=have a header, ^TMP(...)=excess from last read, HLACKWT=wait for ack
  1. S (HLRDOUT,HLINE,HLIND1,HLHDR)=0,HLX=$G(^TMP("HLCSTCP",$J,0)),HLACKWT=HLDBACK
  1. K ^TMP("HLCSTCP",$J,0)
  1. F D RDBLK Q:HLRDOUT
  1. ;save any excess for next time
  1. S:$L(HLX) ^TMP("HLCSTCP",$J,0)=HLX
  1. I +HLIND1,'$P(HLIND1,U,3) D DELMSG(HLIND1) S HLIND1=0
  1. Q HLIND1
  1. ;
  1. RDBLK S HLDB=HLDBSIZE-$L(HLX)
  1. U IO R X#HLDB:HLDREAD
  1. ;switch to null device if opened to prevent 'leakage'
  1. I $G(IO(0))'="",$G(IO(0))'=IO U IO(0)
  1. ; timedout, check ack timeout, clean up
  1. I '$T,X="",HLX="" S HLACKWT=HLACKWT-HLDREAD D:HLACKWT<0&'HLHDR CLEAN Q
  1. ;data stream: <sb>dddd<cr><eb><cr>
  1. ;add incoming line to what wasn't processed in last read
  1. S HLX=$G(HLX)_X
  1. ; look for segment= <CR>
  1. F Q:HLX'[HLRS D Q:HLRDOUT
  1. . ; Get the first piece, save the rest of the line
  1. . S HLINE=HLINE+1,HLMSG(HLINE,0)=$P(HLX,HLRS),HLX=$P(HLX,HLRS,2,999)
  1. . ; check for start block, Quit if no ien
  1. . I HLMSG(HLINE,0)[HLDSTRT!HLHDR D Q
  1. .. D:HLMSG(HLINE,0)[HLDSTRT
  1. ... S X=$L(HLMSG(HLINE,0),HLDSTRT)
  1. ... S:X>2 HLMSG(HLINE,0)=HLDSTRT_$P(HLMSG(HLINE,0),HLDSTRT,X)
  1. ... S HLMSG(HLINE,0)=$P(HLMSG(HLINE,0),HLDSTRT,2)
  1. ... D RESET:(HLINE>1)
  1. .. ;ping message
  1. .. I $E(HLMSG(1,0),1,9)="MSH^PING^" D PING Q
  1. .. ; get next ien to store
  1. .. D MIEN
  1. .. K HLMSG
  1. .. S (HLINE,HLHDR)=0
  1. . ; check for end block; HLMSG(HLINE) = <eb><cr>
  1. . I HLMSG(HLINE,0)[HLDEND D
  1. .. ;no msg. ien
  1. .. Q:'HLIND1
  1. .. ; Kill just the last line
  1. .. K HLMSG(HLINE,0) S HLINE=HLINE-1
  1. .. ; move into 772
  1. .. D SAVE(.HLMSG,"^HL(772,"_+$P(HLIND1,U,2)_",""IN"")")
  1. .. ;mark that end block has been received
  1. .. ;HLIND1=ien in 773^ien in 772^1 if end block was received
  1. .. S $P(HLIND1,U,3)=1
  1. .. ;reset variables for next message
  1. .. D CLEAN
  1. . ;add blank line for carriage return
  1. . I HLINE'=0,HLMSG(HLINE,0)]"" S HLINE=HLINE+1,HLMSG(HLINE,0)=""
  1. Q:HLRDOUT
  1. ;If the line is long and no <CR> move it into the array.
  1. I ($L(HLX)=HLDBSIZE),(HLX'[HLRS),(HLX'[HLDEND),(HLX'[HLDSTRT) D Q
  1. . S HLINE=HLINE+1,HLMSG(HLINE,0)=HLX,HLX=""
  1. ;have start block but no record seperator
  1. I HLX[HLDSTRT D Q
  1. . ;check for more than 1 start block
  1. . S X=$L(HLX,HLDSTRT) S:X>2 HLX=HLDSTRT_$P(HLX,HLDSTRT,X)
  1. . S:$L($P(HLX,HLDSTRT,2))>8 HLINE=HLINE+1,HLMSG(HLINE,0)=$P(HLX,HLDSTRT,2),HLX="",HLHDR=1
  1. . D RESET:(HLHDR&(HLINE>1))
  1. ;if no ien, then we don't have start block, reset
  1. I 'HLIND1 D CLEAN Q
  1. ; big message-merge from local to global every 100 lines
  1. I (HLINE-$O(HLMSG(0)))>100 D
  1. . M ^HL(772,+$P(HLIND1,U,2),"IN")=HLMSG
  1. . ; reset working array
  1. . K HLMSG
  1. Q
  1. ;
  1. SAVE(SRC,DEST) ;save into global & set top node
  1. ;SRC=source array (passed by ref.), DEST=destination global
  1. M @DEST=SRC
  1. S @DEST@(0)="^^"_HLINE_"^"_HLINE_"^"_DT_"^"
  1. Q
  1. ;
  1. DELMSG(HLMAMT) ;delete message from Message Administration/Message Text files.
  1. N DIK,DA
  1. S DA=+HLMAMT,DIK="^HLMA("
  1. D ^DIK
  1. S DA=$P(HLMAMT,U,2),DIK="^HL(772,"
  1. D ^DIK
  1. Q
  1. MIEN ; sets HLIND1=ien in 773^ien in 772 for message
  1. N HLMID,X
  1. I HLIND1 D
  1. . S:'$G(^HLMA(+HLIND1,0)) HLIND1=0
  1. . S:'$G(^HL(772,+$P(HLIND1,U,2),0)) HLIND1=0
  1. ;msg. id is 10th of MSH & 11th for BSH or FSH
  1. S X=10+($E(HLMSG(1,0),1,3)'="MSH"),HLMID=$$PMSH(.HLMSG,X)
  1. ;if HLIND1 is set, kill old message, use HLIND1 for new
  1. ;message, it means we never got end block for 1st msg.
  1. I HLIND1 D Q
  1. . ;get pointer to 772, kill header
  1. . K ^HLMA(+HLIND1,"MSH")
  1. . I $D(^HL(772,+$P(HLIND1,U,2),"IN")) K ^("IN")
  1. . S X=$$MAID^HLTF(+HLIND1,HLMID)
  1. . D SAVE(.HLMSG,"^HLMA("_+HLIND1_",""MSH"")")
  1. . S:$P(HLIND1,U,3) $P(HLIND1,U,3)=""
  1. D TCP^HLTF(.HLMID,.X,.HLDT)
  1. I 'X D Q
  1. . ;error - record and reset array
  1. . ;killing HLLSTN will allow MON^HLCSTCP to work with multi-server
  1. . D CLEAN K HLLSTN
  1. . ;error 100=LLP Could not Enqueue the Message, reset array
  1. . D MONITOR^HLCSDR2(100,19,HLDP),MON^HLCSTCP("ERROR") H 30
  1. ;HLIND1=ien in 773^ien in 772
  1. S HLIND1=X_U_+$G(^HLMA(X,0))
  1. ;save MSH into 773
  1. D SAVE(.HLMSG,"^HLMA("_+HLIND1_",""MSH"")")
  1. Q
  1. ;
  1. PMSH(MSH,P) ;get piece P from MSH array (passed by ref.)
  1. N FS,I,L,L1,L2,X,Y
  1. S FS=$E(MSH(1,0),4),(L2,Y)=0,X=""
  1. F I=1:1 S L1=$L($G(MSH(I,0)),FS),L=L1+Y-1 D Q:$L(X)!'$D(MSH(I,0))
  1. . S:L1=1 L=L+1
  1. . S:P'>L X=$P($G(MSH(I-1,0)),FS,P-L2)_$P($G(MSH(I,0)),FS,(P-Y))
  1. . S L2=Y,Y=L
  1. Q X
  1. ;
  1. PING ;process PING message
  1. S X=HLMSG(1,0)
  1. I X[HLDEND U IO W X,! I $G(IO(0))'="",$G(IO(0))'=IO U IO(0) ;switch to null device if opened to prevent 'leakage'
  1. ;
  1. CLEAN ;reset var. for next message
  1. K HLMSG
  1. S HLINE=0,HLRDOUT=1
  1. Q
  1. ;
  1. ERROR ; Error trap for disconnect error and return back to the read loop.
  1. S $ETRAP="D UNWIND^%ZTER"
  1. I $$EC^%ZOSV["READ"!($$EC^%ZOSV["NOTOPEN")!($$EC^%ZOSV["DEVNOTOPN") D UNWIND^%ZTER Q
  1. I $$EC^%ZOSV["WRITE" D CC("Wr-err") D UNWIND^%ZTER Q
  1. S HLCSOUT=1 D ^%ZTER,CC("Error")
  1. D UNWIND^%ZTER
  1. Q
  1. ;
  1. CC(X) ;cleanup and close
  1. D MON^HLCSTCP(X)
  1. H 2
  1. Q
  1. RESET ;reset info as a result of no end block
  1. N %
  1. S HLMSG(1,0)=HLMSG(HLINE,0)
  1. F %=2:1:HLINE K HLMSG(%,0)
  1. S HLINE=1
  1. Q