func()

in fragmenting_reader.go [256:309]


func (r *fragmentingReader) recvAndParseNextFragment(initial bool) error {
	if r.err != nil {
		return r.err
	}

	if r.curFragment != nil {
		r.curFragment.done()
	}

	r.curFragment, r.err = r.receiver.recvNextFragment(initial)
	if r.err != nil {
		if err, ok := r.err.(errorMessage); ok {
			// Serialized system errors are still reported (e.g. latency, trace reporting).
			r.err = err.AsSystemError()
			r.doneReading(r.err)
		}
		return r.err
	}

	// Set checksum, or confirm new checksum is the same type as the prior checksum
	if r.checksum == nil {
		r.checksum = r.curFragment.checksumType.New()
	} else if r.checksum.TypeCode() != r.curFragment.checksumType {
		return errMismatchedChecksumTypes
	}

	// Split fragment into underlying chunks
	r.hasMoreFragments = (r.curFragment.flags & hasMoreFragmentsFlag) == hasMoreFragmentsFlag
	r.remainingChunks = nil
	for r.curFragment.contents.BytesRemaining() > 0 && r.curFragment.contents.Err() == nil {
		chunkSize := r.curFragment.contents.ReadUint16()
		if chunkSize > uint16(r.curFragment.contents.BytesRemaining()) {
			return errChunkExceedsFragmentSize
		}
		chunkData := r.curFragment.contents.ReadBytes(int(chunkSize))
		r.remainingChunks = append(r.remainingChunks, chunkData)
		r.checksum.Add(chunkData)
	}

	if r.curFragment.contents.Err() != nil {
		return r.curFragment.contents.Err()
	}

	// Validate checksums
	localChecksum := r.checksum.Sum()
	if bytes.Compare(r.curFragment.checksum, localChecksum) != 0 {
		r.err = errMismatchedChecksums
		return r.err
	}

	// Pull out the first chunk to act as the current chunk
	r.curChunk, r.remainingChunks = r.remainingChunks[0], r.remainingChunks[1:]
	return nil
}