326aad23ae
Introduce a subscription based lookup model, in order for a client to be able to listen to a future spawning service. The client can register any number of queries with the ns and the ns will post lookup-results as services are registred. As a special case the list of lookup-results that is sent out as a result of the registration of a new lookup will be finished by an empty lookup response, allowing tools like qrtr-lookup to terminate as the entire list of currently registed services is received. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
98 lines
3.3 KiB
Python
Executable File
98 lines
3.3 KiB
Python
Executable File
#!/usr/bin/env python2.7
|
|
|
|
import ctypes
|
|
import collections
|
|
|
|
from ctypes import CDLL, CFUNCTYPE, POINTER, cast, py_object
|
|
from ctypes import c_char_p, c_void_p, c_int, pointer
|
|
|
|
_qrtr = CDLL("./libqrtr.so")
|
|
|
|
class qrtr:
|
|
Result = collections.namedtuple('Result', ['service', 'instance', 'addr'])
|
|
_cbtype = CFUNCTYPE(None, c_void_p, c_int, c_int, c_int, c_int)
|
|
def __init__(self, port=0):
|
|
self.sock = _qrtr.qrtr_open(port)
|
|
if self.sock < 0:
|
|
raise RuntimeError("unable to open qrtr socket")
|
|
self.service = None
|
|
self._qrtr = _qrtr
|
|
|
|
def __del__(self):
|
|
self._qrtr.qrtr_close(self.sock)
|
|
|
|
def _lookup_list_add(self, ptr, srv, instance, node, port):
|
|
res = qrtr.Result(srv, instance, (node, port))
|
|
cast(ptr, POINTER(py_object)).contents.value.append(res)
|
|
|
|
def lookup(self, srv, instance=0, ifilter=0):
|
|
results = []
|
|
err = _qrtr.qrtr_lookup(self.sock, srv, instance, ifilter,
|
|
qrtr._cbtype(self._lookup_list_add), cast(pointer(py_object(results)), c_void_p))
|
|
if err:
|
|
raise RuntimeError("query failed")
|
|
return results
|
|
|
|
def publish(self, service, version, instance):
|
|
err = _qrtr.qrtr_publish(self.sock, service, version, instance)
|
|
if err:
|
|
raise RuntimeError("publish failed")
|
|
self.service = (service, version, instance)
|
|
|
|
def new_server(self, service, version, instance):
|
|
err = _qrtr.qrtr_new_server(self.sock, service, version, instance)
|
|
if err:
|
|
raise RuntimeError("new_server failed")
|
|
self.service = (service, version, instance)
|
|
|
|
return self.service
|
|
|
|
def remove_server(self, service):
|
|
err = _qrtr.qrtr_remove_server(self.sock, *service)
|
|
if err:
|
|
raise RuntimeError("remove_server failed")
|
|
self.service = None
|
|
|
|
def new_lookup(self, service, version, instance):
|
|
err = _qrtr.qrtr_new_lookup(self.sock, service, version, instance)
|
|
if err:
|
|
raise RuntimeError("new_lookup failed")
|
|
return (service, version, instance)
|
|
|
|
def remove_lookup(self, lookup):
|
|
err = _qrtr.qrtr_remove_lookup(self.sock, *lookup)
|
|
if err:
|
|
raise RuntimeError("remove_lookup failed")
|
|
|
|
def send(self, addr, data):
|
|
node, port = addr
|
|
n = _qrtr.qrtr_sendto(self.sock, node, port, c_char_p(data), len(data))
|
|
if n:
|
|
raise RuntimeError("sendto failed")
|
|
|
|
def recv(self, sz=65536):
|
|
buf = ctypes.create_string_buffer(sz)
|
|
n = _qrtr.qrtr_recv(self.sock, c_char_p(ctypes.addressof(buf)), sz)
|
|
if n <= 0:
|
|
raise RuntimeError("recv failed")
|
|
return buf[0:n]
|
|
|
|
def recvfrom(self, sz=65536):
|
|
node = ctypes.c_int()
|
|
port = ctypes.c_int()
|
|
buf = ctypes.create_string_buffer(sz)
|
|
n = _qrtr.qrtr_recvfrom(self.sock, c_char_p(ctypes.addressof(buf)),
|
|
ctypes.byref(node), ctypes.byref(port))
|
|
if n <= 0:
|
|
raise RuntimeError("recvfrom failed")
|
|
return (buf[0:n], (node.value, port.value))
|
|
|
|
def poll(self, tout=0):
|
|
return _qrtr.qrtr_poll(self.sock, tout)
|
|
|
|
if __name__ == "__main__":
|
|
svcs = qrtr().lookup(15) # 15 is the test service
|
|
print " service instance addr"
|
|
for svc in svcs:
|
|
print "% 8d % 8d %s" % (svc.service, svc.instance, svc.addr)
|