--- 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);
};
/**