Class: Sip2::Message::BaseMessage

Inherits:
Dry::Struct
  • Object
show all
Defined in:
lib/sip2/message/base_message.rb

Constant Summary collapse

SEQUENCE_NUMBER_FORMAT =
Sip2::FIELDS.fetch(:sequence_number).fetch(:format)
CHECKSUM_CODE =
Sip2::FIELDS.fetch(:checksum).fetch(:code)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.delimited_fieldsObject



22
23
24
25
26
# File 'lib/sip2/message/base_message.rb', line 22

def delimited_fields
  @delimited_fields ||=
    (@required_delimited_fields + @optional_delimited_fields)
      .sort_by { |field| Sip2::FIELDS[field][:code] }
end

.ordered_fieldsObject



18
19
20
# File 'lib/sip2/message/base_message.rb', line 18

def ordered_fields
  @ordered_fields
end

Instance Method Details

#checksum(msg) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/sip2/message/base_message.rb', line 54

def checksum(msg)
  # Add each character as an unsigned binary number
  sum = msg.codepoints.sum

  # Take the lower 16 bits of the total
  sum16 = sum & 0xFFFF

  # Perform a 2's complement
  comp2 = (sum16 ^ 0xFFFF) + 1

  # The checksum field is the result represented by four hex digits
  sprintf("%04X", comp2)
end

#checksum_field(message, checksum_encoder: nil) ⇒ Object



68
69
70
71
72
73
74
75
76
# File 'lib/sip2/message/base_message.rb', line 68

def checksum_field(message, checksum_encoder: nil)
  msg =
    if checksum_encoder
      checksum_encoder.call(message)
    else
      message
    end
  CHECKSUM_CODE + checksum(msg + CHECKSUM_CODE)
end

#delimited_fieldsObject



38
39
40
# File 'lib/sip2/message/base_message.rb', line 38

def delimited_fields
  self.class.delimited_fields
end

#encode(add_error_detection: true, checksum_encoder: nil, strip_extra_fields: false) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/sip2/message/base_message.rb', line 110

def encode(add_error_detection: true, checksum_encoder: nil, strip_extra_fields: false)
  message = sprintf(
    "%<code>s%<ordered_fields>s%<delimited_fields>s%<unexpected_fields>s",
    code: self.class::CODE,
    ordered_fields:
      ordered_fields.map { |f| format_field(f) }.join,
    delimited_fields:
      delimited_fields.map { |f| format_field(f) }.join,
    unexpected_fields:
      if strip_extra_fields then "" else format_unexpected_fields end
  )
  error_detection =
    if add_error_detection 
      error_detection_fields(message, checksum_encoder: checksum_encoder)
    else
      ""
    end
  sprintf("%s%s\r", message, error_detection)
end

#error_detection_fields(message, **checksum_options) ⇒ Object



86
87
88
89
90
91
92
93
# File 'lib/sip2/message/base_message.rb', line 86

def error_detection_fields(message, **checksum_options)
  if attributes.has_key?(:checksum)
    sequence_number = sequence_number_field
    sequence_number + checksum_field(message + sequence_number, **checksum_options)
  else
    ""
  end
end

#fieldsObject



30
31
32
# File 'lib/sip2/message/base_message.rb', line 30

def fields
  self.class.fields
end

#format_field(field_name) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/sip2/message/base_message.rb', line 42

def format_field(field_name)
  field_info = Sip2::FIELDS.fetch(field_name)
  attribute_name = field_info.fetch(:name, field_name)
  format = field_info.fetch(:format)

  if self.attributes.key?(attribute_name)
    format.call(self[attribute_name])
  else
    ""
  end
end

#format_unexpected_field(code:, value:) ⇒ Object



95
96
97
# File 'lib/sip2/message/base_message.rb', line 95

def format_unexpected_field(code:, value:)
  sprintf("%s%s|", code, value)
end

#format_unexpected_fieldsObject



99
100
101
102
103
104
105
106
107
108
# File 'lib/sip2/message/base_message.rb', line 99

def format_unexpected_fields

  if self.attributes.key?(:unexpected_fields)
    Array(self[:unexpected_fields])
      .map { |f| format_unexpected_field(**f) }
      .join
  else
    ""
  end
end

#ordered_fieldsObject



34
35
36
# File 'lib/sip2/message/base_message.rb', line 34

def ordered_fields
  self.class.ordered_fields
end

#sequence_number_fieldObject



78
79
80
81
82
83
84
# File 'lib/sip2/message/base_message.rb', line 78

def sequence_number_field
  if attributes.has_key?(:sequence_number)
    SEQUENCE_NUMBER_FORMAT.call(self[:sequence_number])
  else
    ""
  end
end

#to_sObject



130
131
132
# File 'lib/sip2/message/base_message.rb', line 130

def to_s
  encode
end