Alexander Afanasyev | 5ba9036 | 2013-07-15 19:58:38 -0700 | [diff] [blame] | 1 | ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- |
| 2 | # |
| 3 | # Copyright (c) 2011-2013, Regents of the University of California |
| 4 | # Alexander Afanasyev |
| 5 | # |
| 6 | # GNU 3.0 license, See the LICENSE file for more information |
| 7 | # |
| 8 | # Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu> |
| 9 | # |
| 10 | |
| 11 | # |
| 12 | # Based on PyCCN code, copyrighted and licensed as follows |
| 13 | # |
| 14 | # Copyright (c) 2011-2013, Regents of the University of California |
| 15 | # BSD license, See the COPYING file for more information |
| 16 | # Written by: Derek Kulinski <takeda@takeda.tk> |
| 17 | # Jeff Burke <jburke@ucla.edu> |
| 18 | # |
| 19 | |
| 20 | __TT_BITS__ = 3 |
| 21 | __TT_MASK__ = (1 << __TT_BITS__) - 1 |
| 22 | __TT_HBIT__ = (1 << 7) |
| 23 | __TT_LBIT__ = __TT_HBIT__ - 1 |
| 24 | |
| 25 | DTAG_NAME = 14 |
| 26 | DTAG_COLLECTION = 17 |
| 27 | DTAG_LINK = 31 |
| 28 | |
| 29 | def blob(value): |
| 30 | return _encode(len(value), 5) + value |
| 31 | |
| 32 | def dtag(tag, value): |
| 33 | return _encode(tag, 2) + value + '\x00' |
| 34 | |
| 35 | def _encode(value, tt): |
| 36 | global __TT_BITS__, __TT_HBIT__, __TT_LBIT__ |
| 37 | |
| 38 | header = (value << __TT_BITS__) | tt |
| 39 | |
| 40 | blocks = [] |
| 41 | blocks.append((header & __TT_LBIT__) | __TT_HBIT__) |
| 42 | header >>= 7 |
| 43 | |
| 44 | while header != 0: |
| 45 | blocks.append(header & __TT_LBIT__) |
| 46 | header >>= 7 |
| 47 | |
| 48 | blocks.reverse() |
| 49 | |
| 50 | return bytearray(blocks) |
| 51 | |
| 52 | class CCNBDecoder(object): |
| 53 | def __init__(self, ccnb_data): |
| 54 | self.ccnb_data = ccnb_data |
| 55 | self.reset() |
| 56 | |
| 57 | def reset(self): |
| 58 | self.position = 0 |
| 59 | self.decoded = 0 |
| 60 | self.stack = [] |
| 61 | |
| 62 | def _process_next_byte(self): |
| 63 | global __TT_HBIT__, __TT_LBIT__ |
| 64 | |
| 65 | assert self.position < len(self.ccnb_data) |
| 66 | |
| 67 | char = ord(self.ccnb_data[self.position]) |
| 68 | self.position += 1 |
| 69 | |
| 70 | if self.decoded == 0 and char == 0: |
| 71 | return None, True |
| 72 | |
| 73 | decoded = (self.decoded << 7) | (char & __TT_LBIT__) |
| 74 | complete = (char & __TT_HBIT__) == __TT_HBIT__ |
| 75 | |
| 76 | self.decoded = decoded if not complete else 0 |
| 77 | |
| 78 | return decoded, complete |
| 79 | |
| 80 | def print_element(self, tt, value, data = None): |
| 81 | if tt == 2: |
| 82 | print "DTAG", |
| 83 | |
| 84 | if value == 14: |
| 85 | print "Name" |
| 86 | elif value == 15: |
| 87 | print "Component" |
| 88 | elif value == 17: |
| 89 | print "Collection" |
| 90 | elif value == 31: |
| 91 | print "Link" |
| 92 | else: |
| 93 | print value |
| 94 | |
| 95 | elif tt == 5: |
| 96 | print "BLOB", |
| 97 | print value, |
| 98 | print repr(data) |
| 99 | else: |
| 100 | print tt, |
| 101 | print value, |
| 102 | print repr(data) |
| 103 | |
| 104 | def get_tags(self): |
| 105 | global __TT_MASK__, __TT_BITS__ |
| 106 | |
| 107 | while self.position < len(self.ccnb_data): |
| 108 | while True: |
| 109 | decoded, complete = self._process_next_byte() |
| 110 | if complete: |
| 111 | break |
| 112 | |
| 113 | if decoded is None: |
| 114 | tt, value = self.stack.pop() |
| 115 | print "Close", |
| 116 | else: |
| 117 | tt = decoded & __TT_MASK__ |
| 118 | value = decoded >> __TT_BITS__ |
| 119 | |
| 120 | data = None |
| 121 | if decoded is not None: |
| 122 | if tt == 2: |
| 123 | self.stack.append((tt, value)) |
| 124 | elif tt == 5: |
| 125 | data = self.ccnb_data[self.position:self.position + value] |
| 126 | self.position += value |
| 127 | |
| 128 | self.print_element(tt, value, data) |
| 129 | |