1 | HLOTCP ;ALB/CJM- TCP/IP I/O - 10/4/94 1pm ;03/22/2007
|
---|
2 | ;;1.6;HEALTH LEVEL SEVEN;**126,131,134**;Oct 13, 1995;Build 30
|
---|
3 | ;Per VHA Directive 2004-038, this routine should not be modified.
|
---|
4 | ;
|
---|
5 | OPEN(HLCSTATE,LOGICAL) ;
|
---|
6 | ;This may be called either in the context of a client or a server.
|
---|
7 | ;For the server, there are 3 situations:
|
---|
8 | ; 1) The server is not concurrent. In this case the TCP device should be opened.
|
---|
9 | ; 2) The server is concurrent, but this process was spawned by the OS
|
---|
10 | ; (via a VMS TCP Service) In this case, the device should be opened
|
---|
11 | ; via the LOGICAL that was passed in.
|
---|
12 | ; 3) The server is concurrent, but this process was spawned by the
|
---|
13 | ; TaskMan multi-listener. In this case TaskMan already opened the
|
---|
14 | ; device. This case can be determined by the absence of the LOGICAL
|
---|
15 | ; input parameter.
|
---|
16 | ;
|
---|
17 | N IP,PORT,DNSFLAG
|
---|
18 | ;
|
---|
19 | S DNSFLAG=0 ;DNS has not been contacted for IP
|
---|
20 | ;
|
---|
21 | S:'$G(HLCSTATE("SERVER")) IP=HLCSTATE("LINK","IP")
|
---|
22 | S PORT=HLCSTATE("LINK","PORT")
|
---|
23 | S HLCSTATE("CONNECTED")=0
|
---|
24 | S HLCSTATE("READ HEADER")="READHDR^HLOTCP"
|
---|
25 | S HLCSTATE("WRITE HEADER")="WRITEHDR^HLOTCP"
|
---|
26 | S HLCSTATE("READ SEGMENT")="READSEG^HLOTCP"
|
---|
27 | S HLCSTATE("WRITE SEGMENT")="WRITESEG^HLOTCP"
|
---|
28 | S HLCSTATE("END MESSAGE")="ENDMSG^HLOTCP"
|
---|
29 | S HLCSTATE("CLOSE")="CLOSE^HLOTCP"
|
---|
30 | ;
|
---|
31 | ;spawned by TaskMan multi-listener? If so, the device has already been opened
|
---|
32 | I $G(HLCSTATE("SERVER")),$G(HLCSTATE("LINK","SERVER"))="1^M",$G(LOGICAL)="" D Q
|
---|
33 | .S HLCSTATE("DEVICE")=IO(0),HLCSTATE("FLUSH")="!",HLCSTATE("TCP BUFFER SIZE")=510
|
---|
34 | .S HLCSTATE("CONNECTED")=1
|
---|
35 | ;
|
---|
36 | ;if no IP, not a server, give DNS a shot
|
---|
37 | I '$G(HLCSTATE("SERVER")),IP="" S DNSFLAG=1,IP=$$DNS(HLCSTATE("LINK","DOMAIN")),HLCSTATE("LINK","IP")=IP Q:IP=""
|
---|
38 | ;
|
---|
39 | RETRY I HLCSTATE("SYSTEM","OS")="DSM" D
|
---|
40 | .S HLCSTATE("TCP BUFFER SIZE")=512
|
---|
41 | .I $G(LOGICAL)]"" S HLCSTATE("DEVICE")=LOGICAL
|
---|
42 | .E S HLCSTATE("DEVICE")=PORT
|
---|
43 | .S HLCSTATE("FLUSH")="!"
|
---|
44 | .I $G(HLCSTATE("SERVER")) D
|
---|
45 | ..O:$G(LOGICAL)]"" HLCSTATE("DEVICE"):(TCPDEV,BLOCKSIZE=512):HLCSTATE("OPEN TIMEOUT")
|
---|
46 | ..O:$G(LOGICAL)="" HLCSTATE("DEVICE"):(TCPCHAN,BLOCKSIZE=512):HLCSTATE("OPEN TIMEOUT")
|
---|
47 | ..I $T D
|
---|
48 | ...S HLCSTATE("CONNECTED")=1
|
---|
49 | ...U HLCSTATE("DEVICE"):NOECHO
|
---|
50 | .E D ;client
|
---|
51 | ..O HLCSTATE("DEVICE"):(TCPCHAN,ADDRESS=IP,BLOCKSIZE=512):HLCSTATE("OPEN TIMEOUT")
|
---|
52 | ..I $T D
|
---|
53 | ...S HLCSTATE("CONNECTED")=1
|
---|
54 | ...U HLCSTATE("DEVICE"):NOECHO
|
---|
55 | E I HLCSTATE("SYSTEM","OS")="CACHE" D
|
---|
56 | .S HLCSTATE("FLUSH")="!"
|
---|
57 | .I $G(LOGICAL)]"" S HLCSTATE("DEVICE")=LOGICAL
|
---|
58 | .E S HLCSTATE("DEVICE")="|TCP|"_PORT
|
---|
59 | .S HLCSTATE("TCP BUFFER SIZE")=510
|
---|
60 | .I $G(HLCSTATE("SERVER")) D
|
---|
61 | ..I HLCSTATE("SERVER")="1^S" D Q
|
---|
62 | ...;single server (no concurrent connections)
|
---|
63 | ...O HLCSTATE("DEVICE"):(:PORT:"+A-S":::):HLCSTATE("OPEN TIMEOUT")
|
---|
64 | ...I $T D
|
---|
65 | ....N A
|
---|
66 | ....S HLCSTATE("CONNECTED")=1
|
---|
67 | ....U HLCSTATE("DEVICE")
|
---|
68 | ....F R *A:HLCSTATE("READ TIMEOUT") Q:$T I $$CHKSTOP^HLOPROC S HLCSTATE("CONNECTED")=0 D CLOSE(.HLCSTATE) Q
|
---|
69 | ..;
|
---|
70 | ..;multi-server spawned by OS - VMS TCP Services
|
---|
71 | ..O HLCSTATE("DEVICE")::HLCSTATE("OPEN TIMEOUT") I '$T S HLCSTATE("CONNECTED")=0 Q
|
---|
72 | ..S HLCSTATE("CONNECTED")=1
|
---|
73 | ..U HLCSTATE("DEVICE"):(::"-S")
|
---|
74 | ..;
|
---|
75 | .E D ;client
|
---|
76 | ..S HLCSTATE("TCP BUFFER SIZE")=510
|
---|
77 | ..O HLCSTATE("DEVICE"):(IP:PORT:"-S":::):HLCSTATE("OPEN TIMEOUT")
|
---|
78 | ..I $T D
|
---|
79 | ...S HLCSTATE("CONNECTED")=1
|
---|
80 | E D ;any other system but Cache or DSM
|
---|
81 | .S HLCSTATE("TCP BUFFER SIZE")=256
|
---|
82 | .D CALL^%ZISTCP(IP,PORT,HLCSTATE("OPEN TIMEOUT"))
|
---|
83 | .S HLCSTATE("CONNECTED")='POP
|
---|
84 | .I HLCSTATE("CONNECTED") S HLCSTATE("DEVICE")=IO
|
---|
85 | ;
|
---|
86 | ;if not connected, not the server, give DNS a shot if not tried already
|
---|
87 | I '$G(HLCSTATE("SERVER")),'HLCSTATE("CONNECTED"),'DNSFLAG S DNSFLAG=1,IP=$$DNS(HLCSTATE("LINK","DOMAIN")) I IP]"",IP'=HLCSTATE("LINK","IP") S HLCSTATE("LINK","IP")=IP G RETRY
|
---|
88 | I HLCSTATE("CONNECTED"),DNSFLAG S $P(^HLCS(870,HLCSTATE("LINK","IEN"),400),"^")=IP
|
---|
89 | Q
|
---|
90 | ;
|
---|
91 | DNS(DOMAIN) ;
|
---|
92 | Q $P($$ADDRESS^XLFNSLK(DOMAIN),",")
|
---|
93 | ;
|
---|
94 | WRITEHDR(HLCSTATE,HDR) ;
|
---|
95 | ;
|
---|
96 | ;insure that package buffer is empty
|
---|
97 | K HLCSTATE("BUFFER")
|
---|
98 | S HLCSTATE("BUFFER","BYTE COUNT")=0
|
---|
99 | S HLCSTATE("BUFFER","SEGMENT COUNT")=0
|
---|
100 | S HLCSTATE("FIRST WRITE")=1 ;so that FLUSH knows $X should be 0
|
---|
101 | ;
|
---|
102 | ;Start the message with <SB>, then write the header
|
---|
103 | N SEG
|
---|
104 | S SEG(1)=$C(11)_HDR(1)
|
---|
105 | S SEG(2)=HDR(2)
|
---|
106 | Q $$WRITESEG(.HLCSTATE,.SEG)
|
---|
107 | ;
|
---|
108 | WRITESEG(HLCSTATE,SEG) ;
|
---|
109 | N I,LAST
|
---|
110 | S HLCSTATE("BUFFER","SEGMENT COUNT")=HLCSTATE("BUFFER","SEGMENT COUNT")+1
|
---|
111 | S I=0,LAST=$O(SEG(99999),-1)
|
---|
112 | F S I=$O(SEG(I)) Q:'I D
|
---|
113 | .I HLCSTATE("BUFFER","BYTE COUNT")>HLCSTATE("SYSTEM","BUFFER") D FLUSH
|
---|
114 | .I I=LAST S SEG(I)=SEG(I)_$C(13)
|
---|
115 | .S HLCSTATE("BUFFER",HLCSTATE("BUFFER","SEGMENT COUNT"),I)=SEG(I),HLCSTATE("BUFFER","BYTE COUNT")=HLCSTATE("BUFFER","BYTE COUNT")+$L(SEG(I))+20
|
---|
116 | Q HLCSTATE("CONNECTED")
|
---|
117 | ;
|
---|
118 | FLUSH ;flushes the HL7 package buffer, and the system TCP buffer when full
|
---|
119 | N SEGMENT,MAX
|
---|
120 | S SEGMENT=0
|
---|
121 | S MAX=HLCSTATE("TCP BUFFER SIZE")
|
---|
122 | U HLCSTATE("DEVICE") I (HLCSTATE("SYSTEM","OS")="CACHE") S HLCSTATE("CONNECTED")=($ZA\8192#2) I 'HLCSTATE("CONNECTED") D CLOSE(.HLCSTATE)
|
---|
123 | F S SEGMENT=$O(HLCSTATE("BUFFER",SEGMENT)) Q:'SEGMENT D
|
---|
124 | .N I S I=0
|
---|
125 | .F S I=$O(HLCSTATE("BUFFER",SEGMENT,I)) Q:'I D
|
---|
126 | ..N LINE,J
|
---|
127 | ..S J=$S(HLCSTATE("FIRST WRITE"):0,1:$X)
|
---|
128 | ..S HLCSTATE("FIRST WRITE")=0
|
---|
129 | ..S LINE=HLCSTATE("BUFFER",SEGMENT,I)
|
---|
130 | ..F Q:'(J+$L(LINE)>MAX) D
|
---|
131 | ...W $E(LINE,1,MAX-J),@HLCSTATE("FLUSH")
|
---|
132 | ...S LINE=$E(LINE,(MAX-J)+1,99999)
|
---|
133 | ...S J=0
|
---|
134 | ..W:(LINE]"") LINE
|
---|
135 | K HLCSTATE("BUFFER")
|
---|
136 | S HLCSTATE("BUFFER","SEGMENT COUNT")=1
|
---|
137 | S HLCSTATE("BUFFER","BYTE COUNT")=0
|
---|
138 | S HLCSTATE("FIRST WRITE")=0
|
---|
139 | Q
|
---|
140 | ;
|
---|
141 | READSEG(HLCSTATE,SEG) ;
|
---|
142 | ;
|
---|
143 | ;Output:
|
---|
144 | ; SEG - returns the segment (pass by reference)
|
---|
145 | ; Function returns 1 on success, 0 on failure
|
---|
146 | ;
|
---|
147 | N SUCCESS,COUNT,BUF
|
---|
148 | S (COUNT,SUCCESS)=0
|
---|
149 | K SEG
|
---|
150 | ;
|
---|
151 | ;anything left from last read?
|
---|
152 | S BUF=HLCSTATE("READ")
|
---|
153 | S HLCSTATE("READ")=""
|
---|
154 | I BUF]"" D ;something was left!
|
---|
155 | .S COUNT=1
|
---|
156 | .I BUF[$C(13) D Q
|
---|
157 | ..S SEG(1)=$P(BUF,$C(13)),BUF=$P(BUF,$C(13),2,9999)
|
---|
158 | ..S SUCCESS=1
|
---|
159 | .S SEG(1)=BUF,BUF=""
|
---|
160 | I 'SUCCESS U HLCSTATE("DEVICE") F R BUF:HLCSTATE("READ TIMEOUT") Q:'$T D Q:SUCCESS
|
---|
161 | .I BUF[$C(13) S SUCCESS=1,COUNT=COUNT+1,SEG(COUNT)=$P(BUF,$C(13)),BUF=$P(BUF,$C(13),2,9999) Q
|
---|
162 | .S COUNT=COUNT+1,SEG(COUNT)=BUF
|
---|
163 | ;
|
---|
164 | I SUCCESS D
|
---|
165 | .S HLCSTATE("READ")=BUF ;save the leftover
|
---|
166 | .I COUNT>1,SEG(COUNT)="" K SEG(COUNT) S COUNT=COUNT-1
|
---|
167 | ;Cache can return the connection status
|
---|
168 | E I (HLCSTATE("SYSTEM","OS")="CACHE") S HLCSTATE("CONNECTED")=($ZA\8192#2) I 'HLCSTATE("CONNECTED") D CLOSE(.HLCSTATE)
|
---|
169 | ;
|
---|
170 | ;if the <EB> character was encountered, then there are no more segments in the message, set the end of message flag
|
---|
171 | I SUCCESS,SEG(COUNT)[$C(28) D
|
---|
172 | .K SEG
|
---|
173 | .S SUCCESS=0
|
---|
174 | .S HLCSTATE("MESSAGE ENDED")=1
|
---|
175 | Q SUCCESS
|
---|
176 | ;
|
---|
177 | READHDR(HLCSTATE,HDR) ;
|
---|
178 | ;reads the next header segment in the message stream, discarding everything that comes before it
|
---|
179 | ;
|
---|
180 | N SEG,SUCCESS,J,I
|
---|
181 | S SUCCESS=0
|
---|
182 | K HDR
|
---|
183 | F Q:'$$READSEG(.HLCSTATE,.SEG) D Q:SUCCESS
|
---|
184 | .S I=0
|
---|
185 | .;look for the <SB>
|
---|
186 | .;perhaps the <SB> isn't in the first line
|
---|
187 | .F S I=$O(SEG(I)) Q:'I D Q:SUCCESS
|
---|
188 | ..I (SEG(I)'[$C(11)) K SEG(I) Q
|
---|
189 | ..S SEG(I)=$P(SEG(I),$C(11),2)
|
---|
190 | ..S SUCCESS=1
|
---|
191 | ..K:SEG(I)="" SEG(I)
|
---|
192 | I SUCCESS S (I,J)=0 F S J=$O(SEG(J)) Q:'J S I=I+1,HDR(I)=SEG(J)
|
---|
193 | Q SUCCESS
|
---|
194 | ;
|
---|
195 | CLOSE(HLCSTATE) ;
|
---|
196 | CLOSE HLCSTATE("DEVICE")
|
---|
197 | Q
|
---|
198 | ;
|
---|
199 | ENDMSG(HLCSTATE) ;
|
---|
200 | N SEG
|
---|
201 | S SEG(1)=$C(28)
|
---|
202 | I $$WRITESEG(.HLCSTATE,.SEG) D Q 1
|
---|
203 | .D FLUSH
|
---|
204 | .U HLCSTATE("DEVICE")
|
---|
205 | .W:$X @HLCSTATE("FLUSH")
|
---|
206 | Q 0
|
---|