%INET ; slt,bar,CHEM,LD ; 29 Dec 98 14:24;Internet function utility - MSM
;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
;CHCS TLS_4603; GEN 1; 21-MAY-1999
;COPYRIGHT 1998 SAIC
;NOTE: unlike DSM %INET, this version does NOT support multiple client
; connections to the same address simultaneously by a single process.
Q
OPEN(ZICHAN,ZIX,ZIDOMAIN,ZIPORT,ZIPROT) ;open an internet socket
;input:
; ZICHAN --> receives the "IP Address, domain" or "IP Address"
; ZIX --> variable used as 1st argument to RECV procedure
; ZIDOMAIN --> domain name i.e. Internet address (null to open a server connection.)
; ZIPORT --> port number
; ZIPROT --> null, 0 or 1:tcp, 2:udp
;
S $ZT="ERR^"_$T(+0)
N %,INDI S INDI=$G(IO,$I)
S ZICHAN=0,ZIX(1)="",ZIX(2)=""
S ZIPROT=$G(ZIPROT),ZIPROT=$S('ZIPROT!(ZIPROT=1):"TCP",1:"UDP")
C 56 O 56::5
;Xecute statements for ^ZCMS (not proper DSM syntax - duh.)
; :(:1) sets the flag on the TCP port to change the behavior of
; a WRITE ! to the socket - it will transmit <CR><LF> instead of
; merely flushing the buffer. See "MSM-Server User's Guide" in the
; "Using Peripheral Devices" section labeled "TCP/IP Socket Device"
; for more information.
X "U 56:(:1)" ; !=$C(13,10)
X "U 56::ZIPROT W /SOCKET(ZIDOMAIN,ZIPORT) S %=$KEY=""""!$ZC" Q:%
X "S ZICHAN=$KEY" ; $KEY is MSM's "connection" (numeric) identifier
U:INDI]"" INDI
Q
;
CLOSE(ZICHAN) ;close the Internet socket (flush)
;input:
; ZICHAN --> "IP Address, domain" or "IP Address"
;
Q:'$L($G(ZICHAN))
S $ZT="QUIT^"_$T(+0)
X "C:ZICHAN 56:ZICHAN" K ZICHAN
Q
;
SEND(ZIX,ZICHAN,ZICRLF) ;send a message over socket
;input:
; ZIX --> a line of text to be sent
; ZICHAN --> "IP Address, Domain" or "IP Address"
; ZICRLF --> carriage return/line feed flag 0:yes, 1:no
;
S $ZT="ERR^"_$T(+0)
N INDI S INDI=$G(IO,$I) U 56
I '$G(ZICRLF),$L(ZIX)<511 W ZIX_$C(13,10)
E W ZIX W:'$G(ZICRLF) !
U:INDI]"" INDI Q
;
RECV(ZIX,ZICHAN,ZITO,ZICRLF) ;receive message from socket
;input:
; ZIX --> variable/array buffer
; ZICHAN --> "IP Address, Domain" or "IP Address"
; ZITO --> numeric time out valued in seconds
; ZICRLF --> carriage return/line feed flag 0:yes, 1:no
; (YES means we expect a CR LF and wish to strip it before
; returning to calling application.)
;output:
; ZIX --> received message
;
S $ZT="ERR^"_$T(+0)
N INDI S INDI=$G(IO,$I) U 56 ; note: 4 separate exit points
S ZICRLF=$G(ZICRLF) K ZIX(0)
S ZITO=$S('$D(ZITO):600,1:ZITO),ZIX(1)=$G(ZIX(1)),ZIX(2)=$G(ZIX(2))
;
; If a <CR> <LF> is expected as delimiter, and should be stripped...
I 'ZICRLF D U:INDI]"" INDI Q
.;Loop until we either get a terminator or a read timeout
.N INOK S INOK=0,ZIX="" F D Q:$D(ZIX(0))!(INOK)
..S ZIX(2)=ZIX(2)_ZIX
..;If data left in buffer, use that first
..I $L(ZIX(2)),$F(ZIX(2),$C(10)) D S INOK=1 Q
...N Y S Y=$F(ZIX(2),$C(10)),ZIX=$E(ZIX(2),1,Y-($A(ZIX(2),Y-2)=13)-2),ZIX(2)=$E(ZIX(2),Y,$L(ZIX(2)))
...I $L(ZIX)>512 S ZIX(2)=$E(ZIX,513,$L(ZIX))_$C(10)_ZIX(2),ZIX=$E(ZIX,1,512)
..I $L(ZIX(2))>511 S INOK=1,ZIX=$E(ZIX(2),1,512),ZIX(2)=$E(ZIX(2),513,$L(ZIX(2))) Q
..;Read more from socket...
..I ZITO R ZIX:ZITO E S ZIX(0)="Connection timed out",ZIX="" Q
..I ZITO,$ZC S ZIX(0)="Socket closed: MSM Error $ZB="_$ZB,ZIX="" Q
..I 'ZITO R ZIX S INOK=1 Q
..;and append result to the string we will check on next pass
..S ZIX=ZIX(2)_ZIX,ZIX(2)=""
;
;If we are reading just packets, with no terminators (eg CR LF)
;
;If data left in buffer, use that first
I ZICRLF,$L(ZIX(2)) D U:INDI]"" INDI Q
.S ZIX=$E(ZIX(2),1,512),ZIX(2)=$E(ZIX(2),513,$L(ZIX(2)))
;
;Read more from socket
I ZITO R ZIX:ZITO E S ZIX(0)="Connection timed out",ZIX="" U:INDI]"" INDI Q
I 'ZITO R ZIX
;
S ZIX=ZIX(2)_ZIX,ZIX(2)=""
;
I $L(ZIX)>512 S ZIX(2)=$E(ZIX,513,$L(ZIX)),ZIX=$E(ZIX,1,512)
U:INDI]"" INDI
Q
;
ERR ; Handle error trap
I $ZE["<DSCON" S ZIX(0)="Remote end disconected" X:$G(ZICHAN) "C 56:ZICHAN S ZICHAN=""""" U:INDI]"" INDI Q
G ^%ET
QUIT ; Ignore all errors when closing the channel. Just close it.
Q
%INET ; slt,bar,CHEM,LD ; 29 Dec 98 14:24;Internet function utility - MSM
+1 ;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
+2 ;CHCS TLS_4603; GEN 1; 21-MAY-1999
+3 ;COPYRIGHT 1998 SAIC
+4 ;NOTE: unlike DSM %INET, this version does NOT support multiple client
+5 ; connections to the same address simultaneously by a single process.
+6 QUIT
OPEN(ZICHAN,ZIX,ZIDOMAIN,ZIPORT,ZIPROT) ;open an internet socket
+1 ;input:
+2 ; ZICHAN --> receives the "IP Address, domain" or "IP Address"
+3 ; ZIX --> variable used as 1st argument to RECV procedure
+4 ; ZIDOMAIN --> domain name i.e. Internet address (null to open a server connection.)
+5 ; ZIPORT --> port number
+6 ; ZIPROT --> null, 0 or 1:tcp, 2:udp
+7 ;
+8 SET $ZT="ERR^"_$TEXT(+0)
+9 NEW %,INDI
SET INDI=$GET(IO,$IO)
+10 SET ZICHAN=0
SET ZIX(1)=""
SET ZIX(2)=""
+11 SET ZIPROT=$GET(ZIPROT)
SET ZIPROT=$SELECT('ZIPROT!(ZIPROT=1):"TCP",1:"UDP")
+12 CLOSE 56
OPEN 56::5
+13 ;Xecute statements for ^ZCMS (not proper DSM syntax - duh.)
+14 ; :(:1) sets the flag on the TCP port to change the behavior of
+15 ; a WRITE ! to the socket - it will transmit <CR><LF> instead of
+16 ; merely flushing the buffer. See "MSM-Server User's Guide" in the
+17 ; "Using Peripheral Devices" section labeled "TCP/IP Socket Device"
+18 ; for more information.
+19 ; !=$C(13,10)
XECUTE "U 56:(:1)"
+20 XECUTE "U 56::ZIPROT W /SOCKET(ZIDOMAIN,ZIPORT) S %=$KEY=""""!$ZC"
IF %
QUIT
+21 ; $KEY is MSM's "connection" (numeric) identifier
XECUTE "S ZICHAN=$KEY"
+22 IF INDI]""
USE INDI
+23 QUIT
+24 ;
CLOSE(ZICHAN) ;close the Internet socket (flush)
+1 ;input:
+2 ; ZICHAN --> "IP Address, domain" or "IP Address"
+3 ;
+4 IF '$LENGTH($GET(ZICHAN))
QUIT
+5 SET $ZT="QUIT^"_$TEXT(+0)
+6 XECUTE "C:ZICHAN 56:ZICHAN"
KILL ZICHAN
+7 QUIT
+8 ;
SEND(ZIX,ZICHAN,ZICRLF) ;send a message over socket
+1 ;input:
+2 ; ZIX --> a line of text to be sent
+3 ; ZICHAN --> "IP Address, Domain" or "IP Address"
+4 ; ZICRLF --> carriage return/line feed flag 0:yes, 1:no
+5 ;
+6 SET $ZT="ERR^"_$TEXT(+0)
+7 NEW INDI
SET INDI=$GET(IO,$IO)
USE 56
+8 IF '$GET(ZICRLF)
IF $LENGTH(ZIX)<511
WRITE ZIX_$CHAR(13,10)
+9 IF '$TEST
WRITE ZIX
IF '$GET(ZICRLF)
WRITE !
+10 IF INDI]""
USE INDI
QUIT
+11 ;
RECV(ZIX,ZICHAN,ZITO,ZICRLF) ;receive message from socket
+1 ;input:
+2 ; ZIX --> variable/array buffer
+3 ; ZICHAN --> "IP Address, Domain" or "IP Address"
+4 ; ZITO --> numeric time out valued in seconds
+5 ; ZICRLF --> carriage return/line feed flag 0:yes, 1:no
+6 ; (YES means we expect a CR LF and wish to strip it before
+7 ; returning to calling application.)
+8 ;output:
+9 ; ZIX --> received message
+10 ;
+11 SET $ZT="ERR^"_$TEXT(+0)
+12 ; note: 4 separate exit points
NEW INDI
SET INDI=$GET(IO,$IO)
USE 56
+13 SET ZICRLF=$GET(ZICRLF)
KILL ZIX(0)
+14 SET ZITO=$SELECT('$DATA(ZITO):600,1:ZITO)
SET ZIX(1)=$GET(ZIX(1))
SET ZIX(2)=$GET(ZIX(2))
+15 ;
+16 ; If a <CR> <LF> is expected as delimiter, and should be stripped...
+17 IF 'ZICRLF
Begin DoDot:1
+18 ;Loop until we either get a terminator or a read timeout
+19 NEW INOK
SET INOK=0
SET ZIX=""
FOR
Begin DoDot:2
+20 SET ZIX(2)=ZIX(2)_ZIX
+21 ;If data left in buffer, use that first
+22 IF $LENGTH(ZIX(2))
IF $FIND(ZIX(2),$CHAR(10))
Begin DoDot:3
+23 NEW Y
SET Y=$FIND(ZIX(2),$CHAR(10))
SET ZIX=$EXTRACT(ZIX(2),1,Y-($ASCII(ZIX(2),Y-2)=13)-2)
SET ZIX(2)=$EXTRACT(ZIX(2),Y,$LENGTH(ZIX(2)))
+24 IF $LENGTH(ZIX)>512
SET ZIX(2)=$EXTRACT(ZIX,513,$LENGTH(ZIX))_$CHAR(10)_ZIX(2)
SET ZIX=$EXTRACT(ZIX,1,512)
End DoDot:3
SET INOK=1
QUIT
+25 IF $LENGTH(ZIX(2))>511
SET INOK=1
SET ZIX=$EXTRACT(ZIX(2),1,512)
SET ZIX(2)=$EXTRACT(ZIX(2),513,$LENGTH(ZIX(2)))
QUIT
+26 ;Read more from socket...
+27 IF ZITO
READ ZIX:ZITO
IF '$TEST
SET ZIX(0)="Connection timed out"
SET ZIX=""
QUIT
+28 IF ZITO
IF $ZC
SET ZIX(0)="Socket closed: MSM Error $ZB="_$ZB
SET ZIX=""
QUIT
+29 IF 'ZITO
READ ZIX
SET INOK=1
QUIT
+30 ;and append result to the string we will check on next pass
+31 SET ZIX=ZIX(2)_ZIX
SET ZIX(2)=""
End DoDot:2
IF $DATA(ZIX(0))!(INOK)
QUIT
End DoDot:1
IF INDI]""
USE INDI
QUIT
+32 ;
+33 ;If we are reading just packets, with no terminators (eg CR LF)
+34 ;
+35 ;If data left in buffer, use that first
+36 IF ZICRLF
IF $LENGTH(ZIX(2))
Begin DoDot:1
+37 SET ZIX=$EXTRACT(ZIX(2),1,512)
SET ZIX(2)=$EXTRACT(ZIX(2),513,$LENGTH(ZIX(2)))
End DoDot:1
IF INDI]""
USE INDI
QUIT
+38 ;
+39 ;Read more from socket
+40 IF ZITO
READ ZIX:ZITO
IF '$TEST
SET ZIX(0)="Connection timed out"
SET ZIX=""
IF INDI]""
USE INDI
QUIT
+41 IF 'ZITO
READ ZIX
+42 ;
+43 SET ZIX=ZIX(2)_ZIX
SET ZIX(2)=""
+44 ;
+45 IF $LENGTH(ZIX)>512
SET ZIX(2)=$EXTRACT(ZIX,513,$LENGTH(ZIX))
SET ZIX=$EXTRACT(ZIX,1,512)
+46 IF INDI]""
USE INDI
+47 QUIT
+48 ;
ERR ; Handle error trap
+1 IF $ZE["<DSCON"
SET ZIX(0)="Remote end disconected"
IF $GET(ZICHAN)
XECUTE "C 56:ZICHAN S ZICHAN="""""
IF INDI]""
USE INDI
QUIT
+2 GOTO ^%ET
QUIT ; Ignore all errors when closing the channel. Just close it.
+1 QUIT