You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

72 line
1.5 KiB

  1. package utils
  2. import (
  3. "github.com/AFASystems/presence/internal/pkg/common/appcontext"
  4. "github.com/AFASystems/presence/internal/pkg/model"
  5. )
  6. // ParseADFast efficiently parses Advertising Data structures
  7. // Returns slice of [startIndex, endIndex] pairs for each AD structure
  8. func ParseADFast(b []byte) [][2]int {
  9. var res [][2]int
  10. i := 0
  11. for i < len(b) {
  12. l := int(b[i])
  13. if l == 0 || i+1+l > len(b) {
  14. break
  15. }
  16. res = append(res, [2]int{i, i + 1 + l})
  17. i += 1 + l
  18. }
  19. return res
  20. }
  21. // RemoveFlagBytes removes Bluetooth advertising flag bytes if present
  22. // Some beacons include flag bytes as the first AD structure
  23. func RemoveFlagBytes(b []byte) []byte {
  24. if len(b) > 1 && b[1] == 0x01 {
  25. l := int(b[0])
  26. if 1+l <= len(b) {
  27. return b[1+l:]
  28. }
  29. }
  30. return b
  31. }
  32. // Generate event based on the Beacon type
  33. func LoopADStructures(b []byte, i [][2]int, id string, parserRegistry *model.ParserRegistry) appcontext.BeaconEvent {
  34. be := appcontext.BeaconEvent{}
  35. for _, r := range i {
  36. ad := b[r[0]:r[1]]
  37. if !isValidADStructure(ad) {
  38. break
  39. }
  40. for name, parser := range parserRegistry.ParserList {
  41. if parser.CanParse(ad) {
  42. event, ok := parser.Parse(name, ad)
  43. if ok {
  44. event.ID = id
  45. event.Name = id
  46. return event
  47. }
  48. }
  49. }
  50. }
  51. return be
  52. }
  53. // IsValidADStructure validates if an AD structure is well-formed
  54. func isValidADStructure(data []byte) bool {
  55. if len(data) < 2 {
  56. return false
  57. }
  58. length := int(data[0])
  59. return length > 0 && int(length)+1 <= len(data)
  60. }