dubbo-ssl-python 0.9.0__tar.gz → 0.9.2__tar.gz
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.
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/PKG-INFO +4 -4
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/README.md +1 -1
- dubbo_ssl_python-0.9.2/dubbo_ssl/codec/__init__.py +1 -0
- dubbo_ssl_python-0.9.2/dubbo_ssl/codec/decoder.py +468 -0
- dubbo_ssl_python-0.9.2/dubbo_ssl/codec/encoder.py +404 -0
- dubbo_ssl_python-0.9.2/dubbo_ssl/common/__init__.py +1 -0
- dubbo_ssl_python-0.9.2/dubbo_ssl/common/constants.py +41 -0
- dubbo_ssl_python-0.9.2/dubbo_ssl/common/exceptions.py +34 -0
- dubbo_ssl_python-0.9.2/dubbo_ssl/common/util.py +95 -0
- dubbo_ssl_python-0.9.2/dubbo_ssl/connection/__init__.py +2 -0
- dubbo_ssl_python-0.9.2/dubbo_ssl/connection/connections.py +409 -0
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/dubbo_ssl_python.egg-info/PKG-INFO +4 -4
- dubbo_ssl_python-0.9.2/dubbo_ssl_python.egg-info/SOURCES.txt +20 -0
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/pyproject.toml +4 -4
- dubbo_ssl_python-0.9.0/dubbo_ssl_python.egg-info/SOURCES.txt +0 -11
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/LICENSE +0 -0
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/dubbo_ssl/__init__.py +0 -0
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/dubbo_ssl/client.py +0 -0
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/dubbo_ssl_python.egg-info/dependency_links.txt +0 -0
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/dubbo_ssl_python.egg-info/requires.txt +0 -0
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/dubbo_ssl_python.egg-info/top_level.txt +0 -0
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/setup.cfg +0 -0
- {dubbo_ssl_python-0.9.0 → dubbo_ssl_python-0.9.2}/tests/test_client.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dubbo-ssl-python
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.2
|
|
4
4
|
Summary: Python client for Apache Dubbo RPC protocol, with Hessian2 serialization and SSL/TLS support.
|
|
5
5
|
Author-email: gigi wang <gigiwgoo@gmail.com>
|
|
6
6
|
License: Apache License
|
|
@@ -205,8 +205,8 @@ License: Apache License
|
|
|
205
205
|
See the License for the specific language governing permissions and
|
|
206
206
|
limitations under the License.
|
|
207
207
|
|
|
208
|
-
Project-URL: Homepage, https://github.
|
|
209
|
-
Project-URL:
|
|
208
|
+
Project-URL: Homepage, https://iocoo.github.io
|
|
209
|
+
Project-URL: Repository, https://github.com/iocoo/dubbo-ssl-python/
|
|
210
210
|
Classifier: Programming Language :: Python :: 3
|
|
211
211
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
212
212
|
Classifier: Operating System :: OS Independent
|
|
@@ -224,7 +224,7 @@ Base on https://github.com/apache/dubbo-python2 and https://github.com/huisongya
|
|
|
224
224
|
## Features
|
|
225
225
|
|
|
226
226
|
- Full Hessian2 serialization/deserialization (primitives, objects, lists, maps, dates, null, circular references)
|
|
227
|
-
- TCP and SSL/
|
|
227
|
+
- TCP and SSL/TLS connections with custom CA certificate support
|
|
228
228
|
- Zookeeper-based services discovery with weighted load balancing
|
|
229
229
|
- Connection pooling with automatic heartbeat and reconnection
|
|
230
230
|
- Support `group` settings for Dubbo, Compatible with Dubbo 2.x
|
|
@@ -6,7 +6,7 @@ Base on https://github.com/apache/dubbo-python2 and https://github.com/huisongya
|
|
|
6
6
|
## Features
|
|
7
7
|
|
|
8
8
|
- Full Hessian2 serialization/deserialization (primitives, objects, lists, maps, dates, null, circular references)
|
|
9
|
-
- TCP and SSL/
|
|
9
|
+
- TCP and SSL/TLS connections with custom CA certificate support
|
|
10
10
|
- Zookeeper-based services discovery with weighted load balancing
|
|
11
11
|
- Connection pooling with automatic heartbeat and reconnection
|
|
12
12
|
- Support `group` settings for Dubbo, Compatible with Dubbo 2.x
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
/*
|
|
4
|
+
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
5
|
+
* contributor license agreements. See the NOTICE file distributed with
|
|
6
|
+
* this work for additional information regarding copyright ownership.
|
|
7
|
+
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
8
|
+
* (the "License"); you may not use this file except in compliance with
|
|
9
|
+
* the License. You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from datetime import datetime
|
|
22
|
+
from struct import unpack
|
|
23
|
+
|
|
24
|
+
from dubbo_ssl.common.exceptions import HessianTypeError, DubboException, DubboResponseException
|
|
25
|
+
from dubbo_ssl.common.constants import response_status_message
|
|
26
|
+
|
|
27
|
+
functions = {}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def ranges(*defined_ranges):
|
|
31
|
+
"""
|
|
32
|
+
根据hessian协议,把处理方法交给其定义好的范围
|
|
33
|
+
:param defined_ranges:
|
|
34
|
+
:return:
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def decorator(func):
|
|
38
|
+
# 遍历所有的范围
|
|
39
|
+
for defined_range in defined_ranges:
|
|
40
|
+
if isinstance(defined_range, (tuple, list)):
|
|
41
|
+
if not len(defined_range) == 2:
|
|
42
|
+
raise ValueError('Invalid range {}'.format(defined_range))
|
|
43
|
+
nums = range(defined_range[0], defined_range[1] + 1)
|
|
44
|
+
for num in nums:
|
|
45
|
+
functions[num] = func
|
|
46
|
+
elif isinstance(defined_range, int):
|
|
47
|
+
functions[defined_range] = func
|
|
48
|
+
else:
|
|
49
|
+
raise ValueError('Defined value {} illegal'.format(defined_ranges))
|
|
50
|
+
|
|
51
|
+
def wrapper(*args, **kwargs):
|
|
52
|
+
return func(*args, **kwargs) # 原始方法正常执行
|
|
53
|
+
|
|
54
|
+
return wrapper
|
|
55
|
+
|
|
56
|
+
return decorator
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Response(object):
|
|
60
|
+
"""
|
|
61
|
+
A class for parsing dubbo response body.
|
|
62
|
+
All types can be parsed:
|
|
63
|
+
* byte
|
|
64
|
+
* boolean
|
|
65
|
+
* int
|
|
66
|
+
* long
|
|
67
|
+
* double
|
|
68
|
+
* string
|
|
69
|
+
* object
|
|
70
|
+
* class
|
|
71
|
+
* generic type
|
|
72
|
+
* list
|
|
73
|
+
* map
|
|
74
|
+
* date
|
|
75
|
+
* null
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def __init__(self, data):
|
|
79
|
+
self.__data = data # data是字节数组
|
|
80
|
+
self.__index = 0
|
|
81
|
+
self.types = []
|
|
82
|
+
self.objects = []
|
|
83
|
+
# 对于一个类来说,有path的地方就应该有field_name
|
|
84
|
+
self.paths = []
|
|
85
|
+
self.field_names = []
|
|
86
|
+
|
|
87
|
+
def get_byte(self):
|
|
88
|
+
"""
|
|
89
|
+
获取到头部的字节数据,只是获取并不移动指针
|
|
90
|
+
:return:
|
|
91
|
+
"""
|
|
92
|
+
return self.__data[self.__index]
|
|
93
|
+
|
|
94
|
+
def length(self):
|
|
95
|
+
"""
|
|
96
|
+
当前的字节长度
|
|
97
|
+
:return:
|
|
98
|
+
"""
|
|
99
|
+
return len(self.__data) - self.__index
|
|
100
|
+
|
|
101
|
+
def read_byte(self):
|
|
102
|
+
"""
|
|
103
|
+
读取一个字节并向后移动一位指针
|
|
104
|
+
:return:
|
|
105
|
+
"""
|
|
106
|
+
if self.__index >= len(self.__data):
|
|
107
|
+
raise ValueError('Index {} bigger than data length {}'.format(self.__index, len(self.__data)))
|
|
108
|
+
value = self.__data[self.__index]
|
|
109
|
+
self.__index += 1
|
|
110
|
+
return value
|
|
111
|
+
|
|
112
|
+
def read_bytes(self, num):
|
|
113
|
+
"""
|
|
114
|
+
读取n个字节并向后移动n位指针
|
|
115
|
+
:param num:
|
|
116
|
+
:return:
|
|
117
|
+
"""
|
|
118
|
+
value = self.__data[self.__index:self.__index + num]
|
|
119
|
+
self.__index += num
|
|
120
|
+
return value
|
|
121
|
+
|
|
122
|
+
@ranges(ord('T'), ord('F'))
|
|
123
|
+
def read_boolean(self):
|
|
124
|
+
"""
|
|
125
|
+
读取一个布尔类型
|
|
126
|
+
:return:
|
|
127
|
+
"""
|
|
128
|
+
value = self.read_byte()
|
|
129
|
+
if value == ord('T'):
|
|
130
|
+
return True
|
|
131
|
+
elif value == ord('F'):
|
|
132
|
+
return False
|
|
133
|
+
else:
|
|
134
|
+
raise HessianTypeError('illegal boolean value: {0}'.format(value))
|
|
135
|
+
|
|
136
|
+
@ranges((0x80, 0xd7), ord('I'))
|
|
137
|
+
def read_int(self):
|
|
138
|
+
"""
|
|
139
|
+
读取一个整型数据
|
|
140
|
+
:return:
|
|
141
|
+
"""
|
|
142
|
+
value = self.read_byte()
|
|
143
|
+
if 0x80 <= value <= 0xbf:
|
|
144
|
+
result = value - 0x90
|
|
145
|
+
elif 0xc0 <= value <= 0xcf:
|
|
146
|
+
i = (value - 0xc8) << 8
|
|
147
|
+
i |= self.read_byte()
|
|
148
|
+
result = i
|
|
149
|
+
elif 0xd0 <= value <= 0xd7:
|
|
150
|
+
i = (value - 0xd4) << 16
|
|
151
|
+
i |= self.read_byte() << 8
|
|
152
|
+
i |= self.read_byte()
|
|
153
|
+
result = i
|
|
154
|
+
else:
|
|
155
|
+
result = unpack('!i', self.read_bytes(4))[0]
|
|
156
|
+
return result
|
|
157
|
+
|
|
158
|
+
@ranges((0x5b, 0x5f), ord('D'))
|
|
159
|
+
def read_double(self):
|
|
160
|
+
"""
|
|
161
|
+
读取一个浮点类型
|
|
162
|
+
:return:
|
|
163
|
+
"""
|
|
164
|
+
value = self.read_byte()
|
|
165
|
+
if value == 0x5b:
|
|
166
|
+
result = 0.0
|
|
167
|
+
elif value == 0x5c:
|
|
168
|
+
result = 1.0
|
|
169
|
+
elif value == 0x5d:
|
|
170
|
+
result = float(unpack('!b', self.read_bytes(1))[0])
|
|
171
|
+
elif value == 0x5e:
|
|
172
|
+
result = float(unpack('!h', self.read_bytes(2))[0])
|
|
173
|
+
elif value == 0x5f:
|
|
174
|
+
result = float(unpack('!i', self.read_bytes(4))[0]) * 0.001
|
|
175
|
+
elif value == ord('D'):
|
|
176
|
+
result = float(unpack('!d', self.read_bytes(8))[0])
|
|
177
|
+
else:
|
|
178
|
+
raise HessianTypeError('{0} is not a float'.format(value))
|
|
179
|
+
return result
|
|
180
|
+
|
|
181
|
+
def _read_utf(self, length):
|
|
182
|
+
"""
|
|
183
|
+
读取n个字符
|
|
184
|
+
:param length:
|
|
185
|
+
:return:
|
|
186
|
+
"""
|
|
187
|
+
value = u''
|
|
188
|
+
for i in range(length):
|
|
189
|
+
ch = self.read_byte()
|
|
190
|
+
if ch < 0x80:
|
|
191
|
+
value += chr(ch)
|
|
192
|
+
elif (ch & 0xe0) == 0xc0:
|
|
193
|
+
ch1 = self.read_byte()
|
|
194
|
+
value += chr(((ch & 0x1f) << 6) + (ch1 & 0x3f))
|
|
195
|
+
elif (ch & 0xf0) == 0xe0:
|
|
196
|
+
ch1 = self.read_byte()
|
|
197
|
+
ch2 = self.read_byte()
|
|
198
|
+
value += chr(((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f))
|
|
199
|
+
else:
|
|
200
|
+
raise ValueError('Can\'t parse utf-8 char {}'.format(ch))
|
|
201
|
+
return value # 将unicode转化为str类型
|
|
202
|
+
|
|
203
|
+
@ranges((0x00, 0x1f), (0x30, 0x33), 0x52, ord('S'))
|
|
204
|
+
def read_string(self):
|
|
205
|
+
"""
|
|
206
|
+
读取一个字符串
|
|
207
|
+
:return:
|
|
208
|
+
"""
|
|
209
|
+
value = self.read_byte()
|
|
210
|
+
string = ''
|
|
211
|
+
while value == 'R':
|
|
212
|
+
length = unpack('!h', self.read_bytes(2))[0]
|
|
213
|
+
string += self._read_utf(length)
|
|
214
|
+
value = self.read_byte()
|
|
215
|
+
|
|
216
|
+
if value == ord('S'):
|
|
217
|
+
length = unpack('!h', self.read_bytes(2))[0]
|
|
218
|
+
elif 0x00 <= value <= 0x1f:
|
|
219
|
+
length = value
|
|
220
|
+
else:
|
|
221
|
+
length = (value - 0x30) << 8 | self.read_byte()
|
|
222
|
+
|
|
223
|
+
string += self._read_utf(length)
|
|
224
|
+
return string
|
|
225
|
+
|
|
226
|
+
@ranges((0x60, 0x6f), ord('O'))
|
|
227
|
+
def read_object(self):
|
|
228
|
+
"""
|
|
229
|
+
读取一个对象
|
|
230
|
+
:return:
|
|
231
|
+
"""
|
|
232
|
+
result = {}
|
|
233
|
+
self.objects.append(result)
|
|
234
|
+
value = self.read_byte()
|
|
235
|
+
if 0x60 <= value <= 0x6f:
|
|
236
|
+
ref = value - 0x60
|
|
237
|
+
else:
|
|
238
|
+
ref = self.read_int()
|
|
239
|
+
field_names = self.field_names[ref]
|
|
240
|
+
for field_name in field_names:
|
|
241
|
+
field_value = self.read_next()
|
|
242
|
+
result[field_name] = field_value
|
|
243
|
+
|
|
244
|
+
path = self.paths[ref]
|
|
245
|
+
if path == 'java.math.BigDecimal':
|
|
246
|
+
result = float(result['value']) or 0
|
|
247
|
+
self.objects[-1] = result
|
|
248
|
+
elif path == 'java.math.BigInteger':
|
|
249
|
+
result = int(result['value'])
|
|
250
|
+
self.objects[-1] = result
|
|
251
|
+
|
|
252
|
+
return result
|
|
253
|
+
|
|
254
|
+
@ranges(ord('C'))
|
|
255
|
+
def read_class(self):
|
|
256
|
+
"""
|
|
257
|
+
读取一个类的类属性,主要是类名和类中的变量名
|
|
258
|
+
:return:
|
|
259
|
+
"""
|
|
260
|
+
self.read_byte()
|
|
261
|
+
path = self.read_string()
|
|
262
|
+
self.paths.append(path)
|
|
263
|
+
|
|
264
|
+
field_length = self.read_int()
|
|
265
|
+
field_names = []
|
|
266
|
+
for i in range(field_length):
|
|
267
|
+
field_names.append(self.read_string())
|
|
268
|
+
self.field_names.append(field_names)
|
|
269
|
+
return self.read_object()
|
|
270
|
+
|
|
271
|
+
def read_type(self):
|
|
272
|
+
"""
|
|
273
|
+
type代表了list或者map中泛型的类型,在Python中此类型无意义
|
|
274
|
+
:return:
|
|
275
|
+
"""
|
|
276
|
+
_type = self.read_next()
|
|
277
|
+
if isinstance(_type, int):
|
|
278
|
+
return self.types[_type]
|
|
279
|
+
elif isinstance(_type, str):
|
|
280
|
+
self.types.append(_type)
|
|
281
|
+
return _type
|
|
282
|
+
else:
|
|
283
|
+
raise HessianTypeError('Unknown _type type for value: {0}'.format(_type))
|
|
284
|
+
|
|
285
|
+
@ranges((0x70, 0x7f), (0x55, 0x58))
|
|
286
|
+
def read_list(self):
|
|
287
|
+
"""
|
|
288
|
+
读取一个列表
|
|
289
|
+
:return:
|
|
290
|
+
"""
|
|
291
|
+
result = []
|
|
292
|
+
self.objects.append(result)
|
|
293
|
+
value = self.read_byte()
|
|
294
|
+
# 固定长度的有类型短小列表
|
|
295
|
+
if 0x70 <= value <= 0x77:
|
|
296
|
+
_type = self.read_type() # type对于Python来说没有用处
|
|
297
|
+
length = value - 0x70
|
|
298
|
+
for i in range(length):
|
|
299
|
+
result.append(self.read_next())
|
|
300
|
+
# 固定长度的无类型短小列表
|
|
301
|
+
elif 0x78 <= value <= 0x7f:
|
|
302
|
+
length = value - 0x78
|
|
303
|
+
for i in range(length):
|
|
304
|
+
result.append(self.read_next())
|
|
305
|
+
# 固定长度的有类型列表
|
|
306
|
+
elif value == 0x56:
|
|
307
|
+
_type = self.read_type()
|
|
308
|
+
length = self.read_int()
|
|
309
|
+
for i in range(length):
|
|
310
|
+
result.append(self.read_next())
|
|
311
|
+
# 固定长度的无类型列表
|
|
312
|
+
elif value == 0x58:
|
|
313
|
+
length = self.read_int()
|
|
314
|
+
for i in range(length):
|
|
315
|
+
result.append(self.read_next())
|
|
316
|
+
# 可变长度的有类型列表
|
|
317
|
+
elif value == 0x55:
|
|
318
|
+
_type = self.read_type()
|
|
319
|
+
# 可变长度的无类型列表
|
|
320
|
+
elif value == 0x57:
|
|
321
|
+
pass
|
|
322
|
+
return result
|
|
323
|
+
|
|
324
|
+
@ranges((0xd8, 0xff), (0x38, 0x3f), 0x59, ord('L'))
|
|
325
|
+
def read_long(self):
|
|
326
|
+
"""
|
|
327
|
+
读取一个long类型的数字
|
|
328
|
+
:return:
|
|
329
|
+
"""
|
|
330
|
+
value = self.read_byte()
|
|
331
|
+
if 0xd8 <= value <= 0xef:
|
|
332
|
+
result = value - 0xe0
|
|
333
|
+
elif 0xf0 <= value <= 0xff:
|
|
334
|
+
result = ((value - 0xf8) << 8) | self.read_byte()
|
|
335
|
+
elif 0x38 <= value <= 0x3f:
|
|
336
|
+
i = (value - 0x3c) << 16
|
|
337
|
+
i |= self.read_byte() << 8
|
|
338
|
+
i |= self.read_byte()
|
|
339
|
+
result = i
|
|
340
|
+
elif value == 0x59:
|
|
341
|
+
result = unpack('!i', self.read_bytes(4))[0]
|
|
342
|
+
elif value == ord('L'):
|
|
343
|
+
result = unpack('!q', self.read_bytes(8))[0]
|
|
344
|
+
else:
|
|
345
|
+
raise HessianTypeError('{0} is not long type'.format(value))
|
|
346
|
+
return result
|
|
347
|
+
|
|
348
|
+
@ranges(ord('N'))
|
|
349
|
+
def read_null(self):
|
|
350
|
+
"""
|
|
351
|
+
读取一个None
|
|
352
|
+
:return:
|
|
353
|
+
"""
|
|
354
|
+
value = self.read_byte()
|
|
355
|
+
if value == ord('N'):
|
|
356
|
+
return None
|
|
357
|
+
else:
|
|
358
|
+
raise HessianTypeError('{0} is not null'.format(value))
|
|
359
|
+
|
|
360
|
+
@ranges(ord('H'), ord('M'))
|
|
361
|
+
def read_map(self):
|
|
362
|
+
"""
|
|
363
|
+
读取一个dict
|
|
364
|
+
:return:
|
|
365
|
+
"""
|
|
366
|
+
value = self.read_byte()
|
|
367
|
+
|
|
368
|
+
if value == ord('M') or value == ord('H'):
|
|
369
|
+
result = {}
|
|
370
|
+
self.objects.append(result)
|
|
371
|
+
while self.get_byte() != ord('Z'):
|
|
372
|
+
key = self.read_next()
|
|
373
|
+
value = self.read_next()
|
|
374
|
+
result[key] = value
|
|
375
|
+
self.read_byte() # 干掉最后一个'Z'字符
|
|
376
|
+
return result
|
|
377
|
+
else:
|
|
378
|
+
raise HessianTypeError('{0} is not a map.'.format(value))
|
|
379
|
+
|
|
380
|
+
@ranges(0x4a, 0x4b)
|
|
381
|
+
def read_date(self):
|
|
382
|
+
"""
|
|
383
|
+
读取一个date类型的值
|
|
384
|
+
:return:
|
|
385
|
+
"""
|
|
386
|
+
value = self.read_byte()
|
|
387
|
+
if value == 0x4a:
|
|
388
|
+
timestamp = unpack('!q', self.read_bytes(8))[0]
|
|
389
|
+
elif value == 0x4b:
|
|
390
|
+
timestamp = unpack('!i', self.read_bytes(4))[0]
|
|
391
|
+
timestamp *= 60000
|
|
392
|
+
else:
|
|
393
|
+
raise HessianTypeError('{0} is not date type'.format(value))
|
|
394
|
+
return datetime.fromtimestamp(timestamp / 1e3).strftime("%Y-%m-%dT%H:%M:%S.%f+0800")
|
|
395
|
+
|
|
396
|
+
@ranges(0x51)
|
|
397
|
+
def read_ref(self):
|
|
398
|
+
"""
|
|
399
|
+
读取一个已知的object/list/map
|
|
400
|
+
:return:
|
|
401
|
+
"""
|
|
402
|
+
self.read_byte() # 干掉0x51
|
|
403
|
+
ref_id = self.read_int()
|
|
404
|
+
return self.objects[ref_id]
|
|
405
|
+
|
|
406
|
+
def read_next(self):
|
|
407
|
+
"""
|
|
408
|
+
读取下一个变量,自动识别变量类型
|
|
409
|
+
:return:
|
|
410
|
+
"""
|
|
411
|
+
data_type = self.get_byte()
|
|
412
|
+
func = functions[data_type]
|
|
413
|
+
return func(self)
|
|
414
|
+
|
|
415
|
+
def read_error(self):
|
|
416
|
+
"""
|
|
417
|
+
解析Java的错误信息,因为需要知道错误的类型,所以需要单独处理
|
|
418
|
+
:return:
|
|
419
|
+
"""
|
|
420
|
+
self.read_byte()
|
|
421
|
+
error_type = self.read_string()
|
|
422
|
+
self.paths.append(error_type)
|
|
423
|
+
|
|
424
|
+
field_length = self.read_int()
|
|
425
|
+
field_names = []
|
|
426
|
+
for i in range(field_length):
|
|
427
|
+
field_names.append(self.read_string())
|
|
428
|
+
self.field_names.append(field_names)
|
|
429
|
+
|
|
430
|
+
error = self.read_object()
|
|
431
|
+
error['cause'] = error_type
|
|
432
|
+
return error
|
|
433
|
+
|
|
434
|
+
def __repr__(self):
|
|
435
|
+
return str(self.__data)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def parse_response_head(response_head):
|
|
439
|
+
"""
|
|
440
|
+
对响应头部的字节做解析
|
|
441
|
+
:param response_head:
|
|
442
|
+
:return:
|
|
443
|
+
"""
|
|
444
|
+
# Magic number
|
|
445
|
+
if not (response_head[0] == 0xda and response_head[1] == 0xbb):
|
|
446
|
+
raise DubboException('illegal response')
|
|
447
|
+
|
|
448
|
+
# 第三位为1表示这是一个心跳包
|
|
449
|
+
if response_head[2] & 0x20 == 0x20:
|
|
450
|
+
if response_head[2] & 0x80 == 0x80:
|
|
451
|
+
# 第一位为1,一个心跳请求的包
|
|
452
|
+
heartbeat = 2
|
|
453
|
+
else:
|
|
454
|
+
# 第一位为0,一个心跳响应的包
|
|
455
|
+
heartbeat = 1
|
|
456
|
+
response_status = response_head[3]
|
|
457
|
+
if response_status != 20:
|
|
458
|
+
raise DubboException(response_status_message[response_status])
|
|
459
|
+
else:
|
|
460
|
+
heartbeat = 0
|
|
461
|
+
response_status = response_head[3]
|
|
462
|
+
if response_status != 20:
|
|
463
|
+
raise DubboResponseException(response_status_message[response_status])
|
|
464
|
+
return heartbeat, unpack('!i', response_head[12:])[0]
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
if __name__ == '__main__':
|
|
468
|
+
pass
|