MCPcopy Create free account
hub / github.com/dotabuff/manta / readOuterMessage

Method readOuterMessage

parser.go:208–269  ·  view source on GitHub ↗

Read the next outer message from the buffer. The message is returned by value so it does not escape to the heap (its single caller, Start, consumes it immediately and never retains it).

()

Source from the content-addressed store, hash-verified

206// value so it does not escape to the heap (its single caller, Start, consumes
207// it immediately and never retains it).
208func (p *Parser) readOuterMessage() (outerMessage, error) {
209 // Read a command header, which includes both the message type
210 // well as a flag to determine whether or not whether or not the
211 // message is compressed with snappy.
212 command, err := p.stream.readCommand()
213 if err != nil {
214 return outerMessage{}, err
215 }
216
217 // Extract the type and compressed flag out of the command
218 msgType := int32(command & ^dota.EDemoCommands_DEM_IsCompressed)
219 msgCompressed := (command & dota.EDemoCommands_DEM_IsCompressed) == dota.EDemoCommands_DEM_IsCompressed
220
221 // Read the tick that the message corresponds with.
222 tick, err := p.stream.readVarUint32()
223 if err != nil {
224 return outerMessage{}, err
225 }
226
227 // This appears to actually be an int32, where a -1 means pre-game.
228 if tick == 4294967295 {
229 tick = 0
230 }
231
232 // Read the size and following buffer.
233 size, err := p.stream.readVarUint32()
234 if err != nil {
235 return outerMessage{}, err
236 }
237
238 // Reject an implausibly large size before allocating, so a corrupt or
239 // truncated stream fails cleanly instead of attempting a huge allocation.
240 if size > maxOuterMessageSize {
241 return outerMessage{}, _errorf("outer message size %d exceeds maximum %d", size, maxOuterMessageSize)
242 }
243
244 buf, err := p.stream.readBytes(size)
245 if err != nil {
246 return outerMessage{}, err
247 }
248
249 // If the buffer is compressed, decompress it with snappy, reusing a
250 // parser-level scratch buffer across messages. snappy.Decode reuses the
251 // destination when it is large enough, amortizing the decompression
252 // allocation to roughly the largest compressed message seen. This is safe
253 // because the decoded buffer is consumed within the dispatch of this
254 // message and never retained across outer messages.
255 if msgCompressed {
256 var err error
257 if buf, err = snappy.Decode(p.snappyScratch[:cap(p.snappyScratch)], buf); err != nil {
258 return outerMessage{}, err
259 }
260 p.snappyScratch = buf
261 }
262
263 // Return the message
264 return outerMessage{
265 tick: tick,

Callers 1

StartMethod · 0.95

Calls 4

_errorfFunction · 0.85
readCommandMethod · 0.80
readVarUint32Method · 0.45
readBytesMethod · 0.45

Tested by

no test coverage detected