import { CipherContext } from "../context/cipher" ; import { DtlsContext } from "../context/dtls" ; import { Alert } from "../handshake/message/alert" ; import { ContentType } from "./const" ; import { FragmentedHandshake } from "./message/fragment" ; import { DtlsPlaintext } from "./message/plaintext" ; export const parsePacket = ( dtls , cipher ) => ( data ) => { let start = 0 ; const packets = [ ] ; while ( data . length > start ) { const fragmentLength = data . readUInt16BE ( start + 11 ) ; if ( data . length < start + ( 12 + fragmentLength ) ) break ; const packet = DtlsPlaintext . deSerialize ( data . slice ( start ) ) ; packets . push ( packet ) ; start += 13 + fragmentLength ; } let changeCipherSpec = false ; const results = packets . map ( ( p ) => { switch ( p . recordLayerHeader . contentType ) { case ContentType . changeCipherSpec : { changeCipherSpec = true ; return { type : ContentType . changeCipherSpec , data : undefined } ; } case ContentType . handshake : { let raw = p . fragment ; if ( p . recordLayerHeader . epoch > 0 ) { if ( changeCipherSpec && dtls . flight < 5 ) { return { type : - 1 , data : p } ; } raw = cipher . decryptPacket ( p ) ; } return { type : ContentType . handshake , data : FragmentedHandshake . deSerialize ( raw ) , } ; } case ContentType . applicationData : { return { type : ContentType . applicationData , data : cipher . decryptPacket ( p ) , } ; } case ContentType . alert : { const alert = Alert . deSerialize ( p . fragment ) ; console . log ( "ContentType.alert" , alert ) ; if ( alert . level > 1 ) throw new Error ( "alert fatal error" ) ; } default : { return { type : ContentType . alert , data : undefined } ; } } } ) ; return results ; } ;