~ubuntu-branches/ubuntu/wily/d-rats/wily

« back to all changes in this revision

Viewing changes to d_rats/ddt2.py

  • Committer: Bazaar Package Importer
  • Author(s): Steve Conklin
  • Date: 2011-02-18 18:17:24 UTC
  • Revision ID: james.westby@ubuntu.com-20110218181724-kaxw0ceawnu3wgw6
Tags: upstream-0.3.3~b5
ImportĀ upstreamĀ versionĀ 0.3.3~b5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
#
 
3
# Copyright 2008 Dan Smith <dsmith@danplanet.com>
 
4
#
 
5
# This program is free software: you can redistribute it and/or modify
 
6
# it under the terms of the GNU General Public License as published by
 
7
# the Free Software Foundation, either version 3 of the License, or
 
8
# (at your option) any later version.
 
9
#
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 
 
18
import struct
 
19
import zlib
 
20
import base64
 
21
import yencode
 
22
 
 
23
import threading
 
24
 
 
25
import utils
 
26
 
 
27
ENCODED_HEADER = "[SOB]"
 
28
ENCODED_TRAILER = "[EOB]"
 
29
 
 
30
def update_crc(c, crc):
 
31
    for _ in range(0,8):
 
32
        c <<= 1
 
33
 
 
34
        if (c & 0400) != 0:
 
35
            v = 1
 
36
        else:
 
37
            v = 0
 
38
            
 
39
        if (crc & 0x8000):
 
40
            crc <<= 1
 
41
            crc += v
 
42
            crc ^= 0x1021
 
43
        else:
 
44
            crc <<= 1
 
45
            crc += v
 
46
 
 
47
    return crc & 0xFFFF
 
48
 
 
49
def calc_checksum(data):
 
50
    checksum = 0
 
51
    for i in data:
 
52
        checksum = update_crc(ord(i), checksum)
 
53
 
 
54
    checksum = update_crc(0, checksum)
 
55
    checksum = update_crc(0, checksum)
 
56
 
 
57
    return checksum
 
58
 
 
59
def encode(data):
 
60
    return yencode.yencode_buffer(data)
 
61
 
 
62
def decode(data):
 
63
    return yencode.ydecode_buffer(data)
 
64
 
 
65
class DDT2Frame(object):
 
66
    format = "!BHBBHH8s8s"
 
67
    cso = 6
 
68
    csl = 2
 
69
 
 
70
    def __init__(self):
 
71
        self.seq = 0
 
72
        self.session = 0
 
73
        self.type = 0
 
74
        self.d_station = ""
 
75
        self.s_station = ""
 
76
        self.data = ""
 
77
        self.magic = 0xDD
 
78
 
 
79
        self.sent_event = threading.Event()
 
80
        self.ackd_event = threading.Event()
 
81
 
 
82
        self.compress = True
 
83
 
 
84
        self._xmit_s = 0
 
85
        self._xmit_e = 0
 
86
        self._xmit_z = 0
 
87
 
 
88
    def get_xmit_bps(self):
 
89
        if not self._xmit_e:
 
90
            print "Block not sent, can't determine BPS!"
 
91
            return 0
 
92
 
 
93
        if self._xmit_s == self._xmit_e:
 
94
            return self._xmit_z * 100 # Fudge for sockets
 
95
 
 
96
        return self._xmit_z / (self._xmit_e - self._xmit_s)
 
97
 
 
98
    def set_compress(self, compress=True):
 
99
        self.compress = compress
 
100
 
 
101
    def get_packed(self):
 
102
        if self.compress:
 
103
            data = zlib.compress(self.data, 9)
 
104
        else:
 
105
            data = self.data
 
106
            self.magic = (~self.magic) & 0xFF
 
107
 
 
108
        length = len(data)
 
109
        
 
110
        s_station = self.s_station.ljust(8, "~")
 
111
        d_station = self.d_station.ljust(8, "~")
 
112
 
 
113
        val = struct.pack(self.format,
 
114
                          self.magic,
 
115
                          self.seq,
 
116
                          self.session,
 
117
                          self.type,
 
118
                          0,
 
119
                          length,
 
120
                          s_station,
 
121
                          d_station)
 
122
 
 
123
        checksum = calc_checksum(val + data)
 
124
 
 
125
        val = struct.pack(self.format,
 
126
                          self.magic,
 
127
                          self.seq,
 
128
                          self.session,
 
129
                          self.type,
 
130
                          checksum,
 
131
                          length,
 
132
                          s_station,
 
133
                          d_station)
 
134
 
 
135
        self._xmit_z = len(val) + len(data)
 
136
 
 
137
        return val + data
 
138
 
 
139
    def unpack(self, val):
 
140
        magic = ord(val[0])
 
141
        if magic == 0xDD:
 
142
            self.compress = True
 
143
        elif magic == 0x22:
 
144
            self.compress = False
 
145
        else:
 
146
            print "Magic 0x%X not recognized" % magic
 
147
            return False
 
148
 
 
149
        header = val[:25]
 
150
        data = val[25:]
 
151
 
 
152
        (magic, self.seq, self.session, self.type,
 
153
         checksum, length,
 
154
         self.s_station, self.d_station) = struct.unpack(self.format, header)
 
155
 
 
156
        _header = struct.pack(self.format,
 
157
                              magic,
 
158
                              self.seq,
 
159
                              self.session,
 
160
                              self.type,
 
161
                              0,
 
162
                              length,
 
163
                              self.s_station,
 
164
                              self.d_station)
 
165
 
 
166
        _checksum = calc_checksum(_header + data)
 
167
 
 
168
        self.s_station = self.s_station.replace("~", "")
 
169
        self.d_station = self.d_station.replace("~", "")
 
170
 
 
171
        if _checksum != checksum:
 
172
            print "Checksum failed: %s != %s" % (checksum, _checksum)
 
173
            return False
 
174
 
 
175
        if self.compress:
 
176
            self.data = zlib.decompress(data)
 
177
        else:
 
178
            self.data = data
 
179
 
 
180
        return True
 
181
 
 
182
    def __str__(self):
 
183
        if self.compress:
 
184
            c = "+"
 
185
        else:
 
186
            c = "-"
 
187
 
 
188
        data = utils.filter_to_ascii(self.data[:20])
 
189
 
 
190
        return "DDT2%s: %i:%i:%i %s->%s (%s...[%i])" % (c,
 
191
                                                        self.seq,
 
192
                                                        self.session,
 
193
                                                        self.type,
 
194
                                                        self.s_station,
 
195
                                                        self.d_station,
 
196
                                                        data,
 
197
                                                        len(self.data))
 
198
 
 
199
    def get_copy(self):
 
200
        f = self.__class__()
 
201
        f.seq = self.seq
 
202
        f.session = self.session
 
203
        f.type = self.type
 
204
        f.s_station = self.s_station
 
205
        f.d_station = self.d_station
 
206
        f.data = self.data
 
207
        f.set_compress(self.compress)
 
208
        return f
 
209
 
 
210
class DDT2EncodedFrame(DDT2Frame):
 
211
    def get_packed(self):
 
212
        raw = DDT2Frame.get_packed(self)
 
213
 
 
214
        encoded = encode(raw)
 
215
 
 
216
        return ENCODED_HEADER + encoded + ENCODED_TRAILER
 
217
 
 
218
    def unpack(self, val):
 
219
        try:
 
220
            h = val.index(ENCODED_HEADER) + len(ENCODED_TRAILER)
 
221
            t = val.rindex(ENCODED_TRAILER)
 
222
            payload = val[h:t]
 
223
        except Exception, e:
 
224
            print "Block has no header/trailer: %s" % e
 
225
            return False
 
226
 
 
227
        try:
 
228
            decoded = decode(payload)
 
229
        except Exception, e:
 
230
            print "Unable to decode frame: %s" % e
 
231
            return False
 
232
 
 
233
        return DDT2Frame.unpack(self, decoded)
 
234
 
 
235
class DDT2RawData(DDT2Frame):
 
236
    def get_packed(self):
 
237
        return self.data
 
238
 
 
239
    def unpack(self, string):
 
240
        return self.data
 
241
 
 
242
def test_symmetric(compress=True):
 
243
    fin = DDT2EncodedFrame()
 
244
    fin.type = 1
 
245
    fin.session = 2
 
246
    fin.seq = 3
 
247
    fin.s_station = "FOO"
 
248
    fin.d_station = "BAR"
 
249
    fin.data = "This is a test"
 
250
    fin.set_compress(compress)
 
251
    p = fin.get_packed()
 
252
 
 
253
    print p
 
254
 
 
255
    fout = DDT2EncodedFrame()
 
256
    fout.unpack(p)
 
257
 
 
258
    #print fout.__dict__
 
259
    print fout
 
260
 
 
261
def test_crap():
 
262
    f = DDT2EncodedFrame()
 
263
    try:
 
264
        if f.unpack("[SOB]foobar[EOB]"):
 
265
            print "FAIL"
 
266
        else:
 
267
            print "PASS"
 
268
    except Exception, e:
 
269
        print "PASS"
 
270
 
 
271
if __name__ == "__main__":
 
272
    test_symmetric()
 
273
    test_symmetric(False)
 
274
    test_crap()