src/Network/Socket.hh
changeset 380 d193dd1d8a7e
parent 378 5589abf5e61b
child 381 9b35bc329d23
--- a/src/Network/Socket.hh	Tue Dec 16 20:30:35 2008 +0000
+++ b/src/Network/Socket.hh	Tue Dec 16 23:21:26 2008 +0000
@@ -1,8 +1,12 @@
 #ifndef NETWORK_SOCKET_HH
 #define NETWORK_SOCKET_HH
 
+// forward-declare
+class NetworkSocket;
+
 #include "../Error.hh"
 #include "Address.hh"
+#include "Reactor.hh"
 
 /*
  * Platform-specific includes
@@ -19,30 +23,61 @@
     #error "This network code won't compile on win32 :)"
 #endif
 
-#include <cerrno>
-#include <cstring>
-
 /**
  * We use ClanLib's Socket API, but with our own extensions...
  */
 class NetworkSocket {
     private:
+        /**
+         * Socket family/type/protocol
+         */
+        struct socket_type {
+            /** Socket domain */
+            int family;
+
+            /** Socket type */
+            int socktype;
+
+            /** Socket protocol */
+            int protocol;
+            
+            /** Simple constructor */
+            socket_type (int family = 0, int socktype = 0, int protocol = 0) : family(family), socktype(socktype), protocol(protocol) { }
+        };
+
+        /** These are nonzero if given via the constructor, used to filter out unwanted addrinfos */
+        socket_type sock_type;
+
         /** The file descriptor */
         int fd;
 
-        /** Socket domain */
-        int family;
-
-        /** Socket type */
-        int socktype;
-
-        /** Socket protocol */
-        int protocol;
+        /** Our current type, intialized via constructor, but updated by lazy_socket */
+        socket_type type;
 
         /** 
          * Has the socket been explicitly bind()'d? If so, force ourselves to use this socket in connect().
          */
-        bool bound;
+        bool bound : 1;
+
+        /**
+         * Registered to reactor?
+         */
+        bool registered : 1;
+
+        /**
+         * Do we want to know about recv()s?
+         */
+        bool want_read : 1;
+
+        /**
+         * Is the write buffer full?
+         */
+        bool want_write : 1;
+
+        /**
+         * The reactor that we use, defaults to NetworkReactor::current
+         */
+        NetworkReactor *reactor;
 
         /**
          * Read/write signals
@@ -52,14 +87,14 @@
     public:
         /**
          * Construct a socket of the specific type. Family and protocol can be left as NULL, but type should usually
-         * be specified.
+         * be specified. The given reactor is used for polling, defaults to NetworkReactor::current
          */
-        NetworkSocket (int family, int socktype, int protocol = 0);
+        NetworkSocket (int family, int socktype, int protocol = 0, NetworkReactor *reactor = NULL);
         
         /**
          * Create a socket from the given pre-existing fd
          */
-        NetworkSocket (int fd);
+        NetworkSocket (int fd, socket_type type, NetworkReactor *reactor = NULL);
 
         /**
          * Force-close the socket if it's still open
@@ -70,12 +105,17 @@
         // XXX: nocopy
         
         /**
+         * Reset bound+poll
+         */ 
+        void reset (void);
+
+        /**
          * Create a new socket of the given type, unless we already have one
          */
         void lazy_socket (int family, int type, int protocol);
         
         /**
-         * Close, ignoring errors
+         * Close and reset, ignoring errors
          */
         void force_close (void);
 
@@ -138,7 +178,7 @@
         size_t recv (char *buf, size_t size, NetworkAddress *src = NULL);
 
         /**
-         * Close the socket
+         * Close and reset the socket
          */
         void close (void);
 
@@ -151,6 +191,36 @@
          * Triggered when socket becomes writeable after a send that returned zero
          */
         CL_Signal_v0& sig_write (void) { return _sig_write; }
+
+        /**
+         * Register to NetworkReactor unless already registered
+         */
+        void register_poll (void);
+
+        /**
+         * Trigger sig_read() once socket is ready for recv?
+         */
+        void set_poll_read (bool want_read) { this->want_read = want_read; if (!registered) register_poll(); }
+
+        /**
+         * Trigger sig_write() once socket is ready for send?
+         */
+        void set_poll_write (bool want_write) { this->want_write = want_write; if (!registered) register_poll(); }
+
+        /**
+         * What events this socket is interested in.
+         */
+        NetworkPollMask get_poll (void) { 
+            return (want_read ? POLL_READ : 0) | (want_write ? POLL_WRITE : 0); 
+        }
+
+        /**
+         * Notify of events
+         */
+        void notify (NetworkPollMask mask) { 
+            if (mask & POLL_READ) _sig_read();
+            if (mask & POLL_WRITE) _sig_write();
+        }
 };
 
 /**
@@ -167,10 +237,9 @@
 /**
  * Errno-enabled exception, most common type of NetworkSocketError
  */
-class NetworkSocketOSError : public NetworkSocketError {
+class NetworkSocketErrno : public NetworkSocketError {
     public:
-        NetworkSocketOSError (const NetworkSocket &socket, const char *op) :
-            NetworkSocketError(socket, op, strerror(errno)) { }
+        NetworkSocketErrno (const NetworkSocket &socket, const char *op);
 };
 
 /**