Class: Smpp::Pdu::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/smpp/pdu/base.rb

Constant Summary collapse

PROTOCOL_VERSION =

Protocol Version

0x34
ESME_ROK =

Error constants

0x00000000
ESME_RINVMSGLEN =

OK!

0x00000001
ESME_RINVCMDLEN =

Message Length is invalid

0x00000002
ESME_RINVCMDID =

Command Length is invalid

0x00000003
ESME_RINVBNDSTS =

Invalid Command ID

0x00000004
ESME_RALYBND =

Incorrect BIND Status for given com-

0x00000005
ESME_RINVPRTFLG =

ESME Already in Bound State

0x00000006
ESME_RINVREGDLVFLG =

Invalid Priority Flag

0x00000007
ESME_RSYSERR =

Invalid Registered Delivery Flag

0x00000008
ESME_RINVSRCADR =

System Error

0x0000000A
ESME_RINVDSTADR =

Invalid Source Address

0x0000000B
ESME_RINVMSGID =

Invalid Dest Addr

0x0000000C
ESME_RBINDFAIL =

Message ID is invalid

0x0000000D
ESME_RINVPASWD =

Bind Failed

0x0000000E
ESME_RINVSYSID =

Invalid Password

0x0000000F
ESME_RCANCELFAIL =

Invalid System ID

0x00000011
ESME_RREPLACEFAIL =

Cancel SM Failed

0x00000013
ESME_RMSGQFUL =

Replace SM Failed

0x00000014
ESME_RINVSERTYP =

Message Queue Full

0x00000015
ESME_RINVNUMDESTS =

Invalid Service Type

0x00000033
ESME_RINVDLNAME =

Invalid number of destinations

0x00000034
ESME_RINVDESTFLAG =

Invalid Distribution List name

0x00000040
ESME_RINVSUBREP =

Destination flag is invalid

0x00000042
ESME_RINVESMCLASS =

Invalid ‘submit with replace’ request

0x00000043
ESME_RCNTSUBDL =

Invalid esm_class field data

0x00000044
ESME_RSUBMITFAIL =

Cannot Submit to Distribution List

0x00000045
ESME_RINVSRCTON =

submit_sm or submit_multi failed

0x00000048
ESME_RINVSRCNPI =

Invalid Source address TON

0x00000049
ESME_RINVDSTTON =

Invalid Source address NPI

0x00000050
ESME_RINVDSTNPI =

Invalid Destination address TON

0x00000051
ESME_RINVSYSTYP =

Invalid Destination address NPI

0x00000053
ESME_RINVREPFLAG =

Invalid system_type field

0x00000054
ESME_RINVNUMMSGS =

Invalid replace_if_present flag

0x00000055
ESME_RTHROTTLED =

Invalid number of messages

0x00000058
ESME_RX_T_APPN =

Throttling error (ESME has exceeded allowed message limits)

0x00000064
GENERIC_NACK =

PDU types

0X80000000
BIND_RECEIVER =
0X00000001
BIND_RECEIVER_RESP =
0X80000001
BIND_TRANSMITTER =
0X00000002
BIND_TRANSMITTER_RESP =
0X80000002
BIND_TRANSCEIVER =
0X00000009
BIND_TRANSCEIVER_RESP =
0X80000009
QUERY_SM =
0X00000003
QUERY_SM_RESP =
0X80000003
SUBMIT_SM =
0X00000004
SUBMIT_SM_RESP =
0X80000004
DELIVER_SM =
0X00000005
DELIVER_SM_RESP =
0X80000005
UNBIND =
0X00000006
UNBIND_RESP =
0X80000006
REPLACE_SM =
0X00000007
REPLACE_SM_RESP =
0X80000007
CANCEL_SM =
0X00000008
CANCEL_SM_RESP =
0X80000008
0X00000015
0X80000015
SUBMIT_MULTI =
0X00000021
SUBMIT_MULTI_RESP =
0X80000021
OPTIONAL_RECEIPTED_MESSAGE_ID =
0x001E
OPTIONAL_MESSAGE_STATE =
0x0427
SEQUENCE_MAX =
0x7FFFFFFF
@@seq =

PDU sequence number.

[Time.now.to_i]
@@cmd_map =

factory class registry

{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command_id, command_status, seq, body = '') ⇒ Base

Returns a new instance of Base.



85
86
87
88
89
90
91
92
# File 'lib/smpp/pdu/base.rb', line 85

def initialize(command_id, command_status, seq, body='')    
  length = 16 + body.length
  @command_id = command_id
  @command_status = command_status
  @body = body
  @sequence_number = seq
  @data = fixed_int(length) + fixed_int(command_id) + fixed_int(command_status) + fixed_int(seq) + body.force_encoding('binary')
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body.



83
84
85
# File 'lib/smpp/pdu/base.rb', line 83

def body
  @body
end

#command_idObject (readonly)

Returns the value of attribute command_id.



83
84
85
# File 'lib/smpp/pdu/base.rb', line 83

def command_id
  @command_id
end

#command_statusObject (readonly)

Returns the value of attribute command_status.



83
84
85
# File 'lib/smpp/pdu/base.rb', line 83

def command_status
  @command_status
end

#dataObject (readonly)

Returns the value of attribute data.



83
84
85
# File 'lib/smpp/pdu/base.rb', line 83

def data
  @data
end

#sequence_numberObject (readonly)

Returns the value of attribute sequence_number.



83
84
85
# File 'lib/smpp/pdu/base.rb', line 83

def sequence_number
  @sequence_number
end

Class Method Details

.create(data) ⇒ Object

PDU factory method for common client PDUs (used to create PDUs from wire data)



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/smpp/pdu/base.rb', line 148

def Base.create(data)
  header = data[0..15]
  if !header
    return nil
  end
  len, cmd, status, seq = header.unpack('N4')
  body = data[16..-1]

  #if a class has been registered to handle this command_id, try
  #to create an instance from the wire data
  if @@cmd_map[cmd]
    @@cmd_map[cmd].from_wire_data(seq, status, body)
  else
    Smpp::Base.logger.error "Unknown PDU: #{"0x%08x" % cmd}"
    return nil
  end
end

.fixed_int(value) ⇒ Object

return int as binary string of 4 octets



105
106
107
108
# File 'lib/smpp/pdu/base.rb', line 105

def Base.fixed_int(value)
  arr = [value >> 24, value >> 16, value >> 8, value & 0xff]
  arr.pack("cccc")
end

.from_wire_data(seq, status, body) ⇒ Object

This factory should be implemented in every subclass that can create itself from wire data. The subclass should also register itself with the ‘handles_cmd’ class method.

Raises:

  • (Exception)


143
144
145
# File 'lib/smpp/pdu/base.rb', line 143

def Base.from_wire_data(seq, status, body)
  raise Exception.new("#{self.class} claimed to handle wire data, but doesn't.")
end

.handles_cmd(command_id) ⇒ Object

maps a subclass as the handler for a particulular pdu



167
168
169
# File 'lib/smpp/pdu/base.rb', line 167

def Base.handles_cmd(command_id)
  @@cmd_map[command_id] = self
end

.next_sequence_numberObject



135
136
137
138
139
# File 'lib/smpp/pdu/base.rb', line 135

def Base.next_sequence_number
  @@seq.synchronize do
    (@@seq[0] += 1) % SEQUENCE_MAX
  end
end

.optional_parameters_to_buffer(optionals) ⇒ Object

expects a hash like => Smpp::OptionalParameter



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/smpp/pdu/base.rb', line 115

def Base.optional_parameters_to_buffer(optionals)
  output = ""
  optionals.each do |tag, optional_param|
    length = optional_param.value.to_s.length
    buffer = []
    buffer += [tag >> 8, tag & 0xff]
    buffer += [length >> 8, length & 0xff]
    output << buffer.pack('cccc') << optional_param.value.force_encoding('binary')
  end
  output
end

.parse_optional_parameters(remaining_bytes) ⇒ Object



171
172
173
174
175
176
177
178
179
180
# File 'lib/smpp/pdu/base.rb', line 171

def Base.parse_optional_parameters(remaining_bytes)
  optionals = {}
  while not remaining_bytes.empty?
    optional = {}
    optional_parameter, remaining_bytes = Smpp::OptionalParameter.from_wire_data(remaining_bytes)
    optionals[optional_parameter.tag] = optional_parameter
  end
  
  return optionals
end

Instance Method Details

#fixed_int(value) ⇒ Object



110
111
112
# File 'lib/smpp/pdu/base.rb', line 110

def fixed_int(value)
  Base.fixed_int(value)
end

#loggerObject



94
95
96
# File 'lib/smpp/pdu/base.rb', line 94

def logger
  Smpp::Base.logger
end

#next_sequence_numberObject



131
132
133
# File 'lib/smpp/pdu/base.rb', line 131

def next_sequence_number
  Base.next_sequence_number
end

#optional_parameters_to_buffer(optionals) ⇒ Object



127
128
129
# File 'lib/smpp/pdu/base.rb', line 127

def optional_parameters_to_buffer(optionals)
  Base.optional_parameters_to_buffer(optionals)
end

#to_humanObject



98
99
100
101
102
# File 'lib/smpp/pdu/base.rb', line 98

def to_human
  # convert header (4 bytes) to array of 4-byte ints
  a = @data.to_s.unpack('N4')
  sprintf("(%22s) len=%3d cmd=%8s status=%1d seq=%03d (%s)", self.class.to_s[11..-1], a[0], a[1].to_s(16), a[2], a[3], @body)
end