diff options
-rw-r--r-- | rpkid/rpki/async.py | 23 | ||||
-rw-r--r-- | rpkid/rpki/https.py | 26 |
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 |