Browse Source

pyln: handle (ignore) notifications, and add notify_msg to send them.

We also sanity check that response id matches our request.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: pyln: pyln.client handles and can send progress notifications.
travis-experimental
Rusty Russell 4 years ago
parent
commit
806f208295
  1. 15
      contrib/pyln-client/pyln/client/lightning.py
  2. 20
      contrib/pyln-client/pyln/client/plugin.py

15
contrib/pyln-client/pyln/client/lightning.py

@ -316,17 +316,26 @@ class UnixDomainSocketRpc(object):
# FIXME: we open a new socket for every readobj call... # FIXME: we open a new socket for every readobj call...
sock = UnixSocket(self.socket_path) sock = UnixSocket(self.socket_path)
this_id = self.next_id
self._writeobj(sock, { self._writeobj(sock, {
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": method, "method": method,
"params": payload, "params": payload,
"id": self.next_id, "id": this_id,
}) })
self.next_id += 1 self.next_id += 1
resp, _ = self._readobj(sock) buf = b''
sock.close() while True:
resp, buf = self._readobj(sock, buf)
# FIXME: We should offer a callback for notifications.
if 'method' not in resp or 'id' in resp:
break
self.logger.debug("Received response for %s call: %r", method, resp) self.logger.debug("Received response for %s call: %r", method, resp)
if 'id' in resp and resp['id'] != this_id:
raise ValueError("Malformed response, id is not {}: {}.".format(this_id, resp))
sock.close()
if not isinstance(resp, dict): if not isinstance(resp, dict):
raise ValueError("Malformed response, response is not a dictionary %s." % resp) raise ValueError("Malformed response, response is not a dictionary %s." % resp)
elif "error" in resp: elif "error" in resp:

20
contrib/pyln-client/pyln/client/plugin.py

@ -608,6 +608,26 @@ class Plugin(object):
for line in message.split('\n'): for line in message.split('\n'):
self.notify('log', {'level': level, 'message': line}) self.notify('log', {'level': level, 'message': line})
def notify_message(self, request: Request, message: str,
level: str = 'info') -> None:
"""Send a notification message to sender of this request"""
self.notify("message", {"id": request.id,
"level": level,
"message": message})
def notify_progress(self, request: Request,
progress: int, progress_total: int,
stage: Optional[int] = None,
stage_total: Optional[int] = None) -> None:
"""Send a progerss message to sender of this request: if more than one stage, set stage and stage_total"""
d: Dict[str, Any] = {"id": request.id,
"num": progress,
"total": progress_total}
if stage_total is not None:
d['stage'] = {"num": stage, "total": stage_total}
self.notify("progress", d)
def _parse_request(self, jsrequest: Dict[str, JSONType]) -> Request: def _parse_request(self, jsrequest: Dict[str, JSONType]) -> Request:
i = jsrequest.get('id', None) i = jsrequest.get('id', None)
if not isinstance(i, int) and i is not None: if not isinstance(i, int) and i is not None:

Loading…
Cancel
Save