]> git.tdb.fi Git - libs/net.git/commitdiff
Add ClientSocket and ServerSocket abstractions
authorMikko Rasa <tdb@tdb.fi>
Sat, 6 Aug 2011 20:17:41 +0000 (23:17 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 6 Aug 2011 20:17:41 +0000 (23:17 +0300)
15 files changed:
examples/netcat.cpp
source/clientsocket.cpp [new file with mode: 0644]
source/clientsocket.h [new file with mode: 0644]
source/datagramsocket.cpp
source/datagramsocket.h
source/serversocket.cpp [new file with mode: 0644]
source/serversocket.h [new file with mode: 0644]
source/socket.cpp
source/socket.h
source/streamlistensocket.cpp [deleted file]
source/streamlistensocket.h [deleted file]
source/streamserversocket.cpp [new file with mode: 0644]
source/streamserversocket.h [new file with mode: 0644]
source/streamsocket.cpp
source/streamsocket.h

index 2532959e56ec7e8b595c035d7334b14c797a8b95..9bbad87b8d0fa944a636cf52e28ba37f67d7e8ee 100644 (file)
@@ -3,7 +3,7 @@
 #include <msp/core/refptr.h>
 #include <msp/io/console.h>
 #include <msp/io/eventdispatcher.h>
-#include <msp/net/streamlistensocket.h>
+#include <msp/net/streamserversocket.h>
 #include <msp/net/streamsocket.h>
 #include <msp/net/resolve.h>
 
@@ -15,7 +15,7 @@ class NetCat: public RegisteredApplication<NetCat>
 private:
        bool ipv6;
        bool listen;
-       Net::StreamListenSocket *server_sock;
+       Net::StreamServerSocket *server_sock;
        Net::StreamSocket *sock;
        IO::EventDispatcher event_disp;
 
@@ -53,7 +53,7 @@ NetCat::NetCat(int argc, char **argv):
        }
        else
        {
-               server_sock = new Net::StreamListenSocket(addr->get_family());
+               server_sock = new Net::StreamServerSocket(addr->get_family());
                server_sock->listen(*addr);
                event_disp.add(*server_sock);
                server_sock->signal_data_available.connect(sigc::mem_fun(this, &NetCat::net_data_available));
diff --git a/source/clientsocket.cpp b/source/clientsocket.cpp
new file mode 100644 (file)
index 0000000..10ba0b0
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef WIN32
+#include <cerrno>
+#include <sys/socket.h>
+#endif
+#include <msp/core/systemerror.h>
+#include "clientsocket.h"
+#include "socket_private.h"
+
+namespace Msp {
+namespace Net {
+
+ClientSocket::ClientSocket(Family af, int type, int proto):
+       Socket(af, type, proto),
+       connecting(false),
+       connected(false),
+       peer_addr(0)
+{ }
+
+ClientSocket::ClientSocket(const Private &p, const SockAddr &paddr):
+       Socket(p),
+       connecting(false),
+       connected(true),
+       peer_addr(paddr.copy())
+{ }
+
+ClientSocket::~ClientSocket()
+{
+       signal_flush_required.emit();
+
+       delete peer_addr;
+}
+
+const SockAddr &ClientSocket::get_peer_address() const
+{
+       if(peer_addr==0)
+               throw bad_socket_state("not connected");
+       return *peer_addr;
+}
+
+unsigned ClientSocket::do_write(const char *buf, unsigned size)
+{
+       if(!connected)
+               throw bad_socket_state("not connected");
+
+       if(size==0)
+               return 0;
+
+       int ret = ::send(priv->handle, buf, size, 0);
+       if(ret<0)
+       {
+               if(errno==EAGAIN)
+                       return 0;
+               else
+                       throw system_error("send");
+       }
+
+       return ret;
+}
+
+unsigned ClientSocket::do_read(char *buf, unsigned size)
+{
+       if(!connected)
+               throw bad_socket_state("not connected");
+
+       if(size==0)
+               return 0;
+
+       int ret = ::recv(priv->handle, buf, size, 0);
+       if(ret<0)
+       {
+               if(errno==EAGAIN)
+                       return 0;
+               else
+                       throw system_error("recv");
+       }
+       else if(ret==0 && !eof_flag)
+       {
+               eof_flag = true;
+               signal_end_of_file.emit();
+               set_events(IO::P_NONE);
+       }
+
+       return ret;
+}
+
+} // namespace Net
+} // namespace Msp
diff --git a/source/clientsocket.h b/source/clientsocket.h
new file mode 100644 (file)
index 0000000..e222a5f
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef MSP_NET_CLIENTSOCKET_H_
+#define MSP_NET_CLIENTSOCKET_H_
+
+#include "socket.h"
+
+namespace Msp {
+namespace Net {
+
+/**
+ClientSockets are used for sending and receiving data over the network.
+*/
+class ClientSocket: public Socket
+{
+protected:
+       bool connecting;
+       bool connected;
+       SockAddr *peer_addr;
+
+       ClientSocket(const Private &, const SockAddr &);
+       ClientSocket(Family, int, int);
+public:
+       virtual ~ClientSocket();
+
+       /** Connects to a remote address.  Exact semantics depend on the socket
+       type.  Returns true if the connection was established, false if it's in
+       progress. */
+       virtual bool connect(const SockAddr &) = 0;
+
+       /** Checks the status of a connection being established.  Returns true if
+       the connection was established successfully, false if it's still in
+       progress.  If an error occurred, an exception is thrown. */
+       virtual bool poll_connect(const Time::TimeDelta &) = 0;
+
+       bool is_connecting() const { return connecting; }
+       bool is_connected() const { return connected; }
+
+       const SockAddr &get_peer_address() const;
+protected:
+       virtual unsigned do_write(const char *, unsigned);
+       virtual unsigned do_read(char *, unsigned);
+};
+
+} // namespace Net
+} // namespace Msp
+
+#endif
index 3f20ba5e242a49f39d47731e97d04ab1674a75e2..32ecc23c629bfe706e174da4ff8b9e5d61f94b90 100644 (file)
@@ -10,7 +10,7 @@ namespace Msp {
 namespace Net {
 
 DatagramSocket::DatagramSocket(Family f, int p):
-       Socket(f, SOCK_DGRAM, p)
+       ClientSocket(f, SOCK_DGRAM, p)
 {
 #ifdef WIN32
        WSAEventSelect(priv->handle, *priv->event, FD_READ|FD_CLOSE);
@@ -18,7 +18,7 @@ DatagramSocket::DatagramSocket(Family f, int p):
        set_events(IO::P_INPUT);
 }
 
-int DatagramSocket::connect(const SockAddr &addr)
+bool DatagramSocket::connect(const SockAddr &addr)
 {
        SockAddr::SysAddr sa = addr.to_sys();
 
@@ -42,7 +42,7 @@ int DatagramSocket::connect(const SockAddr &addr)
 
        connected = true;
 
-       return (err==0)?0:1;
+       return true;
 }
 
 unsigned DatagramSocket::sendto(const char *buf, unsigned size, const SockAddr &addr)
index 3903a6afa8e65ace8e7cdf15ba904c61082278fb..23ca296cbb27b93fb0735617209ff79f75d0066d 100644 (file)
@@ -1,17 +1,19 @@
 #ifndef MSP_NET_DATAGRAMSOCKET_H_
 #define MSP_NET_DATAGRAMSOCKET_H_
 
-#include "socket.h"
+#include "clientsocket.h"
 
 namespace Msp {
 namespace Net {
 
-class DatagramSocket: public Socket
+class DatagramSocket: public ClientSocket
 {
 public:
        DatagramSocket(Family, int = 0);
 
-       int connect(const SockAddr &);
+       virtual bool connect(const SockAddr &);
+       virtual bool poll_connect(const Time::TimeDelta &) { return false; }
+
        unsigned sendto(const char *, unsigned, const SockAddr &);
        unsigned recvfrom(char *, unsigned, SockAddr *&);
 };
diff --git a/source/serversocket.cpp b/source/serversocket.cpp
new file mode 100644 (file)
index 0000000..6028483
--- /dev/null
@@ -0,0 +1,23 @@
+#include "serversocket.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Net {
+
+ServerSocket::ServerSocket(Family af, int type, int proto):
+       Socket(af, type, proto)
+{ }
+
+unsigned ServerSocket::do_write(const char *, unsigned)
+{
+       throw logic_error("can't write to ServerSocket");
+}
+
+unsigned ServerSocket::do_read(char *, unsigned)
+{
+       throw logic_error("can't read from ServerSocket");
+}
+
+} // namespace Net
+} // namespace Msp
diff --git a/source/serversocket.h b/source/serversocket.h
new file mode 100644 (file)
index 0000000..10375f0
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef MSP_NET_SERVERSOCKET_H_
+#define MSP_NET_SERVERSOCKET_H_
+
+#include "socket.h"
+
+namespace Msp {
+namespace Net {
+
+class ClientSocket;
+
+/**
+ServerSockets are used to receive incoming connections.  They cannot be used
+for sending and receiving data.
+*/
+class ServerSocket: public Socket
+{
+protected:
+       ServerSocket(Family, int, int);
+
+public:
+       virtual void listen(const SockAddr &, unsigned = 4) = 0;
+
+       virtual ClientSocket *accept() = 0;
+protected:
+       virtual unsigned do_write(const char *, unsigned);
+       virtual unsigned do_read(char *, unsigned);
+};
+
+} // namespace Net
+} // namespace Msp
+
+#endif
index 0e2950930f0e653d7348bcff826d3b0d53fcb57c..b5a6ec856ed615b9e3a8db920b4950f1a657917b 100644 (file)
@@ -41,11 +41,9 @@ WinSockHelper wsh;
 namespace Msp {
 namespace Net {
 
-Socket::Socket(const Private &p, const SockAddr &paddr):
+Socket::Socket(const Private &p):
        priv(new Private),
-       connected(true),
-       local_addr(0),
-       peer_addr(paddr.copy())
+       local_addr(0)
 {
        priv->handle = p.handle;
 
@@ -62,9 +60,7 @@ Socket::Socket(const Private &p, const SockAddr &paddr):
 
 Socket::Socket(Family af, int type, int proto):
        priv(new Private),
-       connected(false),
-       local_addr(0),
-       peer_addr(0)
+       local_addr(0)
 {
        priv->handle = socket(family_to_sys(af), type, proto);
 
@@ -77,7 +73,6 @@ Socket::Socket(Family af, int type, int proto):
 
 Socket::~Socket()
 {
-       signal_flush_required.emit();
 #ifdef WIN32
        closesocket(priv->handle);
        CloseHandle(*priv->event);
@@ -86,7 +81,6 @@ Socket::~Socket()
 #endif
 
        delete local_addr;
-       delete peer_addr;
        delete priv;
 }
 
@@ -143,13 +137,6 @@ const SockAddr &Socket::get_local_address() const
        return *local_addr;
 }
 
-const SockAddr &Socket::get_peer_address() const
-{
-       if(peer_addr==0)
-               throw bad_socket_state("not connected");
-       return *peer_addr;
-}
-
 int Socket::set_option(int level, int optname, const void *optval, socklen_t optlen)
 {
 #ifdef WIN32
@@ -168,52 +155,5 @@ int Socket::get_option(int level, int optname, void *optval, socklen_t *optlen)
 #endif
 }
 
-unsigned Socket::do_write(const char *buf, unsigned size)
-{
-       if(!connected)
-               throw bad_socket_state("not connected");
-
-       if(size==0)
-               return 0;
-
-       int ret = ::send(priv->handle, buf, size, 0);
-       if(ret<0)
-       {
-               if(errno==EAGAIN)
-                       return 0;
-               else
-                       throw system_error("send");
-       }
-
-       return ret;
-}
-
-unsigned Socket::do_read(char *buf, unsigned size)
-{
-       if(!connected)
-               throw bad_socket_state("not connected");
-
-
-       if(size==0)
-               return 0;
-
-       int ret = ::recv(priv->handle, buf, size, 0);
-       if(ret<0)
-       {
-               if(errno==EAGAIN)
-                       return 0;
-               else
-                       throw system_error("recv");
-       }
-       else if(ret==0 && !eof_flag)
-       {
-               eof_flag = true;
-               signal_end_of_file.emit();
-               set_events(IO::P_NONE);
-       }
-
-       return ret;
-}
-
 } // namespace Net
 } // namespace Msp
index 861012b8cc50c0bb2114440f0de2439fcacaa744..38d65da40da560ba3443d81d561cd38df71cea24 100644 (file)
@@ -28,11 +28,9 @@ protected:
        struct Private;
 
        Private *priv;
-       bool connected;
        SockAddr *local_addr;
-       SockAddr *peer_addr;
 
-       Socket(const Private &, const SockAddr &);
+       Socket(const Private &);
        Socket(Family, int, int);
 public:
        ~Socket();
@@ -40,24 +38,15 @@ public:
        void set_block(bool);
        const IO::Handle &get_event_handle();
 
-       bool is_connected() const { return connected; }
-       
        /** Associates the socket with a local address.  There must be no existing
        users of the address. */
        void bind(const SockAddr &);
 
-       /** Connects to a remote address.  Exact semantics depend on the socket
-       type. */
-       virtual int connect(const SockAddr &) = 0;
-
        void set_timeout(const Time::TimeDelta &);
        const SockAddr &get_local_address() const;
-       const SockAddr &get_peer_address() const;
 protected:
        int set_option(int, int, const void *, socklen_t);
        int get_option(int, int, void *, socklen_t *) const;
-       unsigned do_write(const char *, unsigned);
-       unsigned do_read(char *, unsigned);
 };
 
 } // namespace Net
diff --git a/source/streamlistensocket.cpp b/source/streamlistensocket.cpp
deleted file mode 100644 (file)
index 681aded..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#include <cerrno>
-#include <msp/core/refptr.h>
-#include <msp/core/systemerror.h>
-#include <msp/io/handle_private.h>
-#include <msp/strings/format.h>
-#include "sockaddr_private.h"
-#include "socket_private.h"
-#include "streamlistensocket.h"
-#include "streamsocket.h"
-
-using namespace std;
-
-namespace Msp {
-namespace Net {
-
-StreamListenSocket::StreamListenSocket(Family af, int proto):
-       Socket(af, SOCK_STREAM, proto),
-       listening(false)
-{ }
-
-int StreamListenSocket::connect(const SockAddr &)
-{
-       // XXX This function needs to go away
-       throw logic_error("Can't connect a listen socket");
-}
-
-void StreamListenSocket::listen(const SockAddr &addr, unsigned backlog)
-{
-       bind(addr);
-
-       int err = ::listen(priv->handle, backlog);
-       if(err==-1)
-               throw system_error("listen");
-
-#ifdef WIN32
-       WSAEventSelect(priv->handle, *priv->event, FD_ACCEPT);
-#endif
-       set_events(IO::P_INPUT);
-
-       listening = true;
-}
-
-StreamSocket *StreamListenSocket::accept()
-{
-       if(!listening)
-               throw bad_socket_state("not listening");
-
-       SockAddr::SysAddr sa;
-       Private new_p;
-       new_p.handle = ::accept(priv->handle, reinterpret_cast<sockaddr *>(&sa.addr), &sa.size);
-
-       RefPtr<SockAddr> paddr = SockAddr::from_sys(sa);
-       return new StreamSocket(new_p, *paddr);
-}
-
-} // namespace Net
-} // namespace Msp
diff --git a/source/streamlistensocket.h b/source/streamlistensocket.h
deleted file mode 100644 (file)
index a24e731..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef MSP_NET_STREAMLISTENSOCKET_H_
-#define MSP_NET_STREAMLISTENSOCKET_H_
-
-#include "socket.h"
-
-namespace Msp {
-namespace Net {
-
-class StreamSocket;
-
-class StreamListenSocket: public Socket
-{
-private:
-       bool listening;
-
-public:
-       StreamListenSocket(Family, int = 0);
-
-       int connect(const SockAddr &);
-       void listen(const SockAddr &, unsigned = 4);
-       StreamSocket *accept();
-};
-
-} // namespace Net
-} // namespace Msp
-
-#endif
diff --git a/source/streamserversocket.cpp b/source/streamserversocket.cpp
new file mode 100644 (file)
index 0000000..2809742
--- /dev/null
@@ -0,0 +1,51 @@
+#include <cerrno>
+#include <msp/core/refptr.h>
+#include <msp/core/systemerror.h>
+#include <msp/io/handle_private.h>
+#include <msp/strings/format.h>
+#include "sockaddr_private.h"
+#include "socket_private.h"
+#include "streamserversocket.h"
+#include "streamsocket.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Net {
+
+StreamServerSocket::StreamServerSocket(Family af, int proto):
+       ServerSocket(af, SOCK_STREAM, proto),
+       listening(false)
+{ }
+
+void StreamServerSocket::listen(const SockAddr &addr, unsigned backlog)
+{
+       bind(addr);
+
+       int err = ::listen(priv->handle, backlog);
+       if(err==-1)
+               throw system_error("listen");
+
+#ifdef WIN32
+       WSAEventSelect(priv->handle, *priv->event, FD_ACCEPT);
+#endif
+       set_events(IO::P_INPUT);
+
+       listening = true;
+}
+
+StreamSocket *StreamServerSocket::accept()
+{
+       if(!listening)
+               throw bad_socket_state("not listening");
+
+       SockAddr::SysAddr sa;
+       Private new_p;
+       new_p.handle = ::accept(priv->handle, reinterpret_cast<sockaddr *>(&sa.addr), &sa.size);
+
+       RefPtr<SockAddr> paddr = SockAddr::from_sys(sa);
+       return new StreamSocket(new_p, *paddr);
+}
+
+} // namespace Net
+} // namespace Msp
diff --git a/source/streamserversocket.h b/source/streamserversocket.h
new file mode 100644 (file)
index 0000000..aa4868c
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef MSP_NET_STREAMSERVERSOCKET_H_
+#define MSP_NET_STREAMSERVERSOCKET_H_
+
+#include "serversocket.h"
+#include "streamsocket.h"
+
+namespace Msp {
+namespace Net {
+
+class StreamServerSocket: public ServerSocket
+{
+private:
+       bool listening;
+
+public:
+       StreamServerSocket(Family, int = 0);
+
+       virtual void listen(const SockAddr &, unsigned = 4);
+       virtual StreamSocket *accept();
+};
+
+} // namespace Net
+} // namespace Msp
+
+#endif
index 5794ecd82914b16c3c8d22c7edc28a56ffffcbf5..3fa6b9a13daafda29f3cd47f8ee1ef7d01cc3953 100644 (file)
@@ -14,8 +14,7 @@ namespace Msp {
 namespace Net {
 
 StreamSocket::StreamSocket(const Private &p, const SockAddr &paddr):
-       Socket(p, paddr),
-       connecting(false)
+       ClientSocket(p, paddr)
 {
 #ifdef WIN32
        WSAEventSelect(priv->handle, *priv->event, FD_READ|FD_CLOSE);
@@ -24,11 +23,10 @@ StreamSocket::StreamSocket(const Private &p, const SockAddr &paddr):
 }
 
 StreamSocket::StreamSocket(Family af, int proto):
-       Socket(af, SOCK_STREAM, proto),
-       connecting(false)
+       ClientSocket(af, SOCK_STREAM, proto)
 { }
 
-int StreamSocket::poll_connect(const Time::TimeDelta &timeout)
+bool StreamSocket::poll_connect(const Time::TimeDelta &timeout)
 {
        if(!connecting)
                throw bad_socket_state("not connecting");
@@ -64,14 +62,12 @@ int StreamSocket::poll_connect(const Time::TimeDelta &timeout)
                set_events(IO::P_INPUT);
 
                connected = true;
-
-               return 0;
        }
 
-       return 1;
+       return connected;
 }
 
-int StreamSocket::connect(const SockAddr &addr)
+bool StreamSocket::connect(const SockAddr &addr)
 {
        if(connected)
                throw bad_socket_state("already connected");
@@ -121,7 +117,7 @@ int StreamSocket::connect(const SockAddr &addr)
                signal_connect_finished.emit(0);
        }
 
-       return (err==0)?0:1;
+       return connected;
 }
 
 void StreamSocket::on_event(IO::PollEvent ev)
index 3ffe72aa164441f1510c383a7ca322dcdd29d4d3..3fc6d04c4e038acaa53a34f60f8f45ac0dbd4965 100644 (file)
@@ -1,16 +1,14 @@
 #ifndef MSP_NET_STREAMSOCKET_H_
 #define MSP_NET_STREAMSOCKET_H_
 
-#include "socket.h"
+#include "clientsocket.h"
 
 namespace Msp {
 namespace Net {
 
-class StreamSocket: public Socket
+class StreamSocket: public ClientSocket
 {
-       friend class StreamListenSocket;
-private:
-       bool connecting;
+       friend class StreamServerSocket;
 
 public:
        /** Emitted when the socket finishes connecting.  The argument is a
@@ -30,14 +28,9 @@ public:
        If the socket is non-blocking, this function may return before the
        connection is fully established.  The caller must then use either the
        poll_connect function or an EventDispatcher to finish the process. */
-       virtual int connect(const SockAddr &);
-
-       bool is_connecting() const { return connecting; }
+       virtual bool connect(const SockAddr &);
 
-       /** Checks the status of a connection being established.  Returns 0 if the
-       connection was established successfully, 1 if it's still in progress.  If
-       the attempt finished due to an error, an exception is thrown. */
-       int poll_connect(const Time::TimeDelta &);
+       virtual bool poll_connect(const Time::TimeDelta &);
 
 private:
        void on_event(IO::PollEvent);