fec.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Package fec implements the systematic Reed-Solomon erasure code used to carry
  2. // handshake messages that do not fit in a single UDP packet.
  3. //
  4. // A message is split into K equally sized data symbols (the last one zero
  5. // padded). Symbol indexes 0..K-1 are the data symbols themselves; indexes
  6. // K..MaxSymbols-1 are repair symbols. Any K distinct symbols reconstruct the
  7. // message. Repair symbols are generated on demand, so a sender can emit fresh
  8. // ones on every retransmit and a receiver can merge everything it has seen.
  9. package fec
  10. import (
  11. "errors"
  12. "fmt"
  13. )
  14. // MaxSymbols is the number of distinct symbols, data and repair together, one
  15. // message can be encoded into. It is bounded by the size of GF(2^8).
  16. const MaxSymbols = 256
  17. var (
  18. ErrInvalidLayout = errors.New("invalid fec layout")
  19. ErrIndexRange = errors.New("symbol index out of range")
  20. ErrSymbolSize = errors.New("symbol has the wrong size")
  21. ErrNotEnough = errors.New("not enough symbols to decode")
  22. ErrCorrupt = errors.New("decoded message has non-zero padding")
  23. )
  24. // Layout describes how a message is split into symbols. Both ends derive it
  25. // from the message length alone, so it never has to be sent.
  26. type Layout struct {
  27. MsgLen int // length of the message in bytes
  28. K int // number of data symbols
  29. SymbolSize int // size of every symbol, data and repair
  30. }
  31. // NewLayout returns the layout for a message of msgLen bytes carried in symbols
  32. // of at most maxSymbolSize bytes. Symbols are balanced, so padding is always
  33. // less than K bytes.
  34. func NewLayout(msgLen, maxSymbolSize int) (Layout, error) {
  35. if msgLen <= 0 || maxSymbolSize <= 0 {
  36. return Layout{}, ErrInvalidLayout
  37. }
  38. k := (msgLen + maxSymbolSize - 1) / maxSymbolSize
  39. if k >= MaxSymbols {
  40. return Layout{}, fmt.Errorf("%w: %d data symbols", ErrInvalidLayout, k)
  41. }
  42. return Layout{
  43. MsgLen: msgLen,
  44. K: k,
  45. SymbolSize: (msgLen + k - 1) / k,
  46. }, nil
  47. }
  48. // Encoder produces symbols for one message.
  49. type Encoder struct {
  50. layout Layout
  51. data [][]byte
  52. }
  53. // NewEncoder copies msg into padded data symbols.
  54. func NewEncoder(msg []byte, maxSymbolSize int) (*Encoder, error) {
  55. l, err := NewLayout(len(msg), maxSymbolSize)
  56. if err != nil {
  57. return nil, err
  58. }
  59. buf := make([]byte, l.K*l.SymbolSize)
  60. copy(buf, msg)
  61. data := make([][]byte, l.K)
  62. for i := range data {
  63. data[i] = buf[i*l.SymbolSize : (i+1)*l.SymbolSize]
  64. }
  65. return &Encoder{layout: l, data: data}, nil
  66. }
  67. func (e *Encoder) Layout() Layout {
  68. return e.layout
  69. }
  70. // Symbol appends the symbol with the given index to dst and returns the result.
  71. func (e *Encoder) Symbol(dst []byte, index int) ([]byte, error) {
  72. if index < 0 || index >= MaxSymbols {
  73. return nil, ErrIndexRange
  74. }
  75. if index < e.layout.K {
  76. return append(dst, e.data[index]...), nil
  77. }
  78. start := len(dst)
  79. dst = append(dst, make([]byte, e.layout.SymbolSize)...)
  80. out := dst[start:]
  81. for col, d := range e.data {
  82. mulAdd(out, d, coefficient(index, col))
  83. }
  84. return dst, nil
  85. }
  86. // Decoder collects symbols for one message until it can reconstruct it.
  87. // It stores at most K symbols, so its memory is bounded by the layout no matter
  88. // how many symbols arrive.
  89. type Decoder struct {
  90. layout Layout
  91. have [MaxSymbols]bool
  92. syms map[int][]byte
  93. }
  94. // NewDecoder returns a decoder for a message of msgLen bytes that was encoded
  95. // with the same maxSymbolSize.
  96. func NewDecoder(msgLen, maxSymbolSize int) (*Decoder, error) {
  97. l, err := NewLayout(msgLen, maxSymbolSize)
  98. if err != nil {
  99. return nil, err
  100. }
  101. return &Decoder{layout: l, syms: make(map[int][]byte, l.K)}, nil
  102. }
  103. func (d *Decoder) Layout() Layout {
  104. return d.layout
  105. }
  106. // Stored returns the number of symbols held.
  107. func (d *Decoder) Stored() int {
  108. return len(d.syms)
  109. }
  110. // Has reports whether the symbol with the given index is held.
  111. func (d *Decoder) Has(index int) bool {
  112. return index >= 0 && index < MaxSymbols && d.have[index]
  113. }
  114. // Ready reports whether enough symbols have arrived to decode.
  115. func (d *Decoder) Ready() bool {
  116. return len(d.syms) >= d.layout.K
  117. }
  118. // Add stores a copy of the symbol. Duplicates, and anything beyond the first K
  119. // distinct symbols, are ignored. It returns whether the decoder is ready.
  120. func (d *Decoder) Add(index int, sym []byte) (bool, error) {
  121. if index < 0 || index >= MaxSymbols {
  122. return d.Ready(), ErrIndexRange
  123. }
  124. if len(sym) != d.layout.SymbolSize {
  125. return d.Ready(), ErrSymbolSize
  126. }
  127. if d.have[index] || d.Ready() {
  128. return d.Ready(), nil
  129. }
  130. d.have[index] = true
  131. d.syms[index] = append([]byte(nil), sym...)
  132. return d.Ready(), nil
  133. }
  134. // Decode reconstructs the message from the stored symbols.
  135. func (d *Decoder) Decode() ([]byte, error) {
  136. if !d.Ready() {
  137. return nil, ErrNotEnough
  138. }
  139. l := d.layout
  140. out := make([]byte, l.K*l.SymbolSize)
  141. var missing, repair []int
  142. for i := range l.K {
  143. if s, ok := d.syms[i]; ok {
  144. copy(out[i*l.SymbolSize:], s)
  145. } else {
  146. missing = append(missing, i)
  147. }
  148. }
  149. if len(missing) > 0 {
  150. for i := l.K; i < MaxSymbols && len(repair) < len(missing); i++ {
  151. if d.have[i] {
  152. repair = append(repair, i)
  153. }
  154. }
  155. if len(repair) < len(missing) {
  156. return nil, ErrNotEnough
  157. }
  158. // Each repair symbol r satisfies r = sum_col coefficient(r, col) * data[col].
  159. // Move the known data columns to the left hand side, leaving a square
  160. // Cauchy system in the missing columns.
  161. rhs := make([][]byte, len(repair))
  162. m := make([][]byte, len(repair))
  163. for ri, row := range repair {
  164. rhs[ri] = append([]byte(nil), d.syms[row]...)
  165. m[ri] = make([]byte, len(missing))
  166. mi := 0
  167. for col := range l.K {
  168. if mi < len(missing) && missing[mi] == col {
  169. m[ri][mi] = coefficient(row, col)
  170. mi++
  171. continue
  172. }
  173. mulAdd(rhs[ri], out[col*l.SymbolSize:(col+1)*l.SymbolSize], coefficient(row, col))
  174. }
  175. }
  176. if !invert(m) {
  177. // Unreachable for a Cauchy matrix; kept so a broken invariant fails loudly.
  178. return nil, errors.New("fec: singular decode matrix")
  179. }
  180. for mi, col := range missing {
  181. dst := out[col*l.SymbolSize : (col+1)*l.SymbolSize]
  182. for ri := range repair {
  183. mulAdd(dst, rhs[ri], m[mi][ri])
  184. }
  185. }
  186. }
  187. for _, b := range out[l.MsgLen:] {
  188. if b != 0 {
  189. return nil, ErrCorrupt
  190. }
  191. }
  192. return out[:l.MsgLen], nil
  193. }