mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-18 17:00:24 +00:00
make more things work
This commit is contained in:
parent
38ed6a094a
commit
816ceb12cb
@ -1,3 +1,5 @@
|
||||
import json
|
||||
|
||||
from autobahn.twisted.resource import WebSocketResource
|
||||
from autobahn.twisted.websocket import WebSocketServerFactory
|
||||
from autobahn.twisted.websocket import WebSocketServerProtocol
|
||||
@ -6,6 +8,8 @@ from autobahn.websocket.types import ConnectionDeny
|
||||
from twisted.web import resource, server
|
||||
from twisted.python.failure import Failure
|
||||
|
||||
import eliot
|
||||
|
||||
from allmydata.util.hashutil import timing_safe_compare
|
||||
from .common import humanize_failure
|
||||
|
||||
@ -16,45 +20,55 @@ class TokenAuthenticatedWebSocketServerProtocol(WebSocketServerProtocol):
|
||||
|
||||
def onConnect(self, req):
|
||||
if 'authorization' in req.headers:
|
||||
token = req.headers['authorization'].encode('ascii')
|
||||
if timing_safe_compare(token, self.factory.tahoe_client.get_auth_token()):
|
||||
print("we're here, it's fine")
|
||||
# we don't care what WebSocket sub-protocol is
|
||||
# negotiated, nor do we need to send headers to the
|
||||
# client, so we ask Autobahn to just allow this
|
||||
# connectino with the defaults. We could return a
|
||||
# (headers, protocol) pair here instead if required.
|
||||
return None
|
||||
auth = req.headers['authorization'].encode('ascii').split(' ', 1)
|
||||
if len(auth) == 2:
|
||||
tag, token = auth
|
||||
if tag == "tahoe-lafs":
|
||||
if timing_safe_compare(token, self.factory.tahoe_client.get_auth_token()):
|
||||
# we don't care what WebSocket sub-protocol is
|
||||
# negotiated, nor do we need to send headers to the
|
||||
# client, so we ask Autobahn to just allow this
|
||||
# connection with the defaults. We could return a
|
||||
# (headers, protocol) pair here instead if required.
|
||||
return None
|
||||
|
||||
# everything else -- i.e. no Authorization header, or it's
|
||||
# wrong -- means we deny the websocket connection
|
||||
raise ConnectionDeny(
|
||||
code=406,
|
||||
code=ConnectionDeny.NOT_ACCEPTABLE,
|
||||
reason=u"Invalid or missing token"
|
||||
)
|
||||
|
||||
def _received_eliot_log(self, message):
|
||||
# probably want a try/except around here? what do we do if
|
||||
# transmission fails or anything else bad?
|
||||
self.sendMessage(json.dumps(message))
|
||||
|
||||
class LogStreamingWebSocket(resource.Resource):
|
||||
def onOpen(self):
|
||||
# self.factory.tahoe_client.add_log_streaming_client(self)
|
||||
# hmm, instead of something like ^ maybe we just add eliot
|
||||
# stuff ourselves...
|
||||
eliot.add_destination(self._received_eliot_log)
|
||||
|
||||
def onClose(self, wasClean, code, reason):
|
||||
#self.factory.tahoe_client.remove_log_streaming_client(self)
|
||||
try:
|
||||
eliot.remove_destination(self._received_eliot_log)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
def create_log_streaming_resource(client, websocket_url):
|
||||
"""
|
||||
Create a new resource that accepts WebSocket connections if they
|
||||
include a correct `Authorization: tahoe-lafs <api_auth_token>`
|
||||
header (where `api_auth_token` matches the private configuration
|
||||
value).
|
||||
"""
|
||||
|
||||
def __init__(self, client):
|
||||
self._client = client
|
||||
self._factory = WebSocketServerFactory(u"ws://127.0.0.1:6301/logs_v1")
|
||||
self._factory.tahoe_client = client
|
||||
self._factory.protocol = TokenAuthenticatedWebSocketServerProtocol
|
||||
self._ws_resource = WebSocketResource(self._factory)
|
||||
|
||||
def render(self, req):
|
||||
print(req)
|
||||
print(dir(req.headers))
|
||||
print(req.headers.keys())
|
||||
return self._ws_resource.render(req)
|
||||
|
||||
|
||||
|
||||
def create_log_streaming_resource(client):
|
||||
return LogStreamingWebSocket(client)
|
||||
factory = WebSocketServerFactory(websocket_url)
|
||||
factory.tahoe_client = client
|
||||
factory.protocol = TokenAuthenticatedWebSocketServerProtocol
|
||||
return WebSocketResource(factory)
|
||||
|
||||
|
||||
def _create_log_streaming_resource(client):
|
||||
|
@ -1,6 +1,7 @@
|
||||
import time, os, json
|
||||
|
||||
from twisted.web import http
|
||||
from twisted.internet import endpoints
|
||||
from nevow import rend, url, tags as T
|
||||
from nevow.inevow import IRequest
|
||||
from nevow.static import File as nevow_File # TODO: merge with static.File?
|
||||
@ -150,7 +151,7 @@ class Root(MultiFormatPage):
|
||||
"no": "Disconnected",
|
||||
}
|
||||
|
||||
def __init__(self, client, clock=None, now_fn=None):
|
||||
def __init__(self, client, clock=None, now_fn=None, webport=None):
|
||||
rend.Page.__init__(self, client)
|
||||
self.client = client
|
||||
# If set, clock is a twisted.internet.task.Clock that the tests
|
||||
@ -170,7 +171,13 @@ class Root(MultiFormatPage):
|
||||
self.child_magic_folder = magic_folder.MagicFolderWebApi(client)
|
||||
|
||||
# handler for "/logs_v1" URIs
|
||||
self.child_logs_v1 = create_log_streaming_resource(client)
|
||||
# note, webport can be a bare port or a Twisted endpoint-string
|
||||
if webport.startswith("tcp:"):
|
||||
port = webport.split(':')[1]
|
||||
else:
|
||||
port = webport
|
||||
websocket_url = u"ws://127.0.0.1:{}/logs_v1".format(port)
|
||||
self.child_logs_v1 = create_log_streaming_resource(client, websocket_url)
|
||||
|
||||
self.child_file = FileHandler(client)
|
||||
self.child_named = FileHandler(client)
|
||||
|
@ -161,7 +161,11 @@ class WebishServer(service.MultiService):
|
||||
# twisted.internet.task.Clock that is provided by the unit tests
|
||||
# so that they can test features that involve the passage of
|
||||
# time in a deterministic manner.
|
||||
self.root = root.Root(client, clock, now_fn)
|
||||
|
||||
# beware, 'webport' can be a Twisted endpoint-string sometimes
|
||||
# it seems
|
||||
print("webport {}".format(webport))
|
||||
self.root = root.Root(client, clock, now_fn, webport=webport)
|
||||
self.buildServer(webport, nodeurl_path, staticdir)
|
||||
if self.root.child_operations:
|
||||
self.site.remember(self.root.child_operations, IOpHandleTable)
|
||||
|
81
ws_client.py
81
ws_client.py
@ -1,56 +1,63 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import json
|
||||
import sys
|
||||
|
||||
from twisted.internet.task import react
|
||||
from twisted.internet.defer import inlineCallbacks, Deferred
|
||||
|
||||
from autobahn.twisted.websocket import (
|
||||
WebSocketClientProtocol,
|
||||
WebSocketClientFactory,
|
||||
)
|
||||
|
||||
|
||||
|
||||
from autobahn.twisted.websocket import WebSocketClientProtocol, \
|
||||
WebSocketClientFactory
|
||||
|
||||
|
||||
class MyClientProtocol(WebSocketClientProtocol):
|
||||
|
||||
def onConnect(self, response):
|
||||
print("Server connected: {0}".format(response.peer))
|
||||
class TahoeLogProtocol(WebSocketClientProtocol):
|
||||
"""
|
||||
"""
|
||||
|
||||
def onOpen(self):
|
||||
print("WebSocket connection open.")
|
||||
|
||||
def hello():
|
||||
self.sendMessage(u"Hello, world!".encode('utf8'))
|
||||
self.sendMessage(b"\x00\x01\x03\x04", isBinary=True)
|
||||
self.factory.reactor.callLater(1, hello)
|
||||
|
||||
# start sending messages every second ..
|
||||
hello()
|
||||
pass#print("connected")
|
||||
|
||||
def onMessage(self, payload, isBinary):
|
||||
if isBinary:
|
||||
print("Binary message received: {0} bytes".format(len(payload)))
|
||||
if False:
|
||||
log_data = json.loads(payload.decode('utf8'))
|
||||
print("eliot message:")
|
||||
for k, v in log_data.items():
|
||||
print(" {}: {}".format(k, v))
|
||||
else:
|
||||
print("Text message received: {0}".format(payload.decode('utf8')))
|
||||
print(payload)
|
||||
sys.stdout.flush()
|
||||
|
||||
def onClose(self, wasClean, code, reason):
|
||||
print("WebSocket connection closed: {0}".format(reason))
|
||||
def onClose(self, *args):
|
||||
print("bye", args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@inlineCallbacks
|
||||
def main(reactor):
|
||||
|
||||
import sys
|
||||
|
||||
from twisted.python import log
|
||||
from twisted.internet import reactor
|
||||
|
||||
log.startLogging(sys.stdout)
|
||||
|
||||
with open("alice/private/api_auth_token", "r") as f:
|
||||
with open("testgrid/alice/private/api_auth_token", "r") as f:
|
||||
#with open("alice/private/api_auth_token", "r") as f:
|
||||
token = f.read().strip()
|
||||
|
||||
factory = WebSocketClientFactory(
|
||||
url=u"ws://127.0.0.1:6301/logs_v1",
|
||||
url=u"ws://127.0.0.1:8890/logs_v1",
|
||||
headers={
|
||||
"Authorization": token,
|
||||
"Authorization": "tahoe-lafs {}".format(token),
|
||||
}
|
||||
)
|
||||
factory.protocol = MyClientProtocol
|
||||
factory.protocol = TahoeLogProtocol
|
||||
port = yield reactor.connectTCP("127.0.0.1", 8890, factory)
|
||||
if False:
|
||||
print("port {}".format(port))
|
||||
print(dir(port))
|
||||
print(port.getDestination())
|
||||
print(port.transport)
|
||||
print(dir(port.transport))
|
||||
print(port.transport.protocol)
|
||||
# can we like 'listen' for this connection/etc to die?
|
||||
yield Deferred()
|
||||
|
||||
reactor.connectTCP("127.0.0.1", 6301, factory)
|
||||
|
||||
reactor.run()
|
||||
if __name__ == '__main__':
|
||||
react(main)
|
||||
|
Loading…
x
Reference in New Issue
Block a user