Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add custom node ids #107

Open
wants to merge 65 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
31756fc
A little error in the documentation of dce.go
Kerrigan29a Aug 12, 2017
54117db
Remove never-true conditional
kortschak Oct 19, 2017
25152bc
add FromBytes constructor
loderunner Nov 10, 2017
230f397
make 'go vet' happy
martinlindhe Nov 22, 2017
2ff2f17
remove false claim about NewRandom() panic, pointed out in https://gi…
martinlindhe Nov 22, 2017
f6e8fa1
fix some typos
martinlindhe Nov 22, 2017
022d377
remove net when targeting JS
elliott5 Nov 29, 2017
dcffc13
Remove leftover comment.
Aug 27, 2018
2b9926f
add MustParse(), which returns an UUID or panics
martinlindhe Nov 22, 2017
365a136
edit slice
OrlovEvgeny Aug 24, 2018
016417f
Add parsing support for:
pborman Sep 9, 2018
188cd61
add go.mod file
dmitris Sep 17, 2018
68d2743
added source to enable concurrent reproducible usage
trabetti Feb 20, 2019
fa18a78
simplify test
trabetti Feb 26, 2019
8099a41
reused version4 NewRandom() and added better testing
trabetti Feb 28, 2019
bd0ed1c
Add darkfeline's change to set ifname if no interface is found.
pborman Feb 27, 2019
db93772
use strings.NewReader() instead of math/rand.Rand
trabetti Feb 28, 2019
b1ffb76
remove uuid_source
trabetti Mar 13, 2019
30f4987
Update README.md
kveselkov Mar 4, 2020
82cee2d
Resolved code issues of gofmt and golint (#55)
panjf2000 Mar 31, 2020
c79c161
refactor (*UUID).UnmarshalText (#58)
prochac May 19, 2020
08aa6f5
Fix race in NewUUID() (#64)
Jul 2, 2020
4bd0972
Use a custom error type for invalid lengths, replacing `fmt.Errorf` (…
joewreschnig Dec 30, 2020
202f68e
Reduce custom error allocation (#70)
johejo Jan 4, 2021
4d03d2e
Update sql.go (#72)
Jan 15, 2021
7f58482
hash.go hash error covered and linter error fixed (#71)
yusufpapurcu Jan 15, 2021
084597c
Add NewString Func (#73)
jackterm Jan 22, 2021
e45ac43
feat: add public matcher function for custom error type invalidLength…
charlielukman Mar 31, 2021
3118c53
Add randomness pool mode for V4 UUID (#80)
puzpuzpuz Jul 8, 2021
f75a282
feat(uuid): Added support for NullUUID (#76)
sejr Jul 12, 2021
c2ab6d3
Remove TestConformance from null_test.go. It was useful to demonstrate
pborman Jul 12, 2021
cc36f0e
Minor cleanup.
pborman Jul 12, 2021
795fbe8
fix: add proper handling of custom node ids simultaneously
tkarrass Oct 3, 2022
478088c
chore(ci): add Action-based tests (#121)
noahdietz Aug 17, 2023
89a7041
fix: Use .EqualFold() to parse urn prefixed UUIDs (#118)
ayang64 Aug 17, 2023
9f17c0a
docs: fix typo node_js docs (#117)
alexandear Aug 17, 2023
8d1f8d2
docs: shell format go tool command (#111)
SallesCosta Aug 18, 2023
79c64ec
docs: update link to RFC 4122 (#93)
cwlowder Aug 18, 2023
82139fd
docs: change godoc URL in README (#124)
alexandear Aug 18, 2023
7075f98
chore(ci): add apidiff check for API compatibility (#123)
noahdietz Aug 18, 2023
fff62d2
chore(ci): configure release-please, update contrib (#122)
noahdietz Aug 18, 2023
b8a5ae7
fix(ci): switch to release-please app (#126)
noahdietz Aug 18, 2023
d52bbfc
chore(master): release 1.3.1 (#127)
release-please[bot] Aug 21, 2023
9cebf06
chore(tests): Add json.Unmarshal test with empty value cases (#116)
wawan93 Aug 21, 2023
ef4fa67
chore(tests): add Fuzz tests (#128)
noahdietz Aug 22, 2023
b753fe2
docs: fix a typo in CONTRIBUTING.md (#130)
alexandear Sep 21, 2023
1a3d1fe
feat: UUIDs slice type with Strings() convenience method (#133)
dzbee Oct 26, 2023
3d70877
Clarify the documentation of Parse to state its job is to parse, not …
bormanp Oct 26, 2023
efde914
chore(master): release 1.4.0 (#134)
release-please[bot] Oct 26, 2023
5ddafa4
add uuid version 6 and 7 (#139)
it512 Nov 23, 2023
f9cfc07
feat: Validate UUID without creating new UUID (#141)
ljahier Dec 12, 2023
16526d6
chore(master): release 1.5.0 (#145)
release-please[bot] Dec 12, 2023
240aae1
feat: add Max UUID constant (#149)
it512 Jan 9, 2024
3d4e2e0
fix: Monotonicity in UUIDv7 (#150)
it512 Jan 11, 2024
9c5f7a8
ci: set token permissions to github workflows (#143)
joycebrum Jan 11, 2024
52193aa
fix: fix typo in version 7 uuid documentation (#153)
anopheles Jan 12, 2024
6862850
chore(tests): add strict monotonicity test case for uuid v7. (#154)
it512 Jan 16, 2024
88d2624
chore(master): release 1.6.0 (#151)
release-please[bot] Jan 23, 2024
b56d222
docs: fixing typos (#156)
deining Feb 12, 2024
0ed5eff
fix: use MustParse("xxx") instead of Must(Parse("xxxx")) (#106)
kotaroyamazaki Feb 22, 2024
9bd7b9c
fix: incorrect timestamp in uuid v6 (#161)
ls4154 Jun 3, 2024
27f465a
feat: add Compare function (#163)
it512 Jul 1, 2024
a0a48dd
docs: upd links to rfc9562 (#162)
alexbozhenko Jul 1, 2024
56a5f52
feat: add error types for better validation (#166)
plusiv Aug 6, 2024
834ff85
Merge branch 'master' into merge240911
tkarrass Sep 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ dsymonds
cd1
wallclockbuilder
dansouza
tkarrass
84 changes: 84 additions & 0 deletions custom.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package uuid

import (
"sync"
)

// CustomNodeId is a node id with a few tweaks:
// It allows the creation of UUIDs using distinct node ids simultaneously from a single host, without
// calling SetNodeId() repeatedly.
// It avoids collisions with version 1 UUIDs generated based on hardware IEEE 802 addresses.
type CustomNodeId struct {
nodeid // inherit the nodeid
mu sync.Mutex // hold an own mutex
}

// CustomNodeIdError enables clean error handling during CustomNodeId operation.
type CustomNodeIdError string

func (e CustomNodeIdError) Error() string {
return string(e)
}

const (
ErrIncompleteId CustomNodeIdError = "given node id is missing data"
ErrInvalidFlag CustomNodeIdError = "multicast flag not set"
)

// NewCustomNodeId returns a new custom node id or an error, in case invalid or insufficient data is given.
func NewCustomNodeId(id []byte) (*CustomNodeId, error) {
ret := &CustomNodeId{}
err := ret.SetNodeId(id)
if err != nil {
return nil, err
}
return ret, nil
}

// NewUUID generates a new version 1 UUID based on this CustomNodeId.
// This implementation mimics the global NewUUID function.
func (c *CustomNodeId) NewUUID() (UUID, error) {
// Use the plain version 1 uuid generation …
uuid, err := newVersion1UUID()
if err != nil {
return uuid, err
}

// _ And fill in our own node id:
c.mu.Lock()
defer c.mu.Unlock()
copy(uuid[10:], c.nodeid[:])

return uuid, nil
}

// SetNodeId sets the custom node id to the given value.
// Note: RFC-4122 suggest to use a "47-bit cryptographic quality random number" with the least significant bit of the
// first byte set to 1. It also states, the data is "system specific".
func (c *CustomNodeId) SetNodeId(id []byte) error {
if len(id) < 6 {
return ErrIncompleteId
}

// According to RFC-4122 section 4.5 the unicast/multicast flag of the IEEE 802 MAC has to be set
// for custom node ids in order to avoid conflicts.
// Thereby we should reject node ids with this flag being unset:
if id[0]&0x01 == 0 {
return ErrInvalidFlag
}

c.mu.Lock()
defer c.mu.Unlock()
copy(c.nodeid[:], id)

return nil
}

// NodeID returns the 6 byte node id.
func (c *CustomNodeId) NodeID() []byte {
c.mu.Lock()
defer c.mu.Unlock()
var node nodeid
copy(node[:], c.nodeid[:])
return node[:]
}
9 changes: 6 additions & 3 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ import (
"sync"
)

// nodeid represents the node id being used in Version 1 and 2 UUIDs
type nodeid [6]byte

var (
nodeMu sync.Mutex
ifname string // name of interface being used
nodeID [6]byte // hardware for version 1 UUIDs
zeroID [6]byte // nodeID with only 0's
ifname string // name of interface being used
nodeID nodeid // hardware for version 1 UUIDs
zeroID nodeid // nodeID with only 0's
)

// NodeInterface returns the name of the interface from which the NodeID was
Expand Down
24 changes: 16 additions & 8 deletions version1.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ import (
//
// In most cases, New should be used.
func NewUUID() (UUID, error) {
uuid, err := newVersion1UUID()
if err != nil {
return uuid, err
}

nodeMu.Lock()
if nodeID == zeroID {
setNodeInterface("")
}
copy(uuid[10:], nodeID[:])
nodeMu.Unlock()

return uuid, nil
}

func newVersion1UUID() (UUID, error) {
var uuid UUID
now, seq, err := GetTime()
if err != nil {
Expand All @@ -32,13 +48,5 @@ func NewUUID() (UUID, error) {
binary.BigEndian.PutUint16(uuid[4:], timeMid)
binary.BigEndian.PutUint16(uuid[6:], timeHi)
binary.BigEndian.PutUint16(uuid[8:], seq)

nodeMu.Lock()
if nodeID == zeroID {
setNodeInterface("")
}
copy(uuid[10:], nodeID[:])
nodeMu.Unlock()

return uuid, nil
}