empp 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE.txt +20 -0
- data/README +0 -0
- data/README.rdoc +19 -0
- data/lib/empp.rb +2 -0
- data/lib/empp/constants.rb +28 -0
- data/lib/empp/delivery_state.rb +11 -0
- data/lib/empp/empp.rb +375 -0
- data/lib/empp/empp_base.rb +37 -0
- data/lib/empp/empp_connection.rb +90 -0
- data/lib/empp/empp_logger.rb +45 -0
- data/lib/empp/empp_msg_listener.rb +9 -0
- data/lib/empp/empp_parser.rb +176 -0
- data/lib/empp/empp_result_listener.rb +16 -0
- data/lib/empp/msg_active_test.rb +28 -0
- data/lib/empp/msg_active_test_resp.rb +14 -0
- data/lib/empp/msg_connect.rb +52 -0
- data/lib/empp/msg_connect_resp.rb +22 -0
- data/lib/empp/msg_delivery.rb +21 -0
- data/lib/empp/msg_delivery_resp.rb +35 -0
- data/lib/empp/msg_submit.rb +105 -0
- data/lib/empp/msg_submit_resp.rb +23 -0
- data/lib/empp/tcp_connection.rb +103 -0
- data/lib/empp/utils/bytebuffer.rb +39 -0
- data/lib/empp/utils/hashtable.rb +36 -0
- data/lib/empp/utils/utils.rb +120 -0
- data/test/helper.rb +3 -0
- data/test/test_empp.rb +161 -0
- data/test/test_msg_submit.rb +16 -0
- data/test/test_tcp_connection.rb +29 -0
- data/test/test_utils.rb +49 -0
- metadata +157 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module Empp
|
5
|
+
|
6
|
+
class EmppBase
|
7
|
+
@@sequenceId = 1;
|
8
|
+
@@mutex = Mutex.new
|
9
|
+
attr_accessor :total_length, :command_id, :sequence_id
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def setSequenceId
|
14
|
+
@@mutex.synchronize {
|
15
|
+
if @@sequenceId == 0xFFFFFFFF
|
16
|
+
@@sequenceId = 1
|
17
|
+
end
|
18
|
+
result = @@sequenceId
|
19
|
+
@sequence_id = result
|
20
|
+
@@sequenceId += 1
|
21
|
+
|
22
|
+
return result
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
"total_length=#{@total_length}, command_id=0x#{@command_id.to_s(16)}, sequence_id=#{@sequence_id}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def package
|
31
|
+
end
|
32
|
+
|
33
|
+
def unpackage
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'empp/tcp_connection'
|
2
|
+
require 'empp/msg_connect'
|
3
|
+
require 'empp/empp_parser'
|
4
|
+
require 'empp/empp_logger'
|
5
|
+
|
6
|
+
module Empp
|
7
|
+
|
8
|
+
class EmppConnection
|
9
|
+
|
10
|
+
attr_reader :alive
|
11
|
+
|
12
|
+
def initialize(host, port, account_id, password, service_id)
|
13
|
+
@host = host
|
14
|
+
@port = port
|
15
|
+
@account_id = account_id
|
16
|
+
@password = password
|
17
|
+
@service_id = service_id
|
18
|
+
@tcp_connection = TcpConnection.getConnection(host, port)
|
19
|
+
@logger = EmppLogger.instance
|
20
|
+
end
|
21
|
+
|
22
|
+
def alive?
|
23
|
+
@alive
|
24
|
+
end
|
25
|
+
|
26
|
+
def close
|
27
|
+
|
28
|
+
if @tcp_connection
|
29
|
+
@tcp_connection.close
|
30
|
+
end
|
31
|
+
|
32
|
+
@alive = false
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def connect
|
37
|
+
@logger.debug("Enter EmppConnection::connect")
|
38
|
+
|
39
|
+
@tcp_connection.connect
|
40
|
+
|
41
|
+
msgConn = MsgConnect.new(@account_id, @password)
|
42
|
+
connReq = msgConn.package
|
43
|
+
|
44
|
+
@tcp_connection.send(connReq)
|
45
|
+
|
46
|
+
object = receive()
|
47
|
+
if object
|
48
|
+
@alive = true if object.status == Constants::EMPP_CONNECT_OK
|
49
|
+
end
|
50
|
+
|
51
|
+
@logger.debug("Leave EmppConnection::connect with status=#{@alive}")
|
52
|
+
@alive
|
53
|
+
end
|
54
|
+
|
55
|
+
def receive
|
56
|
+
@logger.debug("Enter EmppConnection::receive")
|
57
|
+
# read header
|
58
|
+
header = @tcp_connection.receive(12)
|
59
|
+
body = ''
|
60
|
+
object = nil
|
61
|
+
|
62
|
+
if header
|
63
|
+
object = EmppParser.parseHeader(header)
|
64
|
+
|
65
|
+
if object.total_length - 12 > 0
|
66
|
+
body = @tcp_connection.receive(object.total_length - 12)
|
67
|
+
EmppParser.parseBody(object, body)
|
68
|
+
end
|
69
|
+
@logger.debug( "EmppConnection::receive bytes:" + (header + body).unpack("H*").to_s )
|
70
|
+
@logger.debug("EmppConnection::receive object=#{object}")
|
71
|
+
# @logger.info("EmppConnection::receive object:" + object.to_s)
|
72
|
+
end
|
73
|
+
|
74
|
+
@logger.debug("Leave EmppConnection::receive")
|
75
|
+
object
|
76
|
+
end
|
77
|
+
|
78
|
+
def send(emppObject)
|
79
|
+
@logger.debug("Enter EmppConnection::send")
|
80
|
+
|
81
|
+
@logger.info("EmppConnection::send object=#{emppObject}")
|
82
|
+
bytes = @tcp_connection.send(emppObject.package)
|
83
|
+
|
84
|
+
@logger.debug("Leave EmppConnection::send")
|
85
|
+
bytes
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
require 'logger'
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
# require 'empp/empp'
|
6
|
+
|
7
|
+
module Empp
|
8
|
+
|
9
|
+
class EmppLogger < Logger
|
10
|
+
|
11
|
+
@@loggerfolder = File.expand_path(File.dirname(__FILE__)) + "/log"
|
12
|
+
@@loggerfile = @@loggerfolder + '/empp.log'
|
13
|
+
@@loggerlevel = Logger::DEBUG
|
14
|
+
@@logger = nil
|
15
|
+
|
16
|
+
def self.config(config = {})
|
17
|
+
@@loggerfile = config[:logfile] || @@loggerfile
|
18
|
+
@@loggerlevel = config[:loglevel] || @@loggerlevel
|
19
|
+
@@logger = config[:logger]
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.instance
|
23
|
+
if @@logger
|
24
|
+
return @@logger
|
25
|
+
else
|
26
|
+
if !File::exist?@@loggerfolder
|
27
|
+
Dir::mkdir @@loggerfolder
|
28
|
+
end
|
29
|
+
@@logger = self.new
|
30
|
+
return @@logger
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize
|
36
|
+
# super(File.dirname(__FILE__) + "/log/empp.log", shift_age = 7, shift_size = 1024*1024 )
|
37
|
+
super(@@loggerfile, shift_age = 7, shift_size = 1024*1024 )
|
38
|
+
# super(Empp::logfile, shift_age = 7, shift_size = 1024*1024 )
|
39
|
+
# @level = Empp::loglevel
|
40
|
+
@level = @@loggerlevel
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
|
2
|
+
require 'bindata'
|
3
|
+
require 'empp/empp_base'
|
4
|
+
require 'empp/msg_connect_resp'
|
5
|
+
require 'empp/constants'
|
6
|
+
require 'empp/msg_active_test_resp'
|
7
|
+
require 'empp/msg_submit_resp'
|
8
|
+
require 'empp/msg_delivery'
|
9
|
+
require 'empp/empp_logger'
|
10
|
+
require 'empp/delivery_state'
|
11
|
+
require 'empp/utils/utils'
|
12
|
+
|
13
|
+
module Empp
|
14
|
+
|
15
|
+
class EmppParser
|
16
|
+
@@logger = EmppLogger.instance
|
17
|
+
|
18
|
+
def self.logger=(logger)
|
19
|
+
@@logger = logger
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.parseHeader(header)
|
23
|
+
|
24
|
+
sio = StringIO.new(header)
|
25
|
+
|
26
|
+
total_length = ''
|
27
|
+
sio.read(4, total_length)
|
28
|
+
total_length = BinData::Uint32be.read(total_length)
|
29
|
+
|
30
|
+
command_id = ''
|
31
|
+
sio.read(4, command_id)
|
32
|
+
command_id = BinData::Uint32be.read(command_id)
|
33
|
+
|
34
|
+
sequence_id = ''
|
35
|
+
sio.read(4, sequence_id)
|
36
|
+
sequence_id = BinData::Uint32be.read(sequence_id)
|
37
|
+
|
38
|
+
object = nil
|
39
|
+
|
40
|
+
case command_id
|
41
|
+
when Constants::EMPP_CONNECT_RESP
|
42
|
+
object = MsgConnectResp.new
|
43
|
+
|
44
|
+
when Constants::EMPP_ACTIVE_TEST_RESP
|
45
|
+
object = MsgActiveTestResp.new
|
46
|
+
|
47
|
+
when Constants::EMPP_SUBMIT_RESP
|
48
|
+
object = MsgSubmitResp.new
|
49
|
+
|
50
|
+
when Constants::EMPP_DELIVER
|
51
|
+
object = MsgDelivery.new
|
52
|
+
else
|
53
|
+
object = EmppBase.new
|
54
|
+
object.command_id = -1
|
55
|
+
end # end case
|
56
|
+
|
57
|
+
object.total_length = total_length
|
58
|
+
object.sequence_id = sequence_id
|
59
|
+
|
60
|
+
object
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.parseBody(object, body)
|
65
|
+
@@logger.debug("Enter EmppParser:: parse body")
|
66
|
+
case object.command_id
|
67
|
+
when Constants::EMPP_CONNECT_RESP
|
68
|
+
parseConnectResp(object, body)
|
69
|
+
|
70
|
+
# no need to process active_test resp
|
71
|
+
#when Constants::EMPP_ACTIVE_TEST_RESP
|
72
|
+
# ;
|
73
|
+
when Constants::EMPP_SUBMIT_RESP
|
74
|
+
parseSubmitResp(object, body)
|
75
|
+
|
76
|
+
when Constants::EMPP_DELIVER
|
77
|
+
parseEmppDeliver(object, body)
|
78
|
+
end # end case
|
79
|
+
@@logger.debug("Leave EmppParser parse body")
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.parseConnectResp(object, body)
|
83
|
+
sio = StringIO.new(body)
|
84
|
+
status = ''
|
85
|
+
sio.read(4, status)
|
86
|
+
status = BinData::Uint32be.read(status)
|
87
|
+
object.status = status
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.parseSubmitResp(object, body)
|
91
|
+
@@logger.debug("Enter EmppParser::parseSubmitResp")
|
92
|
+
@@logger.debug("EmppParser parseSubmitResp object=#{object}")
|
93
|
+
|
94
|
+
sio = StringIO.new(body)
|
95
|
+
status = ''
|
96
|
+
msg_id = sio.read(10)
|
97
|
+
sio.read(4, status)
|
98
|
+
status = BinData::Uint32be.read(status)
|
99
|
+
|
100
|
+
object.msg_id = msg_id
|
101
|
+
object.status = status
|
102
|
+
|
103
|
+
@@logger.debug("Leave EmppParser::parseSubmitResp")
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.parseEmppDeliver(object, body)
|
107
|
+
@@logger.debug("Enter EmppParser::parseEmppDeliver")
|
108
|
+
@@logger.debug("EmppParser::parseEmppDeliver object=#{object}")
|
109
|
+
|
110
|
+
sio = StringIO.new(body)
|
111
|
+
tmpVal = ''
|
112
|
+
msg_id = sio.read(10)
|
113
|
+
dest_id = sio.read(21)
|
114
|
+
service_id = sio.read(10)
|
115
|
+
|
116
|
+
sio.read(2)
|
117
|
+
|
118
|
+
msg_fmt = sio.read(1)
|
119
|
+
msg_fmt = msg_fmt[0] # 1 byte integer
|
120
|
+
|
121
|
+
src_terminal_id = sio.read(32)
|
122
|
+
src_terminal_id = src_terminal_id.unpack("A*")[0] # delete trailing zeros
|
123
|
+
src_terminal_id = Utils::Utils.deal_with_terminal_id(src_terminal_id)
|
124
|
+
|
125
|
+
sio.read(1)
|
126
|
+
|
127
|
+
registered_delivery = sio.read(1)
|
128
|
+
registered_delivery = registered_delivery[0]
|
129
|
+
|
130
|
+
msg_length = sio.read(1)
|
131
|
+
msg_length = msg_length[0]
|
132
|
+
|
133
|
+
msg_content = sio.read(msg_length)
|
134
|
+
|
135
|
+
object.msg_id = msg_id
|
136
|
+
object.dest_id = dest_id
|
137
|
+
object.service_id = service_id
|
138
|
+
object.msg_format = msg_fmt
|
139
|
+
object.src_terminal_id = src_terminal_id
|
140
|
+
object.msg_length = msg_length
|
141
|
+
object.msg_content = msg_content
|
142
|
+
object.registered_delivery = registered_delivery
|
143
|
+
|
144
|
+
@@logger.debug("Leave EmppParser::parseEmppDeliver")
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.parseDeliveryState(content)
|
148
|
+
@@logger.debug("Enter EmppParser::parseDeliveryState")
|
149
|
+
|
150
|
+
@@logger.debug("EmppParser::parseDeliveryState content=#{content}")
|
151
|
+
sio = StringIO.new(content)
|
152
|
+
msg_id = sio.read(10)
|
153
|
+
state = sio.read(7)
|
154
|
+
submit_time = sio.read(10)
|
155
|
+
done_time = sio.read(10)
|
156
|
+
dest_terminal_id = sio.read(32)
|
157
|
+
dest_terminal_id = dest_terminal_id.unpack("A*")[0] # delete tailing zeros
|
158
|
+
sequence_id = sio.read(4)
|
159
|
+
sequence_id = BinData::Uint32be.read(sequence_id)
|
160
|
+
|
161
|
+
deliveryState = DeliveryState.new
|
162
|
+
deliveryState.msg_id = msg_id
|
163
|
+
deliveryState.state = state
|
164
|
+
deliveryState.submit_time = submit_time
|
165
|
+
deliveryState.done_time = done_time
|
166
|
+
deliveryState.dest_terminal_id = dest_terminal_id
|
167
|
+
deliveryState.sequence_id = sequence_id
|
168
|
+
@@logger.debug("mppParser::parseDeliveryState get Object=#{deliveryState}")
|
169
|
+
|
170
|
+
@@logger.debug("LeaveEmppParser::parseDeliveryState")
|
171
|
+
deliveryState
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Empp
|
2
|
+
|
3
|
+
class EmppResultListener
|
4
|
+
|
5
|
+
##################################
|
6
|
+
# on_result callback #
|
7
|
+
# status: #
|
8
|
+
# true : Sending OK #
|
9
|
+
# false : Sending Fail #
|
10
|
+
##################################
|
11
|
+
def on_result(terminal_id, status)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'empp/empp_base'
|
2
|
+
require 'empp/constants'
|
3
|
+
|
4
|
+
module Empp
|
5
|
+
|
6
|
+
class MsgActiveTest < EmppBase
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@command_id = Constants::EMPP_ACTIVE_TEST
|
10
|
+
@total_length = 12
|
11
|
+
setSequenceId
|
12
|
+
end
|
13
|
+
|
14
|
+
def package
|
15
|
+
|
16
|
+
buf = Utils::ByteBuffer.new
|
17
|
+
# add header
|
18
|
+
buf.append_uint_be(@total_length)
|
19
|
+
|
20
|
+
buf.append_uint_be(@command_id)
|
21
|
+
buf.append_uint_be(@sequence_id)
|
22
|
+
|
23
|
+
buf.data
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
require 'empp/empp_base'
|
3
|
+
require 'empp/utils/bytebuffer'
|
4
|
+
require 'empp/utils/utils'
|
5
|
+
require 'empp/constants'
|
6
|
+
|
7
|
+
require 'md5'
|
8
|
+
|
9
|
+
module Empp
|
10
|
+
|
11
|
+
class MsgConnect < EmppBase
|
12
|
+
|
13
|
+
def initialize(accountId, password)
|
14
|
+
@accountId = accountId
|
15
|
+
@password = password
|
16
|
+
|
17
|
+
@total_length = 12 + 21 + 16 + 1 + 4
|
18
|
+
@command_id = Constants::EMPPCONNECT
|
19
|
+
setSequenceId
|
20
|
+
end
|
21
|
+
|
22
|
+
def package
|
23
|
+
buf = Utils::ByteBuffer.new
|
24
|
+
# add header
|
25
|
+
buf.append_uint_be(@total_length)
|
26
|
+
|
27
|
+
buf.append_uint_be(@command_id)
|
28
|
+
buf.append_uint_be(@sequence_id)
|
29
|
+
|
30
|
+
# 21 bytes accountId
|
31
|
+
act_id = @accountId.to_s
|
32
|
+
buf.append_string( act_id.ljust(21, "\0") )
|
33
|
+
|
34
|
+
timestampStr = Utils::Utils.getTimestampStr(Time.now)
|
35
|
+
|
36
|
+
# 16 bytes AuthenticatorSource
|
37
|
+
authSource = @accountId.to_s + ''.rjust(9, "\0") + @password + timestampStr
|
38
|
+
buf.append_string( MD5.digest(authSource) )
|
39
|
+
|
40
|
+
# 1 byte version, fixed
|
41
|
+
buf.append_string( Utils::Utils.getVersion )
|
42
|
+
|
43
|
+
# 4 bytes timestamp
|
44
|
+
buf.append_string( Utils::Utils.getUintBe(timestampStr.to_i) )
|
45
|
+
|
46
|
+
buf.data
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|