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  }