aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2009-05-03 22:17:06 +0000
committerRob Austein <sra@hactrn.net>2009-05-03 22:17:06 +0000
commit324117c277c4fd0395093583dab7c12acba9d2a2 (patch)
treea7fb41afc46e826afc68a9192423576705878503 /scripts
parent4b31f400f6509bb26c390d688fa47eba73e7a3cb (diff)
Checkpoint. Client side code not working right, closes before
completing all tasks. Dropped event, queuing data to closed socket, not sure what problem is yet. svn path=/scripts/async-http.py; revision=2394
Diffstat (limited to 'scripts')
-rw-r--r--scripts/async-http.py63
1 files changed, 29 insertions, 34 deletions
diff --git a/scripts/async-http.py b/scripts/async-http.py
index 47412d94..89cd6957 100644
--- a/scripts/async-http.py
+++ b/scripts/async-http.py
@@ -39,7 +39,7 @@ PERFORMANCE OF THIS SOFTWARE.
# significantly depending on whether client signals HTTP 1.0 or 1.1;
# the latter produces chunked output.
-import sys, os, time, socket, asyncore, asynchat, traceback, urlparse
+import sys, os, time, socket, asyncore, asynchat, traceback, urlparse, signal
import rpki.async, rpki.sundial
debug = True
@@ -174,12 +174,13 @@ class http_stream(asynchat.async_chat):
self.timer = rpki.async.timer(self.handle_timeout)
self.restart()
- def restart(self):
+ def restart(self, idle = True):
assert not self.buffer
self.chunk_handler = None
self.set_terminator("\r\n\r\n")
- if self.idle_timeout is not None:
- self.timer.set(self.idle_timeout)
+ timeout = self.idle_timeout if idle else self.active_timeout
+ if timeout is not None:
+ self.timer.set(timeout)
else:
self.timer.cancel()
@@ -366,7 +367,7 @@ class http_client(http_stream):
self.state = "request-sent"
msg.headers["Connection"] = "Close" if self.expect_close else "Keep-Alive"
self.push(msg.format())
- self.restart()
+ self.restart(idle = False)
def handle_message(self):
if not self.msg.persistent():
@@ -396,10 +397,13 @@ class http_client(http_stream):
if msg is not None:
self.log("Got a new message to send from my queue")
self.send_request(msg)
- else:
+ elif self.expect_close:
self.log("Closing")
self.state = "closing"
self.close_when_done()
+ else:
+ self.log("Idling")
+ self.timer.set(self.idle_timeout)
def handle_connect(self):
self.log("Connected")
@@ -419,11 +423,13 @@ class http_queue(object):
log = logger
def __init__(self, hostport, *requests):
+ self.log("Creating queue for %r with initial requests %r" % (hostport, requests))
self.hostport = hostport
self.queue = list(requests)
self.client = http_client(self, hostport)
def request(self, *requests):
+ self.log("Adding requests %r" % requests)
need_kick = self.client.state == "idle" and not self.queue
self.queue.extend(requests)
if need_kick:
@@ -458,39 +464,15 @@ class http_manager(dict):
request = http_request(cmd = "POST", path = u.path, body = body, callback = callback,
Host = u.hostname, Content_Type = "text/plain")
hostport = (u.hostname or "localhost", u.port or 80)
+ self.log("Created request %r for %r" % (request, hostport))
if hostport in self:
self[hostport].request(request)
else:
self[hostport] = http_queue(hostport, request)
-# server: reuse rest-style dispatcher from current https code.
-#
-# add downcall to set result: don't do this presently, because
-# can't, but want it in new code. so break async_http
-# http_server.handle_message() into two method, one handles
-# upcall to app dispatch, other is downcall to send result;
-# latter probably used as bound method passed as callback to
-# app.
-#
-# dunno if client method hack (below) would work for server.
-# maybe. if so it would be a method of the request message
-# which would need to include a handle on the server stream.
-#
-# client: need callback; right now demo code just consumes result
-# directly (by printing it), for real use we need to give result
-# to somebody. hand them the query message too, for matchup?
-# we're pulling it off queue as part of response processing
-# anyway, might be useful to make it available. or even make
-# the callback for the result be a method of the query message,
-# which has the cute property that we can have multiple methods,
-# eg one for callback, one for errback.
-
-
def client(msg, url, timeout = 300, callback = None):
pass
-import signal
-
def server(handlers, port, host ="", catch_signals = (signal.SIGINT, signal.SIGTERM)):
if not isinstance(handlers, (tuple, list)):
handlers = (("/", handlers),)
@@ -529,13 +511,26 @@ if len(sys.argv) == 1:
else:
- def got_it(msg):
+ def got_one(msg):
print "Got response:"
print msg
print
manager = http_manager()
- for url in sys.argv[1:]:
- manager.query(url = url, callback = got_it, body = "Hi, I'm trying to talk to URL %s" % url)
+
+ timer = rpki.async.timer()
+
+ def loop(iterator, url):
+ print "[Scheduler loop]"
+ manager.query(url = url, callback = got_one, body = "Hi, I'm trying to talk to URL %s" % url)
+ timer.set(rpki.sundial.timedelta(seconds = 3))
+
+ def done():
+ print "[Scheduler done]"
+ for q in manager.values():
+ assert not q.queue, "Requests still scheduled: %r %r" % (q.hostport, q.queue)
+ assert not async.timer.queue, "Timers still scheduled: %r" % async.timer.queue
+
+ timer.set_handler(rpki.async.iterator(sys.argv[1:], loop, done))
rpki.async.event_loop()