--- a/src/Network/Socket.hh Mon Dec 15 16:41:00 2008 +0000
+++ b/src/Network/Socket.hh Mon Dec 15 23:56:42 2008 +0000
@@ -2,23 +2,165 @@
#define NETWORK_SOCKET_HH
#include "../Error.hh"
+#include "Address.hh"
-#include <ClanLib/Network/Socket/socket.h>
+/*
+ * Platform-specific includes
+ */
+#ifndef WIN32
+ // linux
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+
+ #define closesocket close
+#else
+ #error "This network code won't compile on win32 :)"
+#endif
+
#include <cerrno>
#include <cstring>
/**
- * We use ClanLib's Socket API, but with our own name
+ * We use ClanLib's Socket API, but with our own extensions...
*/
-typedef CL_Socket NetworkSocket;
+class NetworkSocket {
+ private:
+ /** The file descriptor */
+ int fd;
+
+ /** Socket domain */
+ int family;
+
+ /** Socket type */
+ int socktype;
+
+ /** Socket protocol */
+ int protocol;
+
+ /**
+ * Has the socket been explicitly bind()'d? If so, force ourselves to use this socket in connect().
+ */
+ bool bound;
+
+ /**
+ * Read/write signals
+ */
+ CL_Signal_v0 _sig_read, _sig_write;
+
+ public:
+ /**
+ * Construct a socket of the specific type. Family and protocol can be left as NULL, but type should usually
+ * be specified.
+ */
+ NetworkSocket (int family, int socktype, int protocol = 0);
+
+ /**
+ * Create a socket from the given pre-existing fd
+ */
+ NetworkSocket (int fd);
+
+ /**
+ * Force-close the socket if it's still open
+ */
+ ~NetworkSocket (void);
+
+ private:
+ // XXX: nocopy
+
+ /**
+ * 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
+ */
+ void force_close (void);
+
+ public:
+ /**
+ * Get the socket fd... promise not to break it
+ */
+ int get_socket (void) const { return fd; }
+
+ /**
+ * Bind to a specific local address
+ */
+ void bind (const NetworkAddress &addr);
+
+ /**
+ * Put socket into listen mode
+ */
+ void listen (int backlog);
+
+ /**
+ * Get local address
+ */
+ NetworkAddress get_local_address (void);
+
+ /**
+ * Get remote address
+ */
+ NetworkAddress get_remote_address (void);
+
+ /**
+ * Make send/recv/connect non-blocking
+ */
+ void set_nonblocking (bool nonblocking);
+
+ /**
+ * Accept a new connection, optionally giving the connection's source address
+ */
+ NetworkSocket* accept (NetworkAddress *src);
+
+ /**
+ * Establish a new connection
+ */
+ void connect (const NetworkAddress &addr);
+
+ /**
+ * Send, optionally using the specific destination
+ *
+ * @return number of bytes sent, zero if busy
+ * @throw NetworkSocketError on error
+ */
+ size_t send (const char *buf, size_t size, const NetworkAddress *dest = NULL);
+
+ /**
+ * Recv, optionally storing the source in src
+ *
+ * @return number of bytes received, zero if none available
+ * @throw NetworkSocketEOFError if the connection was closed
+ * @throw NetworkSocketError on error
+ */
+ size_t recv (char *buf, size_t size, NetworkAddress *src = NULL);
+
+ /**
+ * Close the socket
+ */
+ void close (void);
+
+ /**
+ * Triggered when socket becomes readable
+ */
+ CL_Signal_v0& sig_read (void) { return _sig_read; }
+
+ /**
+ * Triggered when socket becomes writeable after a send that returned zero
+ */
+ CL_Signal_v0& sig_write (void) { return _sig_write; }
+};
/**
* Base class for expcetions thrown by socket methods
*/
class NetworkSocketError : public Error {
protected:
- std::string build_str (const NetworkSocket &socket, const char *op, const char *err);
-
+ static std::string build_str (const NetworkSocket &socket, const char *op, const char *err);
+
+ public:
NetworkSocketError (const NetworkSocket &socket, const char *op, const char *err);
};