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