frag.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package hysteria
  2. func FragUDPMessage(m *UDPMessage, maxSize int) []UDPMessage {
  3. if m.Size() <= maxSize {
  4. return []UDPMessage{*m}
  5. }
  6. fullPayload := m.Data
  7. maxPayloadSize := maxSize - m.HeaderSize()
  8. off := 0
  9. fragID := uint8(0)
  10. fragCount := uint8((len(fullPayload) + maxPayloadSize - 1) / maxPayloadSize) // round up
  11. frags := make([]UDPMessage, fragCount)
  12. for off < len(fullPayload) {
  13. payloadSize := len(fullPayload) - off
  14. if payloadSize > maxPayloadSize {
  15. payloadSize = maxPayloadSize
  16. }
  17. frag := *m
  18. frag.FragID = fragID
  19. frag.FragCount = fragCount
  20. frag.Data = fullPayload[off : off+payloadSize]
  21. frags[fragID] = frag
  22. off += payloadSize
  23. fragID++
  24. }
  25. return frags
  26. }
  27. // Defragger handles the defragmentation of UDP messages.
  28. // The current implementation can only handle one packet ID at a time.
  29. // If another packet arrives before a packet has received all fragments
  30. // in their entirety, any previous state is discarded.
  31. type Defragger struct {
  32. pktID uint16
  33. frags []*UDPMessage
  34. count uint8
  35. size int // data size
  36. }
  37. func (d *Defragger) Feed(m *UDPMessage) *UDPMessage {
  38. if m.FragCount <= 1 {
  39. return m
  40. }
  41. if m.FragID >= m.FragCount {
  42. // wtf is this?
  43. return nil
  44. }
  45. if m.PacketID != d.pktID || m.FragCount != uint8(len(d.frags)) {
  46. // new message, clear previous state
  47. d.pktID = m.PacketID
  48. d.frags = make([]*UDPMessage, m.FragCount)
  49. d.frags[m.FragID] = m
  50. d.count = 1
  51. d.size = len(m.Data)
  52. } else if d.frags[m.FragID] == nil {
  53. d.frags[m.FragID] = m
  54. d.count++
  55. d.size += len(m.Data)
  56. if int(d.count) == len(d.frags) {
  57. // all fragments received, assemble
  58. data := make([]byte, d.size)
  59. off := 0
  60. for _, frag := range d.frags {
  61. off += copy(data[off:], frag.Data)
  62. }
  63. m.Data = data
  64. m.FragID = 0
  65. m.FragCount = 1
  66. return m
  67. }
  68. }
  69. return nil
  70. }