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

INHVTMT2.m

Go to the documentation of this file.
  1. INHVTMT2 ; KAC ; 02 Nov 1999 17:54 ; Multi-threaded TCP/IP socket utilities
  1. ;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
  1. ;COPYRIGHT 1991-2000 SAIC
  1. Q
  1. ;
  1. RECEIVE(INCHNL,INIP,INERR,INMEM) ; Function - Read messages from
  1. ; TCP bfr and process into GIS. Once in this routine, reading is
  1. ; atomic (the transceiver may be told to stop, but RECEIVE will
  1. ; finish to a logical conclusion instead of throwing away data
  1. ; in the buffer or INREC).
  1. ;
  1. ; Called by: INHVTMT
  1. ;
  1. ; Input:
  1. ; INCHNL - (req) Socket from which to read
  1. ; INIP - (pbr) Array of parameters
  1. ; INERR - (pbr) Error array
  1. ; INMEM - not used (placeholder. %INET secondary memory)
  1. ;
  1. ; Function returns:
  1. ; 0=ok
  1. ; 1=no response at all
  1. ; 2=failure in middle of receive
  1. ; 3=remote system disconnected
  1. ;
  1. ; Note: The check for remote system disconnect is based on a string
  1. ; match from utility routine %INET. If that utility is changed, this
  1. ; must also be changed.
  1. ;
  1. N I,INBFR,INCLRMSG,INDELIM,INDONE,INEOL,INEOM,INFIRST,INFRMPOS,INFS,INIVBLD,INLOGMSG,INMSG,INMSGCNT,INNORESP,INNULLRD,INPOS,INREC,INRECCNT,INRSTATE,INSMIN,INSOD,INSOM,INV,REC,X,Y,Z
  1. ;
  1. ; Constants
  1. S INEOL=INIP("EOL"),INSOM=INIP("SOM"),INEOM=INIP("EOM")
  1. S:$D(INIP("SOD")) INSOD=INIP("SOD")
  1. S:$D(INIP("FS")) INFS=INIP("FS")
  1. S INSMIN=$S($P($G(^INRHSITE(1,0)),U,14):$P(^(0),U,14),1:2500)
  1. S INDELIM=$$FIELD^INHUT()
  1. ;
  1. ; Variables
  1. S (INBFR,INIVBLD,INMSG)="",(INDONE,INMSGCNT,INNORESP,INNULLRD,INRECCNT)=0
  1. S INREC="REC" K @INREC
  1. S INRSTATE="SOM" ; looking for SOM
  1. S INFIRST=1 ; 1st time thru decryptor per msg
  1. S INCLRMSG='$G(INIP("CRYPT")) ; 1 = do not decrypt rcv'd msg
  1. ;
  1. ; Main Loop
  1. F D Q:INDONE!INNORESP ; til no response or disconnect
  1. . D:$G(INDEBUG) LOG^INHVCRA1("Reading from buffer.",5)
  1. .; read input bfr (up to 512 bytes)
  1. . D RECV^%INET(.INBFR,.INCHNL,INIP("RTO"),1)
  1. .;
  1. .; Disconnect
  1. . I $G(INBFR(0))["Remote end disconnect" D Q
  1. .. S INDISCNT=INDISCNT+1
  1. .. I INIP("DTRY")'>INDISCNT D Q ; shutdwn xceiver
  1. ... S INRUNMT=0,INDONE=1
  1. ... S INLOGMSG="Disconnect retries exceeded for background process "_INBPNM
  1. ... D:$G(INDEBUG) LOG^INHVCRA1(INLOGMSG,7)
  1. ... D ENR^INHE(INBPN,INLOGMSG)
  1. .. S INDONE=3 ; retries not exceeded
  1. .;
  1. .; No response (on 1st or subsequent reads, therefore a 1 or 2 error)
  1. .; Read retries prevent dropping 1st part of msg cos 2nd part was delayed
  1. . I INBFR="" D Q
  1. ..; stop reading if not expecting any responses
  1. ..; pend que empty, not expecting HB response, not in middle of building msg
  1. .. I '$D(^INLHDEST(INDSTR,"PEND",INBPN)),(INSTATE'="HB"),'INRECCNT,'$D(INRSTATE("SOMFRAG")) S INPEND=0,INDONE=1 Q
  1. .. S INNULLRD=INNULLRD+1
  1. .. I INIP("RTRY")'>INNULLRD S INNORESP=1 Q ; read tries exceeded
  1. .. D WAIT^INHUVUT2(INBPN,INIP("RHNG"),"Waiting "_INIP("RHNG")_" seconds to read buffer",.INRUNMT)
  1. .. S INRUNMT='INRUNMT ; wait rtns opposite
  1. ..; if signalled to stop xceiver, stop if not in middle of building msg
  1. .. I 'INRUNMT,'INRECCNT,'$D(INRSTATE("SOMFRAG")) S INDONE=1 Q
  1. . S (INNULLRD,INDISCNT)=0 ; reset upon receipt
  1. .;
  1. .; Ck for bfr continuation (SOM frags). If no frags found, continue
  1. .; search for current state in this new bfr.
  1. . I $D(INRSTATE("SOMFRAG")) D ; SOM frags exist from prev read
  1. .. S X=$L(INSOM)-$L(INRSTATE("SOMFRAG")) ; # SOM chars expected @ start of in this bfr
  1. .. I (INRSTATE("SOMFRAG")_$E(INBFR,1,X)=INSOM) D
  1. ...; found frag completion at start of new bfr
  1. ... D:$G(INRECCNT) DATAFRAG^INHVTMT3(@INREC@(INRECCNT),0,$L(@INREC@(INRECCNT))) ; log msg in progress as data frag
  1. ... S INBFR=$E(INBFR,X+1,999999) ; remove SOM from msg
  1. ... S INRSTATE="SOD" ; SOM found - look for SOD
  1. .. K INRSTATE("SOMFRAG")
  1. .;
  1. .; create array (INFRMPOS) of framing chars in this bfr subscripted by position
  1. . K INFRMPOS
  1. . D GETFRAME^INHVTMT3(INBFR,INSOM,.INFRMPOS)
  1. . D:$D(INSOD) GETFRAME^INHVTMT3(INBFR,INSOD,.INFRMPOS)
  1. . D GETFRAME^INHVTMT3(INBFR,INEOM,.INFRMPOS)
  1. .;
  1. . S INPOS=0,INPOS("PREV")=0 ; must be remembered while reading bfr
  1. .;
  1. . F D Q:'INPOS ; scan for multiple msgs til bfr exhausted
  1. ..;
  1. ..; Scan bfr for single msg (or portion of msg)
  1. .. F I="SOM","SOD","EOM" S INPOS(I)=0
  1. .. F S INPOS=$O(INFRMPOS(INPOS)) Q:'INPOS D Q:INPOS("EOM")
  1. ... I (INRSTATE="SOM"),(INFRMPOS(INPOS)=INSOM) D Q
  1. .... S INPOS("SOM")=INPOS
  1. .... S INRSTATE=$S($D(INSOD):"SOD",1:"EOM") ; SOD may not be used
  1. ... I $D(INSOD),(INRSTATE="SOD"),(INFRMPOS(INPOS)=INSOD) D Q
  1. .... S INPOS("SOD")=INPOS
  1. .... S INRSTATE="EOM"
  1. ... I (INRSTATE="EOM"),(INFRMPOS(INPOS)=INEOM) D Q
  1. .... S INPOS("EOM")=INPOS
  1. .... S INRSTATE="SOM"
  1. ....; last position this bfr after which to log data frags
  1. .... S INPOS("PREV")=INPOS
  1. ...;
  1. ...; Data Fragmentation (possibly across bfrs)
  1. ... D DATAFRAG^INHVTMT3(INBFR,INPOS("PREV")+1,INPOS)
  1. ... S INPOS("PREV")=INPOS
  1. ...; incorrectly placed SOM may be start of good msg
  1. ... I INFRMPOS(INPOS)=INSOM D Q
  1. .... S INPOS("SOM")=INPOS
  1. .... S INRSTATE=$S($D(INSOD):"SOD",1:"EOM") ; SOD may not be used
  1. ...;
  1. ..; Scanning complete - ck for bfr continuation or SOM fragments
  1. ..; Scan returns incomplete msg
  1. .. I 'INPOS D Q ; reached end of bfr during scan before finding complete msg
  1. ...; SOM frags @ end of bfr?
  1. ... I $L(INSOM)>1,($E(INBFR,$L(INBFR)-$L(INSOM)+1,$L(INBFR))'=INSOM) D
  1. .... S X=$L(INBFR)+1,Y=$L(INSOM)-1
  1. .... F I=1:1:Y S Z=$E(INBFR,X-I,$L(INBFR)) I Z=$E(INSOM,1,I) S INRSTATE("SOMFRAG")=Z Q ; save frags
  1. ...;
  1. ... I "^SOD^EOM^"[(U_INRSTATE_U) D Q ; bfr continuation
  1. .... S INMSG=$E(INBFR,INPOS("SOM"),$L(INBFR))
  1. .... D PUTINREC^INHVTMT3(INMSG)
  1. ...;
  1. ...; If looking for SOM, log data frag (if any) thru end of bfr
  1. ... I (INRSTATE="SOM") D Q
  1. .... S X=INPOS("PREV"),Y=$L(INBFR)-$L($G(INRSTATE("SOMFRAG")))
  1. .... D:((Y-X)>0) DATAFRAG^INHVTMT3(INBFR,INPOS("PREV")+1,Y)
  1. ..;
  1. ..; Scan returns complete msg (EOM found)
  1. .. I INPOS D
  1. ... I $G(INRECCNT) D ; multiple-bfrs of data in INREC
  1. .... S INMSG=$E(INBFR,1,INPOS("EOM"))
  1. .... D PUTINREC^INHVTMT3(INMSG)
  1. ... I '$G(INRECCNT) D ; msg all in 1 bfr (includes SOM frags - $E expects INPOS("SOM")=0)
  1. .... S INMSG=$E(INBFR,INPOS("SOM"),INPOS("EOM"))
  1. .... D PUTINREC^INHVTMT3(INMSG)
  1. ..;
  1. .. Q:'INRECCNT ; no complete, raw msg to parse/validate
  1. ..;
  1. ..; Process msg @INREC
  1. .. S INV="INDATA" K @INV
  1. .. D PARSE^INHUVUT1 ; put INREC into INV
  1. .. K @INREC S INREC="REC",INRECCNT=0
  1. .. D EVAL^INHVTMT3(INV) ; submit msg for validation
  1. .. K @INV
  1. .. S INMSGCNT=INMSGCNT+1 ; # msgs read since call to $$RECEIVE
  1. ;
  1. ;
  1. ; Finished reading - return final state of connection
  1. ;
  1. ; Remote end disconnected
  1. I INDONE=3 S INERR=$G(INBFR(0)) K @INREC Q 3
  1. ;
  1. ; Remote system timed-out / log error
  1. I INRECCNT,INNORESP D Q 2
  1. . S INERR="Remote system on "_INBPNM_" timed out during transmission of message"
  1. . D DATAFRAG^INHVTMT3($G(@INREC@(1)),0,$L($G(@INREC@(1)))) ; log msg in progress as data frag
  1. ;
  1. ; No message received
  1. I 'INMSGCNT,INNORESP S INERR="No message received from remote system on transceiver "_INBPNM K @INREC Q 1
  1. ;
  1. Q 0
  1. ;
  1. ;