Class: Nts::Sntp::Message

Inherits:
Object
  • Object
show all
Defined in:
lib/nts/sntp/message.rb

Overview

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ntp_header, extensions = []) ⇒ Message

Returns a new instance of Message.

Parameters:

  • ntp_header (String)

    48-octet NTP header(leap ~ xmt)

  • extensions (Array of Nts::Sntp::Extension::$Object) (defaults to: [])

Raises:

  • (Exception)


16
17
18
19
20
21
22
23
24
# File 'lib/nts/sntp/message.rb', line 16

def initialize(ntp_header, extensions = [])
  @ntp_header = ntp_header
  @extensions = extensions

  raise 'extensions include only Sntp::Extension::$Object' \
    unless @extensions.all? do |ex|
      ex.class.ancestors.include?(Sntp::Extension)
    end
end

Instance Attribute Details

#extensionsObject (readonly)

Returns the value of attribute extensions.



10
11
12
# File 'lib/nts/sntp/message.rb', line 10

def extensions
  @extensions
end

#ntp_headerObject (readonly)

Returns the value of attribute ntp_header.



9
10
11
# File 'lib/nts/sntp/message.rb', line 9

def ntp_header
  @ntp_header
end

Class Method Details

.deserialize(s) ⇒ Nts::Sntp::Message

Parameters:

  • s (String)

Returns:

Raises:

  • (Exception)


51
52
53
54
55
56
57
58
# File 'lib/nts/sntp/message.rb', line 51

def self.deserialize(s)
  raise Exception if s.length < 48

  ntp_header = s.slice(0, 48)
  extensions = extensions_deserialize(s[48..])

  Message.new(ntp_header, extensions)
end

.extensions_deserialize(s) ⇒ Array of Nts::Sntp::Extension::$Object

rubocop: disable Metrics/AbcSize rubocop: disable Metrics/CyclomaticComplexity

Parameters:

  • s (String)

Returns:

Raises:

  • (Exception)


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/nts/sntp/message.rb', line 67

def self.extensions_deserialize(s)
  i = 0
  extensions = []
  while i < s.length
    raise Exception if i + 4 > s.length

    field_type = s.slice(i, 2).unpack1('n')
    value_len = s.slice(i + 2, 2).unpack1('n')
    raise Exception if i + value_len > s.length

    # `value_len` indicates the length of the entire extension field
    # in octets.
    sv = s.slice(i + 4, value_len - 4)
    case field_type
    when ExtensionFieldType::UNIQUE_IDENTIFIER
      extensions << Extension::UniqueIdentifier.deserialize(sv)
    when ExtensionFieldType::NTS_COOKIE
      extensions << Extension::NtsCookie.deserialize(sv)
    when ExtensionFieldType::NTS_COOKIE_PLACEHOLDER
      # unsupported NtsCookiePlaceholder
      warn sv.bytes.map { |x| x.to_s(16).rjust(2, '0') }.join(' ')
    when ExtensionFieldType::NTS_AUTHENTICATOR
      extensions << Extension::NtsAuthenticator.deserialize(sv)
    else
      extensions \
      << Extension::UnknownExtension.deserialize(sv, field_type)
    end
    i += value_len
  end
  raise Exception unless i == s.length

  extensions
end

Instance Method Details

#nts_authenticatorNts::Sntp::Extension::NtsAuthenticator



37
38
39
# File 'lib/nts/sntp/message.rb', line 37

def nts_authenticator
  @extensions.find { |ex| ex.is_a?(Extension::NtsAuthenticator) }
end


32
33
34
# File 'lib/nts/sntp/message.rb', line 32

def nts_cookie
  @extensions.find { |ex| ex.is_a?(Extension::NtsCookie) }
end

#origin_timestampString

Returns:

  • (String)


104
105
106
# File 'lib/nts/sntp/message.rb', line 104

def origin_timestamp
  @ntp_header.slice(24, 8)
end

#receive_timestampString

Returns:

  • (String)


109
110
111
# File 'lib/nts/sntp/message.rb', line 109

def receive_timestamp
  @ntp_header.slice(32, 8)
end

#serializeString

Returns:

  • (String)


42
43
44
# File 'lib/nts/sntp/message.rb', line 42

def serialize
  @ntp_header + @extensions.map(&:serialize).join
end

#transmit_timestampString

Returns:

  • (String)


114
115
116
# File 'lib/nts/sntp/message.rb', line 114

def transmit_timestamp
  @ntp_header.slice(40, 8)
end

#unique_identifierNts::Sntp::Extension::UniqueIdentifier



27
28
29
# File 'lib/nts/sntp/message.rb', line 27

def unique_identifier
  @extensions.find { |ex| ex.is_a?(Extension::UniqueIdentifier) }
end