class LibWwqParseCFFI(LibWwqLyParseBase): def __init__(self): super(LibWwqParseCFFI, self).__init__() from cffi import FFI self.ffi = FFI() self.lib = self.ffi.dlopen(self.lib_path) self.ffi.cdef(""" char * get_uuid(); char * get_name(); int parse(char * c,int length,char **result,int *result_length); int free_str(char * c); """) self.lib.__class__.__repr__ = lambda s: "<%s object at 0x%016X>" % (s.__class__.__name__, id(s)) logging.debug("successful load lib %s" % self.lib) weakref.finalize(self, lambda: logging.debug("%s released" % self.lib) if self.ffi.dlclose(self.lib) or 1 else None) def get_uuid(self) -> bytes: return self.ffi.string(self.lib.get_uuid()) def get_name(self) -> bytes: return self.ffi.string(self.lib.get_name()) def lib_parse(self, byte_str: bytes) -> bytes: length = self.ffi.cast("int", len(byte_str)) result_length = self.ffi.new("int *") result_p = self.ffi.new("char **") # p = self.ffi.new("char []", byte_str) p = self.ffi.from_buffer(byte_str) self.lib.parse(p, length, result_p, result_length) result = self.ffi.unpack(result_p[0], result_length[0]) self.lib.free_str(result_p[0]) return result
class PythonLib: def load(self, filterpath): self.ffi = FFI() self.ffi.cdef(""" void *pythonGetData(const char *); const char *pythonGetType(const char *); const char *pythonGetCast(const char *); const char *pythonGetDims(const char *); """) self.filterlib = self.ffi.dlopen(filterpath) def getData(self, name): name = self.ffi.new("char[]", name.encode("utf-8")) cast = self.filterlib.pythonGetCast(name) data = self.filterlib.pythonGetData(name) ctype = self.ffi.string(cast).decode("utf-8") return self.ffi.cast(ctype, data) def getType(self, name): name = self.ffi.new("char[]", name.encode("utf-8")) return self.ffi.string(self.filterlib.pythonGetType(name)) def getDims(self, name): name = self.ffi.new("char[]", name.encode("utf-8")) dims = self.filterlib.pythonGetDims(name) dims = self.ffi.string(dims).decode("utf-8") return tuple([int(dim) for dim in dims.split("x")])
def test_char16_t(self): ffi = FFI() x = ffi.new("char16_t[]", 5) assert len(x) == 5 and ffi.sizeof(x) == 10 x[2] = u + '\u1324' assert x[2] == u + '\u1324' y = ffi.new("char16_t[]", u + '\u1234\u5678') assert len(y) == 3 assert list(y) == [u + '\u1234', u + '\u5678', u + '\x00'] assert ffi.string(y) == u + '\u1234\u5678' z = ffi.new("char16_t[]", u + '\U00012345') assert len(z) == 3 assert list(z) == [u + '\ud808', u + '\udf45', u + '\x00'] assert ffi.string(z) == u + '\U00012345'
def test_char16_t(self): ffi = FFI() x = ffi.new("char16_t[]", 5) assert len(x) == 5 and ffi.sizeof(x) == 10 x[2] = u+'\u1324' assert x[2] == u+'\u1324' y = ffi.new("char16_t[]", u+'\u1234\u5678') assert len(y) == 3 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00'] assert ffi.string(y) == u+'\u1234\u5678' z = ffi.new("char16_t[]", u+'\U00012345') assert len(z) == 3 assert list(z) == [u+'\ud808', u+'\udf45', u+'\x00'] assert ffi.string(z) == u+'\U00012345'
def test_variable_of_unknown_size(): ffi = FFI() ffi.cdef(""" typedef ... opaque_t; opaque_t globvar; """) lib = verify( ffi, 'test_constant_of_unknown_size', """ typedef char opaque_t[6]; opaque_t globvar = "hello"; """) # can't read or write it at all e = py.test.raises(TypeError, getattr, lib, 'globvar') assert str(e.value) in [ "cdata 'opaque_t' is opaque", "'opaque_t' is opaque or not completed yet" ] #pypy e = py.test.raises(TypeError, setattr, lib, 'globvar', []) assert str(e.value) in [ "'opaque_t' is opaque", "'opaque_t' is opaque or not completed yet" ] #pypy # but we can get its address p = ffi.addressof(lib, 'globvar') assert ffi.typeof(p) == ffi.typeof('opaque_t *') assert ffi.string(ffi.cast("char *", p), 8) == b"hello"
def load_ffi_interface(): ''' Load and return the FFI library instance, and DLL interface to the avmu DLL. return value is a 2-tuple (ffi_lib, dll_handle) ''' # We have to use globals or some sort of persistent state here, because if # we load the DLL twice, it'll create two typedef classes for all the DLL objects, # which will then fail to interoperate. global STATIC_FFI global STATIC_LIB if STATIC_FFI is not None and STATIC_LIB is not None: return STATIC_FFI, STATIC_LIB dll_path = find_dll() from . import load_header from cffi import FFI ffi = FFI() headers = load_header.load() ffi.cdef(headers) lib = ffi.dlopen(dll_path) print("Loaded library version: ", ffi.string(lib.versionString()).decode("utf-8")) STATIC_FFI = ffi STATIC_LIB = lib return ffi, lib
class QmixError(object): """ Qmix SDK error messages. """ def __init__(self, error_number): dll_dir = config.read_config().get('qmix_dll_dir', None) dll_filename = 'usl.dll' dll_path = find_dll(dll_dir=dll_dir, dll_filename=dll_filename) if dll_path is None: msg = 'Could not find the Qmix SDK DLL %s.' % dll_filename raise RuntimeError(msg) else: self.dll_path = dll_path self._ffi = FFI() self._ffi.cdef(ERROR_HEADER) self._dll = self._ffi.dlopen(self.dll_path) self.error_number = error_number self._error_code = self._ffi.new('TErrCode *') @property def error_code(self): self._error_code = hex(abs(self.error_number)) return self._error_code @property def error_string(self): e = self.error_code s = self._dll.ErrorToString(int(e, 16)) return self._ffi.string(s).decode('utf8')
def test_strchr(self): ffi = FFI(backend=self.Backend()) ffi.cdef(""" char *strchr(const char *s, int c); """) ffi.C = ffi.dlopen(None) p = ffi.new("char[]", b"hello world!") q = ffi.C.strchr(p, ord('w')) assert ffi.string(q) == b"world!"
class BGPDump: def __init__(self, filename): self.filename = str(filename) if isinstance(filename, unicode) else filename self.ffi = None self.libc = None self.libbgpdump = None self.handle = None def __enter__(self): self.ffi = FFI() libdir = resource_filename('bgpdumpy', 'lib') or '' self.libc = self.ffi.dlopen(None) self.libbgpdump = self.ffi.dlopen(os.path.join(libdir, 'libbgpdump.so')) self.ffi.cdef(CTypes) self.handle = self.libbgpdump.bgpdump_open_dump(self.filename) return self def __exit__(self, exc_type, exc_val, exc_tb): self.libbgpdump.bgpdump_close_dump(self.handle) del self.libbgpdump self.libbgpdump = None del self.libc self.libc = None del self.ffi self.ffi = None def __iter__(self): while True: if self.handle.eof == 1: break currentEntry = self.libbgpdump.bgpdump_read_next(self.handle) if currentEntry == self.ffi.NULL: continue # sometimes we get NULL back for no apparent reason try: yield BGPEntry(self, currentEntry) finally: self.libbgpdump.bgpdump_free_mem(currentEntry) @property def version(self): return self.ffi.string(self.libbgpdump.bgpdump_version())
class BGPDump: def __init__(self, filename): self.filename = str(filename) if isinstance( filename, unicode ) else filename self.ffi = None self.libc = None self.libbgpdump = None self.handle = None def __enter__(self): self.ffi = FFI() libdir = resource_filename( 'bgpdumpy', 'lib' ) or '' self.libc = self.ffi.dlopen(None) self.libbgpdump = self.ffi.dlopen( os.path.join( libdir, 'libbgpdump.so' ) ) self.ffi.cdef(CTypes) self.handle = self.libbgpdump.bgpdump_open_dump(self.filename) return self def __exit__(self, exc_type, exc_val, exc_tb): self.libbgpdump.bgpdump_close_dump(self.handle) del self.libbgpdump self.libbgpdump = None del self.libc self.libc = None del self.ffi self.ffi = None def __iter__(self): while True: if self.handle.eof == 1: break currentEntry = self.libbgpdump.bgpdump_read_next(self.handle) if currentEntry == self.ffi.NULL: continue # sometimes we get NULL back for no apparent reason try: yield BGPEntry(self, currentEntry) finally: self.libbgpdump.bgpdump_free_mem(currentEntry) @property def version(self): return self.ffi.string(self.libbgpdump.bgpdump_version())
class KaldiGmmDecoder(KaldiDecoderBase): """docstring for KaldiGmmDecoder""" def __init__(self, graph_dir=None, words_file=None, graph_file=None, model_conf_file=None): super(KaldiGmmDecoder, self).__init__() self._ffi = FFI() self._ffi.cdef(""" void* init_gmm(float beam, int32_t max_active, int32_t min_active, float lattice_beam, char* word_syms_filename_cp, char* fst_in_str_cp, char* config_cp); bool decode_gmm(void* model_vp, float samp_freq, int32_t num_frames, float* frames, bool finalize); bool get_output_gmm(void* model_vp, char* output, int32_t output_length, double* likelihood_p); """) self._lib = self._ffi.dlopen(self._library_binary) if words_file is None and graph_dir is not None: words_file = graph_dir + r"graph\words.txt" if graph_file is None and graph_dir is not None: graph_file = graph_dir + r"graph\HCLG.fst" self.words_file = os.path.normpath(words_file) self.graph_file = os.path.normpath(graph_file) self.model_conf_file = os.path.normpath(model_conf_file) self._model = self._lib.init_gmm(7.0, 7000, 200, 8.0, words_file, graph_file, model_conf_file) self.sample_rate = 16000 def decode(self, frames, finalize, grammars_activity=None): if not isinstance(frames, np.ndarray): frames = np.frombuffer(frames, np.int16) frames = frames.astype(np.float32) frames_char = self._ffi.from_buffer(frames) frames_float = self._ffi.cast('float *', frames_char) self._start_decode_time(len(frames)) result = self._lib.decode_gmm(self._model, self.sample_rate, len(frames), frames_float, finalize) self._stop_decode_time(finalize) if not result: raise RuntimeError("decoding error") return finalize def get_output(self, output_max_length=4 * 1024): output_p = self._ffi.new('char[]', output_max_length) likelihood_p = self._ffi.new('double *') result = self._lib.get_output_gmm(self._model, output_p, output_max_length, likelihood_p) output_str = self._ffi.string(output_p) likelihood = likelihood_p[0] return output_str, likelihood
def test_cffi_asprintf(): from cffi import FFI ffi = FFI() ffi.cdef( """int asprintf(char** buf, const char *format, ...); // copy-pasted from the man page""" ) C = ffi.dlopen(None) # loads the entire C namespace buf = ffi.new("char**") arg1 = ffi.new("char[]", b"wo") arg2 = ffi.new("char[]", b"ld") C.asprintf(buf, b"hello %sr%s", arg1, arg2) assert ffi.string(buf[0]).decode() == "hello world"
class RangeLib: def __init__(self, config_file): self.ffi = FFI() self.ffi.cdef(""" typedef void easy_lr ; // avoid exposing the struct internals, fake it as void easy_lr* range_easy_create(const char* config_file); const char ** range_easy_expand(easy_lr* elr, const char * c_range); const char * range_easy_eval(easy_lr* elr, const char * c_range); char * range_easy_compress(easy_lr* elr, const char ** c_nodes); int range_easy_destroy(easy_lr* elr); """) self.rangelib_ffi = self.ffi.dlopen("libcrange.so") self.elr = self.rangelib_ffi.range_easy_create(self.ffi.new("char[]", config_file)) def __charpp_to_native(self, arg): i = 0 arr = [] while arg[i] != self.ffi.NULL: arr.append(self.ffi.string(arg[i])) i = i + 1 return arr def expand(self, c_range): ret = self.rangelib_ffi.range_easy_expand(self.elr, self.ffi.new("char[]", c_range)) return self.__charpp_to_native(ret) def compress(self, nodes): char_arg = map(lambda x: self.ffi.new("char[]", x), nodes) char_arg.append(self.ffi.NULL) ret = self.rangelib_ffi.range_easy_compress(self.elr, self.ffi.new("char*[]", char_arg)) return self.ffi.string(ret) def eval(self, c_range): ret = self.rangelib_ffi.range_easy_eval(self.elr, self.ffi.new("char[]", c_range)) return self.ffi.string(ret) def __del__(self): self.rangelib_ffi.range_easy_destroy(self.elr)
def c_string_as_py_string(ffi: FFI, ptr: CffiData) -> str: """Convert if possible a cffi pointer to an ANSI C string <char*> to a python string. Args: ffi (FFI): FFI instance wrapping the native compilation module owning the native memory ptr (CffiData): cffi pointer (FFI.CData) Raises: RuntimeError: conversion is not supported Returns: str: converted string """ return as_string(ffi.string(ptr))
def test_function_with_struct_argument(self): if sys.platform == 'win32': py.test.skip("no 'inet_ntoa'") if (self.Backend is CTypesBackend and '__pypy__' in sys.builtin_module_names): py.test.skip("ctypes limitation on pypy") ffi = FFI(backend=self.Backend()) ffi.cdef(""" struct in_addr { unsigned int s_addr; }; char *inet_ntoa(struct in_addr in); """) ffi.C = ffi.dlopen(None) ina = ffi.new("struct in_addr *", [0x04040404]) a = ffi.C.inet_ntoa(ina[0]) assert ffi.string(a) == b'4.4.4.4'
def test_char32_t(self): ffi = FFI() x = ffi.new("char32_t[]", 5) assert len(x) == 5 and ffi.sizeof(x) == 20 x[3] = u+'\U00013245' assert x[3] == u+'\U00013245' y = ffi.new("char32_t[]", u+'\u1234\u5678') assert len(y) == 3 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00'] py_uni = u+'\U00012345' z = ffi.new("char32_t[]", py_uni) assert len(z) == 2 assert list(z) == [py_uni, u+'\x00'] # maybe a 2-unichars string assert ffi.string(z) == py_uni if len(py_uni) == 1: # 4-bytes unicodes in Python s = ffi.new("char32_t[]", u+'\ud808\udf00') assert len(s) == 3 assert list(s) == [u+'\ud808', u+'\udf00', u+'\x00']
def test_char32_t(self): ffi = FFI() x = ffi.new("char32_t[]", 5) assert len(x) == 5 and ffi.sizeof(x) == 20 x[3] = u + '\U00013245' assert x[3] == u + '\U00013245' y = ffi.new("char32_t[]", u + '\u1234\u5678') assert len(y) == 3 assert list(y) == [u + '\u1234', u + '\u5678', u + '\x00'] py_uni = u + '\U00012345' z = ffi.new("char32_t[]", py_uni) assert len(z) == 2 assert list(z) == [py_uni, u + '\x00'] # maybe a 2-unichars string assert ffi.string(z) == py_uni if len(py_uni) == 1: # 4-bytes unicodes in Python s = ffi.new("char32_t[]", u + '\ud808\udf00') assert len(s) == 3 assert list(s) == [u + '\ud808', u + '\udf00', u + '\x00']
def symbols(headers): ffi = FFI() ffi.cdef(headers) nanomsg = ffi.dlopen("nanomsg") lines = [] for i in range(1024): val = ffi.new("int*") name = nanomsg.nn_symbol(i, val) if name == ffi.NULL: break name = ffi.string(name).decode() name = name[3:] if name.startswith("NN_") else name lines.append("%s = %s" % (name, val[0])) return "\n".join(lines) + "\n"
def symbols(headers): ffi = FFI() ffi.cdef(headers) nanomsg = ffi.dlopen('nanomsg') lines = [] for i in range(1024): val = ffi.new('int*') name = nanomsg.nn_symbol(i, val) if name == ffi.NULL: break name = ffi.string(name).decode() name = name[3:] if name.startswith('NN_') else name lines.append('%s = %s' % (name, val[0])) return '\n'.join(lines) + '\n'
def c_charptrptr_as_string_list(ffi: FFI, ptr: CffiData, size: int) -> List[str]: """Convert if possible a cffi pointer to a C data array char** , into a list of python strings. Args: ffi (FFI): FFI instance wrapping the native compilation module owning the native memory ptr (CffiData): cffi pointer (FFI.CData) size (int): number of character strings in the char** pointer Raises: RuntimeError: conversion is not supported Returns: List[str]: converted data """ # TODO check type strings = ffi.cast('char*[%d]' % (size, ), ptr) res = [as_string(ffi.string(strings[i])) for i in range(size)] return res
def test_variable_of_unknown_size(): ffi = FFI() ffi.cdef(""" typedef ... opaque_t; opaque_t globvar; """) lib = verify(ffi, 'test_variable_of_unknown_size', """ typedef char opaque_t[6]; opaque_t globvar = "hello"; """) # can't read or write it at all e = py.test.raises(TypeError, getattr, lib, 'globvar') assert str(e.value) in ["cdata 'opaque_t' is opaque", "'opaque_t' is opaque or not completed yet"] #pypy e = py.test.raises(TypeError, setattr, lib, 'globvar', []) assert str(e.value) in ["'opaque_t' is opaque", "'opaque_t' is opaque or not completed yet"] #pypy # but we can get its address p = ffi.addressof(lib, 'globvar') assert ffi.typeof(p) == ffi.typeof('opaque_t *') assert ffi.string(ffi.cast("char *", p), 8) == b"hello"
rc = ngspice_shared.ngSpice_Command('bg_run') print 'ngSpice_Command returned', rc time.sleep(.1) # required before to test if the simulation is running while (ngspice_shared.ngSpice_running()): time.sleep(.1) print "Simulation is done" all_plots = ngspice_shared.ngSpice_AllPlots() i = 0 while (True): if all_plots[i] == ffi.NULL: break else: print ffi.string(all_plots[i]) i += 1 plot_name = 'tran1' all_vectors = ngspice_shared.ngSpice_AllVecs(plot_name) i = 0 while (True): if all_vectors[i] == ffi.NULL: break else: vector_name = ffi.string(all_vectors[i]) vector_info = ngspice_shared.ngGet_Vec_Info('.'.join((plot_name, vector_name))) length = vector_info.v_length print "vector[{}] {} type {} flags {} length {}".format(i, vector_name, vector_info.v_type,
class DTrace: ## /usr/src/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h DTRACE_PROBESPEC_NONE = -1 DTRACE_PROBESPEC_PROVIDER = 0 DTRACE_PROBESPEC_MOD = 1 DTRACE_PROBESPEC_FUNC = 2 DTRACE_PROBESPEC_NAME = 3 def __init__(self): self._DTRACE_VERSION = 3 self._ffi = FFI() self._C = self._ffi.dlopen(None) # print "X"*10, self._C.stdout self._dtrace = get_dtrace(self._ffi) self._dtp = None self._fd = None def get_error(self): if self._dtp: err_no = self._dtrace.dtrace_errno(self._dtp) err_msg_c = self._dtrace.dtrace_errmsg(self._dtp, err_no) err_msg = self._ffi.string(err_msg_c).decode("utf8") return err_no, err_msg else: return 0, None def open(self): error = self._ffi.new("int*") self._dtp = self._dtrace.dtrace_open(self._DTRACE_VERSION, 0, error) if self._dtp == self._ffi.NULL: err_msg_c = self._dtrace.dtrace_errmsg(self._dtp, error) err_msg = self._ffi.string(err_msg_c).decode("utf8") raise Exception(err_msg) def set_option(self, key, value): if self._dtp: res = self._dtrace.dtrace_setopt(self._dtp, key.encode("utf8"), value.encode("utf8")) if res == -1: err_no, err_msg = self.get_error() raise Exception("could not set DTrace option '{}' to '{}' - {}".format(key, value, err_msg)) def compile(self, program): prog = self._dtrace.dtrace_program_strcompile( self._dtp, program.encode("utf8"), self._dtrace.DTRACE_PROBESPEC_NAME, 0, 0, self._ffi.NULL ) if prog == self._ffi.NULL: err_no, err_msg = self.get_error() raise Exception("could not compile D program - {}".format(err_msg)) return DTraceProgram(self, prog) def go(self, fd=None): if self._dtp: fd = fd or sys.stdout self._fd = self._ffi.cast("FILE*", fd) self._chew = self._ffi.callback( "int (const dtrace_probedata_t*, const dtrace_recdesc_t*, void*)", self.chew ) res = self._dtrace.dtrace_go(self._dtp) if res != 0: err_no, err_msg = self.get_error() raise Exception("could not start instrumentation: {}".format(e)) else: print ("instrumentation started") def work(self): if self._dtp: res = self._dtrace.dtrace_work(self._dtp, self._fd, self._ffi.NULL, self._chew, self._ffi.NULL) print ("work result: {}".format(res)) def sleep(self): if self._dtp: res = self._dtrace.dtrace_sleep(self._dtp) print ("woke up") def stop(self): if self._dtp: res = self._dtrace.dtrace_stop(self._dtp) if res == -1: err_no, err_msg = self.get_error() raise Exception("could not stop instrumentation: {}".format(err_msg)) else: print ("instrumentation stopped") def close(self): if self._dtp: self._dtrace.dtrace_close(self._dtp) self._dtp = None def chew(self, data, rec, arg): print ("chew!", data, rec, arg) # A NULL rec indicates that we've processed the last record. if rec == self._ffi.NULL: return self._dtrace.DTRACE_CONSUME_NEXT return self._dtrace.DTRACE_CONSUME_THIS
class NFLOG(object): _instance = None def __new__(cls): if not cls._instance: cls._instance = super(NFLOG, cls).__new__(cls) return cls._instance def __init__(self): global _cdef, _clibs_includes, _clibs_link self.ffi = FFI() self.ffi.cdef(_cdef) self.libnflog = self.ffi.verify(_clibs_includes, libraries=list(_clibs_link)) self.libnflog_cache = dict() _cdef = _clibs_includes = _clibs_link = None def _ffi_call( self, func, args, no_check=False, check_gt0=False, check_notnull=False ): '''Call libnflog function through cffi, checking return value and raising error, if necessary. Checks if return is >0 by default.''' res = func(*args) if no_check\ or (check_gt0 and res > 0)\ or (check_notnull and res)\ or res >= 0: return res errno_ = self.ffi.errno raise NFLogError(errno_, os.strerror(errno_)) def __getattr__(self, k): if not (k.startswith('nflog_') or k.startswith('c_')): return super(NFLOG, self).__getattr__(k) if k.startswith('c_'): k = k[2:] if k not in self.libnflog_cache: func = getattr(self.libnflog, k) self.libnflog_cache[k] = lambda *a,**kw: self._ffi_call(func, a, **kw) return self.libnflog_cache[k] def generator( self, qids, pf=(socket.AF_INET, socket.AF_INET6), qthresh=None, timeout=None, nlbufsiz=None, buff_size=None, extra_attrs=None, handle_overflows=True ): '''Generator that yields: - on first iteration - netlink fd that can be poll'ed or integrated into some event loop (twisted, gevent, ...). Also, that is the point where uid/gid/caps can be dropped. - on all subsequent iterations it does recv() on that fd, returning either None (if no packet can be assembled yet) or captured packet payload. qids: nflog group ids to bind to (nflog_bind_group) Keywords: pf: address families to pass to nflog_bind_pf extra_attrs: metadata to extract from captured packets, returned in a list after packet payload, in the same order nlbufsiz (bytes): set size of netlink socket buffer for the created queues qthresh (packets): set the maximum amount of logs in buffer for each group timeout (seconds): set the maximum time to push log buffer for this group buff_size (bytes): size of the batch to fetch from libnflog to process in python (default: min(nlbufsiz, 1 MiB)) handle_overflows: supress ENOBUFS NFLogError on queue overflows (but do log warnings, default: True)''' handle = self.nflog_open(check_notnull=True) for pf in (pf if not isinstance(pf, int) else [pf]): self.nflog_unbind_pf(handle, pf) self.nflog_bind_pf(handle, pf) if isinstance(extra_attrs, bytes): extra_attrs = [extra_attrs] cb_results = list() @self.ffi.callback('nflog_callback') def recv_callback( qh, nfmsg, nfad, data, extra_attrs=extra_attrs, ts_slot=self.ffi.new('struct timeval *'), pkt_slot=self.ffi.new('char **'), ts_err_mask=frozenset([0, errno.EAGAIN]), result=None ): try: pkt_len = self.nflog_get_payload(nfad, pkt_slot) result = self.ffi.buffer(pkt_slot[0], pkt_len)[:] if extra_attrs: result = [result] for attr in extra_attrs: if attr == 'len': result.append(pkt_len) elif attr == 'ts': # Fails quite often (EAGAIN, SUCCESS, ...), not sure why try: self.nflog_get_timestamp(nfad, ts_slot) except NFLogError as err: if err.errno not in ts_err_mask: raise result.append(None) else: result.append(ts_slot.tv_sec + ts_slot.tv_usec * 1e-6) elif attr == 'prefix': result.append(self.ffi.string(self.nflog_get_prefix(nfad)) or None) else: raise NotImplementedError('Unknown nflog attribute: {}'.format(attr)) cb_results.append(result) except: cb_results.append(StopIteration) # breaks the generator raise return 0 for qid in (qids if not isinstance(qids, int) else [qids]): qh = self.nflog_bind_group(handle, qid, check_notnull=True) self.nflog_set_mode(qh, self.libnflog.NFULNL_COPY_PACKET, 0xffff) if qthresh: self.nflog_set_qthresh(qh, qthresh) if timeout: self.nflog_set_timeout(qh, int(timeout * 100)) if nlbufsiz: self.nflog_set_nlbufsiz(qh, nlbufsiz) self.nflog_callback_register(qh, recv_callback, self.ffi.NULL) fd = self.nflog_fd(handle) if not buff_size: if nlbufsiz: buff_size = min(nlbufsiz, 1*2**20) else: buff_size = 1*2**20 buff = self.ffi.new('char[]', buff_size) peek = yield fd # yield fd for poll() on first iteration while True: if peek: peek = yield NFWouldBlock # poll/recv is required continue # Receive/process netlink data, which may contain multiple packets try: nlpkt_size = self.c_recv(fd, buff, buff_size, 0) except NFLogError as err: if handle_overflows and err.errno == errno.ENOBUFS: log.warn( 'nlbufsiz seem' ' to be insufficient to hold unprocessed packets,' ' consider raising it via corresponding function keyword' ) continue raise self.nflog_handle_packet(handle, buff, nlpkt_size, no_check=True) # yield individual L3 packets for result in cb_results: if result is StopIteration: raise result peek = yield result cb_results = list()
class LibWwqParseCFFI(LibWwqLyParseBase): def __init__(self): super(LibWwqParseCFFI, self).__init__() from cffi import FFI self.ffi = FFI() self.lib = self.ffi.dlopen(self.lib_path) self.ffi.cdef(""" char * get_uuid(); char * get_name(); int parse(char * c,int length,char **result,int *result_length); int free_str(char * c); void* atomic_int64_init(); int atomic_int64_destroy(void* ptr); int64_t atomic_int64_get(void* ptr); int64_t atomic_int64_set(void* ptr, int64_t val); int64_t atomic_int64_add(void* ptr, int64_t val); int64_t atomic_int64_sub(void* ptr, int64_t val); int64_t atomic_int64_and(void* ptr, int64_t val); int64_t atomic_int64_or(void* ptr, int64_t val); int64_t atomic_int64_xor(void* ptr, int64_t val); typedef union epoll_data { void* ptr; int fd; uint32_t u32; uint64_t u64; uintptr_t sock; /* Windows specific */ void* hnd; /* Windows specific */ } epoll_data_t; typedef struct { uint32_t events; /* Epoll events and flags */ epoll_data_t data; /* User data variable */ } epoll_event ; void* epoll_create(int size); void* epoll_create1(int flags); int epoll_close(void* ephnd); int epoll_ctl(void* ephnd, int op, uintptr_t sock, epoll_event* event); int epoll_wait(void* ephnd, epoll_event* events, int maxevents, int timeout); """) self.lib.__class__.__repr__ = lambda s: "<%s object at 0x%016X>" % (s.__class__.__name__, id(s)) logging.debug("successful load lib %s" % self.lib) weakref.finalize(self, lambda: logging.debug("%s released" % self.lib) if self.ffi.dlclose(self.lib) or 1 else None) def get_uuid(self) -> bytes: return self.ffi.string(self.lib.get_uuid()) def get_name(self) -> bytes: return self.ffi.string(self.lib.get_name()) def lib_parse(self, byte_str: bytes) -> bytes: length = self.ffi.cast("int", len(byte_str)) result_length = self.ffi.new("int *") result_p = self.ffi.new("char **") # p = self.ffi.new("char []", byte_str) p = self.ffi.from_buffer(byte_str) self.lib.parse(p, length, result_p, result_length) result = self.ffi.unpack(result_p[0], result_length[0]) self.lib.free_str(result_p[0]) return result
def test_shm(): shmstep0() shmstep1() shmstep2() def setup_function(function): print("setting up %s" % function) if __name__ == "__main__": global shm import sys shmstep0() print shm.fd, shm.size, ffi.string(shm.name) c = sys.stdin.readline() print "readlins is return", c if c[:4] == "open": print "into openex test process 2" shmstep1x() print "copy 7 bytes " caddr = ffi.cast("void*", shm.addr) C.memcpy(caddr, "welcome", 7) sys.stdin.readline() print "copy %d bytes" % (4096 * 2 + 1) C.memcpy(caddr, "welcome" * 2000, 4096 * 2 + 1) sys.stdin.readline() shmstep2() elif c[:5] == "close": pass
from cffi import FFI ffi = FFI() ffi.cdef(""" // some declarations from the man page struct passwd { char *pw_shell; ...; }; struct passwd *getpwuid(int uid); """) C = ffi.verify(""" // passed to the real C compiler #include <sys/types.h> #include <pwd.h> """, libraries=[]) # or a list of libraries to link with p = C.getpwuid(0) print ffi.string(p.pw_shell)
class Sunlink: ''' Wraper for sunlink c lib ''' def __init__(self, header="include/sunlink.h"): self.ffi = FFI() self.ffi.cdef(self.headerFromFile(header)) self.sunlink = self.ffi.dlopen("lib/libsunlink.so") def headerFromFile(self, file): header = None with open(file) as conf: header = conf.read() return header def cli_sndrcv(self, nodeid, head, reqdata, reqfiles, timeout=60): ret, arg_ip, arg_port = self.getaddr(nodeid) if ret != 0: sys.exit("Can't get address(ip, port)") arg_head = self.ffi.new("TAPIHEAD *", head) arg_reqdata = self.ffi.new("char [1024]", reqdata) arg_reqfiles = self.ffi.new("char [1024]", reqfiles) arg_ansdta = self.ffi.new("char [1024]") arg_resfiles = self.ffi.new("char [1024]") ret = self.sunlink.cli_sndrcv(arg_ip, arg_port[0], arg_head, arg_reqdata, arg_reqfiles, arg_ansdta, arg_resfiles, timeout) if ret != 0: sys.exit("Send data fail.") return tuple(map(self.ffi.string, (arg_ansdta, arg_resfiles))) def svr_snd(self, head, ansdata, resfiles, timeout=60): ret = 0 arg_head = self.ffi.new("TAPIHEAD *", head) arg_ansdta = self.ffi.new("char [1024]", ansdata) arg_resfiles = self.ffi.new("char [1024]", resfiles) ret = self.sunlink.svr_snd(arg_head, arg_ansdta, arg_resfiles, timeout) return ret def svr_rcv(self, timeout=60): ret = 0 arg_head = self.ffi.new("TAPIHEAD *") arg_reqdata = self.ffi.new("char [1024]") arg_reqfiles = self.ffi.new("char [1024]") ret = self.sunlink.svr_rcv(arg_head, arg_reqdata, arg_reqfiles, timeout) return (ret, self.ffi.string(arg_reqdata), self.ffi.string(arg_reqfiles)) def svrend(self): ret = self.sunlink.tapi_svrend() return ret def getaddr(self, nodeid): ret = 0 arg_svrname = self.ffi.new("char [16]", nodeid) arg_ip = self.ffi.new("char [16]") arg_port = self.ffi.new("int *") ret = self.sunlink.tapi_getaddr(arg_svrname, arg_ip, arg_port) return (ret, arg_ip, arg_port[0])
def record(): global disable_native_grab signal.signal(signal.SIGINT, exit_gracefully) signal.signal(signal.SIGTERM, exit_gracefully) time.sleep(5) state = State.WAITING recordPath = '.' if (disable_native_grab == False): ffi = FFI() mscLib = ffi.dlopen('msc_x64.dll') ffi.cdef(''' int init(); void close(); int get_capture_width(); int get_capture_height(); int get_bytes_per_pixel(); int capture_frame(uint8_t* buffer); const char* get_last_error(); ''') ret = mscLib.init() print(ret) print(ffi.string(mscLib.get_last_error())) else: sct = mss() # if not os.path.exists(os.path.dirname(recordPath)): # try: # os.makedirs(os.path.dirname(recordPath)) # except OSError as exc: # Guard against race condition # if exc.errno != errno.EEXIST: # print('Recording name already exists. Please use another one') # raise # else: # print('Recording name already exists. Please use another one') # exit(1) try: counter = 0 id = 0 prevSec = datetime.now().time().second while True: # Excplicit update call because I'm lazy telemetry.update() speed = telemetry.get_telemetry_value('m_speed') * 3.6 laptime = telemetry.get_telemetry_value('m_lapTime') g_lat = telemetry.get_telemetry_value('m_gforce_lat') g_lon = telemetry.get_telemetry_value('m_gforce_lon') if (laptime > 0 and state == State.WAITING): print('Driving started') counter = 0 state = State.DRIVING recordPath = get_record_path() try: os.makedirs(os.path.dirname(recordPath)) except OSError as exc: # Guard against race condition if exc.errno != errno.EEXIST: print('Recording name already exists. Please use another one') raise with open(recordPath + 'meta.json', 'w') as f: f.write( '{"inputs":[' '"cam/image_array",' '"telemetry/speed",' '"user/throttle",' '"user/angle",' '"user/brake",' '"user/mode"],' '"types":[' '"image_array",' '"float",' '"float",' '"float",' '"float",' '"str"]}') # print(laptime) elif (laptime == 0 and state != State.WAITING): print('New lap starting') state = State.WAITING elif (state == State.WAITING): print('Waiting for start') if (g_lat > 6 or g_lon > 6): # state = State.CRASHED print('Crashed', g_lon, g_lat) if (state == State.DRIVING): # print(speed, g_lon, g_lat) captureJoystick(counter, recordPath, speed) if (disable_native_grab): capture_screen_py(sct, counter, recordPath) else: capture_screen(ffi, mscLib, counter, recordPath) id = id + 1 counter = counter + 1 currSec = datetime.now().time().second if currSec is not prevSec: print('Change', id, 'fps') id = 0 prevSec = currSec # sleep(0.1) except Exception as e: print('\a') time.sleep(1) print('\a') time.sleep(1) print('\a') quit()
from cffi import FFI ffi = FFI() ffi.cdef(""" // some declarations from the man page struct passwd { char *pw_name; ...; }; struct passwd *getpwuid(int uid); double addch(double x, double y); """) C = ffi.verify(""" // passed to the real C compiler #include <sys/types.h> #include <pwd.h> double addch(double x, double y) { return x + 10.0 * y; } """, libraries=[]) # or a list of libraries to link with p = C.getpwuid(0) print 'hello1' assert ffi.string(p.pw_name) == 'root' # on Python 3: b'root' print 'hello2' print C.addch(1.0,2.0)
def invoke(func, *args): retcode = func(*args) if retcode != 0: ret = lib.SpcGetErrMsg(retcode) print ret raise invoke(lib.SpcInitEnvEx) invoke(lib.SpcVerifyPIN,ffi.new("char[]","88888888"),8) userName = ffi.new("char[250]") lenUserName = ffi.new("unsigned int*") lenUserName[0] = 250 invoke(lib.SpcGetCardUserInfo,userName, lenUserName) print "Actual len:",len(userName)," ret len: ",lenUserName[0] print ffi.string(userName) cert = ffi.new("uint8_t[4096]") lenCert = ffi.new("unsigned int*") lenCert[0] = 4096 invoke(lib.SpcGetEnvCert,cert, lenCert) print "Cert Len:",lenCert[0] print bytes(ffi.buffer(cert,lenCert[0])) lib.SpcClearEnv()
class _PcapFfi(object): ''' This class represents the low-level interface to the libpcap library. It encapsulates all the cffi calls and C/Python conversions, as well as translation of errors and error codes to PcapExceptions. It is intended to be used as a singleton class through the PcapDumper and PcapLiveDevice classes, below. ''' _instance = None __slots__ = ['_ffi', '_libpcap', '_interfaces', '_windoze'] def __init__(self): ''' Assumption: this class is instantiated once in the main thread before any other threads have a chance to try instantiating it. ''' if _PcapFfi._instance: raise Exception("Can't initialize this class more than once!") _PcapFfi._instance = self self._windoze = False self._ffi = FFI() self._ffi.cdef(''' struct pcap; typedef struct pcap pcap_t; struct pcap_dumper; typedef struct pcap_dumper pcap_dumper_t; struct pcap_addr { struct pcap_addr *next; struct sockaddr *addr; struct sockaddr *netmask; struct sockaddr *broadaddr; struct sockaddr *dstaddr; }; typedef struct pcap_addr pcap_addr_t; struct pcap_if { struct pcap_if *next; char *name; char *description; pcap_addr_t *addresses; int flags; }; typedef struct pcap_if pcap_if_t; int pcap_findalldevs(pcap_if_t **, char *); void pcap_freealldevs(pcap_if_t *); struct pcap_pkthdr { long tv_sec; long tv_usec; unsigned int caplen; unsigned int len; }; struct pcap_stat { unsigned int recv; unsigned int drop; unsigned int ifdrop; }; typedef void (*pcap_handler)(unsigned char *, const struct pcap_pkthdr *, const unsigned char *); pcap_t *pcap_open_dead(int, int); pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(pcap_dumper_t *, struct pcap_pkthdr *, unsigned char *); // live capture pcap_t *pcap_create(const char *, char *); pcap_t *pcap_open_live(const char *, int, int, int, char *); pcap_t *pcap_open_offline(const char *fname, char *errbuf); int pcap_set_snaplen(pcap_t *, int); int pcap_snapshot(pcap_t *); int pcap_set_promisc(pcap_t *, int); int pcap_set_timeout(pcap_t *, int); int pcap_set_buffer_size(pcap_t *, int); int pcap_set_tstamp_precision(pcap_t *, int); int pcap_get_tstamp_precision(pcap_t *); int pcap_set_tstamp_type(pcap_t *, int); int pcap_list_tstamp_types(pcap_t *, int **); void pcap_free_tstamp_types(int *); int pcap_setdirection(pcap_t *, int); int pcap_datalink(pcap_t *); int pcap_setnonblock(pcap_t *, int, char *); int pcap_getnonblock(pcap_t *, char *); int pcap_set_immediate_mode(pcap_t *, int); int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const unsigned char **); int pcap_dispatch(pcap_t *, int, pcap_handler, unsigned char *); int pcap_loop(pcap_t *, int, pcap_handler, unsigned char *); void pcap_breakloop(pcap_t *); int pcap_activate(pcap_t *); void pcap_close(pcap_t *); int pcap_get_selectable_fd(pcap_t *); int pcap_sendpacket(pcap_t *, const unsigned char *, int); char *pcap_geterr(pcap_t *); char *pcap_lib_version(); int pcap_stats(pcap_t *, struct pcap_stat *); struct bpf_insn; struct bpf_program { unsigned int bf_len; struct bpf_insn *bf_insns; }; int pcap_setfilter(pcap_t *, struct bpf_program *); int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, unsigned int); void pcap_freecode(struct bpf_program *); ''') if sys.platform == 'darwin': libname = 'libpcap.dylib' elif sys.platform == 'win32': libname = 'wpcap.dll' # winpcap self._windoze = True else: # if not macOS (darwin) or windows, assume we're on # some unix-based system and try for libpcap.so libname = 'libpcap.so' try: self._libpcap = self._ffi.dlopen(libname) except Exception as e: raise PcapException("Error opening libpcap: {}".format(e)) self._interfaces = [] self.discoverdevs() @staticmethod def instance(): if not _PcapFfi._instance: _PcapFfi._instance = _PcapFfi() return _PcapFfi._instance @property def version(self): return self._ffi.string(self._libpcap.pcap_lib_version()) def discoverdevs(self): ''' Find all the pcap-eligible devices on the local system. ''' if len(self._interfaces): raise PcapException("Device discovery should only be done once.") ppintf = self._ffi.new("pcap_if_t * *") errbuf = self._ffi.new("char []", 128) rv = self._libpcap.pcap_findalldevs(ppintf, errbuf) if rv: raise PcapException("pcap_findalldevs returned failure: {}".format( self._ffi.string(errbuf))) pintf = ppintf[0] tmp = pintf pindex = 0 while tmp != self._ffi.NULL: xname = self._ffi.string( tmp.name) # "internal name"; still stored as bytes object xname = xname.decode('ascii', 'ignore') if self._windoze: ext_name = "port{}".format(pindex) else: ext_name = xname pindex += 1 if tmp.description == self._ffi.NULL: xdesc = ext_name else: xdesc = self._ffi.string(tmp.description) xdesc = xdesc.decode('ascii', 'ignore') # NB: on WinPcap, only loop flag is set isloop = (tmp.flags & 0x1) == 0x1 isup = (tmp.flags & 0x2) == 0x2 isrunning = (tmp.flags & 0x4) == 0x4 # JS: I've observed that the isup and isrunning flags # are patently false on some systems. As a result, we # blindly include all interfaces, regardless of their # reported status (though we still include status flags # in the interface object). # if isup and isrunning: xif = PcapInterface(ext_name, xname, xdesc, isloop, isup, isrunning) self._interfaces.append(xif) tmp = tmp.next self._libpcap.pcap_freealldevs(pintf) @property def devices(self): return self._interfaces @property def lib(self): return self._libpcap @property def ffi(self): return self._ffi def _recv_packet(self, xdev): phdr = self._ffi.new("struct pcap_pkthdr **") pdata = self._ffi.new("unsigned char **") rv = self._libpcap.pcap_next_ex(xdev, phdr, pdata) if rv == 1: rawpkt = bytes(self._ffi.buffer(pdata[0], phdr[0].caplen)) #dt = datetime.fromtimestamp(phdr[0].tv_sec) usec = int(xffi.cast("int", phdr[0].tv_usec)) #ts = dt.replace(microsecond=usec) ts = float("{:d}.{:06d}".format(phdr[0].tv_sec, usec)) return PcapPacket(ts, phdr[0].caplen, phdr[0].len, rawpkt) elif rv == 0: # timeout; nothing to return return None elif rv == -1: # error on receive; raise an exception s = self._ffi.string(self._libpcap.pcap_geterr(xpcap)) raise PcapException("Error receiving packet: {}".format(s)) elif rv == -2: # reading from savefile, but none left return None def _set_filter(self, xdev, filterstr): bpf = self._ffi.new("struct bpf_program *") cfilter = self._ffi.new("char []", bytes(filterstr, 'ascii')) compile_result = self._libpcap.pcap_compile(xdev, bpf, cfilter, 0, 0xffffffff) if compile_result < 0: # get error, raise exception s = self._ffi.string(self._libpcap.pcap_geterr(xdev)) raise PcapException( "Error compiling filter expression: {}".format(s)) sf_result = self._libpcap.pcap_setfilter(xdev, bpf) if sf_result < 0: # get error, raise exception s = self._ffi.string(self._libpcap.pcap_geterr(xdev)) raise PcapException( "Error setting filter on pcap handle: {}".format(s)) self._libpcap.pcap_freecode(bpf)
from cffi import FFI ffi = FFI() ffi.cdef(""" // some declarations from the man page struct passwd { char *pw_name; ...; }; struct passwd *getpwuid(int uid); """) C = ffi.verify(""" // passed to the real C compiler #include <sys/types.h> #include <pwd.h> """) print ffi.string(C.getpwuid(0).pw_name)
the case in validation functions), or throw exceptions. :raises: :class:`OATHError` containing error message on non-OK return value. """ if retval != c.OATH_OK and (not positive_ok or retval < 0): errno = _ffi.cast('oath_rc', retval) err_str = _ffi.string(c.oath_strerror(errno)) err = OATHError(err_str) err.code = errno raise err _handle_retval(c.oath_init()) atexit.register(c.oath_done) library_version = _ffi.string(c.oath_check_version(b'0')) def check_library_version(version): """ Determine whether the library version is greater than or equal to the specified version. :param bytes version: The dotted version number to check :rtype: :func:`bool` """ return c.oath_check_version(to_bytes(version)) != _ffi.NULL def base32_decode(data): """
:param bool positive_ok: Whether positive integers are acceptable (as is the case in validation functions), or throw exceptions. :raises: :class:`OATHError` containing error message on non-OK return value. """ if retval != c.OATH_OK and (not positive_ok or retval < 0): errno = _ffi.cast('oath_rc', retval) err_str = _ffi.string(c.oath_strerror(errno)) err = OATHError(err_str) err.code = errno raise err _handle_retval(c.oath_init()) atexit.register(c.oath_done) library_version = _ffi.string(c.oath_check_version(b'0')) def check_library_version(version): """ Determine whether the library version is greater than or equal to the specified version. :param bytes version: The dotted version number to check :rtype: :func:`bool` """ return c.oath_check_version(to_bytes(version)) != _ffi.NULL def base32_decode(data): """
class _PcapFfi(object): """ This class represents the low-level interface to the libpcap library. It encapsulates all the cffi calls and C/Python conversions, as well as translation of errors and error codes to PcapExceptions. It is intended to be used as a singleton class through the PcapDumper and PcapLiveDevice classes, below. """ _instance = None __slots__ = ["_ffi", "_libpcap", "_interfaces", "_windoze"] def __init__(self): """ Assumption: this class is instantiated once in the main thread before any other threads have a chance to try instantiating it. """ if _PcapFfi._instance: raise Exception("Can't initialize this class more than once!") _PcapFfi._instance = self self._windoze = False self._ffi = FFI() self._ffi.cdef( """ struct pcap; typedef struct pcap pcap_t; struct pcap_dumper; typedef struct pcap_dumper pcap_dumper_t; struct pcap_addr { struct pcap_addr *next; struct sockaddr *addr; struct sockaddr *netmask; struct sockaddr *broadaddr; struct sockaddr *dstaddr; }; typedef struct pcap_addr pcap_addr_t; struct pcap_if { struct pcap_if *next; char *name; char *description; pcap_addr_t *addresses; int flags; }; typedef struct pcap_if pcap_if_t; int pcap_findalldevs(pcap_if_t **, char *); void pcap_freealldevs(pcap_if_t *); struct pcap_pkthdr { unsigned long tv_sec; unsigned long tv_usec; unsigned int caplen; unsigned int len; }; struct pcap_stat { unsigned int recv; unsigned int drop; unsigned int ifdrop; }; pcap_t *pcap_open_dead(int, int); pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(pcap_dumper_t *, struct pcap_pkthdr *, unsigned char *); // live capture pcap_t *pcap_create(const char *, char *); // source, errbuf pcap_t *pcap_open_live(const char *, int, int, int, char *); pcap_t *pcap_open_offline(const char *fname, char *errbuf); int pcap_set_snaplen(pcap_t *, int); // 0 on success int pcap_snapshot(pcap_t *); int pcap_set_promisc(pcap_t *, int); // 0 on success int pcap_set_buffer_size(pcap_t *, int); // 0 on success int pcap_datalink(pcap_t *); int pcap_setnonblock(pcap_t *, int, char *); // 0 on success int pcap_getnonblock(pcap_t *, char *); int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const unsigned char **); int pcap_activate(pcap_t *); void pcap_close(pcap_t *); int pcap_get_selectable_fd(pcap_t *); int pcap_sendpacket(pcap_t *, const unsigned char *, int); char *pcap_geterr(pcap_t *); char *pcap_lib_version(); int pcap_stats(pcap_t *, struct pcap_stat *); struct bpf_insn; struct bpf_program { unsigned int bf_len; struct bpf_insn *bf_insns; }; int pcap_setfilter(pcap_t *, struct bpf_program *); int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, unsigned int); void pcap_freecode(struct bpf_program *); """ ) if sys.platform == "darwin": self._libpcap = self._ffi.dlopen("libpcap.dylib") # standard libpcap elif sys.platform == "linux": self._libpcap = self._ffi.dlopen("libpcap.so") # standard libpcap elif sys.platform == "win32": self._libpcap = self._ffi.dlopen("wpcap.dll") # winpcap self._windoze = True else: raise PcapException("Don't know how to locate libpcap on this platform: {}".format(sys.platform)) self._interfaces = [] self.discoverdevs() @staticmethod def instance(): if not _PcapFfi._instance: _PcapFfi._instance = _PcapFfi() return _PcapFfi._instance @property def version(self): return self._ffi.string(self._libpcap.pcap_lib_version()) def discoverdevs(self): """ Find all the pcap-eligible devices on the local system. """ if len(self._interfaces): raise PcapException("Device discovery should only be done once.") ppintf = self._ffi.new("pcap_if_t * *") errbuf = self._ffi.new("char []", 128) rv = self._libpcap.pcap_findalldevs(ppintf, errbuf) if rv: raise PcapException("pcap_findalldevs returned failure: {}".format(self._ffi.string(errbuf))) pintf = ppintf[0] tmp = pintf pindex = 0 while tmp != self._ffi.NULL: xname = self._ffi.string(tmp.name) # "internal name"; still stored as bytes object xname = xname.decode("ascii", "ignore") if self._windoze: ext_name = "port{}".format(pindex) else: ext_name = xname pindex += 1 if tmp.description == self._ffi.NULL: xdesc = ext_name else: xdesc = self._ffi.string(tmp.description) xdesc = xdesc.decode("ascii", "ignore") # NB: on WinPcap, only loop flag is set isloop = (tmp.flags & 0x1) == 0x1 isup = (tmp.flags & 0x2) == 0x2 isrunning = (tmp.flags & 0x4) == 0x4 xif = Interface(ext_name, xname, xdesc, isloop, isup, isrunning) self._interfaces.append(xif) tmp = tmp.next self._libpcap.pcap_freealldevs(pintf) @property def devices(self): return self._interfaces def open_dumper(self, outfile, dltype=Dlt.DLT_EN10MB, snaplen=65535): pcap = self._libpcap.pcap_open_dead(dltype.value, snaplen) xoutfile = self._ffi.new("char []", bytes(outfile, "ascii")) pcapdump = self._libpcap.pcap_dump_open(pcap, xoutfile) dl = self._libpcap.pcap_datalink(pcap) snaplen = self._libpcap.pcap_snapshot(pcap) return PcapDev(Dlt(dl), 0, snaplen, self.version, pcapdump) def close_dumper(self, pcapdump): self._libpcap.pcap_dump_close(pcapdump) def write_packet(self, dumper, pkt, ts=None): pkthdr = self._ffi.new("struct pcap_pkthdr *") if not ts: ts = time() pkthdr.tv_sec = int(ts) pkthdr.tv_usec = int(1000000 * (ts - int(ts))) pkthdr.caplen = len(pkt) pkthdr.len = len(pkt) xpkt = self._ffi.new("char []", pkt) self._libpcap.pcap_dump(dumper, pkthdr, xpkt) def open_pcap_file(self, filename): errbuf = self._ffi.new("char []", 128) pcap = self._libpcap.pcap_open_offline(bytes(filename, "ascii"), errbuf) if pcap == self._ffi.NULL: raise PcapException( "Failed to open pcap file for reading: {}: {}".format(filename, self._ffi.string(errbuf)) ) dl = self._libpcap.pcap_datalink(pcap) try: dl = Dlt(dl) except ValueError as e: raise PcapException("Don't know how to handle datalink type {}".format(dl)) return PcapDev(dl, 0, 0, self.version, pcap) def open_live(self, device, snaplen=65535, promisc=1, to_ms=100, nonblock=True): errbuf = self._ffi.new("char []", 128) internal_name = None for dev in self._interfaces: if dev.name == device: internal_name = dev.internal_name break if internal_name is None: raise Exception("No such device {} exists.".format(device)) pcap = self._libpcap.pcap_open_live(bytes(internal_name, "ascii"), snaplen, promisc, to_ms, errbuf) if pcap == self._ffi.NULL: raise PcapException("Failed to open live device {}: {}".format(internal_name, self._ffi.string(errbuf))) if nonblock: rv = self._libpcap.pcap_setnonblock(pcap, 1, errbuf) if rv != 0: raise PcapException( "Error setting pcap device in nonblocking state: {}".format(self._ffi.string(errbuf)) ) # gather what happened nblock = self._libpcap.pcap_getnonblock(pcap, errbuf) snaplen = self._libpcap.pcap_snapshot(pcap) dl = self._libpcap.pcap_datalink(pcap) try: dl = Dlt(dl) except ValueError as e: raise PcapException("Don't know how to handle datalink type {}".format(dl)) return PcapDev(dl, nblock, snaplen, self.version, pcap) def close_live(self, pcap): self._libpcap.pcap_close(pcap) def get_select_fd(self, xpcap): try: return self._libpcap.pcap_get_selectable_fd(xpcap) except: return -1 def send_packet(self, xpcap, xbuffer): if not isinstance(xbuffer, bytes): raise PcapException("Packets to be sent via libpcap must be serialized as a bytes object") xlen = len(xbuffer) rv = self._libpcap.pcap_sendpacket(xpcap, xbuffer, xlen) if rv == 0: return True s = self._ffi.string(self._libpcap.pcap_geterr(xpcap)) raise PcapException("Error sending packet: {}".format(s)) def recv_packet(self, xpcap): phdr = self._ffi.new("struct pcap_pkthdr **") pdata = self._ffi.new("unsigned char **") rv = self._libpcap.pcap_next_ex(xpcap, phdr, pdata) if rv == 1: rawpkt = bytes(self._ffi.buffer(pdata[0], phdr[0].caplen)) ts = float("{}.{}".format(phdr[0].tv_sec, phdr[0].tv_usec)) return PcapPacket(ts, phdr[0].caplen, phdr[0].len, rawpkt) elif rv == 0: # timeout; nothing to return return None elif rv == -1: # error on receive; raise an exception s = self._ffi.string(self._libpcap.pcap_geterr(xpcap)) raise PcapException("Error receiving packet: {}".format(s)) elif rv == -2: # reading from savefile, but none left return None def set_filter(self, xpcap, filterstr): bpf = self._ffi.new("struct bpf_program *") cfilter = self._ffi.new("char []", bytes(filterstr, "ascii")) compile_result = self._libpcap.pcap_compile(xpcap.pcap, bpf, cfilter, 0, 0xFFFFFFFF) if compile_result < 0: # get error, raise exception s = self._ffi.string(self._libpcap.pcap_geterr(xpcap.pcap)) raise PcapException("Error compiling filter expression: {}".format(s)) sf_result = self._libpcap.pcap_setfilter(xpcap.pcap, bpf) if sf_result < 0: # get error, raise exception s = self._ffi.string(self._libpcap.pcap_geterr(xpcap.pcap)) raise PcapException("Error setting filter on pcap handle: {}".format(s)) self._libpcap.pcap_freecode(bpf) def stats(self, xpcap): pstat = self._ffi.new("struct pcap_stat *") rv = self._libpcap.pcap_stats(xpcap, pstat) if rv == 0: return PcapStats(pstat.recv, pstat.drop, pstat.ifdrop) else: s = self._ffi.string(self._libpcap.pcap_geterr(xpcap)) raise PcapException("Error getting stats: {}".format(s))
# Strings are a bit harder. Go's strings are stored in a struct {char*, int}, # so we have to do conversion. This is further complicated by CFFI's ownership # semantics - we have to ensure that the char* lives as long as the struct, # otherwise the string will be garbage. We'll use a global weakref dictionary # to track that. import weakref global_weakrefs = weakref.WeakKeyDictionary() def toGoString(string): """Converts a Python string into the equivalent Go string and ensures the memory for the string lives as long as the struct reference.""" string_p = ffi.new('char[]', string) v = ffi.new('GoString*', { 'p': string_p, 'n': len(string) })[0] global_weakrefs[v] = (string_p,) return v # Now we can call the ReturnString function # Note that Go strings are passed by value and not by pointer, but toGoString # is required by CFFI to make a GoString*. We can use [0] to deference it to # a value. print ffi.string(dnslib.ReturnString(toGoString("golang.org")))
from cffi import FFI ffi = FFI() ffi.cdef(""" // some declarations from the man page struct passwd { char *pw_name; ...; }; struct passwd *getpwuid(int uid); """) C = ffi.verify(""" // passed to the real C compiler #include <sys/types.h> #include <pwd.h> """, libraries=[]) # or a list of libraries to link with p = C.getpwuid(0) print(p) print(ffi.string(p.pw_name)) assert ffi.string(p.pw_name) == b'root' # on Python 3: b'root'
#!/usr/bin/env python3 from cffi import FFI import os ffi = FFI() ffi.set_source("_vosk", None) ffi.cdef(os.popen("cpp ../../src/vosk_api.h").read()) ffi.compile() C = ffi.dlopen("libvosk.so") model = C.vosk_model_new("model".encode('utf-8')) rec = C.vosk_recognizer_new(model, 16000) with open("test.wav", "rb") as wf: while True: data = wf.read(8000) if len(data) == 0: break if C.vosk_recognizer_accept_waveform(rec, data, len(data)): print(ffi.string(C.vosk_recognizer_result(rec)).decode('utf-8')) else: print( ffi.string( C.vosk_recognizer_partial_result(rec)).decode('utf-8')) print(ffi.string(C.vosk_recognizer_final_result(rec)).decode('utf-8')) C.vosk_recognizer_free(rec) C.vosk_model_free(model)
callback = ffi.callback("sr_datafeed_callback_t", callback_imp) assert sigrok.sr_init(ctx) == sigrok.SR_OK try: dlist = sigrok.sr_driver_list() i = 0 while True: driver = dlist[i] i += 1 if driver == ffi.NULL: break assert sigrok.sr_driver_init(ctx[0], driver) == sigrok.SR_OK res = sigrok.sr_driver_scan(driver, ffi.NULL) if res != ffi.NULL: name = ffi.string(driver[0].name) print(name) if name == "fx2lafw": sdi = ffi.cast("struct sr_dev_inst*", res.data) print (ffi.string(sdi.vendor)) assert sigrok.sr_dev_open(sdi) == sigrok.SR_OK j = 0 for idx in range(sigrok.g_slist_length(sdi.probes)): probe = ffi.cast('struct sr_probe*',sdi.probes[idx].data) print (ffi.string(probe.name)) session = sigrok.sr_session_new() assert sigrok.sr_session_dev_add(sdi) == sigrok.SR_OK sigrok.sr_session_datafeed_callback_add(callback, ffi.NULL) assert sigrok.sr_session_start() == sigrok.SR_OK def stop():
class _PcapFfi(object): ''' This class represents the low-level interface to the libpcap library. It encapsulates all the cffi calls and C/Python conversions, as well as translation of errors and error codes to PcapExceptions. It is intended to be used as a singleton class through the PcapDumper and PcapLiveDevice classes, below. ''' _instance = None __slots__ = ['_ffi', '_libpcap','_interfaces','_windoze'] def __init__(self): ''' Assumption: this class is instantiated once in the main thread before any other threads have a chance to try instantiating it. ''' if _PcapFfi._instance: raise Exception("Can't initialize this class more than once!") _PcapFfi._instance = self self._windoze = False self._ffi = FFI() self._ffi.cdef(''' struct pcap; typedef struct pcap pcap_t; struct pcap_dumper; typedef struct pcap_dumper pcap_dumper_t; struct pcap_addr { struct pcap_addr *next; struct sockaddr *addr; struct sockaddr *netmask; struct sockaddr *broadaddr; struct sockaddr *dstaddr; }; typedef struct pcap_addr pcap_addr_t; struct pcap_if { struct pcap_if *next; char *name; char *description; pcap_addr_t *addresses; int flags; }; typedef struct pcap_if pcap_if_t; int pcap_findalldevs(pcap_if_t **, char *); void pcap_freealldevs(pcap_if_t *); struct pcap_pkthdr { long tv_sec; long tv_usec; unsigned int caplen; unsigned int len; }; struct pcap_stat { unsigned int recv; unsigned int drop; unsigned int ifdrop; }; typedef void (*pcap_handler)(unsigned char *, const struct pcap_pkthdr *, const unsigned char *); pcap_t *pcap_open_dead(int, int); pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(pcap_dumper_t *, struct pcap_pkthdr *, unsigned char *); // live capture pcap_t *pcap_create(const char *, char *); pcap_t *pcap_open_live(const char *, int, int, int, char *); pcap_t *pcap_open_offline(const char *fname, char *errbuf); int pcap_set_snaplen(pcap_t *, int); int pcap_snapshot(pcap_t *); int pcap_set_promisc(pcap_t *, int); int pcap_set_timeout(pcap_t *, int); int pcap_set_buffer_size(pcap_t *, int); int pcap_set_tstamp_precision(pcap_t *, int); int pcap_get_tstamp_precision(pcap_t *); int pcap_set_tstamp_type(pcap_t *, int); int pcap_list_tstamp_types(pcap_t *, int **); void pcap_free_tstamp_types(int *); int pcap_setdirection(pcap_t *, int); int pcap_datalink(pcap_t *); int pcap_setnonblock(pcap_t *, int, char *); int pcap_getnonblock(pcap_t *, char *); int pcap_set_immediate_mode(pcap_t *, int); int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const unsigned char **); int pcap_dispatch(pcap_t *, int, pcap_handler, unsigned char *); int pcap_loop(pcap_t *, int, pcap_handler, unsigned char *); void pcap_breakloop(pcap_t *); int pcap_activate(pcap_t *); void pcap_close(pcap_t *); int pcap_get_selectable_fd(pcap_t *); int pcap_sendpacket(pcap_t *, const unsigned char *, int); char *pcap_geterr(pcap_t *); char *pcap_lib_version(); int pcap_stats(pcap_t *, struct pcap_stat *); struct bpf_insn; struct bpf_program { unsigned int bf_len; struct bpf_insn *bf_insns; }; int pcap_setfilter(pcap_t *, struct bpf_program *); int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, unsigned int); void pcap_freecode(struct bpf_program *); ''') if sys.platform == 'darwin': libname = 'libpcap.dylib' elif sys.platform == 'win32': libname = 'wpcap.dll' # winpcap self._windoze = True else: # if not macOS (darwin) or windows, assume we're on # some unix-based system and try for libpcap.so libname = 'libpcap.so' try: self._libpcap = self._ffi.dlopen(libname) except Exception as e: raise PcapException("Error opening libpcap: {}".format(e)) self._interfaces = [] self.discoverdevs() @staticmethod def instance(): if not _PcapFfi._instance: _PcapFfi._instance = _PcapFfi() return _PcapFfi._instance @property def version(self): return self._ffi.string(self._libpcap.pcap_lib_version()) def discoverdevs(self): ''' Find all the pcap-eligible devices on the local system. ''' if len(self._interfaces): raise PcapException("Device discovery should only be done once.") ppintf = self._ffi.new("pcap_if_t * *") errbuf = self._ffi.new("char []", 128) rv = self._libpcap.pcap_findalldevs(ppintf, errbuf) if rv: raise PcapException("pcap_findalldevs returned failure: {}".format(self._ffi.string(errbuf))) pintf = ppintf[0] tmp = pintf pindex = 0 while tmp != self._ffi.NULL: xname = self._ffi.string(tmp.name) # "internal name"; still stored as bytes object xname = xname.decode('ascii', 'ignore') if self._windoze: ext_name = "port{}".format(pindex) else: ext_name = xname pindex += 1 if tmp.description == self._ffi.NULL: xdesc = ext_name else: xdesc = self._ffi.string(tmp.description) xdesc = xdesc.decode('ascii', 'ignore') # NB: on WinPcap, only loop flag is set isloop = (tmp.flags & 0x1) == 0x1 isup = (tmp.flags & 0x2) == 0x2 isrunning = (tmp.flags & 0x4) == 0x4 # JS: I've observed that the isup and isrunning flags # are patently false on some systems. As a result, we # blindly include all interfaces, regardless of their # reported status (though we still include status flags # in the interface object). # if isup and isrunning: xif = PcapInterface(ext_name, xname, xdesc, isloop, isup, isrunning) self._interfaces.append(xif) tmp = tmp.next self._libpcap.pcap_freealldevs(pintf) @property def devices(self): return self._interfaces @property def lib(self): return self._libpcap @property def ffi(self): return self._ffi def _recv_packet(self, xdev): phdr = self._ffi.new("struct pcap_pkthdr **") pdata = self._ffi.new("unsigned char **") rv = self._libpcap.pcap_next_ex(xdev, phdr, pdata) if rv == 1: rawpkt = bytes(self._ffi.buffer(pdata[0], phdr[0].caplen)) #dt = datetime.fromtimestamp(phdr[0].tv_sec) usec = int(xffi.cast("int", phdr[0].tv_usec)) #ts = dt.replace(microsecond=usec) ts = float("{:d}.{:06d}".format(phdr[0].tv_sec, usec)) return PcapPacket(ts, phdr[0].caplen, phdr[0].len, rawpkt) elif rv == 0: # timeout; nothing to return return None elif rv == -1: # error on receive; raise an exception s = self._ffi.string(self._libpcap.pcap_geterr(xpcap)) raise PcapException("Error receiving packet: {}".format(s)) elif rv == -2: # reading from savefile, but none left return None def _set_filter(self, xdev, filterstr): bpf = self._ffi.new("struct bpf_program *") cfilter = self._ffi.new("char []", bytes(filterstr, 'ascii')) compile_result = self._libpcap.pcap_compile(xdev, bpf, cfilter, 0, 0xffffffff) if compile_result < 0: # get error, raise exception s = self._ffi.string(self._libpcap.pcap_geterr(xdev)) raise PcapException("Error compiling filter expression: {}".format(s)) sf_result = self._libpcap.pcap_setfilter(xdev, bpf) if sf_result < 0: # get error, raise exception s = self._ffi.string(self._libpcap.pcap_geterr(xdev)) raise PcapException("Error setting filter on pcap handle: {}".format(s)) self._libpcap.pcap_freecode(bpf)
class _PcapFfi(object): """ This class represents the low-level interface to the libpcap library. It encapsulates all the cffi calls and C/Python conversions, as well as translation of errors and error codes to PcapExceptions. It is intended to be used as a singleton class through the PcapDumper and PcapLiveDevice classes, below. """ _instance = None __slots__ = ['_ffi', '_libpcap', '_interfaces', '_windows'] def __init__(self): """ Assumption: this class is instantiated once in the main thread before any other threads have a chance to try instantiating it. """ if _PcapFfi._instance: raise Exception("Can't initialize this class more than once!") _PcapFfi._instance = self self._windows = False self._ffi = FFI() self._ffi.cdef(cc, override=True) self._ffi.cdef(cc_packed, override=True, packed=1) if sys.platform == 'darwin': libname = 'libpcap.dylib' elif "win" in sys.platform[:3]: libname = 'wpcap.dll' # winpcap self._windows = True else: # if not macOS (darwin) or windows, assume we're on # some unix-based system and try for libpcap.so libname = 'libpcap.so' try: self._libpcap = self._ffi.dlopen(libname) except Exception as e: raise PcapException("Error opening libpcap: {}".format(e)) self._interfaces = [] self.discoverdevs() @staticmethod def instance(): if not _PcapFfi._instance: _PcapFfi._instance = _PcapFfi() return _PcapFfi._instance @property def version(self): return self._ffi.string(self._libpcap.pcap_lib_version()) def discoverdevs(self): """ Find all the pcap-eligible devices on the local system. """ if len(self._interfaces): raise PcapException("Device discovery should only be done once.") ppintf = self._ffi.new("pcap_if_t * *") errbuf = self._ffi.new("char []", 128) rv = self._libpcap.pcap_findalldevs(ppintf, errbuf) if rv: raise PcapException("pcap_findalldevs returned failure: {}".format( self._ffi.string(errbuf))) pintf = ppintf[0] tmp = pintf pindex = 0 while tmp != self._ffi.NULL: xname = self._ffi.string( tmp.name) # "internal name"; still stored as bytes object xname = xname.decode('ascii', 'ignore') if self._windows: ext_name = "port{}".format(pindex) else: ext_name = xname pindex += 1 if tmp.description == self._ffi.NULL: xdesc = ext_name else: xdesc = self._ffi.string(tmp.description) xdesc = xdesc.decode('ascii', 'ignore') # NB: on WinPcap, only loop flag is set isloop = (tmp.flags & 0x1) == 0x1 isup = (tmp.flags & 0x2) == 0x2 isrunning = (tmp.flags & 0x4) == 0x4 xif = PcapInterface(ext_name, xname, xdesc, isloop, isup, isrunning) self._interfaces.append(xif) tmp = tmp.next self._libpcap.pcap_freealldevs(pintf) @property def devices(self): return self._interfaces @property def lib(self): return self._libpcap @property def ffi(self): return self._ffi def _process_packet(self, xdev, header, packet, nroots): # MPLS header mpls = self._ffi.new("union mpls *") # IP header iph = self._ffi.new("struct nfstream_iphdr *") # IPv6 header iph6 = self._ffi.new("struct nfstream_ipv6hdr *") # lengths and offsets eth_offset = 0 radio_len = 0 fc = 0 type = 0 wifi_len = 0 pyld_eth_len = 0 check = 0 ip_offset = 0 ip_len = 0 frag_off = 0 vlan_id = 0 proto = 0 time = 0 time = (header.tv_sec * TICK_RESOLUTION) + (header.tv_usec / (1000000 / TICK_RESOLUTION)) datalink_type = self._libpcap.pcap_datalink(xdev) datalink_check = True while datalink_check: datalink_check = False if Dlt(datalink_type) == Dlt.DLT_NULL: tmp_dlt_null = self._ffi.cast('struct pp_32 *', packet + eth_offset) if int(ntohs(tmp_dlt_null.value)) == 2: type = 0x0800 else: type = 0x86dd ip_offset = 4 + eth_offset elif Dlt( datalink_type ) == Dlt.DLT_PPP_SERIAL: # Cisco PPP in HDLC - like framing - 50 chdlc = self._ffi.cast('struct nfstream_chdlc *', packet + eth_offset) ip_offset = self._ffi.sizeof( 'struct nfstream_chdlc') # CHDLC_OFF = 4 type = ntohs(chdlc.proto_code) elif (Dlt(datalink_type) == Dlt.DLT_C_HDLC) or ( Dlt(datalink_type) == Dlt.DLT_PPP): # Cisco PPP - 9 or 104 chdlc = self._ffi.cast('struct nfstream_chdlc *', packet + eth_offset) # CHDLC_OFF = 4 ip_offset = self._ffi.sizeof( 'struct nfstream_chdlc') # CHDLC_OFF = 4 type = ntohs(chdlc.proto_code) elif Dlt(datalink_type ) == Dlt.DLT_EN10MB: # IEEE 802.3 Ethernet - 1 */ ethernet = self._ffi.cast('struct nfstream_ethhdr *', packet + eth_offset) ip_offset = self._ffi.sizeof( 'struct nfstream_ethhdr') + eth_offset check = ntohs(ethernet.h_proto) if check <= 1500: pyld_eth_len = check elif check >= 1536: type = check if pyld_eth_len != 0: llc = self._ffi.cast('struct nfstream_llc_header_snap *', packet + ip_offset) if (llc.dsap == 0xaa) or ( llc.ssap == 0xaa): # check for LLC layer with SNAP ext type = llc.snap.proto_ID ip_offset += 8 elif (llc.dsap == 0x42) or (llc.ssap == 0x42): # No SNAP ext return None elif Dlt(datalink_type ) == Dlt.DLT_LINUX_SLL: # Linux Cooked Capture - 113 type = (packet[eth_offset + 14] << 8) + packet[eth_offset + 15] ip_offset = 16 + eth_offset elif Dlt( datalink_type ) == Dlt.DLT_IEEE802_11_RADIO: # Radiotap link - layer - 127 radiotap = self._ffi.cast('struct nfstream_radiotap_header *', packet + eth_offset) radio_len = radiotap.len if (radiotap.flags & 0x50) == 0x50: # Check Bad FCS presence return None # Calculate 802.11 header length(variable) wifi = self._ffi.cast('struct nfstream_wifi_header *', packet + (eth_offset + radio_len)) fc = wifi.fc # Check wifi data presence if fcf_type(fc) == 0x2: if (fcf_to_ds(fc) and fcf_from_ds(fc) == 0x0) or ( fcf_to_ds(fc) == 0x0 and fcf_from_ds(fc)): wifi_len = 26 # + 4 byte fcs else: pass # Check ether_type from LLC llc = self._ffi.cast( 'struct nfstream_llc_header_snap *', packet + (eth_offset + wifi_len + radio_len)) if llc.dsap == 0xaa: type = ntohs(llc.snap.proto_ID) # Set IP header offset ip_offset = wifi_len + radio_len + self._ffi.sizeof( 'struct nfstream_llc_header_snap') + eth_offset elif Dlt(datalink_type) == Dlt.DLT_RAW: ip_offset = 0 eth_offset = 0 else: return None ether_type_check = True while ether_type_check: ether_type_check = False if type == 0x8100: vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset + 1]) & 0xFFF type = (packet[ip_offset + 2] << 8) + packet[ip_offset + 3] ip_offset += 4 while type == 0x8100 and ip_offset < header.caplen: # Double tagging for 802.1Q vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset + 1]) & 0xFFF type = ( packet[ip_offset + 2] << 8) + packet[ip_offset + 3] ip_offset += 4 ether_type_check = True elif (type == 0x8847) or (type == 0x8848): tmp_u32 = self._ffi.cast('struct pp_32 *', packet + ip_offset) mpls.u32 = int(ntohl(tmp_u32.value)) type = 0x0800 ip_offset += 4 while not mpls.mpls.s: tmp_u32_loop = self._ffi.cast('struct pp_32 *', packet + ip_offset) mpls.u32 = int(ntohl(tmp_u32_loop.value)) ip_offset += 4 ether_type_check = True elif type == 0x8864: type = 0x0800 ip_offset += 8 ether_type_check = True else: pass ip_check = True while ip_check: ip_check = False # Check and set IP header size and total packet length iph = self._ffi.cast('struct nfstream_iphdr *', packet + ip_offset) # Just work on Ethernet packets that contain IP if (type == 0x0800) and (header.caplen >= ip_offset): frag_off = ntohs(iph.frag_off) if header.caplen < header.len: pass if iph.version == 4: ip_len = iph.ihl * 4 iph6 = self._ffi.NULL if iph.protocol == 41: # IPPROTO_IPV6 ip_offset += ip_len ip_check = True if (frag_off & 0x1FFF) != 0: return None elif iph.version == 6: iph6 = self._ffi.cast('struct nfstream_ipv6hdr *', packet + ip_offset) ip_len = self._ffi.sizeof('struct nfstream_ipv6hdr') if iph6.ip6_hdr.ip6_un1_nxt == 60: # IPv6 destination option options = self._ffi.cast('uint8_t *', packet + (ip_offset + ip_len)) ip_len += 8 * (options[1] + 1) iph = self._ffi.NULL else: return None l4_offset = 0 ipsize = 0 src_addr = 0 dst_addr = 0 l4_packet_len = 0 version = 0 nfstream_hash = 0 if iph6 == self._ffi.NULL: version = 4 l4_packet_len = ntohs(iph.tot_len) - (iph.ihl * 4) ipsize = header.caplen - ip_offset proto = iph.protocol src_addr = ntohl(iph.saddr) dst_addr = ntohl(iph.daddr) nfstream_hash += iph.saddr + iph.daddr + proto + vlan_id else: version = 6 src_addr = ntohl(iph6.ip6_src.u6_addr.u6_addr32[0]) << 96 | ntohl( iph6.ip6_src.u6_addr.u6_addr32[1]) << 64 | ntohl( iph6.ip6_src.u6_addr.u6_addr32[2]) << 32 | ntohl( iph6.ip6_src.u6_addr.u6_addr32[3]) dst_addr = ntohl(iph6.ip6_dst.u6_addr.u6_addr32[0]) << 96 | ntohl( iph6.ip6_dst.u6_addr.u6_addr32[1]) << 64 | ntohl( iph6.ip6_dst.u6_addr.u6_addr32[2]) << 32 | ntohl( iph6.ip6_dst.u6_addr.u6_addr32[3]) proto = iph6.ip6_hdr.ip6_un1_nxt if proto == 60: options = self._ffi.cast( 'uint8_t *', iph6) + self._ffi.sizeof('struct nfstream_ipv6hdr') proto = options[0] l4_packet_len = ntohs(iph6.ip6_hdr.ip6_un1_plen) nfstream_hash += ( iph6.ip6_src.u6_addr.u6_addr32[2] + iph6.ip6_src.u6_addr.u6_addr32[3]) + ( iph6.ip6_dst.u6_addr.u6_addr32[2] + iph6.ip6_dst.u6_addr.u6_addr32[3]) + proto + vlan_id if version == 4: if ipsize < 20: return None if ((iph.ihl * 4) > ipsize) or (ipsize < ntohs(iph.tot_len)): return None l4_offset = iph.ihl * 4 l3 = self._ffi.cast('uint8_t *', iph) else: l4_offset = self._ffi.sizeof('struct nfstream_ipv6hdr') l3 = self._ffi.cast('uint8_t *', iph6) l4 = self._ffi.cast('uint8_t *', l3) + l4_offset syn, cwr, ece, urg, ack, psh, rst, fin = 0, 0, 0, 0, 0, 0, 0, 0 if (proto == 6 ) and l4_packet_len >= self._ffi.sizeof('struct nfstream_tcphdr'): tcph = self._ffi.cast('struct nfstream_tcphdr *', l4) sport = int(ntohs(tcph.source)) dport = int(ntohs(tcph.dest)) syn = int(tcph.syn) cwr = int(tcph.cwr) ece = int(tcph.ece) urg = int(tcph.urg) ack = int(tcph.ack) psh = int(tcph.psh) rst = int(tcph.rst) fin = int(tcph.fin) elif (proto == 17) and l4_packet_len >= self._ffi.sizeof( 'struct nfstream_udphdr'): udph = self._ffi.cast('struct nfstream_udphdr *', l4) sport = int(ntohs(udph.source)) dport = int(ntohs(udph.dest)) else: sport = 0 dport = 0 nfstream_hash += sport + dport if version == 4: return NFPacket(time=int(time), capture_length=header.caplen, length=header.len, nfhash=nfstream_hash, ip_src=src_addr, ip_dst=dst_addr, src_port=sport, dst_port=dport, protocol=proto, vlan_id=vlan_id, version=version, tcpflags=tcpflags(syn=syn, cwr=cwr, ece=ece, urg=urg, ack=ack, psh=psh, rst=rst, fin=fin), raw=bytes(xffi.buffer(iph, ipsize)), root_idx=nfstream_hash % nroots) else: return NFPacket(time=int(time), capture_length=header.caplen, length=header.len, nfhash=nfstream_hash, ip_src=src_addr, ip_dst=dst_addr, src_port=sport, dst_port=dport, protocol=proto, vlan_id=vlan_id, version=version, tcpflags=tcpflags(syn=syn, cwr=cwr, ece=ece, urg=urg, ack=ack, psh=psh, rst=rst, fin=fin), raw=bytes(xffi.buffer(iph6, header.len - ip_offset)), root_idx=nfstream_hash % nroots) def _recv_packet(self, xdev, nroots=1): phdr = self._ffi.new("struct pcap_pkthdr **") pdata = self._ffi.new("unsigned char **") rv = self._libpcap.pcap_next_ex(xdev, phdr, pdata) if rv == 1: return self._process_packet(xdev, phdr[0], pdata[0], nroots) elif rv == 0: # timeout; nothing to return return 0 elif rv == -1: # error on receive; raise an exception s = self._ffi.string(self._libpcap.pcap_geterr(xdev)) raise PcapException("Error receiving packet: {}".format(s)) elif rv == -2: # reading from savefile, but none left return -2
from cffi import FFI ffi = FFI() ffi.cdef(open('hello.h').read()) lib = ffi.dlopen('./libhello.so') #lib = ffi.verify("#include <hello.h>", include_dirs=["."]) a = ffi.string(lib.hello()) print a
void Add(const char *host); void Remove(const char *host); const char *Hash(const char *key); void SetReplica(GoInt replica); void Cfree(void *p); """) lib = ffi.dlopen("./consistent.so") print lib.Add, lib.Remove, lib.Hash, lib.Cfree host1 = ffi.new("char[]", "host1") lib.Add(host1) key = ffi.new("char[]", "test_key") host = lib.Hash(key) print ffi.string(host) lib.Cfree(host) # print("awesome.Add(12,99) = %d" % lib.Add(12,99)) # print("awesome.Cosine(1) = %f" % lib.Cosine(1)) # # data = ffi.new("GoInt[]", [74,4,122,9,12]) # nums = ffi.new("GoSlice*", {'data':data, 'len':5, 'cap':5}) # lib.Sort(nums[0]) # print("awesome.Sort(74,4,122,9,12) = %s" % [ # ffi.cast("GoInt*", nums.data)[i] # for i in range(nums.len)]) # # data = ffi.new("char[]", b"Hello Python!") # msg = ffi.new("GoString*", {'data':data, 'len':13}) # print("log id %d" % lib.Log(msg[0]))
'libressl_version', 'libressl_version_info', 'version', 'version_info', ] libcrypto_path = _backend_config().get('libcrypto_path') if libcrypto_path is None: libcrypto_path = find_library('crypto') if not libcrypto_path: raise LibraryNotFoundError('The library libcrypto could not be found') try: vffi = FFI() vffi.cdef("const char *SSLeay_version(int type);") version_string = vffi.string( vffi.dlopen(libcrypto_path).SSLeay_version(0)).decode('utf-8') except (AttributeError): vffi = FFI() vffi.cdef("const char *OpenSSL_version(int type);") version_string = vffi.string( vffi.dlopen(libcrypto_path).OpenSSL_version(0)).decode('utf-8') is_libressl = 'LibreSSL' in version_string version_match = re.search('\\b(\\d\\.\\d\\.\\d[a-z]*)\\b', version_string) if not version_match: version_match = re.search('(?<=LibreSSL )(\\d\\.\\d(\\.\\d)?)\\b', version_string) if not version_match: raise LibraryNotFoundError('Error detecting the version of libcrypto') version = version_match.group(1)
class FC_Solve: # TEST:$num_befs_weights=5; NUM_BEFS_WEIGHTS = 5 FCS_STATE_SUSPEND_PROCESS = 5 def __init__(self): self.ffi = FFI() self.lib = self.ffi.dlopen( "../libfreecell-solver." + ("dll" if (platform.system() == 'Windows') else "so")) self.ffi.cdef(''' void * freecell_solver_user_alloc(); typedef struct{ char s[20];}fcs_move_t; int freecell_solver_user_get_moves_left (void * user); int freecell_solver_user_get_next_move (void * user, fcs_move_t * move); void freecell_solver_user_free(void * instance); double fc_solve_user_INTERNAL_get_befs_weight(void * user, int idx); typedef char * freecell_solver_str_t; typedef int (*freecell_solver_user_cmd_line_known_commands_callback_t)( void *instance, int argc, freecell_solver_str_t argv[], int arg_index, int *num_to_skip, int *ret, void *context); int freecell_solver_user_cmd_line_parse_args_with_file_nesting_count( void *instance, int argc, freecell_solver_str_t argv[], int start_arg, freecell_solver_str_t *known_parameters, freecell_solver_user_cmd_line_known_commands_callback_t callback, void *callback_context, char **error_string, int *last_arg, int file_nesting_count, freecell_solver_str_t opened_files_dir); int freecell_solver_user_set_flares_plan(void * instance, char * s); int freecell_solver_user_INTERNAL_compile_all_flares_plans(void * instance, char * * s); int fc_solve_user_INTERNAL_get_flares_plan_num_items(void * i); char * fc_solve_user_INTERNAL_get_flares_plan_item_type(void * i, int item_idx); int fc_solve_user_INTERNAL_get_flares_plan_item_flare_idx(void * i, int item_idx); int fc_solve_user_INTERNAL_get_flares_plan_item_iters_count(void * i, int item_idx); int fc_solve_user_INTERNAL_compile_all_flares_plans(void * i, char **error_string); int fc_solve_user_INTERNAL_get_num_by_depth_tests_order( void * api_instance); int fc_solve_user_INTERNAL_get_by_depth_tests_max_depth( void * api_instance, int depth_idx); long freecell_solver_user_get_num_times_long(void * user); long freecell_solver_user_get_num_states_in_collection_long(void * user); void freecell_solver_user_limit_iterations_long( void * api_instance, const long max_iters); int freecell_solver_user_solve_board(void *api_instance, const char *const state_as_string); int freecell_solver_user_resume_solution(void * user); void freecell_solver_user_recycle(void *api_instance); ''') self.user = self.lib.freecell_solver_user_alloc() def is_SUSPEND(self, ret_code): """docstring for is_SUSPEND""" return ret_code == self.FCS_STATE_SUSPEND_PROCESS def get_next_move(self): move = self.ffi.new('fcs_move_t *') num_moves = self.lib.freecell_solver_user_get_moves_left(self.user) if not num_moves: return None ret = self.lib.freecell_solver_user_get_next_move(self.user, move) SUCCESS = 0 return (move if ret == SUCCESS else None) def input_cmd_line__generic(self, cmd_line_args): last_arg = self.ffi.new('int *') error_string = self.ffi.new('char * *') known_params = self.ffi.new('char * *') opened_files_dir = self.ffi.new('char [32001]') prefix = 'freecell_solver_user_cmd_line' func = 'parse_args_with_file_nesting_count' getattr(self.lib, prefix + '_' + func)( self.user, # instance len(cmd_line_args), # argc [self.ffi.new('char[]', bytes(s, 'UTF-8')) \ for s in cmd_line_args], # argv 0, # start_arg known_params, # known_params self.ffi.NULL, # callback self.ffi.NULL, # callback_context error_string, # error_string last_arg, # last_arg -1, # file_nesting_count opened_files_dir ) return (last_arg[0], len(cmd_line_args)) # TEST:$set_befs=0; def _set_befs_weights(self, name, weights_s): # TEST:$set_befs=$set_befs+$input_cmd_line; self.input_cmd_line(name, ["-asw", weights_s]) def __destroy__(self): self.ffi.freecell_solver_user_free(self.user) def _get_plan_type(self, item_idx): return self.ffi.string( self.lib.fc_solve_user_INTERNAL_get_flares_plan_item_type( self.user, item_idx)) def solve_board(self, board): return self.lib.freecell_solver_user_solve_board( self.user, bytes(board, 'UTF-8') ) def resume_solution(self): return self.lib.freecell_solver_user_resume_solution(self.user) def limit_iterations(self, max_iters): self.lib.freecell_solver_user_limit_iterations_long( self.user, max_iters ) def get_num_times(self): return self.lib.freecell_solver_user_get_num_times_long( self.user) def get_num_states_in_col(self): return self.lib.freecell_solver_user_get_num_states_in_collection_long( self.user) def recycle(self): self.lib.freecell_solver_user_recycle(self.user)
""") try: _lib = _ffi.dlopen( os.path.join( os.path.dirname(os.path.abspath(__file__)), "libcadical.so" ) ) except OSError as err: raise RuntimeError( "libcadical.so not found, run build_libcadical.sh" ) from err version = _ffi.string(_lib.ccadical_signature()) _status_to_bool = {0: None, 10: True, 20: False} _value_to_bool = {1: True, 0: None, -1: False} class Solver: def __init__(self): self.__solver = _lib.ccadical_init() self.__exception = None def __del__(self): _lib.ccadical_release(self.__solver) def add(self, lit): _lib.ccadical_add(self.__solver, lit)
class AbiInlineDeviceReader(CffiDeviceReader): def __init__(self, library: CffiDeviceReader.Library): super().__init__() self.ffi = FFI() self.ffi.cdef(""" char* get_cell(char *device, int row, int column); void free_resource(char *resource); """) library_name = library.get_library_name() self.lib = self.ffi.dlopen( os.path.join(os.path.dirname(__file__), library_name)) def get_cell(self, device: bytes, row: int, col: int): """ Returns the requested cell value of the specified device Parameters ---------- device bytes The device you want to retrieve the cell value on row int The table row of the value you want to retrieve col int The table column of the value you want to retrieve Returns ------- The pointer to the byte array containing the value of the cell **NOTE:** call free_resource() or free_resources() to free the allocated memory """ self.allocated_resources.append(self.lib.get_cell(device, row, col)) return self.allocated_resources[-1] def to_string(self, c_char_ptr) -> str: return self.ffi.string(c_char_ptr) def free_resource(self, resource) -> None: """Releases the resource previously allocated when calling get_cell Parameters ---------- resource: c_void_p The pointer to the byte array previously allocated by get_cell() Returns ------- None When the resource has been successfully released Raises ------ ResourceNotAllocated If the resource was not previously allocated """ if resource in self.allocated_resources: self.allocated_resources.remove(resource) self.lib.free_resource(resource) else: raise self.ResourceNotAllocated def free_resources(self): """Release all previously allocated resources""" for resource in reversed(self.allocated_resources): self.free_resource(resource) def num_allocated_resources(self) -> int: """Return the number of allocated resources Returns int The number of allocated resources """ return len(self.allocated_resources)
class CStrACL(object): _lazy = None @classmethod def lazy_instance(cls): if not cls._lazy: cls._lazy = cls() return cls._lazy def __init__(self): self.ffi = FFI() cdef = ''' struct __acl_ext; typedef struct __acl_ext *acl_t; typedef unsigned int acl_type_t; typedef unsigned int mode_t; static const acl_type_t ACL_TYPE_ACCESS; static const acl_type_t ACL_TYPE_DEFAULT; static const int TEXT_ABBREVIATE; static const int TEXT_NUMERIC_IDS; static const int TEXT_SOME_EFFECTIVE; static const int TEXT_ALL_EFFECTIVE; static const int TEXT_SMART_INDENT; acl_t acl_init(int count); acl_t acl_get_file(const char *path_p, acl_type_t type); acl_t acl_from_mode(mode_t mode); acl_t acl_from_text(const char *buf_p); char *acl_to_any_text( acl_t acl, const char *prefix, char separator, int options ); int acl_calc_mask(acl_t *acl_p); int acl_set_file(const char *path_p, acl_type_t type, acl_t acl); int acl_set_fd(int fd, acl_t acl); int acl_free(void *obj_p); ''' self.ffi.cdef(cdef) self.libacl = self.ffi.verify(''' #include <sys/types.h> #include <sys/acl.h> #include <acl/libacl.h> ''', libraries=['acl']) self._flag_cache = dict() for k, pre, alias in re.findall(r'\b((ACL_TYPE|TEXT)_([A-Z_]+))\b', cdef): v = getattr(self.libacl, k) setattr(self, k, v) if alias not in self._flag_cache: self._flag_cache[alias] = v else: self._flag_cache[alias] = None def _flag(self, k): if isinstance(k, (int, long)): return k elif not isinstance(k, types.StringTypes): return reduce(op.or_, it.imap(self._flag, k), 0) v = self._flag_cache[k] if v is not None: return v else: raise KeyError('Ambiguous flag name: {}'.format(k)) def get( self, src, acl_type='ACCESS', text_options=['ABBREVIATE', 'ALL_EFFECTIVE'] ): if isinstance(src, types.StringTypes): func = self.libacl.acl_get_file else: if not isinstance(src, (int, long)): src = src.fileno() func = self.libacl.acl_get_fd acl = func(src, self._flag(acl_type)) try: if acl == self.ffi.NULL: if self.ffi.errno == errno.ENODATA: return '' raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) acl_str = self.libacl.acl_to_any_text( acl, self.ffi.NULL, '\n', self._flag(text_options) ) if acl == self.ffi.NULL: raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) acl_str = self.ffi.string(acl_str) return acl_str finally: if acl != self.ffi.NULL and self.libacl.acl_free(acl): raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) def _set(self, dst, acl_str, acl_type='ACCESS'): acl = self.libacl.acl_from_text(acl_str)\ if acl_str is not None else self.libacl.acl_init(5) if acl == self.ffi.NULL: raise ValueError('Invalid ACL specification: {!r}'.format(acl_str)) try: acl_p = self.ffi.new('acl_t *', acl) if self.libacl.acl_calc_mask(acl_p): raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) acl_type = self._flag(acl_type) if isinstance(dst, types.StringTypes): err = self.libacl.acl_set_file(dst, acl_type, acl) else: if not isinstance(dst, (int, long)): dst = dst.fileno() err = self.libacl.acl_set_fd(dst, acl) if err: raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) finally: if self.libacl.acl_free(acl): raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) def set(self, dst, acl_str, acl_type='ACCESS'): return self._set(dst, acl_str, acl_type=acl_type) def unset(self, dst, acl_type='ACCESS'): return self._set(dst, None, acl_type=acl_type) def from_mode( self, mode, text_options=['ABBREVIATE', 'ALL_EFFECTIVE'] ): acl = self.libacl.acl_from_mode(mode) if acl == self.ffi.NULL: raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) try: acl_str = self.libacl.acl_to_any_text( acl, self.ffi.NULL, '\n', self._flag(text_options) ) return self.ffi.string(acl_str) finally: if self.libacl.acl_free(acl): raise OSError(self.ffi.errno, os.strerror(self.ffi.errno))
print "ret errno", ret, ffi.errno if ret != 0: print "errno is ", ffi.errno assert ret == 0 def test_shm(): shmstep0() shmstep1() shmstep2() def setup_function(function): print ("setting up %s" % function) if __name__ == "__main__": global shm import sys shmstep0() print shm.fd, shm.size,ffi.string(shm.name) c= sys.stdin.readline() print "readlins is return",c if c[:4] == "open": print "into openex test process 2" shmstep1x() print "copy 7 bytes " caddr = ffi.cast("void*", shm.addr) C.memcpy(caddr, "welcome", 7) sys.stdin.readline() print "copy %d bytes" % (4096*2+1) C.memcpy(caddr, "welcome"*2000, 4096*2+1) sys.stdin.readline() shmstep2() elif c[:5] == "close": pass
'version_info', ] ffi = FFI() ffi.cdef("const char *SSLeay_version(int type);") libcrypto_path = find_library('crypto') if not libcrypto_path: raise LibraryNotFoundError('The library libcrypto could not be found') libcrypto = ffi.dlopen(libcrypto_path) register_ffi(libcrypto, ffi) version_string = ffi.string(libcrypto.SSLeay_version(0)).decode('utf-8') version_match = re.search('\\b(\\d\\.\\d\\.\\d[a-z]*)\\b', version_string) if not version_match: version_match = re.search('(?<=LibreSSL )(\\d\\.\\d(\\.\\d)?)\\b', version_string) if not version_match: raise LibraryNotFoundError('Error detecting the version of libcrypto') version = version_match.group(1) version_parts = re.sub('(\\d)([a-z]+)', '\\1.\\2', version).split('.') version_info = tuple(int(part) if part.isdigit() else part for part in version_parts) if version_info < (0, 9, 8): raise LibraryNotFoundError(pretty_message( ''' OpenSSL versions older than 0.9.8 are not supported - found version %s ''', version
JSON_FALSE, JSON_NULL } json_type; typedef struct json_t { json_type type; size_t refcount; } json_t; ''') py_boot = ffi.cast("t_pypy_bootstrap *",c_argument) try: import os.path gfile = os.path.join(ffi.string(py_boot.paths.data).decode('utf-8'),'..','c_src','globals.h') print("trying for globals.h at '%s'"%gfile) if not os.path.isfile(gfile): raise OSError("could not find globals.h! eeeeep!") gfile = open(gfile,'r').read() cdefs = io.StringIO() lines = gfile.splitlines() for i,line in enumerate(lines): line = line.strip() if line.startswith('#'): continue cdefs.write(line+'\n') ffi.cdef(cdefs.getvalue(), override=True)#over ride old def's if they exist. trust globals.h
rc = ngspice_shared.ngSpice_Command('bg_run'.encode('utf8')) print('ngSpice_Command returned', rc) time.sleep(.1) # required before to test if the simulation is running while (ngspice_shared.ngSpice_running()): time.sleep(.1) print("Simulation is done") all_plots = ngspice_shared.ngSpice_AllPlots() i = 0 while (True): if all_plots[i] == ffi.NULL: break else: print(ffi.string(all_plots[i])) i += 1 plot_name = 'tran1' all_vectors = ngspice_shared.ngSpice_AllVecs(plot_name.encode('utf8')) i = 0 while (True): if all_vectors[i] == ffi.NULL: break else: vector_name = ffi.string(all_vectors[i]) name = '.'.join((plot_name, vector_name.decode('utf8'))) vector_info = ngspice_shared.ngGet_Vec_Info(name.encode('utf8')) length = vector_info.v_length print("vector[{}] {} type {} flags {} length {}".format( i, vector_name, vector_info.v_type, vector_info.v_flags, length))
class CStrCaps(object): _lazy = None @classmethod def lazy_instance(cls): if not cls._lazy: cls._lazy = cls() return cls._lazy def __init__(self): self.ffi = FFI() cdef = ''' struct _cap_struct; typedef struct _cap_struct *cap_t; cap_t cap_get_file(const char *path_p); int cap_set_file(const char *path_p, cap_t cap_p); cap_t cap_get_fd(int fd); int cap_set_fd(int fd, cap_t caps); cap_t cap_from_text(const char *buf_p); char *cap_to_text(cap_t caps, ssize_t *length_p); int cap_free(void *obj_d); ''' self.ffi.cdef(cdef) self.libcap = self.ffi.verify(''' #include <sys/types.h> #include <sys/capability.h> ''', libraries=['cap']) def get_file(self, src): if isinstance(src, types.StringTypes): func = self.libcap.cap_get_file else: if not isinstance(src, (int, long)): src = src.fileno() func = self.libcap.cap_get_fd caps = func(src) try: if caps == self.ffi.NULL: if self.ffi.errno == errno.ENODATA: return '' raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) else: caps_len_p = self.ffi.new('ssize_t *') caps_p = self.libcap.cap_to_text(caps, caps_len_p) if caps_p == self.ffi.NULL: raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) return self.ffi.string(caps_p, caps_len_p[0]) finally: if caps != self.ffi.NULL and self.libcap.cap_free(caps): raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) def set_file(self, dst, caps_str): caps = self.libcap.cap_from_text(caps_str) if caps == self.ffi.NULL: raise ValueError('Invalid capabilities specification: {!r}'.format(caps_str)) try: if isinstance(dst, types.StringTypes): err = self.libcap.cap_set_file(dst, caps) else: if not isinstance(dst, (int, long)): dst = dst.fileno() err = self.libcap.cap_set_fd(dst, caps) if err: raise OSError(self.ffi.errno, os.strerror(self.ffi.errno)) finally: if self.libcap.cap_free(caps): raise OSError(self.ffi.errno, os.strerror(self.ffi.errno))
class RangeLib(object): def __init__(self, config_file): self.ffi = FFI() self.ffi.cdef(""" typedef void easy_lr ; // avoid exposing the struct internals, fake it as void easy_lr* range_easy_create(const char* config_file); const char ** range_easy_expand(easy_lr* elr, const char * c_range); const char * range_easy_eval(easy_lr* elr, const char * c_range); char * range_easy_compress(easy_lr* elr, const char ** c_nodes); int range_easy_destroy(easy_lr* elr); void free(void *ptr); """) self.rangelib_ffi = self.ffi.dlopen("libcrange.so") self.libc_ffi = self.ffi.dlopen("libc.so.6") self.elr = self.rangelib_ffi.range_easy_create(self.ffi.new("char[]", config_file)) def __charpp_to_native(self, arg): i = 0 arr = [] while arg[i] != self.ffi.NULL: x = self.ffi.string(arg[i]) self.libc_ffi.free(arg[i]) arr.append(x) i += 1 self.libc_ffi.free(arg) return arr def expand(self, c_range): ret = self.rangelib_ffi.range_easy_expand(self.elr, self.ffi.new("char[]", c_range)) x = self.__charpp_to_native(ret) return x def compress(self, nodes): char_arg = [ self.ffi.new("char[]", x) for x in nodes ] char_arg.append(self.ffi.NULL) retptr = self.rangelib_ffi.range_easy_compress(self.elr, self.ffi.new("char*[]", char_arg)) ret = self.ffi.string(retptr) self.libc_ffi.free(retptr) return ret def eval(self, c_range): retptr = self.rangelib_ffi.range_easy_eval(self.elr, self.ffi.new("char[]", c_range)) ret = self.ffi.string(retptr) self.libc_ffi.free(retptr) return ret def __del__(self): self.rangelib_ffi.range_easy_destroy(self.elr)