1
1
from __future__ import absolute_import
2
2
3
+ import zlib
4
+
3
5
from collections import namedtuple
4
6
from enum import IntEnum
5
7
6
8
from .. import rw
9
+ from ..exceptions import InvalidChecksumException
10
+ from .types import Types
7
11
8
12
PROTOCOL_VERSION = 0x02
9
13
@@ -24,6 +28,11 @@ class ChecksumType(IntEnum):
24
28
crc32 = 0x01
25
29
farm32 = 0x02
26
30
31
+ @staticmethod
32
+ def standardize (checksum ):
33
+ return (ChecksumType (checksum [0 ]), checksum [1 ])
34
+
35
+
27
36
checksum_rw = rw .switch (
28
37
rw .number (1 ), # csumtype:1
29
38
{
@@ -32,3 +41,64 @@ class ChecksumType(IntEnum):
32
41
ChecksumType .farm32 : rw .number (4 ), # csum:4
33
42
}
34
43
)
44
+
45
+
46
+ CHECKSUM_MSG_TYPES = [Types .CALL_REQ ,
47
+ Types .CALL_REQ_CONTINUE ,
48
+ Types .CALL_RES ,
49
+ Types .CALL_RES_CONTINUE ]
50
+
51
+
52
+ def compute_checksum (checksum_type , args , csum = 0 ):
53
+ if csum is None :
54
+ csum = 0
55
+
56
+ if checksum_type == ChecksumType .none :
57
+ return None
58
+ elif checksum_type == ChecksumType .crc32 :
59
+ for arg in args :
60
+ csum = zlib .crc32 (arg , csum ) & 0xffffffff
61
+ # TODO figure out farm32 cross platform issue
62
+ elif checksum_type == ChecksumType .farm32 :
63
+ raise NotImplementedError ()
64
+ else :
65
+ raise InvalidChecksumException ()
66
+
67
+ return csum
68
+
69
+
70
+ def generate_checksum (message ):
71
+ """Generate checksum for messages with
72
+ CALL_REQ, CALL_REQ_CONTINUE,
73
+ CALL_RES,CALL_RES_CONTINUE types
74
+
75
+ :param message: outgoing message
76
+ """
77
+ if message .message_type in CHECKSUM_MSG_TYPES :
78
+ csum = compute_checksum (
79
+ message .checksum [0 ],
80
+ [message .arg_1 ,
81
+ message .arg_2 ,
82
+ message .arg_3 ])
83
+
84
+ message .checksum = (message .checksum [0 ], csum )
85
+
86
+
87
+ def verify_checksum (message ):
88
+ """
89
+ :return return True if message checksum type is None
90
+ or checksum is correct
91
+ """
92
+ if message .message_type in CHECKSUM_MSG_TYPES :
93
+ csum = compute_checksum (
94
+ message .checksum [0 ],
95
+ [message .arg_1 ,
96
+ message .arg_2 ,
97
+ message .arg_3 ])
98
+
99
+ if csum == message .checksum [1 ]:
100
+ return True
101
+ else :
102
+ return False
103
+ else :
104
+ return True
0 commit comments