[Server-devel] [PATCH 1/2] xs-activation-tcpserver: use non-blocking reads
Daniel Drake
dsd at laptop.org
Thu Dec 29 15:55:33 EST 2011
Using non-blocking reads cleans up the code a little and paves the
way for easy addition of further request formats.
The only functional change here is the logging of unknown requests
(truncated to 48 characters max) - the server should otherwise
behave as before.
---
xs-activation-tcpserver.py | 77 +++++++++++++++++++++++--------------------
1 files changed, 41 insertions(+), 36 deletions(-)
diff --git a/xs-activation-tcpserver.py b/xs-activation-tcpserver.py
index 40f7424..942eaf1 100755
--- a/xs-activation-tcpserver.py
+++ b/xs-activation-tcpserver.py
@@ -8,6 +8,8 @@ import sys, os.path
from subprocess import *
import re
import oat
+import select
+import fcntl
# Setup logging to logger.
# The logger process will be reaped
@@ -19,6 +21,11 @@ sys.stderr = loggersocket
myoat = oat.oat()
+# make stdin a non-blocking file
+fd = sys.stdin.fileno()
+fl = fcntl.fcntl(fd, fcntl.F_GETFL)
+fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
+
def log_error(str):
sys.stderr.write(str + "\n")
@@ -40,13 +47,7 @@ def check_stolen(sn):
sys.stderr.write("STOLEN: %s\n" % sn)
exit()
-######## Main ###########
-
-# first we read 11 chars
-req = sys.stdin.read(11)
-
-if re.match('^[A-Z0-9]{11}$', req):
-
+def send_lease(req):
# naked sn
sn = req
@@ -70,37 +71,41 @@ if re.match('^[A-Z0-9]{11}$', req):
sys.stdout.write("UNKNOWN\n")
exit()
-else:
- m = re.match('^([a-zA-Z0-9]+): ', req)
- if not m:
- log_error("cannot understand input: " + req)
+def send_time(req):
+ # remove time01: prefix
+ req = req[8:]
+
+ # read params
+ (sn, nonce) = req.split(' ')
+ if not (len(sn)==11 and len(nonce)==22):
+ log_error("cannot understand input: " + params)
exit(1)
- cmd = m.group(1)
- paramhead = req[len(m.group(0)):]
-
- if cmd == 'time01':
- # read the remainder of the 11 char sn
- paramtail = sys.stdin.read(11+1+22 - len(paramhead))
- params = paramhead+paramtail
- (sn, nonce) = params.split(' ')
- if not (len(sn)==11 and len(nonce)==22):
- log_error("cannot understand input: " + params)
- exit(1)
-
- sys.stderr.write("Time request for %s\n" % sn)
- check_stolen(sn)
- timemsg = myoat.get_time(sn, nonce)
-
- if timemsg:
- # log
- sys.stdout.write(timemsg)
- exit()
- else:
- sys.stderr.write("Could not serve time request for %s - probable cause: no lease available\n" % sn)
+ sys.stderr.write("Time request for %s\n" % sn)
+ check_stolen(sn)
+ timemsg = myoat.get_time(sn, nonce)
+ if timemsg:
+ # log
+ sys.stdout.write(timemsg)
+ exit()
else:
- # unknown command?
- log_error("unknown command: " + cmd)
- exit(1)
+ sys.stderr.write("Could not serve time request for %s - probable cause: no lease available\n" % sn)
+
+######## Main ###########
+
+# wait for data to arrive
+if not select.select([sys.stdin], [], [], 30):
+ log_error("Timeout receiving data")
+ exit(1)
+
+req = sys.stdin.read()
+if re.match('^[A-Z0-9]{11}$', req):
+ send_lease(req)
+elif req.startswith('time01: '):
+ send_time(req)
+else:
+ # unknown command? log up to 48 chars to minimize chance of DoS flood
+ log_error("unknown request: " + req[:48])
+ exit(1)
--
1.7.7.4
More information about the Server-devel
mailing list