src/Network/Socket.hh
changeset 378 5589abf5e61b
parent 284 27ce69fd1e06
child 380 d193dd1d8a7e
--- 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);
 };