aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rpkid/rpki/async.py23
-rw-r--r--rpkid/rpki/https.py26
2 files changed, 38 insertions, 11 deletions
diff --git a/rpkid/rpki/async.py b/rpkid/rpki/async.py
index 83df75eb..5b7cfa48 100644
--- a/rpkid/rpki/async.py
+++ b/rpkid/rpki/async.py
@@ -18,7 +18,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
"""
-import asyncore, signal
+import asyncore, signal, traceback
import rpki.log, rpki.sundial
class iterator(object):
@@ -76,9 +76,11 @@ class timer(object):
queue = []
- def __init__(self, handler = None):
+ def __init__(self, handler = None, errback = None):
if handler is not None:
self.set_handler(handler)
+ if errback is not None:
+ self.set_errback(errback)
def set(self, when):
"""Set a timer. Argument can be a datetime, to specify an
@@ -126,13 +128,28 @@ class timer(object):
"""
self.handler = handler
+ def errback(self, e):
+ """Error callback. May be overridden, or set with set_errback()."""
+ rpki.log.error("Unhandled exception from timer: %s" % e)
+ rpki.log.error(traceback.format_exc())
+
+ def set_errback(self, errback):
+ """Set a timer's errback. Like set_handler(), for errbacks."""
+ self.errback = errback
+
@classmethod
def runq(cls):
"""Run the timer queue: for each timer whose call time has passed,
pull the timer off the queue and call its handler() method.
"""
while cls.queue and rpki.sundial.now() >= cls.queue[0].when:
- cls.queue.pop(0).handler()
+ t = cls.queue.pop(0)
+ try:
+ t.handler()
+ except asyncore.ExitNow:
+ raise
+ except Exception, e:
+ t.errback(e)
def __repr__(self):
return "<%s %r %r>" % (self.__class__.__name__, self.when, self.handler)
diff --git a/rpkid/rpki/https.py b/rpkid/rpki/https.py
index 97c3678d..cdaa4c64 100644
--- a/rpkid/rpki/https.py
+++ b/rpkid/rpki/https.py
@@ -130,13 +130,14 @@ class http_message(object):
class http_request(http_message):
- def __init__(self, cmd = None, path = None, version = default_http_version, body = None, callback = None, **headers):
+ def __init__(self, cmd = None, path = None, version = default_http_version, body = None, callback = None, errback = None, **headers):
if cmd is not None and cmd != "POST" and body is not None:
raise RuntimeError
http_message.__init__(self, version = version, body = body, headers = headers)
self.cmd = cmd
self.path = path
self.callback = callback
+ self.errback = errback
self.retried = False
def retry(self):
@@ -401,12 +402,16 @@ class http_client(http_stream):
raise RuntimeError, "[%r: Unexpected state]" % self
self.state = "idle"
if msg != None:
- if self.msg.code != 200:
- rpki.log.debug("HTTPS client returned failure")
- msg.callback(rpki.exceptions.HTTPRequestFailed("HTTP request failed with status %s, reason %s, response %s" % (self.msg.code, self.msg.reason, self.msg.body)))
- else:
- self.log("Delivering HTTPS client result")
- msg.callback(self.msg.body)
+ try:
+ if self.msg.code != 200:
+ rpki.log.debug("HTTPS client returned failure")
+ msg.errback(rpki.exceptions.HTTPRequestFailed("HTTP request failed with status %s, reason %s, response %s" % (self.msg.code, self.msg.reason, self.msg.body)))
+ else:
+ self.log("Delivering HTTPS client result")
+ msg.callback(self.msg.body)
+ except Exception, data:
+ self.log("Unhandled exception from callback")
+ rpki.log.error(traceback.format_exc())
msg = self.queue.next_request(not self.expect_close)
if msg is not None and self.state is "idle":
self.log("Got a new message to send from my queue")
@@ -492,6 +497,7 @@ class http_queue(object):
self.queue[0].retry()
except:
self.log("Queue is not empty, but request has already been transmitted, giving up")
+ self.client = None
raise
else:
self.log("Queue is not empty, starting new client")
@@ -499,7 +505,11 @@ class http_queue(object):
queues = {}
-def client(msg, client_key, client_cert, server_ta, url, timeout = 300, callback = None):
+def default_client_errback(e):
+ """Default errback for clients."""
+ raise e
+
+def client(msg, client_key, client_cert, server_ta, url, timeout = 300, callback = None, errback = default_client_errback):
"""Open client HTTPS connection, send a message, wait for response.
THIS VERSION DOES NOT DO TLS. THIS IS EXPERIMENTAL CODE. DO NOT