Last active
August 29, 2015 14:04
-
-
Save jxinging/997a641a778dea6f211a to your computer and use it in GitHub Desktop.
17monipdb 格式解码
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #coding: utf8 | |
| """17monipdb 解码""" | |
| import socket | |
| import struct | |
| _unpack_ulong_little = lambda x: struct.unpack("<L", x) | |
| _unpack_ulong_big = lambda x: struct.unpack(">L", x) | |
| class IPDB(object): | |
| def __init__(self, datafn=None): | |
| if not datafn: | |
| datafn = "17monipdb.dat" | |
| self._datafn = datafn | |
| self._datafile = None | |
| self._index_end = None | |
| self._index = None | |
| self._cache = dict() | |
| def _do_init(self): | |
| if self._datafile is not None: | |
| return | |
| self._datafile = open(self._datafn, 'rb') | |
| # 头4字节保存着索引数据的结束位置 | |
| self._index_end = _unpack_ulong_big(self._datafile.read(4))[0] | |
| index_len = self._index_end - self._datafile.tell() # 索引数值的实际长度 | |
| self._index = self._datafile.read(index_len) | |
| def find(self, host): | |
| ip_str = socket.gethostbyname(host) | |
| ip_int = socket.inet_aton(ip_str) | |
| if self._datafile is None: | |
| self._do_init() | |
| if ip_int in self._cache: | |
| return self._cache[ip_int] | |
| # 通过IP地址第一段找到一级索引的位置。一个索引数据占4字节,所以要乘以4 | |
| this_index1_pos = int(ip_str.split(".")[0]) * 4 | |
| index2_offset = 1024 # index2 在 index 里的偏移 | |
| index2_len = len(self._index) - index2_offset | |
| # 通过一级索引找到2级索引的位置 | |
| this_index2_num = _unpack_ulong_little(self._index[this_index1_pos:this_index1_pos+4])[0] | |
| # 二级索引一个索引数值占8字节 | |
| this_index2_start = this_index2_num * 8 | |
| curr_pos = this_index2_start | |
| this_index2_pos = None | |
| while curr_pos < index2_len: | |
| abs_index_pos = curr_pos + index2_offset | |
| if self._index[abs_index_pos:abs_index_pos+4] >= ip_int: | |
| this_index2_pos = abs_index_pos+4 | |
| break | |
| curr_pos += 8 | |
| else: | |
| return None | |
| data_pos = _unpack_ulong_little(self._index[this_index2_pos:this_index2_pos+3]+"\x00")[0] | |
| data_len = ord(self._index[this_index2_pos+3]) | |
| self._datafile.seek(self._index_end+data_pos-1024) | |
| self._cache[ip_int] = self._datafile.read(data_len).decode("utf8") | |
| return self._cache[ip_int] | |
| ipdb = IPDB() | |
| find = ipdb.find | |
| if __name__ == "__main__": | |
| print find("tool.17mon.cn") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment