class PDUTools::Decoder
Constants
- DecodeError
Public Class Methods
new(pdu_hex, direction=:sc_to_ms)
click to toggle source
read.pudn.com/downloads150/sourcecode/embed/646395/Short%20Message%20in%20PDU%20Encoding.pdf
# File lib/pdu_tools/decoder.rb, line 6 def initialize pdu_hex, direction=:sc_to_ms @pdu_hex = pdu_hex.dup @direction = direction end
Public Instance Methods
decode()
click to toggle source
# File lib/pdu_tools/decoder.rb, line 11 def decode @sca_length = take(2, :integer) * 2 # Service center address length if @sca_length > 0 @sca_type = parse_address_type take(2) # Service center address type @sca = parse_address take(@sca_length - 2), @sca_type, @sca_length # Service center address end @pdu_type = parse_pdu_type take(2, :binary) # PDU type octet @message_reference = take(2) if @pdu_type[:mti] == :sms_submit @address_length = take(2, :integer) @address_type = parse_address_type take(2) @address_length = @address_length.odd? ? @address_length + 1 : @address_length # Always take byte aligned - hexdecimal F is added when odd number @address = parse_address take(@address_length), @address_type, @address_length @pid = take(2) @data_coding_scheme = parse_data_coding_scheme take(2, :binary) @sc_timestamp = parse_7byte_timestamp take(14) if [:sms_deliver, :sms_deliver_report].include? @pdu_type[:mti] case @pdu_type[:vpf] when :absolute @validity_period = parse_7byte_timestamp take(14) when :relative @validity_period = parse_validity_period take(2, :integer) end @user_data_length = take(2, :integer) parse_user_data @user_data_length MessagePart.new @address, @message, @sc_timestamp, @validity_period, @user_data_header end
inspect2()
click to toggle source
# File lib/pdu_tools/decoder.rb, line 38 def inspect2 r = "<PDUTools::Decoder" r << "PDU: #{@pdu_hex}\n" r << "SCA LENGTH: #{@sca_length}\n" r << "SCA TYPE: #{@sca_type}\n" r << "SCA: #{@sca}\n" r << "PDU TYPE: #{@pdu_type}\n" r << "MESSAGE REFERENCE: #{@message_reference}\n" if @message_reference r << ">" r end
Private Instance Methods
parse_7byte_timestamp(timestamp)
click to toggle source
# File lib/pdu_tools/decoder.rb, line 149 def parse_7byte_timestamp timestamp year, month, day, hour, minute, second, zone = swapped2normal(timestamp).split('').in_groups_of(2).collect(&:join) d = "#{year}-#{month}-#{day} #{hour}:#{minute}:#{second} +%02d:00" % (zone.to_i / 4) Time.parse(d) end
parse_address(address, type, length)
click to toggle source
# File lib/pdu_tools/decoder.rb, line 80 def parse_address address, type, length if type == :a7bit address = decode7bit address else address = swapped2normal address if type == :international address.prepend "+" end end address end
parse_address_type(type)
click to toggle source
# File lib/pdu_tools/decoder.rb, line 65 def parse_address_type type map = { "000" => :unknown, "001" => :international, "010" => :national, "011" => :network_specific, "100" => :subscriber, "101" => :a7bit, "110" => :abbreviated, "111" => :reserved } bin_type = type.to_i(16).to_s(2)[1,3] map[bin_type] end
parse_data_coding_scheme(scheme)
click to toggle source
# File lib/pdu_tools/decoder.rb, line 139 def parse_data_coding_scheme scheme { coding_group: scheme.slice!(0,2), compresion: scheme.slice!(0,1) == "1", klass_meaning: scheme.slice!(0,1) == "1", alphabet: ALPHABETS.key(scheme.slice!(0,2)), klass: scheme.slice!(0,2) } end
parse_pdu_type(pdu_type)
click to toggle source
# File lib/pdu_tools/decoder.rb, line 92 def parse_pdu_type pdu_type rp = pdu_type.slice!(0,1) == "1" udhi = pdu_type.slice!(0,1) == "1" srr_or_sri = pdu_type.slice!(0,1) == "1" vpf = (case pdu_type.slice!(0,2) when "00", "01" :none when "10" :relative when "11" :absolute end) rd_or_mms = pdu_type.slice!(0,1) mti = pdu_type.slice!(0,2) type = { rp: rp, udhi: udhi, vpf: vpf } case @direction when :sc_to_ms type[:mti] = case mti when "00" :sms_deliver when "01" :sms_submit_report when "10" :sms_status_report when "11" :reserved end type[:sri] = srr_or_sri type[:mms] = rd_or_mms == "0" when :ms_to_sc type[:mti] = case mti when "00" :sms_deliver_report when "01" :sms_submit when "10" :sms_command when "11" :reserved end type[:srr] = srr_or_sri type[:rd] = rd_or_mms == "0" end type end
parse_user_data(data_length)
click to toggle source
# File lib/pdu_tools/decoder.rb, line 168 def parse_user_data data_length @offset_7bit = 1 if @pdu_type[:udhi] @udh_length = take(2, :integer) * 2 udh = take(@udh_length) @user_data_header = parse_user_data_header udh end case @data_coding_scheme[:alphabet] when :a7bit @message = gsm0338_to_utf8 decode7bit(@pdu_hex, data_length, @offset_7bit) when :a8bit @message = gsm0338_to_utf8 decode8bit(@pdu_hex, data_length) when :a16bit @message = gsm0338_to_utf8 decode16bit(@pdu_hex, data_length) end end
parse_user_data_header(header)
click to toggle source
# File lib/pdu_tools/decoder.rb, line 185 def parse_user_data_header header ret = {} while header.length > 0 iei_type = take 2, :string, header iei_length = take 2, :integer, header iei_data = take iei_length * 2, :string, header case iei_type when "00" reference = take 2, :integer, iei_data parts = take 2, :integer, iei_data part_number = take 2, :integer, iei_data ret[:multipart] = { reference: reference, parts: parts, part_number: part_number, iei_type: iei_type } @offset_7bit = 0 when '05' dest_port = take 4, :integer, iei_data source_port = take 4, :integer, iei_data ret[:addressing] = { source: source_port, destination: dest_port } when "08" reference = take 4, :integer, iei_data parts = take 2, :integer, iei_data part_number = take 2, :integer, iei_data ret[:multipart] = { reference: reference, parts: parts, part_number: part_number, iei_type: iei_type } @offset_7bit = 1 else ret[:unknown] ||= {} ret[:unknown][iei_type] = iei_data.dup iei_data = '' end if iei_data.length != 0 raise DecodeError, "Failure to decode: iei length is not correct for type" end end ret end
parse_validity_period(period)
click to toggle source
# File lib/pdu_tools/decoder.rb, line 155 def parse_validity_period period case period when 0..143 ((period + 1) * 5).minutes when 144..167 12.hours + ((period - 143) * 30).minutes when 168..196 (period - 166).days when 197..255 (period - 192).weeks end end
take(n, format=:string, data=@pdu_hex)
click to toggle source
# File lib/pdu_tools/decoder.rb, line 52 def take n, format=:string, data=@pdu_hex part = data.slice!(0,n) case format when :string return part when :integer return part.to_i(16) when :binary bytes = n/2 return "%0#{bytes*8}b" % part.to_i(16) end end