mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-28 08:03:36 +00:00
Started moving protocol-specific out of Santiago.
This commit is contained in:
parent
2f3741f7a3
commit
7c35b58363
@ -1,97 +0,0 @@
|
||||
import cherrypy
|
||||
import santiago
|
||||
from simplejson import JSONEncoder
|
||||
|
||||
encoder = JSONEncoder()
|
||||
|
||||
|
||||
# dirty hacks for Debian Squeeze (stable)
|
||||
# =======================================
|
||||
|
||||
def fix_old_cherrypy():
|
||||
"""Make Squeeze's CherryPy forward-compatible."""
|
||||
|
||||
for y in range(0,3):
|
||||
for x in range(0, 7):
|
||||
print "WARNING",
|
||||
print ""
|
||||
|
||||
print("You're using an old CherryPy version! We're faking it!")
|
||||
print("Expect the unexpected! Raar!")
|
||||
|
||||
def jsonify_tool_callback(*args, **kwargs):
|
||||
response = cherrypy.response
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = encoder.iterencode(response.body)
|
||||
|
||||
cherrypy.tools.json_out = cherrypy.Tool('before_finalize', jsonify_tool_callback, priority=30)
|
||||
|
||||
if cherrypy.__version__ < "3.2":
|
||||
fix_old_cherrypy()
|
||||
|
||||
|
||||
# actual HTTP Santiago classes.
|
||||
# =============================
|
||||
|
||||
class SantiagoHttpListener(santiago.SantiagoListener):
|
||||
"""Listens for connections on the HTTP protocol."""
|
||||
|
||||
DEFAULT_RESPONSE = """\
|
||||
<html><head><title>Use it right.</title></head><body>
|
||||
|
||||
<p>Nice try, now try again with a request like:</p>
|
||||
<p>http://localhost:8080/serve/(requester)/(server)/(service)</p>
|
||||
|
||||
<dl>
|
||||
<dt>requster</dt><dd>james, ian</dd>
|
||||
<dt>server</dt><dd>nick</dd>
|
||||
<dt>service</dt><dd>wiki, web</dd>
|
||||
</dl>
|
||||
|
||||
<p>This'll get you good results:</p>
|
||||
<code><a href="http://localhost:8080/serve/james/wiki/nick">
|
||||
http://localhost:8080/serve/james/wiki/nick</a></code>
|
||||
|
||||
<p>See the <code>serving_to</code>, <code>serving_what</code>, and
|
||||
<code>me</code> variables.</p>
|
||||
|
||||
</body></html>"""
|
||||
|
||||
def __init__(self, instance, location="localhost:8080"):
|
||||
super(SantiagoHttpListener, self).__init__(instance, location)
|
||||
self.socket_port = location.rpartition(":")[2]
|
||||
|
||||
@cherrypy.expose
|
||||
@cherrypy.tools.json_out()
|
||||
def serve(self, key=None, service=None, server=None, hops=3, santiagi=None):
|
||||
"""Handles an incoming request."""
|
||||
|
||||
return super(SantiagoHttpListener, self).serve(
|
||||
key, service, server, hops, santiagi)
|
||||
|
||||
@cherrypy.expose
|
||||
def index(self):
|
||||
"""Do nothing, unless we're debugging."""
|
||||
|
||||
if santiago.DEBUG:
|
||||
return self.DEFAULT_RESPONSE
|
||||
|
||||
|
||||
class SantiagoHttpSender(santiago.SantiagoSender):
|
||||
"""Responsible for answering HTTP requests."""
|
||||
|
||||
import urllib, urllib2
|
||||
|
||||
@cherrypy.tools.json_out()
|
||||
def proxy(self, key, service, server, hops=3):
|
||||
"""Forwards on a request to another Santiago."""
|
||||
|
||||
return super(SantiagoHttpSender, self).proxy(key, service, server, hops)
|
||||
|
||||
@cherrypy.tools.json_out()
|
||||
def send(self):
|
||||
"""Send messages to other Santiagi."""
|
||||
|
||||
for message in super(SantiagoSender, self).send():
|
||||
if message["location"].startswith("http"):
|
||||
urllib2.Request(message["location"],urllib.urlencode(message))
|
||||
@ -29,15 +29,14 @@ We also don't:
|
||||
- Use a reasonable data-store.
|
||||
- Have a decent control mechanism.
|
||||
|
||||
FIXME: Split into protocol-specific listeners and senders.
|
||||
FIXME: add that whole pgp thing.
|
||||
FIXME: remove @cherrypy.expose from everything but index.
|
||||
TODO: add doctests
|
||||
|
||||
"""
|
||||
import cherrypy
|
||||
from collections import defaultdict as DefaultDict
|
||||
#import gnupg
|
||||
import httplib, urllib
|
||||
import gnupg
|
||||
import sys
|
||||
|
||||
try:
|
||||
@ -54,10 +53,8 @@ def load_data(server, item):
|
||||
FIXME: use withsqlite instead.
|
||||
|
||||
"""
|
||||
data = ""
|
||||
with open("%s_%s" % (server, item)) as infile:
|
||||
data = eval(infile.read())
|
||||
return data
|
||||
return eval(infile.read())
|
||||
|
||||
|
||||
class SimpleSantiago(object):
|
||||
@ -103,6 +100,20 @@ class SimpleSantiago(object):
|
||||
def _create_listeners(self):
|
||||
"""Iterates through each known protocol creating listeners for all."""
|
||||
|
||||
# FIXME: Split into protocol-specific listeners and senders.
|
||||
|
||||
# def configure_gui(self):
|
||||
# """Launch the gui specified in the launcher's config files.
|
||||
#
|
||||
# """
|
||||
# gui_name = self.config.get(self.META_DATA, "gui")
|
||||
# import_name = "guis.%(gui_name)s.gemrb_gui_%(gui_name)s" % locals()
|
||||
# __import__(import_name) # TODO import every gui in the gui dir until one succeeds
|
||||
#
|
||||
# gui_module = sys.modules[import_name]
|
||||
#
|
||||
# self.gui = gui_module.Gui(self)
|
||||
|
||||
for protocol in self.listeners.iterkeys():
|
||||
method = "_create_%s_listener" % protocol
|
||||
|
||||
@ -111,25 +122,6 @@ class SimpleSantiago(object):
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def _create_http_listener(self, *args, **kwargs):
|
||||
"""Register an HTTP listener.
|
||||
|
||||
Merely a wrapper for _create_https_listener.
|
||||
|
||||
"""
|
||||
self._create_https_listener(*args, **kwargs)
|
||||
|
||||
def _create_https_listener(self, socket_port=0,
|
||||
ssl_certificate="", ssl_private_key=""):
|
||||
"""Registers an HTTPS listener."""
|
||||
|
||||
cherrypy.server.socket_port = socket_port
|
||||
cherrypy.server.ssl_certificate = ssl_certificate
|
||||
cherrypy.server.ssl_private_key = ssl_private_key
|
||||
|
||||
# reach deep into the voodoo to actually serve the index
|
||||
SimpleSantiago.index.__dict__["exposed"] = True
|
||||
|
||||
def am_i(self, server):
|
||||
"""Verify whether this server is the specified server."""
|
||||
|
||||
@ -166,7 +158,6 @@ class SimpleSantiago(object):
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
@cherrypy.expose
|
||||
def query(self, host, service):
|
||||
"""Request a service from another Santiago.
|
||||
|
||||
@ -178,7 +169,7 @@ class SimpleSantiago(object):
|
||||
self.request(host, self.me, host, self.me,
|
||||
service, None, self.get_client_locations(host, "santiago"))
|
||||
|
||||
def request(self, from_, to, host, client,
|
||||
def outgoing_request(self, from_, to, host, client,
|
||||
service, locations, reply_to):
|
||||
"""Send a request to another Santiago service.
|
||||
|
||||
@ -188,40 +179,15 @@ class SimpleSantiago(object):
|
||||
# best guess reply_to if we don't know.
|
||||
reply_to = reply_to or self.get_host_locations(to, "santiago")
|
||||
|
||||
request = self.gpg.sign_encrypt({
|
||||
"from": from_, "to": to, "host": host, "client": client,
|
||||
"service": service, "locations": locations or "",
|
||||
"reply_to": reply_to})
|
||||
|
||||
for destination in self.get_client_locations(to, "santiago"):
|
||||
getattr(self, destination.split(":")[0] + "_request") \
|
||||
(from_, to, host, client,
|
||||
service, locations, destination, reply_to)
|
||||
getattr(self, destination.split(":")[0] + "_request")(request)
|
||||
|
||||
def https_request(self, from_, to, host, client,
|
||||
service, locations, destination, reply_to):
|
||||
"""Send an HTTPS request to each Santiago client.
|
||||
|
||||
Don't queue, just immediately send the reply to each location we know.
|
||||
|
||||
It's both simple and as reliable as possible.
|
||||
|
||||
TODO: pgp sign and encrypt
|
||||
|
||||
"""
|
||||
params = urllib.urlencode(
|
||||
{"from": from_, "to": to, "host": host, "client": client,
|
||||
"service": service, "locations": locations or "",
|
||||
"reply_to": reply_to})
|
||||
|
||||
proxy = self.senders["https"]
|
||||
|
||||
# TODO: Does HTTPSConnection require the cert and key?
|
||||
# Is the fact that the server has it sufficient? I think so.
|
||||
connection = httplib.HTTPSConnection(destination.split("//")[1])
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
connection.set_tunnel(proxy["host"], proxy["port"])
|
||||
|
||||
connection.request("GET", "/?%s" % params)
|
||||
connection.close()
|
||||
|
||||
def index(self, **kwargs):
|
||||
def incoming_request(self, **kwargs):
|
||||
"""Provide a service to a client.
|
||||
|
||||
This tag doesn't do any real processing, it just catches and hides
|
||||
@ -309,6 +275,8 @@ class SimpleSantiago(object):
|
||||
Attempt to contact the other Santiago and ask it to reply both to the
|
||||
original host as well as me.
|
||||
|
||||
TODO: add tests.
|
||||
|
||||
"""
|
||||
self.request(self.me, to, host, client,
|
||||
service, reply_to)
|
||||
@ -343,14 +311,13 @@ class SimpleSantiago(object):
|
||||
self.learn_service(host, service, locations)
|
||||
self.requests[host].remove(service)
|
||||
|
||||
@cherrypy.expose
|
||||
def save_server(self):
|
||||
"""Save all operational data to files.
|
||||
|
||||
Save all files with the ``self.me`` prefix.
|
||||
|
||||
"""
|
||||
for datum in ("hosting", "consuming", "listeners", "senders"):
|
||||
for datum in ("hosting", "consuming"):
|
||||
name = "%s_%s" % (self.me, datum)
|
||||
|
||||
try:
|
||||
@ -359,6 +326,18 @@ class SimpleSantiago(object):
|
||||
except:
|
||||
pass
|
||||
|
||||
class SantiagoListener(object):
|
||||
"""Generic Santiago Listener superclass."""
|
||||
|
||||
def __init__(self, santiago):
|
||||
self.santiago = santiago
|
||||
|
||||
class SantiagoSender(object):
|
||||
"""Generic Santiago Sender superclass."""
|
||||
|
||||
def __init__(self, santiago):
|
||||
self.santiago = santiago
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# FIXME: convert this to the withsqlite setup.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user