writer.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright 2012 Google, Inc. All rights reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the LICENSE file in the root of the source
  5. // tree.
  6. package gopacket
  7. import (
  8. "fmt"
  9. )
  10. // SerializableLayer allows its implementations to be written out as a set of bytes,
  11. // so those bytes may be sent on the wire or otherwise used by the caller.
  12. // SerializableLayer is implemented by certain Layer types, and can be encoded to
  13. // bytes using the LayerWriter object.
  14. type SerializableLayer interface {
  15. // SerializeTo writes this layer to a slice, growing that slice if necessary
  16. // to make it fit the layer's data.
  17. // Args:
  18. // b: SerializeBuffer to write this layer on to. When called, b.Bytes()
  19. // is the payload this layer should wrap, if any. Note that this
  20. // layer can either prepend itself (common), append itself
  21. // (uncommon), or both (sometimes padding or footers are required at
  22. // the end of packet data). It's also possible (though probably very
  23. // rarely needed) to overwrite any bytes in the current payload.
  24. // After this call, b.Bytes() should return the byte encoding of
  25. // this layer wrapping the original b.Bytes() payload.
  26. // opts: options to use while writing out data.
  27. // Returns:
  28. // error if a problem was encountered during encoding. If an error is
  29. // returned, the bytes in data should be considered invalidated, and
  30. // not used.
  31. //
  32. // SerializeTo calls SHOULD entirely ignore LayerContents and
  33. // LayerPayload. It just serializes based on struct fields, neither
  34. // modifying nor using contents/payload.
  35. SerializeTo(b SerializeBuffer, opts SerializeOptions) error
  36. // LayerType returns the type of the layer that is being serialized to the buffer
  37. LayerType() LayerType
  38. }
  39. // SerializeOptions provides options for behaviors that SerializableLayers may want to
  40. // implement.
  41. type SerializeOptions struct {
  42. // FixLengths determines whether, during serialization, layers should fix
  43. // the values for any length field that depends on the payload.
  44. FixLengths bool
  45. // ComputeChecksums determines whether, during serialization, layers
  46. // should recompute checksums based on their payloads.
  47. ComputeChecksums bool
  48. }
  49. // SerializeBuffer is a helper used by gopacket for writing out packet layers.
  50. // SerializeBuffer starts off as an empty []byte. Subsequent calls to PrependBytes
  51. // return byte slices before the current Bytes(), AppendBytes returns byte
  52. // slices after.
  53. //
  54. // Byte slices returned by PrependBytes/AppendBytes are NOT zero'd out, so if
  55. // you want to make sure they're all zeros, set them as such.
  56. //
  57. // SerializeBuffer is specifically designed to handle packet writing, where unlike
  58. // with normal writes it's easier to start writing at the inner-most layer and
  59. // work out, meaning that we often need to prepend bytes. This runs counter to
  60. // typical writes to byte slices using append(), where we only write at the end
  61. // of the buffer.
  62. //
  63. // It can be reused via Clear. Note, however, that a Clear call will invalidate the
  64. // byte slices returned by any previous Bytes() call (the same buffer is
  65. // reused).
  66. //
  67. // 1) Reusing a write buffer is generally much faster than creating a new one,
  68. // and with the default implementation it avoids additional memory allocations.
  69. // 2) If a byte slice from a previous Bytes() call will continue to be used,
  70. // it's better to create a new SerializeBuffer.
  71. //
  72. // The Clear method is specifically designed to minimize memory allocations for
  73. // similar later workloads on the SerializeBuffer. IE: if you make a set of
  74. // Prepend/Append calls, then clear, then make the same calls with the same
  75. // sizes, the second round (and all future similar rounds) shouldn't allocate
  76. // any new memory.
  77. type SerializeBuffer interface {
  78. // Bytes returns the contiguous set of bytes collected so far by Prepend/Append
  79. // calls. The slice returned by Bytes will be modified by future Clear calls,
  80. // so if you're planning on clearing this SerializeBuffer, you may want to copy
  81. // Bytes somewhere safe first.
  82. Bytes() []byte
  83. // PrependBytes returns a set of bytes which prepends the current bytes in this
  84. // buffer. These bytes start in an indeterminate state, so they should be
  85. // overwritten by the caller. The caller must only call PrependBytes if they
  86. // know they're going to immediately overwrite all bytes returned.
  87. PrependBytes(num int) ([]byte, error)
  88. // AppendBytes returns a set of bytes which appends the current bytes in this
  89. // buffer. These bytes start in an indeterminate state, so they should be
  90. // overwritten by the caller. The caller must only call AppendBytes if they
  91. // know they're going to immediately overwrite all bytes returned.
  92. AppendBytes(num int) ([]byte, error)
  93. // Clear resets the SerializeBuffer to a new, empty buffer. After a call to clear,
  94. // the byte slice returned by any previous call to Bytes() for this buffer
  95. // should be considered invalidated.
  96. Clear() error
  97. // Layers returns all the Layers that have been successfully serialized into this buffer
  98. // already.
  99. Layers() []LayerType
  100. // PushLayer adds the current Layer to the list of Layers that have been serialized
  101. // into this buffer.
  102. PushLayer(LayerType)
  103. }
  104. type serializeBuffer struct {
  105. data []byte
  106. start int
  107. prepended, appended int
  108. layers []LayerType
  109. }
  110. // NewSerializeBuffer creates a new instance of the default implementation of
  111. // the SerializeBuffer interface.
  112. func NewSerializeBuffer() SerializeBuffer {
  113. return &serializeBuffer{}
  114. }
  115. // NewSerializeBufferExpectedSize creates a new buffer for serialization, optimized for an
  116. // expected number of bytes prepended/appended. This tends to decrease the
  117. // number of memory allocations made by the buffer during writes.
  118. func NewSerializeBufferExpectedSize(expectedPrependLength, expectedAppendLength int) SerializeBuffer {
  119. return &serializeBuffer{
  120. data: make([]byte, expectedPrependLength, expectedPrependLength+expectedAppendLength),
  121. start: expectedPrependLength,
  122. prepended: expectedPrependLength,
  123. appended: expectedAppendLength,
  124. }
  125. }
  126. func (w *serializeBuffer) Bytes() []byte {
  127. return w.data[w.start:]
  128. }
  129. func (w *serializeBuffer) PrependBytes(num int) ([]byte, error) {
  130. if num < 0 {
  131. panic("num < 0")
  132. }
  133. if w.start < num {
  134. toPrepend := w.prepended
  135. if toPrepend < num {
  136. toPrepend = num
  137. }
  138. w.prepended += toPrepend
  139. length := cap(w.data) + toPrepend
  140. newData := make([]byte, length)
  141. newStart := w.start + toPrepend
  142. copy(newData[newStart:], w.data[w.start:])
  143. w.start = newStart
  144. w.data = newData[:toPrepend+len(w.data)]
  145. }
  146. w.start -= num
  147. return w.data[w.start : w.start+num], nil
  148. }
  149. func (w *serializeBuffer) AppendBytes(num int) ([]byte, error) {
  150. if num < 0 {
  151. panic("num < 0")
  152. }
  153. initialLength := len(w.data)
  154. if cap(w.data)-initialLength < num {
  155. toAppend := w.appended
  156. if toAppend < num {
  157. toAppend = num
  158. }
  159. w.appended += toAppend
  160. newData := make([]byte, cap(w.data)+toAppend)
  161. copy(newData[w.start:], w.data[w.start:])
  162. w.data = newData[:initialLength]
  163. }
  164. // Grow the buffer. We know it'll be under capacity given above.
  165. w.data = w.data[:initialLength+num]
  166. return w.data[initialLength:], nil
  167. }
  168. func (w *serializeBuffer) Clear() error {
  169. w.start = w.prepended
  170. w.data = w.data[:w.start]
  171. w.layers = w.layers[:0]
  172. return nil
  173. }
  174. func (w *serializeBuffer) Layers() []LayerType {
  175. return w.layers
  176. }
  177. func (w *serializeBuffer) PushLayer(l LayerType) {
  178. w.layers = append(w.layers, l)
  179. }
  180. // SerializeLayers clears the given write buffer, then writes all layers into it so
  181. // they correctly wrap each other. Note that by clearing the buffer, it
  182. // invalidates all slices previously returned by w.Bytes()
  183. //
  184. // Example:
  185. // buf := gopacket.NewSerializeBuffer()
  186. // opts := gopacket.SerializeOptions{}
  187. // gopacket.SerializeLayers(buf, opts, a, b, c)
  188. // firstPayload := buf.Bytes() // contains byte representation of a(b(c))
  189. // gopacket.SerializeLayers(buf, opts, d, e, f)
  190. // secondPayload := buf.Bytes() // contains byte representation of d(e(f)). firstPayload is now invalidated, since the SerializeLayers call Clears buf.
  191. func SerializeLayers(w SerializeBuffer, opts SerializeOptions, layers ...SerializableLayer) error {
  192. w.Clear()
  193. for i := len(layers) - 1; i >= 0; i-- {
  194. layer := layers[i]
  195. err := layer.SerializeTo(w, opts)
  196. if err != nil {
  197. return err
  198. }
  199. w.PushLayer(layer.LayerType())
  200. }
  201. return nil
  202. }
  203. // SerializePacket is a convenience function that calls SerializeLayers
  204. // on packet's Layers().
  205. // It returns an error if one of the packet layers is not a SerializebleLayer.
  206. func SerializePacket(buf SerializeBuffer, opts SerializeOptions, packet Packet) error {
  207. sls := []SerializableLayer{}
  208. for _, layer := range packet.Layers() {
  209. sl, ok := layer.(SerializableLayer)
  210. if !ok {
  211. return fmt.Errorf("layer %s is not serializable", layer.LayerType().String())
  212. }
  213. sls = append(sls, sl)
  214. }
  215. return SerializeLayers(buf, opts, sls...)
  216. }