You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

85 lines
2.9 KiB

import json
from autobahn.twisted.websocket import WebSocketServerFactory, \
WebSocketServerProtocol
from .auth import JMTokenAuthority
from jmbitcoin import human_readable_transaction
from jmbase import get_log
jlog = get_log()
class JmwalletdWebSocketServerProtocol(WebSocketServerProtocol):
def onOpen(self):
self.active_session = False
self.factory.register(self)
def sendNotification(self, info):
""" Passes on an object (json encoded) to the client,
if currently authenticated.
"""
if not self.active_session:
# not sending any data if the session is
# not active, i.e. client hasn't authenticated.
jlog.warn("Websocket not sending notification, "
"the session is not active.")
return
self.sendMessage(json.dumps(info).encode())
def connectionLost(self, reason):
""" Overridden to ensure that we aren't attempting to
send notifications on broken connections.
"""
WebSocketServerProtocol.connectionLost(self, reason)
self.factory.unregister(self)
def onMessage(self, payload, isBinary):
""" We currently only allow messages which
are JWT tokens used for authentication. Any
other message will drop the connection.
"""
if not isBinary:
token = payload.decode('utf8')
# check that the token set for this protocol
# instance is valid.
try:
self.factory.token.verify(token)
self.active_session = True
except Exception as e:
jlog.debug(e)
self.dropConnection()
class JmwalletdWebSocketServerFactory(WebSocketServerFactory):
def __init__(self, url, token_authority = JMTokenAuthority()):
WebSocketServerFactory.__init__(self, url)
self.token = token_authority
self.clients = []
def register(self, client):
if client not in self.clients:
self.clients.append(client)
def unregister(self, client):
if client in self.clients:
self.clients.remove(client)
def sendTxNotification(self, txd, txid):
""" Note that this is a WalletService callback;
the return value is only important for conf/unconf
callbacks, not for 'all' callbacks, so we return
None
"""
json_tx = json.loads(human_readable_transaction(txd))
for client in self.clients:
client.sendNotification({"txid": txid,
"txdetails": json_tx})
def sendCoinjoinStatusUpdate(self, new_state):
""" The state sent is an integer, see
jmclient.wallet_rpc.
0: taker is running
1: maker is running (but not necessarily currently
coinjoining, note)
2: neither is running
"""
for client in self.clients:
client.sendNotification({"coinjoin_state": new_state})