Index: lib/cros_test_proxy.py |
diff --git a/lib/cros_test_proxy.py b/lib/cros_test_proxy.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..2d39c45cdbef5c17ee9d05fc2d2a062c36ce7276 |
--- /dev/null |
+++ b/lib/cros_test_proxy.py |
@@ -0,0 +1,105 @@ |
+#!/usr/bin/python |
+ |
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+import select |
+import socket |
+import SocketServer |
+import threading |
+ |
+class Filter(object): |
+ """Base class for data filters. |
+ |
+ Pass an instance of this to CrosTestProxy |
+ """ |
+ |
+ def setup(self): |
+ """This setup method is called once per connection.""" |
+ pass |
+ |
+ def InBound(self, data): |
+ """This method is called once per packet of incoming data. |
+ |
+ The value returned is what is sent through the proxy. If |
+ None is returned, the connection will be closed. |
+ """ |
+ return data |
+ |
+ def OutBound(self, data): |
+ """This method is called once per packet of outgoing data. |
+ |
+ The value returned is what is sent through the proxy. If |
+ None is returned, the connection will be closed. |
+ """ |
+ return data |
+ |
+ |
+class CrosTestProxy(SocketServer.ThreadingMixIn, SocketServer.TCPServer): |
+ """A transparent proxy for simulating network errors""" |
+ |
+ class _Handler(SocketServer.BaseRequestHandler): |
+ """Proxy connection handler that passes data though a filter""" |
+ |
+ def setup(self): |
adlr
2010/12/07 02:26:51
please add a docstring for each method/function
dgarrett
2010/12/07 03:48:18
Done.
|
+ self.server.filter.setup() |
+ |
+ def handle(self): |
+ # Open outgoing socket |
+ s_in = self.request |
+ s_out = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
+ s_out.connect( (self.server.address_out, self.server.port_out) ) |
sosa
2010/12/07 03:44:36
additional spaces unnecessary
dgarrett
2010/12/07 04:08:51
Done.
|
+ |
+ while True: |
+ rlist, wlist, xlist = select.select([s_in, s_out], [], []) |
+ |
+ if s_in in rlist: |
+ data = s_in.recv(1024) |
+ data = self.server.filter.InBound(data) |
+ if not data: break |
+ try: |
+ s_out.sendall(data) |
+ except: |
+ break |
sosa
2010/12/07 03:44:36
when would get either of these exceptions (here an
dgarrett
2010/12/07 04:08:51
Usually because the connections are closed at the
|
+ |
+ if s_out in rlist: |
+ data = s_out.recv(1024) |
+ data = self.server.filter.OutBound(data) |
+ if not data: break |
+ try: |
+ s_in.sendall(data) |
+ except: |
+ break |
+ |
+ s_in.close() |
+ s_out.close() |
+ |
+ def __init__(self, |
sosa
2010/12/07 03:44:36
i try to define this at the top of classes...up to
dgarrett
2010/12/07 04:08:51
Done.
|
+ filter, |
+ port_in=8081, |
+ address_out='127.0.0.1', port_out=8080): |
+ self.port_in = port_in |
+ self.address_out = address_out |
+ self.port_out = port_out |
+ self.filter = filter |
+ |
+ SocketServer.TCPServer.__init__(self, |
+ ('', port_in), |
+ self._Handler) |
+ |
+ def serve_forever_in_thread(self): |
+ """Call serve_forever in a new thread""" |
+ server_thread = threading.Thread(target=self.serve_forever) |
+ server_thread.setDaemon(True) |
+ server_thread.start() |
+ |
+ return server_thread |
+ |
+ |
+def main(): |
+ s = CrosTestProxy(port_in=2222, port_out=22, filter=Filter()) |
+ s.serve_forever() |
+ |
sosa
2010/12/07 03:44:36
two lines
dgarrett
2010/12/07 04:08:51
Done.
|
+if __name__ == '__main__': |
+ main() |