mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-11-04 00:11:04 +00:00 
			
		
		
		
	* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
		
			
				
	
	
		
			137 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package uuid
 | 
						|
 | 
						|
/****************
 | 
						|
 * Date: 14/02/14
 | 
						|
 * Time: 7:43 PM
 | 
						|
 ***************/
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"log"
 | 
						|
	seed "math/rand"
 | 
						|
	"net"
 | 
						|
	"sync"
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
// **************************************************** State
 | 
						|
 | 
						|
func SetupCustomStateSaver(pSaver StateSaver) {
 | 
						|
	state.Lock()
 | 
						|
	pSaver.Init(&state)
 | 
						|
	state.init()
 | 
						|
	state.Unlock()
 | 
						|
}
 | 
						|
 | 
						|
// Holds package information about the current
 | 
						|
// state of the UUID generator
 | 
						|
type State struct {
 | 
						|
 | 
						|
	// A flag which informs whether to
 | 
						|
	// randomly create a node id
 | 
						|
	randomNode bool
 | 
						|
 | 
						|
	// A flag which informs whether to
 | 
						|
	// randomly create the sequence
 | 
						|
	randomSequence bool
 | 
						|
 | 
						|
	// the last time UUID was saved
 | 
						|
	past Timestamp
 | 
						|
 | 
						|
	// the next time the state will be saved
 | 
						|
	next Timestamp
 | 
						|
 | 
						|
	// the last node which saved a UUID
 | 
						|
	node []byte
 | 
						|
 | 
						|
	// An iterated value to help ensure different
 | 
						|
	// values across the same domain
 | 
						|
	sequence uint16
 | 
						|
 | 
						|
	sync.Mutex
 | 
						|
 | 
						|
	// save state interface
 | 
						|
	saver StateSaver
 | 
						|
}
 | 
						|
 | 
						|
// Changes the state with current data
 | 
						|
// Compares the current found node to the last node stored,
 | 
						|
// If they are the same or randomSequence is already set due
 | 
						|
// to an earlier read issue then the sequence is randomly generated
 | 
						|
// else if there is an issue with the time the sequence is incremented
 | 
						|
func (o *State) read(pNow Timestamp, pNode net.HardwareAddr) {
 | 
						|
	if bytes.Equal([]byte(pNode), o.node) || o.randomSequence {
 | 
						|
		o.sequence = uint16(seed.Int()) & 0x3FFF
 | 
						|
	} else if pNow < o.past {
 | 
						|
		o.sequence++
 | 
						|
	}
 | 
						|
	o.past = pNow
 | 
						|
	o.node = pNode
 | 
						|
}
 | 
						|
 | 
						|
func (o *State) persist() {
 | 
						|
	if o.saver != nil {
 | 
						|
		o.saver.Save(o)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Initialises the UUID state when the package is first loaded
 | 
						|
// it first attempts to decode the file state into State
 | 
						|
// if this file does not exist it will create the file and do a flush
 | 
						|
// of the random state which gets loaded at package runtime
 | 
						|
// second it will attempt to resolve the current hardware address nodeId
 | 
						|
// thirdly it will check the state of the clock
 | 
						|
func (o *State) init() {
 | 
						|
	if o.saver != nil {
 | 
						|
		intfcs, err := net.Interfaces()
 | 
						|
		if err != nil {
 | 
						|
			log.Println("uuid.State.init: address error: will generate random node id instead", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		a := getHardwareAddress(intfcs)
 | 
						|
		if a == nil {
 | 
						|
			log.Println("uuid.State.init: address error: will generate random node id instead", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		// Don't use random as we have a real address
 | 
						|
		o.randomSequence = false
 | 
						|
		if bytes.Equal([]byte(a), state.node) {
 | 
						|
			state.sequence++
 | 
						|
		}
 | 
						|
		state.node = a
 | 
						|
		state.randomNode = false
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func getHardwareAddress(pInterfaces []net.Interface) net.HardwareAddr {
 | 
						|
	for _, inter := range pInterfaces {
 | 
						|
		// Initially I could multicast out the Flags to get
 | 
						|
		// whether the interface was up but started failing
 | 
						|
		if (inter.Flags & (1 << net.FlagUp)) != 0 {
 | 
						|
			//if inter.Flags.String() != "0" {
 | 
						|
			if addrs, err := inter.Addrs(); err == nil {
 | 
						|
				for _, addr := range addrs {
 | 
						|
					if addr.String() != "0.0.0.0" && !bytes.Equal([]byte(inter.HardwareAddr), make([]byte, len(inter.HardwareAddr))) {
 | 
						|
						return inter.HardwareAddr
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// *********************************************** StateSaver interface
 | 
						|
 | 
						|
// Use this interface to setup a custom state saver if you wish to have
 | 
						|
// v1 UUIDs based on your node id and constant time.
 | 
						|
type StateSaver interface {
 | 
						|
	// Init is run if Setup() is false
 | 
						|
	// Init should setup the system to save the state
 | 
						|
	Init(*State)
 | 
						|
 | 
						|
	// Save saves the state and is called only if const V1Save and
 | 
						|
	// Setup() is true
 | 
						|
	Save(*State)
 | 
						|
}
 | 
						|
 |