param buffer param header export const extractHeaderValue = ( buffer , header ) => { const anchor = `\n${ header . toLowerCase ( ) }: ` ; const start = buffer . toString ( ) . toLowerCase ( ) . indexOf ( anchor ) ; if ( start >= 0 ) { const end = buffer . indexOf ( '\n' , start + anchor . length ) ; const headerValue = buffer . toString ( 'ascii' , start + anchor . length , end ) . trim ( ) ; return headerValue ; } return null ; } ; export const sequence = ( buffer ) => { /**
     * CSeq           =  "CSeq" HCOLON cseq-nr
     * cseq-nr        =  1*9DIGIT
     */ const val = extractHeaderValue ( buffer , 'CSeq' ) ; if ( val !== null ) { return Number ( val ) ; } return null ; } ; export const sessionId = ( buffer ) => { /**
     * Session          =  "Session" HCOLON session-id
     *                     [ SEMI "timeout" EQUAL delta-seconds ]
     * session-id        =  1*256( ALPHA / DIGIT / safe )
     * delta-seconds     =  1*19DIGIT
     */ const val = extractHeaderValue ( buffer , 'Session' ) ; return val ? val . split ( ';' ) [ 0 ] : null ; } ; export const sessionTimeout = ( buffer ) => { /**
     * Session          =  "Session" HCOLON session-id
     *                     [ SEMI "timeout" EQUAL delta-seconds ]
     * session-id        =  1*256( ALPHA / DIGIT / safe )
     * delta-seconds     =  1*19DIGIT
     */ const val = extractHeaderValue ( buffer , 'Session' ) ; if ( val === null ) { return null ; } const defaultTimeout = 60 ; const timeoutToken = 'timeout=' ; const timeoutPosition = val . toLowerCase ( ) . indexOf ( timeoutToken ) ; if ( timeoutPosition !== - 1 ) { let timeoutVal = val . substring ( timeoutPosition + timeoutToken . length ) ; timeoutVal = timeoutVal . split ( ';' ) [ 0 ] ; const parsedTimeout = parseInt ( timeoutVal ) ; return isNaN ( parsedTimeout ) ? defaultTimeout : parsedTimeout ; } return defaultTimeout ; } ; export const statusCode = ( buffer ) => { return Number ( buffer . toString ( 'ascii' , 9 , 12 ) ) ; } ; export const contentBase = ( buffer ) => { /**
     * Content-Base       =  "Content-Base" HCOLON RTSP-URI
     */ return extractHeaderValue ( buffer , 'Content-Base' ) ; } ; export const contentLocation = ( buffer ) => { /**
     * Content-Location   =  "Content-Location" HCOLON RTSP-REQ-Ref
     */ return extractHeaderValue ( buffer , 'Content-Location' ) ; } ; export const connectionEnded = ( buffer ) => { /**
     * Connection         =  "Connection" HCOLON connection-token
     *                       *(COMMA connection-token)
     * connection-token   =  "close" / token
     */ const connectionToken = extractHeaderValue ( buffer , 'Connection' ) ; return connectionToken !== null && connectionToken . toLowerCase ( ) === 'close' ; } ; export const range = ( buffer ) => { /**
     * Range              =  "Range" HCOLON ranges-spec
     * ranges-spec        =  npt-range / utc-range / smpte-range
     *                       /  range-ext
     * npt-range        =  "npt" [EQUAL npt-range-spec]
     * npt-range-spec   =  ( npt-time "-" [ npt-time ] ) / ( "-" npt-time )
     * npt-time         =  "now" / npt-sec / npt-hhmmss / npt-hhmmss-comp
     * npt-sec          =  1*19DIGIT [ "." 1*9DIGIT ]
     * npt-hhmmss       =  npt-hh ":" npt-mm ":" npt-ss [ "." 1*9DIGIT ]
     * npt-hh           =  2*19DIGIT   ; any positive number
     * npt-mm           =  2*2DIGIT  ; 0-59
     * npt-ss           =  2*2DIGIT  ; 0-59
     * npt-hhmmss-comp  =  npt-hh-comp ":" npt-mm-comp ":" npt-ss-comp
     *                     [ "." 1*9DIGIT ] ; Compatibility format
     * npt-hh-comp      =  1*19DIGIT   ; any positive number
     * npt-mm-comp      =  1*2DIGIT  ; 0-59
     * npt-ss-comp      =  1*2DIGIT  ; 0-59
     */ const npt = extractHeaderValue ( buffer , 'Range' ) ; if ( npt !== null ) { return npt . split ( '=' ) [ 1 ] . split ( '-' ) ; } return undefined ; } ; param chunk return export const bodyOffset = ( chunk ) => { /**
     * Strictly speaking, it seems RTSP MUST have CRLF and doesn't allow CR or LF on its own.
     * That means that the end of the header part should be a pair of CRLF, but we're being
     * flexible here and also allow LF LF or CR CR instead of CRLF CRLF.
     */ const bodyOffsets = [ '\n\n' , '\r\r' , '\r\n\r\n' ] . map ( ( s ) => { const offset = chunk . indexOf ( s ) ; if ( offset !== - 1 ) { return offset + s . length ; } return offset ; } ) . filter ( ( offset ) => offset !== - 1 ) ; if ( bodyOffsets . length > 0 ) { return bodyOffsets . reduce ( ( acc , offset ) => { return Math . min ( acc , offset ) ; } ) ; } else { return - 1 ; } } ;