empp 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|