code: func (cl *Client) gotMetadataExtensionMsg(payload []byte, t *Torrent, c *connection) error {
  	var d map[string]int
  	err := bencode.Unmarshal(payload, &d)
  	if _, ok := err.(bencode.ErrUnusedTrailingBytes); ok {
  	} else if err != nil {
  		return fmt.Errorf("error unmarshalling bencode: %s", err)
  	}
  	msgType, ok := d["msg_type"]
  	if !ok {
  		return errors.New("missing msg_type field")
  	}
  	piece := d["piece"]
  	switch msgType {
  	case pp.DataMetadataExtensionMsgType:
  		c.allStats(add(1, func(cs *ConnStats) *Count { return &cs.MetadataChunksRead }))
  		if !c.requestedMetadataPiece(piece) {
  			return fmt.Errorf("got unexpected piece %d", piece)
  		}
  		c.metadataRequests[piece] = false
  		begin := len(payload) - metadataPieceSize(d["total_size"], piece)
  		if begin < 0 || begin >= len(payload) {
  			return fmt.Errorf("data has bad offset in payload: %d", begin)
  		}
  		t.saveMetadataPiece(piece, payload[begin:])
  		c.lastUsefulChunkReceived = time.Now()
  		return t.maybeCompleteMetadata()
  	case pp.RequestMetadataExtensionMsgType:
  		if !t.haveMetadataPiece(piece) {
  			c.Post(t.newMetadataExtensionMessage(c, pp.RejectMetadataExtensionMsgType, d["piece"], nil))
  			return nil
  		}
  		start := (1 << 14) * piece
  		c.Post(t.newMetadataExtensionMessage(c, pp.DataMetadataExtensionMsgType, piece, t.metadataBytes[start:start+t.metadataPieceSize(piece)]))
  		return nil
  	case pp.RejectMetadataExtensionMsgType:
  		return nil
  	default:
  		return errors.New("unknown msg_type value")
  	}
  }
docs: // Process incoming ut_metadata message.