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

Add a scheme of type self. #161

Merged
merged 2 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
46 changes: 37 additions & 9 deletions id.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@
const (
hexDigits = "0123456789abcdefABCDEF"
macDelimiters = ":-.,"
macPrefix = "mac"
macLength = 12

SchemeMAC = "mac"
SchemeUUID = "uuid"
SchemeDNS = "dns"
SchemeSerial = "serial"
SchemeSelf = "self"
SchemeEvent = "event"
SchemeUnknown = ""
)

var (
Expand All @@ -24,15 +31,24 @@

invalidDeviceID = DeviceID("")

// Locator/DeviceID form:
// {scheme|prefix}:{authority|id}/{service}/{ignored}
//
// If the scheme is "mac", "uuid", or "serial" then the authority is the
// device identifier.
// If the scheme is "dns" then the authority is the FQDN of the service.
// If the scheme is "event" then the authority is the event name.
// If the scheme is "self" then the authority is the empty string.

// DevicIDPattern is the precompiled regular expression that all device identifiers must match.
// Matching is partial, as everything after the service is ignored.
DeviceIDPattern = regexp.MustCompile(
`^(?P<prefix>(?i)mac|uuid|dns|serial):(?P<id>[^/]+)(?P<service>/[^/]+)?`,
`^(?P<prefix>(?i)mac|uuid|dns|serial|self):(?P<id>[^/]+)(?P<service>/[^/]+)?`,
)

// LocatorPattern is the precompiled regular expression that all locators must match.
LocatorPattern = regexp.MustCompile(
`^(?P<scheme>(?i)mac|uuid|dns|serial|event):(?P<authority>[^/]+)(?P<service>/[^/]+)?(?P<ignored>/[^/]+)?`,
`^(?P<scheme>(?i)mac|uuid|dns|serial|event|self):(?P<authority>[^/]+)?(?P<service>/[^/]+)?(?P<ignored>/[^/]+)?`,
)
)

Expand Down Expand Up @@ -85,9 +101,9 @@
// {scheme}:{authority}/{service}/{ignored}
type Locator struct {
// Scheme is the scheme type of the locator. A CPE will have the forms
// `mac`, `uuid`, `serial`. A server or cloud service will have the form
// `dns`. An event locator that is used for pub-sub listeners will have
// the form `event`.
// `mac`, `uuid`, `serial`, `self`. A server or cloud service will have
// the form `dns`. An event locator that is used for pub-sub listeners
// will have the form `event`.
//
// The Scheme MUST NOT be used to determine where to send a message, but
// rather to determine how to interpret the authority and service.
Expand Down Expand Up @@ -133,8 +149,9 @@
l.Ignored = match[4]
}

// If the locator is a device identifier, then we need to parse it.
switch l.Scheme {
case "mac", "uuid", "serial": // device_id locators
case SchemeMAC, SchemeUUID, SchemeSerial, SchemeSelf:
id, err := makeDeviceID(l.Scheme, l.Authority)
if err != nil {
return nil, err
Expand All @@ -146,11 +163,16 @@
return &l, nil
}

// IsDeviceID returns true if the locator is a device identifier.
// HasDeviceID returns true if the locator is a device identifier.
func (l Locator) HasDeviceID() bool {
return l.ID != ""
}

// IsSelf returns true if the locator is a self locator.
func (l Locator) IsSelf() bool {
return l.Scheme == SchemeSelf

Check warning on line 173 in id.go

View check run for this annotation

Codecov / codecov/patch

id.go#L172-L173

Added lines #L172 - L173 were not covered by tests
}

func (l Locator) String() string {
var buf strings.Builder

Expand All @@ -171,7 +193,12 @@

func makeDeviceID(prefix, idPart string) (DeviceID, error) {
prefix = strings.ToLower(prefix)
if prefix == macPrefix {
switch prefix {
case SchemeSelf:
if idPart != "" {
return invalidDeviceID, ErrorInvalidDeviceName
}
case SchemeMAC:
var invalidCharacter rune = -1
idPart = strings.Map(
func(r rune) rune {
Expand All @@ -191,6 +218,7 @@
if invalidCharacter != -1 || len(idPart) != macLength {
return invalidDeviceID, ErrorInvalidDeviceName
}
default:
}

return DeviceID(fmt.Sprintf("%s:%s", prefix, idPart)), nil
Expand Down
49 changes: 40 additions & 9 deletions id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func TestParseLocator(t *testing.T) {
locator: "mac:112233445566",
str: "mac:112233445566",
want: &Locator{
Scheme: "mac",
Scheme: SchemeMAC,
Authority: "112233445566",
ID: "mac:112233445566",
},
Expand All @@ -136,7 +136,7 @@ func TestParseLocator(t *testing.T) {
locator: "Mac:112233445566",
str: "mac:112233445566",
want: &Locator{
Scheme: "mac",
Scheme: SchemeMAC,
Authority: "112233445566",
ID: "mac:112233445566",
},
Expand All @@ -145,7 +145,7 @@ func TestParseLocator(t *testing.T) {
locator: "DNS:foo.bar.com/service",
str: "dns:foo.bar.com/service",
want: &Locator{
Scheme: "dns",
Scheme: SchemeDNS,
Authority: "foo.bar.com",
Service: "service",
},
Expand All @@ -154,11 +154,30 @@ func TestParseLocator(t *testing.T) {
locator: "event:something/service/ignored",
str: "event:something/service/ignored",
want: &Locator{
Scheme: "event",
Scheme: SchemeEvent,
Authority: "something",
Service: "service",
Ignored: "/ignored",
},
}, {
description: "self locator with service",
locator: "SELF:/service",
str: "self:/service",
want: &Locator{
Scheme: SchemeSelf,
Service: "service",
ID: "self:",
},
}, {
description: "self locator with service everything",
locator: "self:/service/ignored",
str: "self:/service/ignored",
want: &Locator{
Scheme: SchemeSelf,
Service: "service",
Ignored: "/ignored",
ID: "self:",
},
},

// Validate all the schemes
Expand All @@ -167,23 +186,23 @@ func TestParseLocator(t *testing.T) {
locator: "dns:foo.bar.com",
str: "dns:foo.bar.com",
want: &Locator{
Scheme: "dns",
Scheme: SchemeDNS,
Authority: "foo.bar.com",
},
}, {
description: "event scheme",
locator: "event:targetedEvent",
str: "event:targetedEvent",
want: &Locator{
Scheme: "event",
Scheme: SchemeEvent,
Authority: "targetedEvent",
},
}, {
description: "mac scheme",
locator: "mac:112233445566",
str: "mac:112233445566",
want: &Locator{
Scheme: "mac",
Scheme: SchemeMAC,
Authority: "112233445566",
ID: "mac:112233445566",
},
Expand All @@ -192,7 +211,7 @@ func TestParseLocator(t *testing.T) {
locator: "serial:AsdfSerial",
str: "serial:AsdfSerial",
want: &Locator{
Scheme: "serial",
Scheme: SchemeSerial,
Authority: "AsdfSerial",
ID: "serial:AsdfSerial",
},
Expand All @@ -201,10 +220,18 @@ func TestParseLocator(t *testing.T) {
locator: "uuid:bbee1f69-2f64-4aa9-a422-27d68b40b152",
str: "uuid:bbee1f69-2f64-4aa9-a422-27d68b40b152",
want: &Locator{
Scheme: "uuid",
Scheme: SchemeUUID,
Authority: "bbee1f69-2f64-4aa9-a422-27d68b40b152",
ID: "uuid:bbee1f69-2f64-4aa9-a422-27d68b40b152",
},
}, {
description: "self scheme",
locator: "self:",
str: "self:",
want: &Locator{
Scheme: SchemeSelf,
ID: "self:",
},
},

// Validate invalid locators are caught
Expand All @@ -219,6 +246,10 @@ func TestParseLocator(t *testing.T) {
description: "invalid mac scheme",
locator: "mac:112invalid66",
expectedErr: ErrorInvalidDeviceName,
}, {
description: "invalid self scheme",
locator: "self:anything",
expectedErr: ErrorInvalidDeviceName,
},
}
for _, tc := range tests {
Expand Down
Loading