1 | HLCSTCP2 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ;09/13/2006
|
---|
2 | ;;1.6;HEALTH LEVEL SEVEN;**19,43,49,57,63,64,66,67,76,77,87,109,133**;Oct 13,1995;Build 13
|
---|
3 | ;Per VHA Directive 2004-038, this routine should not be modified.
|
---|
4 | ;Sender
|
---|
5 | ;Request connection, send outbound message(s) delimited by MLLP
|
---|
6 | ;Input : HLDP=Logical Link to use
|
---|
7 | ; Set up error trap
|
---|
8 | N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2"
|
---|
9 | N HLMSG,HLPORT,HLRETRY,HLRETMG,HLTCPO,POP
|
---|
10 | ;HLRETRY=number of retranmission for this link,HLRETMG=alert sent
|
---|
11 | S HLTCPO=HLDP,HLMSG="",(HLRETRY,HLRETMG)=0
|
---|
12 | ;
|
---|
13 | ;set IO(0) to the null device
|
---|
14 | S IO(0)=$S(^%ZOSF("OS")["OpenM":$S($$OS^%ZOSV()["VMS":"_NLA0:",$$OS^%ZOSV()["UNIX":"/dev/null",1:$P),^%ZOSF("OS")["DSM":"_NLA0:",1:$P)
|
---|
15 | O IO(0) U IO(0)
|
---|
16 | ;
|
---|
17 | ;persistent conection, open connection first, HLPORT=open port
|
---|
18 | I $G(HLTCPLNK)["Y" F Q:$$OPEN G EXIT:$$STOP^HLCSTCP H 1
|
---|
19 | F D QUE Q:$$STOP^HLCSTCP D:'HLMSG Q:$G(HLCSOUT)
|
---|
20 | . ;no messages to send
|
---|
21 | . D MON^HLCSTCP("Idle") H 3
|
---|
22 | . ;persistent connection, no retention
|
---|
23 | . Q:$G(HLTCPLNK)["Y"
|
---|
24 | . D MON^HLCSTCP("Retention")
|
---|
25 | . N % I 0
|
---|
26 | . ;if message comes in or ask to stop
|
---|
27 | . F %=1:1:HLTCPRET H 1 I $$STOP^HLCSTCP!$O(^HLMA("AC","O",HLDP,0)) Q
|
---|
28 | . E S HLCSOUT=2 Q
|
---|
29 | . Q:$$STOP^HLCSTCP
|
---|
30 | . D MON^HLCSTCP("Idle")
|
---|
31 | ;Close port
|
---|
32 | I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT
|
---|
33 | EXIT Q
|
---|
34 | ;
|
---|
35 | QUE ; -- Check "OUT" queue for processing IF there is a message do it
|
---|
36 | ; and then check the link if it open or not
|
---|
37 | N HL,HLN,HLARR,HLHDR,HLI,HLJ,HLMSA,HLRESP,HLRESLT,HLRETRM,HLTCP,HLTCPI,X,Z,HLREREAD
|
---|
38 | D MON^HLCSTCP("Check out")
|
---|
39 | ;HLMSG=next msg, set at tag DONE
|
---|
40 | I 'HLMSG S HLMSG=+$O(^HLMA("AC","O",HLDP,0)),HLRETRY=0 Q:'HLMSG
|
---|
41 | ;
|
---|
42 | ;**109**
|
---|
43 | ;Temporarily lock ^HLMA to flush buffer and ensure edits are complete
|
---|
44 | ;L +^HLMA(HLMSG):1 I '$T S HLMSG=0 Q
|
---|
45 | ;L -^HLMA(HLMSG)
|
---|
46 | ;
|
---|
47 | S HLI=+$G(^HLMA(HLMSG,0)),HLJ=$O(^("MSH",0)),HLTCP=""
|
---|
48 | ;don't have message text or MSH, kill x-ref and decrement 'to send'
|
---|
49 | I 'HLI!'HLJ K ^HLMA("AC","O",HLDP,HLMSG) D LLCNT^HLCSTCP(HLDP,3,1) S HLMSG=0 Q
|
---|
50 | ;update msg status to 'being transmitted'; if cancelled decrement link and quit
|
---|
51 | I '$$CHKMSG(1.5) D LLCNT^HLCSTCP(HLDP,3,1) S HLMSG=0 Q
|
---|
52 | ;number of retransmissions for message
|
---|
53 | S HLRETRM=+$P(^HLMA(HLMSG,"P"),U,5)
|
---|
54 | ;retries exceeded, HLRETRA:action i=ignore, r=restart, s=shutdown
|
---|
55 | ;quit if restart or shutdown, link is going down
|
---|
56 | I HLRETRY>HLDRETR D Q:"I"'[HLRETRA
|
---|
57 | . D MON^HLCSTCP("Error")
|
---|
58 | . ;only 1 alert per link up time, don't send if restart
|
---|
59 | . D:'HLRETMG&(HLRETRA'="R")
|
---|
60 | .. ;send alert
|
---|
61 | .. N XQA,XQAMSG,XQAOPT,XQAROU,XQAID,Z
|
---|
62 | .. ;get mailgroup from file 869.3
|
---|
63 | .. S HLRETMG=1,Z=$P($$PARAM^HLCS2,U,8) Q:Z=""
|
---|
64 | .. S XQA("G."_Z)="",XQAMSG=$$HTE^XLFDT($H,2)_" HL7 LL "_$P(^HLCS(870,HLDP,0),U)_" exceeded retries. LL will "_$S(HLRETRA="S":"shutdown.",HLRETRA="R":"restart.",1:"keep trying.")
|
---|
65 | .. D SETUP^XQALERT
|
---|
66 | . ;quit if action is ignore
|
---|
67 | . Q:"I"[HLRETRA
|
---|
68 | . ;this will shutdown this link
|
---|
69 | . S HLCSOUT=1
|
---|
70 | . ;action is shutdown, set shutdown flag so LM won't restart
|
---|
71 | . S:HLRETRA="S" $P(^HLCS(870,HLDP,0),U,15)=1
|
---|
72 | . D STATUS^HLTF0(HLMSG,4,103,"LLP Exceeded Retry Param")
|
---|
73 | I '$$OPEN Q
|
---|
74 | D MON^HLCSTCP("Send")
|
---|
75 | ; -- data passed in global array, success=1
|
---|
76 | I $$WRITE(HLMSG)<0 Q
|
---|
77 | S (HLTCP,HLTCPI)=HLMSG,HLRETRY=HLRETRY+1,HLRETRM=HLRETRM+1
|
---|
78 | ;update status to awaiting response, decrement link if cancelled
|
---|
79 | I '$$CHKMSG(1.7) D LLCNT^HLCSTCP(HLDP,3,1) S HLMSG=0 Q
|
---|
80 | ;set transmission count, get ACKTIMEOUT override
|
---|
81 | S $P(^HLMA(HLMSG,"P"),U,5)=HLRETRM I $P(^("P"),U,7) S HLN("ACKTIME")=+$P(^("P"),U,7)
|
---|
82 | ;get header of message just sent
|
---|
83 | K HLJ M HLJ=^HLMA(HLMSG,"MSH")
|
---|
84 | ;first component of sending app.
|
---|
85 | S HLN("ECH")=$$P^HLTPCK2(.HLJ,2),HLN("SAN")=$P($$P^HLTPCK2(.HLJ,3),$E(HLN("ECH")))
|
---|
86 | ;msg type, msg. id, commit ack, and app. ack parameter
|
---|
87 | S HLN("TYPE")=$$P^HLTPCK2(.HLJ,1),HLN("MID")=$$P^HLTPCK2(.HLJ,10),HLN("ACAT")=$$P^HLTPCK2(.HLJ,15),HLN("APAT")=$$P^HLTPCK2(.HLJ,16)
|
---|
88 | ;MSA segment, message is a response, can't have an a. ack.
|
---|
89 | S Z=$$MSA^HLTP3(+^HLMA(HLMSG,0)) I Z]"" S:HLN("ACAT")="" HLN("ACAT")="NE" S HLN("APAT")="NE"
|
---|
90 | ;for batch/file with commit ack, reset c. ack and a. ack variables
|
---|
91 | I "BHS,FHS"[HLN("TYPE") S Z=$E(HLJ(1,0),5),X=$$P^HLTPCK2(.HLJ,9),HLN("ACAT")=$P(X,Z,5),HLN("APAT")=$P(X,Z,6),HLN("MID")=$$P^HLTPCK2(.HLJ,11)
|
---|
92 | ;get event protocol
|
---|
93 | S HLN("EID")=+$P(^HLMA(HLMSG,0),U,8),X=$G(^ORD(101,HLN("EID"),770))
|
---|
94 | ;set link counter to msg sent
|
---|
95 | D LLCNT^HLCSTCP(HLDP,4)
|
---|
96 | ;commit and app. ack is never, update status to complete and hang UNI-DIRECTIONAL WAIT
|
---|
97 | I HLN("ACAT")="NE",HLN("APAT")="NE" D Q
|
---|
98 | .D DONE(3)
|
---|
99 | .;
|
---|
100 | .;
|
---|
101 | .H $G(HLDWAIT)
|
---|
102 | ;
|
---|
103 | ;do structure is to stack error
|
---|
104 | D
|
---|
105 | . N $ETRAP,$ESTACK S $ETRAP="D RDERR^HLCSTCP2"
|
---|
106 | . ;HL*1.6*87: Read acknowledgement.
|
---|
107 | . ;Loop to re-read from buffer when receiving incorrect ack.
|
---|
108 | . F D Q:'+$G(HLREREAD)
|
---|
109 | .. S HLREREAD=1
|
---|
110 | .. ;override ack timeout
|
---|
111 | .. I $G(HLN("ACKTIME")) N HLDBACK S HLDBACK=HLN("ACKTIME")
|
---|
112 | .. ;check for response, quit if no-response, msg will be resent
|
---|
113 | .. ;HLRESP=ien 773^ien 772 for response message
|
---|
114 | .. S HLRESP=$$READ^HLCSTCP1()
|
---|
115 | .. ;if no response, decrement counter and quit
|
---|
116 | .. I 'HLRESP D Q
|
---|
117 | ...D LLCNT^HLCSTCP(HLDP,4,1)
|
---|
118 | ...S HLREREAD="0^No Response"
|
---|
119 | ...;check if the port needs to be closed and re-opened before the next re-transmission attempt
|
---|
120 | ...I $G(HLDRETRY("CLOSE")) D CLOSE^%ZISTCP K HLPORT
|
---|
121 | .. ;X 0=re-read msg, 1=commit ack, 3=app ack success, 4=error
|
---|
122 | .. S X=$$RSP^HLTP31(HLRESP,.HLN)
|
---|
123 | .. ;X=0, re-read msg. Incorrect ack (bad MSH,MSA,msg id,or sending app)
|
---|
124 | .. Q:'X
|
---|
125 | .. ;commit ack - done
|
---|
126 | .. I X=1 D S HLREREAD="0^Commit Ack" Q
|
---|
127 | ... ;don't need app. ack, set status to complete
|
---|
128 | ... I "NE"[HLN("APAT") D Q
|
---|
129 | ....D DONE(3)
|
---|
130 | ....;
|
---|
131 | ... ;response is deferred, set status to awaiting ack
|
---|
132 | ... D DONE(2)
|
---|
133 | ...;
|
---|
134 | .. ;Error, HLRESLT=error number^error message from HLTP3
|
---|
135 | .. I X=4 D Q
|
---|
136 | ... D DONE(4,+$G(HLRESLT),$P($G(HLRESLT),U,2))
|
---|
137 | ...;
|
---|
138 | ... S HLREREAD="0^Error"
|
---|
139 | .. ;app ack was successful
|
---|
140 | .. D DONE(3) S HLREREAD="0^App Ack"
|
---|
141 | ..;
|
---|
142 | Q
|
---|
143 | ;
|
---|
144 | DCSEND ;direct connect
|
---|
145 | ; Set up error trap
|
---|
146 | N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2"
|
---|
147 | ;override ack timeout
|
---|
148 | I $G(HLP("ACKTIME")) N HLDBACK S HLDBACK=HLP("ACKTIME")
|
---|
149 | I $$WRITE(HLMSG)<0 D:$G(HLERROR)]"" Q ;HL*1.6*77
|
---|
150 | . D STATUS^HLTF0(HLMSG,4,$P(HLERROR,"^"),$P(HLERROR,"^",2),1) ;HL*1.6*77
|
---|
151 | . D LLCNT^HLCSTCP(HLDP,3,1)
|
---|
152 | D LLCNT^HLCSTCP(HLDP,4)
|
---|
153 | ;do structure is to stack error
|
---|
154 | D
|
---|
155 | . N $ETRAP,$ESTACK S $ETRAP="D RDERR^HLCSTCP2"
|
---|
156 | . ;HLRESP=ien 773^ien 772 for response message
|
---|
157 | . S HLRESP=$$READ^HLCSTCP1()
|
---|
158 | ;
|
---|
159 | D DONE(3):$G(HLRESP),DONE(4,108,$S($G(HLERROR)]"":$P(HLERROR,"^",2),1:"No response")):'$G(HLRESP)
|
---|
160 | I $G(HLERROR)']"" D
|
---|
161 | .D MON^HLCSTCP("Idle")
|
---|
162 | .I '$G(HLRESP) S HLERROR="108^No response"
|
---|
163 | ;Close port
|
---|
164 | I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT
|
---|
165 | Q
|
---|
166 | ;
|
---|
167 | DONE(ST,ERR,ERRMSG) ;set status to complete
|
---|
168 | ;ST=status, ERR=error ien, ERRMSG=error msg
|
---|
169 | D STATUS^HLTF0(HLMSG,ST,$G(ERR),$G(ERRMSG),1)
|
---|
170 | ;
|
---|
171 | ;**109**
|
---|
172 | D DEQUE^HLCSREP(HLDP,"O",HLMSG)
|
---|
173 | ;
|
---|
174 | ;check for more msg.
|
---|
175 | I $G(HLPRIO)'="I" S HLMSG=+$O(^HLMA("AC","O",HLDP,0)),HLRETRY=0
|
---|
176 | Q
|
---|
177 | ;
|
---|
178 | CHKMSG(HLI) ;check status of message and update if not cancelled
|
---|
179 | ;input: HLI=new status, HLMSG=ien of msg in 773
|
---|
180 | ;returns 1=msg was updated, 0=msg has been canceled
|
---|
181 | N X
|
---|
182 | ;
|
---|
183 | ;**109**
|
---|
184 | ;F L +^HLMA(HLMSG,"P"):1 Q:$T H 1
|
---|
185 | ;
|
---|
186 | ;
|
---|
187 | ; New HL*1.6*77 code starting here...
|
---|
188 | I '$D(^HLMA(HLMSG,"P")) D Q 0
|
---|
189 | . S HLERROR="2^Missing status field"
|
---|
190 | . D STATUS^HLTF0(HLMSG,4,$P(HLERROR,U),$P(HLERROR,U,2),1)
|
---|
191 | .;
|
---|
192 | .;**109**
|
---|
193 | . D DEQUE^HLCSREP(HLDP,"O",HLMSG)
|
---|
194 | .;L -^HLMA(HLMSG,"P")
|
---|
195 | ;**end 109**
|
---|
196 | ;
|
---|
197 | ; End of HL*1.6*77 modifications
|
---|
198 | ;
|
---|
199 | ;get status, quit if msg was cancelled
|
---|
200 | ;
|
---|
201 | ;**109**
|
---|
202 | ;S X=+^HLMA(HLMSG,"P") I X=3 L -^HLMA(HLMSG,"P") Q 0
|
---|
203 | S X=+^HLMA(HLMSG,"P") Q:X=3 0
|
---|
204 | ;
|
---|
205 | ;update status if it is different
|
---|
206 | I $G(HLI),HLI'=X D STATUS^HLTF0(HLMSG,HLI)
|
---|
207 | ;
|
---|
208 | ;**109**
|
---|
209 | ;L -^HLMA(HLMSG,"P")
|
---|
210 | ;
|
---|
211 | Q 1
|
---|
212 | ;
|
---|
213 | WRITE(HLDA) ; write message in HL7 format
|
---|
214 | ; HLDA - ien of message in 773
|
---|
215 | ; - start block $C(11)
|
---|
216 | ; - end block $C(28)
|
---|
217 | ; - record separator $C(13)
|
---|
218 | ;Output(s): 1 - Successful
|
---|
219 | ; -1 - Unsuccessful
|
---|
220 | ;
|
---|
221 | N HLDA2,HLAR,HLI,LINENO,X
|
---|
222 | ;set error trap, used when called from HLTP3
|
---|
223 | ;
|
---|
224 | ; New HL*1.6*77 code starts here...
|
---|
225 | N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2"
|
---|
226 | I $G(^HLMA(HLDA,0))'>0 D Q -1
|
---|
227 | . S HLERROR="2^Message Text pointer missing"
|
---|
228 | S HLDA2=+$G(^HLMA(HLDA,0))
|
---|
229 | ; End of HL*1.6*77 modifications...
|
---|
230 | ;
|
---|
231 | Q:'$G(^HLMA(HLDA,0)) -1 ;HL*1.6*77
|
---|
232 | ; header is in ^HLMA(, message is in ^HL(772,
|
---|
233 | S LINENO=1,HLI=0,HLAR="^HLMA(HLDA,""MSH"")"
|
---|
234 | U IO
|
---|
235 | D W $C(13) S HLAR="^HL(772,HLDA2,""IN"")",HLI=0 D
|
---|
236 | . F S HLI=$O(@HLAR@(HLI)) Q:'HLI S X=$G(^(HLI,0)) D
|
---|
237 | .. ;first line, need start block char.
|
---|
238 | .. S:LINENO=1 X=$C(11)_X
|
---|
239 | .. I X]"" W X,!
|
---|
240 | .. ;send CR for blank lines
|
---|
241 | .. I X="" W $C(13)
|
---|
242 | .. S LINENO=LINENO+1
|
---|
243 | ; Sends end block for this message
|
---|
244 | S X=$C(28)_$C(13)
|
---|
245 | U IO W X,!
|
---|
246 | I $G(IO(0))'="",$G(IO(0))'=IO U IO(0) ;switch to null device if opened to prevent 'leakage'
|
---|
247 | Q 1
|
---|
248 | ;
|
---|
249 | OPEN() ; -- Open TCP/IP device (Client)
|
---|
250 | ;HLPORT=port, defined only if port is open
|
---|
251 | ;HLPORTA=number of attempted opens
|
---|
252 | I $D(HLPORT) S IO=HLPORT D Q 1
|
---|
253 | . U IO
|
---|
254 | . I HLOS["OpenM" X "U IO:(::""-M"")" ;use packet mode on Cache'
|
---|
255 | N HLDOM,HLI,HLIP,HLPORTA
|
---|
256 | G OPENA^HLCSTCP3
|
---|
257 | ;
|
---|
258 | RDERR D RDERR^HLCSTCP4 Q ; Exceeded 10,000 bytes, so split on 12/2/03-LJA
|
---|
259 | ERROR D ERROR^HLCSTCP4 Q ; Exceeded 10,000 bytes, so split on 12/2/03-LJA
|
---|
260 | ;
|
---|
261 | CC(X) ;cleanup and close
|
---|
262 | D MON^HLCSTCP(X)
|
---|
263 | I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT
|
---|
264 | H 2
|
---|
265 | Q
|
---|