Browse Source

The run function

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/vorner-sockcreator@3162 e5f2f494-b856-4b98-b285-d166d9295462
Michal Vaner 14 years ago
parent
commit
66bb0f76db
2 changed files with 102 additions and 1 deletions
  1. 101 1
      src/bin/sockcreator/sockcreator.cc
  2. 1 0
      src/bin/sockcreator/sockcreator.h

+ 101 - 1
src/bin/sockcreator/sockcreator.cc

@@ -16,6 +16,10 @@
 
 #include <unistd.h>
 #include <cerrno>
+#include <cstring>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
 
 namespace isc {
 namespace socket_creator {
@@ -42,7 +46,103 @@ int
 run(const int input_fd, const int output_fd, const get_sock_t get_sock,
     const send_fd_t send_fd)
 {
-    // TODO Implement
+// These are macros so they can exit the function
+#define READ(WHERE, HOW_MANY) do { \
+        size_t how_many = (HOW_MANY); \
+        if (read_data(input_fd, (WHERE), how_many) < how_many) { \
+            return 1; \
+        } \
+    } while (0)
+#define WRITE(WHAT, HOW_MANY) do { \
+        size_t how_many = (HOW_MANY); \
+        if (!write_data(output_fd, (WHAT), (HOW_MANY))) { \
+            return 2; \
+        } \
+    } while (0)
+#define DEFAULT \
+    default: /* Unrecognized part of protocol */ \
+        WRITE("FI", 2); \
+        return 3;
+    for (;;) {
+        // Read the command
+        char command;
+        READ(&command, 1);
+        switch (command) {
+            case 'T': // The "terminate" command
+                return 0;
+            case 'S': { // Create a socket
+                // Read what type of socket they want
+                char type[2];
+                READ(type, 2);
+                // Read the address they ask for
+                struct sockaddr *addr(NULL);
+                size_t addr_len(0);
+                struct sockaddr_in addr_in;
+                struct sockaddr_in6 addr_in6;
+                switch (type[1]) { // The address family
+                    /*
+                     * Here are some casts. They are required by C++ and
+                     * the low-level interface (they are implicit in C).
+                     */
+                    case '4':
+                        addr = static_cast<struct sockaddr *>(
+                            static_cast<void *>(&addr_in));
+                        addr_len = sizeof addr_in;
+                        memset(&addr_in, 0, sizeof addr_in);
+                        addr_in.sin_family = AF_INET;
+                        READ(static_cast<char *>(static_cast<void *>(
+                            &addr_in.sin_port)), 2);
+                        READ(static_cast<char *>(static_cast<void *>(
+                            &addr_in.sin_addr.s_addr)), 4);
+                        break;
+                    case '6':
+                        addr = static_cast<struct sockaddr *>(
+                            static_cast<void *>(&addr_in6));
+                        addr_len = sizeof addr_in6;
+                        memset(&addr_in6, 0, sizeof addr_in6);
+                        addr_in6.sin6_family = AF_INET6;
+                        READ(static_cast<char *>(static_cast<void *>(
+                            &addr_in6.sin6_port)), 2);
+                        READ(static_cast<char *>(static_cast<void *>(
+                            &addr_in6.sin6_addr.s6_addr)), 16);
+                        break;
+                    DEFAULT
+                }
+                int sock_type;
+                switch (type[0]) { // Translate the type
+                    case 'T':
+                        sock_type = SOCK_STREAM;
+                        break;
+                    case 'U':
+                        sock_type = SOCK_DGRAM;
+                        break;
+                    DEFAULT
+                }
+                int result(get_sock(sock_type, addr, addr_len));
+                if (result >= 0) { // We got the socket
+                    WRITE("S", 1);
+                    send_fd(output_fd, result);
+                } else {
+                    WRITE("E", 1);
+                    switch (result) {
+                        case -1:
+                            WRITE("S", 1);
+                            break;
+                        case -2:
+                            WRITE("B", 1);
+                            break;
+                        default:
+                            return 4;
+                    }
+                    int error(errno);
+                    WRITE(static_cast<char *>(static_cast<void *>(&error)),
+                        sizeof error);
+                }
+                break;
+            }
+            DEFAULT
+        }
+    }
 }
 
 bool

+ 1 - 0
src/bin/sockcreator/sockcreator.h

@@ -81,6 +81,7 @@ int
  * - 1: Read error
  * - 2: Write error
  * - 3: Protocol error (unknown command, etc)
+ * - 4: Some internal inconsistency detected
  *
  * It terminates either if a command asks it to or when unrecoverable
  * error happens.