github.com/metacubex/mihomo@v1.18.5/transport/hysteria/core/frag.go (about) 1 package core 2 3 func fragUDPMessage(m udpMessage, maxSize int) []udpMessage { 4 if m.Size() <= maxSize { 5 return []udpMessage{m} 6 } 7 fullPayload := m.Data 8 maxPayloadSize := maxSize - m.HeaderSize() 9 off := 0 10 fragID := uint8(0) 11 fragCount := uint8((len(fullPayload) + maxPayloadSize - 1) / maxPayloadSize) // round up 12 var frags []udpMessage 13 for off < len(fullPayload) { 14 payloadSize := len(fullPayload) - off 15 if payloadSize > maxPayloadSize { 16 payloadSize = maxPayloadSize 17 } 18 frag := m 19 frag.FragID = fragID 20 frag.FragCount = fragCount 21 frag.DataLen = uint16(payloadSize) 22 frag.Data = fullPayload[off : off+payloadSize] 23 frags = append(frags, frag) 24 off += payloadSize 25 fragID++ 26 } 27 return frags 28 } 29 30 type defragger struct { 31 msgID uint16 32 frags []*udpMessage 33 count uint8 34 } 35 36 func (d *defragger) Feed(m udpMessage) *udpMessage { 37 if m.FragCount <= 1 { 38 return &m 39 } 40 if m.FragID >= m.FragCount { 41 // wtf is this? 42 return nil 43 } 44 if m.MsgID != d.msgID { 45 // new message, clear previous state 46 d.msgID = m.MsgID 47 d.frags = make([]*udpMessage, m.FragCount) 48 d.count = 1 49 d.frags[m.FragID] = &m 50 } else if d.frags[m.FragID] == nil { 51 d.frags[m.FragID] = &m 52 d.count++ 53 if int(d.count) == len(d.frags) { 54 // all fragments received, assemble 55 var data []byte 56 for _, frag := range d.frags { 57 data = append(data, frag.Data...) 58 } 59 m.DataLen = uint16(len(data)) 60 m.Data = data 61 m.FragID = 0 62 m.FragCount = 1 63 return &m 64 } 65 } 66 return nil 67 }