Browse Source

[1454] The handle_incoming request

Reads the request and passes it to be handled. If it fails, the
connection is closed.
Michal 'vorner' Vaner 13 years ago
parent
commit
a842f40cdd
2 changed files with 66 additions and 1 deletions
  1. 22 1
      src/bin/ddns/ddns.py.in
  2. 44 0
      src/bin/ddns/tests/ddns_test.py

+ 22 - 1
src/bin/ddns/ddns.py.in

@@ -138,11 +138,32 @@ class DDNSServer:
         session = isc.util.io.socketsession.SocketSessionReceiver(socket)
         self._socket_sessions[fileno] = (socket, session)
 
+    def handle_request(self, request):
+        """
+        This is called whenever a new DDNS request comes. Here the magic
+        happens, the rest is either subroutines of the magic or the accounting
+        around it that calls it from time to time.
+
+        It is called with the request being session as received from
+        SocketSessionReceiver, eg. tupple
+        (socket, local_address, remote_address, data).
+        """
+        # TODO: Implement the magic
+        pass
+
     def handle_incoming(self, fileno):
         """
         Handle incoming event on the socket with given fileno.
         """
-        pass
+        (socket, session) = self._socket_sessions[fileno]
+        try:
+            request = session.pop()
+            self.handle_request(request)
+        except isc.util.io.socketsession.SocketSessionError:
+            # No matter why this failed, the connection is in unknown, possibly
+            # broken state. So, we close the socket and remove the session.
+            del self._socket_sessions[fileno]
+            socket.close()
 
     def run(self):
         '''

+ 44 - 0
src/bin/ddns/tests/ddns_test.py

@@ -217,6 +217,50 @@ class TestDDNSServer(unittest.TestCase):
         self.assertIsNone(self.__select_answer)
         self.assertEqual(3, self.__hook_called)
 
+    def test_handle_incoming_ok(self):
+        """
+        Test the handle_incoming pops the session and calls handle_request
+        when everything is OK.
+        """
+        socket = FakeSocket(3)
+        session = FakeSession(socket)
+        # It doesn't really matter what data we use here, it is only passed
+        # through the code
+        param = (FakeSocket(4), ('127.0.0.1', 1234), ('127.0.0.1', 1235),
+                 'Some data')
+        def pop():
+            return param
+        # Prepare data into the session
+        session.pop = pop
+        self.ddns_server._socket_sessions = {3: (socket, session)}
+        self.ddns_server.handle_request = self.__hook
+        # Call it
+        self.ddns_server.handle_incoming(3)
+        # The popped data are passed into the handle_request
+        self.assertEqual(param, self.__hook_called)
+        # The sessions are kept the same
+        self.assertEqual({3: (socket, session)},
+                         self.ddns_server._socket_sessions)
+
+    def test_handle_incoming_fail(self):
+        """
+        Test the handle_incoming removes (and closes) the socket and session
+        when the session complains.
+        """
+        socket = FakeSocket(3)
+        session = FakeSession(socket)
+        def pop():
+            raise isc.util.io.socketsession.SocketSessionError('Test error')
+        session.pop = pop
+        socket.close = self.__hook
+        self.__hook_called = False
+        self.ddns_server._socket_sessions = {3: (socket, session)}
+        self.ddns_server.handle_incoming(3)
+        # The "dead" session is removed
+        self.assertEqual({}, self.ddns_server._socket_sessions)
+        # Close is called with no parameter, so the default None
+        self.assertIsNone(self.__hook_called)
+
 class TestMain(unittest.TestCase):
     def setUp(self):
         self._server = MyDDNSServer()