code: func (f *Fragmentation) Process(id uint32, first, last uint16, more bool, vv buffer.VectorisedView) (buffer.VectorisedView, bool) {
  	f.mu.Lock()
  	r, ok := f.reassemblers[id]
  	if ok && r.tooOld(f.timeout) {
  		// This is very likely to be an id-collision or someone performing a slow-rate attack.
  		f.release(r)
  		ok = false
  	}
  	if !ok {
  		r = newReassembler(id)
  		f.reassemblers[id] = r
  		f.rList.PushFront(r)
  	}
  	f.mu.Unlock()
  
  	res, done, consumed := r.process(first, last, more, vv)
  
  	f.mu.Lock()
  	f.size += consumed
  	if done {
  		f.release(r)
  	}
  	// Evict reassemblers if we are consuming more memory than highLimit until
  	// we reach lowLimit.
  	if f.size > f.highLimit {
  		tail := f.rList.Back()
  		for f.size > f.lowLimit && tail != nil {
  			f.release(tail)
  			tail = tail.Prev()
  		}
  	}
  	f.mu.Unlock()
  	return res, done
  }
docs: // Process processes an incoming fragment beloning to an ID
  // and returns a complete packet when all the packets belonging to that ID have been received.