// generates a random MAC. func genMAC() (mac [6]byte) { rand.Read(mac[:]) mac[0] |= 0x01 // multicast return }
// New returns a unique 32-byte url-safe string. func New() string { var ( timeNow = time.Now() timeNowUnix = timeNow.Unix() timestamp = unix100nano(timeNow) sequence uint32 saltShouldUpdate = false saltSequence uint32 ) gMutex.Lock() // Lock switch { case timestamp > gLastTimestamp: sequence = gSequenceStart gLastTimestamp = timestamp gLastSequence = sequence case timestamp == gLastTimestamp: sequence = (gLastSequence + 1) & sequenceMask if sequence == gSequenceStart { timestamp = tillNext100nano(timestamp) gLastTimestamp = timestamp } gLastSequence = sequence default: gSequenceStart = rand.Uint32() & sequenceMask // NOTE sequence = gSequenceStart gLastTimestamp = timestamp gLastSequence = sequence } if timeNowUnix >= gSaltLastUpdateTimestamp+saltUpdateInterval { saltShouldUpdate = true gSaltLastUpdateTimestamp = timeNowUnix } gSaltSequence++ saltSequence = gSaltSequence gMutex.Unlock() // Unlock // 56bits unix100ns + 12bits pid + 12bits sequence + 48bits node + 64bits hashsum var idx [24]byte // time_low idx[0] = byte(timestamp >> 24) idx[1] = byte(timestamp >> 16) idx[2] = byte(timestamp >> 8) idx[3] = byte(timestamp) // time_mid idx[4] = byte(timestamp >> 40) idx[5] = byte(timestamp >> 32) // time_hi_and_pid_low idx[6] = byte(timestamp >> 48) idx[7] = byte(pid) // clk_seq_hi_pid idx[8] = byte(sequence>>8) & 0x0f idx[8] |= byte(pid>>8) << 4 // clk_seq_low idx[9] = byte(sequence) // node copy(idx[10:], node) // hashsum if saltShouldUpdate { rand.Read(gSalt) copy(idx[16:], gSalt) } else { var src [8 + 4 + saltLen]byte // 8+4+43==55 src[0] = byte(timestamp >> 56) src[1] = byte(timestamp >> 48) src[2] = byte(timestamp >> 40) src[3] = byte(timestamp >> 32) src[4] = byte(timestamp >> 24) src[5] = byte(timestamp >> 16) src[6] = byte(timestamp >> 8) src[7] = byte(timestamp) src[8] = byte(saltSequence >> 24) src[9] = byte(saltSequence >> 16) src[10] = byte(saltSequence >> 8) src[11] = byte(saltSequence) copy(src[12:], gSalt) hashsum := sha1.Sum(src[:]) copy(idx[16:], hashsum[:]) } id := make([]byte, 32) base64.URLEncoding.Encode(id, idx[:]) return string(id) }