Package mobi :: Package mtld :: Package da :: Package carrier :: Module carrier_data
[hide private]
[frames] | no frames]

Source Code for Module mobi.mtld.da.carrier.carrier_data

  1  from mobi.mtld.da.carrier.byte_reader import ByteReader 
  2  from mobi.mtld.da.carrier.bucket_handler import BucketHandler 
  3  from mobi.mtld.da.carrier.bucket_type import BucketType 
  4  from mobi.mtld.da.exception.data_file_exception import DataFileException 
  5  from mobi.mtld.da.data_type import DataType 
  6   
  7  from os import path 
  8  from socket import inet_aton, error 
  9  from struct import unpack 
 10   
11 -class CarrierData(object):
12 _MAGIC_NUMBER = b'DA' 13 _FILE_ID = 1 14 _START_BYTES_LEN = 5 15 _CREATION_DATE_LEN = 24 16 _BUCKET_START_BYTES_LEN = 10 17 18 _copyright = "" 19 _creationDate = "" 20 _version = "" 21 # data for the IPv4 Radix Tree 22 _NULL_PTR = -1 23 _ROOT_PTR = 0 24 _MAX_IPV4_BIT = 0x80000000 25 _treeLefts = [] 26 _treeRights = [] 27 _treeProperties = [] 28 _property_names = None 29 _propertyStringNames = None 30 31 # error messages 32 _PROBLEM_READING_DATA_FILE = 'Problem reading data file.' 33 _INVALID_DATA_FILE = 'Invalid data file.' 34 35 _data = None 36 _cursor = 0 37 38 _propertyStringNames = None 39 _property_names = None 40
41 - def load_data_from_file(self, filePath):
42 try: 43 fsize = path.getsize(filePath) 44 _hdl = open(filePath, 'rb') 45 self._data = _hdl.read(fsize) 46 _hdl.close() 47 self._readHeader() 48 self._readBuckets() 49 except(Exception) as ex: 50 raise DataFileException(self._PROBLEM_READING_DATA_FILE)
51
52 - def _readHeader(self):
53 """ 54 The header of the file contains the following data: 55 2B DA (US-ASCII) 56 1B File type ID (1: carrier data, 2:some other data.... etc) 57 2B Header length - the total size of the header including the preceding bytes 58 2B Length of copyright text 59 ?B Copyright (US-ASCII) "(c) Copyright 2021 - DeviceAtlas Limited" 60 24B Creation date (US-ASCII) "2013-08-07T15:36:44+0000" 61 1B Version, major 62 1B Version, minor 63 4B Licence ID 64 4B CRC-32 - all data after first bucket offset 65 """ 66 headerLength = self._checkFileTypeGetHeaderLength(self._data[:self._START_BYTES_LEN]) 67 reader = ByteReader(self._data[self._START_BYTES_LEN:]) 68 self._cursor = headerLength 69 self._copyright = reader.getStringAscii(reader.getShort()) 70 if type(self._copyright) == bytes: 71 self._copyright = self._copyright.decode("utf-8") 72 self._creationDate = reader.getStringAscii(self._CREATION_DATE_LEN) 73 if type(self._creationDate) == bytes: 74 self._creationDate = self._creationDate.decode("utf-8") 75 self._version = ("%s.%s" % (str(reader.getByte()), str(reader.getByte()))) 76 if type(self._version) == bytes: 77 self._version = self._version.decode("utf-8") 78 79 licenceId = reader.getInt()
80 81
82 - def _checkFileTypeGetHeaderLength(self, startBytes):
83 """ 84 Check the first few bytes to make sure we are opening 85 a Carrier Identification file. 86 """ 87 reader = ByteReader(startBytes) 88 fileMagic = reader.getStringAscii(2) 89 fileTypeId = reader.getByte() 90 91 if fileMagic != self._MAGIC_NUMBER or fileTypeId != self._FILE_ID: 92 raise DataFileException(self._INVALID_DATA_FILE) 93 94 return reader.getShort()
95
96 - def _readBuckets(self):
97 """ 98 Each bucket is comprised of the following. The BucketHandler is 99 responsible for actually parsing the data in each bucket. This method 100 keeps reading until either the end of the file or until all necessary 101 buckets have been read. It will skip buckets with IDs it does not 102 recognise to hopefully future proof the API against possible additions to 103 the data file 104 105 Bucket structure: 106 107 2B Bucket ID 108 4B CRC-32 checksum - NOTE: unsigned int! 109 4B Length of the data 110 ?B Data 111 """ 112 bucketHandler = BucketHandler() 113 114 while(bucketHandler._needsBuckets()): 115 reader = ByteReader(self._data[self._cursor:(self._cursor + self._BUCKET_START_BYTES_LEN)]) 116 self._cursor += self._BUCKET_START_BYTES_LEN 117 bucketId = reader.getShort() 118 vcrc32 = reader.getIntUnsigned() 119 length = reader.getInt() 120 121 if BucketType.isValidId(bucketId): 122 bucketHandler.processBucket(bucketId, vcrc32, self._data[self._cursor:(self._cursor + length)]) 123 124 self._cursor += length 125 126 self._treeLefts = bucketHandler.getTreeLefts() 127 self._treeRights = bucketHandler.getTreeRights() 128 self._treeProperties = bucketHandler.getTreeProperties() 129 130 self._propertyStringNames = bucketHandler.getPropertyNamesAsStrings() 131 self._property_names = bucketHandler.getPropertyNames()
132
133 - def getProperties(self, key):
134 """ 135 Selects a value for a given IPV4 address, traversing tree 136 and choosing most specific value available for a given 137 address. 138 """ 139 try: 140 key = unpack('>L', inet_aton(key))[0] 141 except(error): 142 return None 143 144 bit = self._MAX_IPV4_BIT 145 value = None 146 node = self._ROOT_PTR 147 148 while(node != self._NULL_PTR): 149 if self._treeProperties[node] != None: 150 value = self._treeProperties[node] 151 152 if (key & bit) != 0: 153 node = self._treeRights[node] 154 else: 155 node = self._treeLefts[node] 156 bit >>= 1 157 158 return value
159
160 - def getPropertyNames(self):
161 """ 162 Return a list of all the property names 163 """ 164 return self._property_names
165
167 """ 168 Return a list of all the property names 169 """ 170 return self._propertyStringNames
171
172 - def getCopyright(self):
173 """ 174 Return the copyright 175 """ 176 return self._copyright
177
178 - def getCreationDate(self):
179 """ 180 Return the creation of date 181 """ 182 return self._creationDate
183
184 - def getVersion(self):
185 """ 186 Return the version 187 """ 188 return self._version
189