activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tab...@apache.org
Subject svn commit: r932637 [2/3] - in /activemq/activemq-cpp/trunk/activemq-cpp/src: main/ main/activemq/transport/tcp/ main/decaf/internal/net/tcp/ main/decaf/net/ test/decaf/net/
Date Fri, 09 Apr 2010 22:17:38 GMT
Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ServerSocket.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ServerSocket.cpp?rev=932637&r1=932636&r2=932637&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ServerSocket.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ServerSocket.cpp Fri Apr  9 22:17:38 2010
@@ -16,139 +16,365 @@
  */
 
 #include "ServerSocket.h"
-#include "SocketError.h"
+
+#include <decaf/net/SocketImpl.h>
+#include <decaf/net/Socket.h>
+#include <decaf/net/SocketOptions.h>
 
 #include <decaf/internal/net/tcp/TcpSocket.h>
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <string>
+#include <memory>
 
 using namespace decaf;
+using namespace decaf::io;
 using namespace decaf::net;
+using namespace decaf::lang;
+using namespace decaf::lang::exceptions;
+using namespace decaf::internal;
+using namespace decaf::internal::net;
 using namespace decaf::internal::net::tcp;
 
 ////////////////////////////////////////////////////////////////////////////////
-ServerSocket::ServerSocket() {
-    socketHandle = NULL;
+SocketImplFactory* ServerSocket::factory = NULL;
+
+////////////////////////////////////////////////////////////////////////////////
+ServerSocket::ServerSocket() : impl(NULL), created(false), closed(false), bound(false) {
+
+    this->impl = this->factory != NULL ? factory->createSocketImpl() : new TcpSocket();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+ServerSocket::ServerSocket( int port )
+    throw( decaf::io::IOException, decaf::lang::exceptions::IllegalArgumentException ) :
+        impl(NULL), created(false), closed(false), bound(false) {
+
+    this->impl = this->factory != NULL ? factory->createSocketImpl() : new TcpSocket();
+
+    if( port < 0 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Port value was invalid: %d", port );
+    }
+
+    this->setupSocketImpl( "", port, getDefaultBacklog() );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+ServerSocket::ServerSocket( int port, int backlog )
+    throw( decaf::io::IOException, decaf::lang::exceptions::IllegalArgumentException ) :
+        impl(NULL), created(false), closed(false), bound(false) {
+
+    this->impl = this->factory != NULL ? factory->createSocketImpl() : new TcpSocket();
+
+    if( port < 0 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Port value was invalid: %d", port );
+    }
+
+    this->setupSocketImpl( "", port, backlog );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+ServerSocket::ServerSocket( const std::string& ipAddress, int port, int backlog )
+    throw( decaf::io::IOException, decaf::lang::exceptions::IllegalArgumentException ) :
+        impl(NULL), created(false), closed(false), bound(false) {
+
+    this->impl = this->factory != NULL ? factory->createSocketImpl() : new TcpSocket();
+
+    if( port < 0 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Port value was invalid: %d", port );
+    }
+
+    this->setupSocketImpl( ipAddress, port, backlog );
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 ServerSocket::~ServerSocket() {
-    // No shutdown, just close - dont want blocking destructor.
-    close();
+    try{
+        close();
+
+        delete this->impl;
+    }
+    DECAF_CATCH_NOTHROW( Exception )
+    DECAF_CATCHALL_NOTHROW()
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ServerSocket::setupSocketImpl( const std::string ipAddress, int port, int backlog ) {
+
+    try{
+
+        this->impl->create();
+        this->created = true;
+
+        try {
+            this->impl->bind( ipAddress, port );
+            this->bound = true;
+            this->impl->listen( backlog > 0 ? backlog : getDefaultBacklog() );
+        } catch( IOException& ex ) {
+            close();
+            throw ex;
+        }
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-void ServerSocket::bind( const char* host, int port ) throw ( SocketException ) {
-    this->bind( host, port, SOMAXCONN );
+void ServerSocket::bind( const std::string& host, int port )
+    throw( decaf::io::IOException, decaf::lang::exceptions::IllegalArgumentException ) {
+
+    try{
+        this->bind( host, port, getDefaultBacklog() );
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCHALL_THROW( IOException )
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-void ServerSocket::bind( const char* host,
-                         int port,
-                         int backlog ) throw ( SocketException ) {
+void ServerSocket::bind( const std::string& address, int port, int backlog )
+    throw( decaf::io::IOException, decaf::lang::exceptions::IllegalArgumentException ) {
 
-    apr_status_t result = APR_SUCCESS;
+    checkClosed();
+
+    if( port < 0 || port > 65535 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Specified port value is out of range: %d", port );
+    }
 
     if( isBound() ) {
-        throw SocketException ( __FILE__, __LINE__,
-            "ServerSocket::bind - Socket already bound" );
+        throw IOException(
+            __FILE__, __LINE__, "ServerSocket is already bound." );
     }
 
-    // Verify the port value.
-    if( port <= 0 || port > 65535 ) {
-        throw SocketException(
-            __FILE__, __LINE__,
-            "ServerSocket::bind - Port out of range: %d", port );
+    try{
+
+        ensureCreated();
+
+        try {
+            this->impl->bind( address, port );
+            this->bound = true;
+            this->impl->listen( backlog > 0 ? backlog : getDefaultBacklog() );
+        } catch( IOException& ex ) {
+            close();
+            throw ex;
+        }
     }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
 
-    // Create the Address Info for the Socket
-    result = apr_sockaddr_info_get(
-        &socketAddress, host, APR_INET, (apr_port_t)port, 0, apr_pool.getAprPool() );
+////////////////////////////////////////////////////////////////////////////////
+void ServerSocket::close() throw ( decaf::io::IOException ){
 
-    if( result != APR_SUCCESS ) {
-        socketHandle = NULL;
-        throw SocketException(
-              __FILE__, __LINE__,
-              SocketError::getErrorString().c_str() );
+    try{
+        if( !this->closed ) {
+            this->closed = true;
+            this->impl->close();
+        }
     }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
 
-    // Create the socket.
-    result = apr_socket_create(
-        &socketHandle, APR_INET, SOCK_STREAM, APR_PROTO_TCP, apr_pool.getAprPool() );
+////////////////////////////////////////////////////////////////////////////////
+bool ServerSocket::isBound() const {
+    return this->bound;
+}
 
-    if( result != APR_SUCCESS ) {
-        socketHandle = NULL;
-        throw SocketException(
-              __FILE__, __LINE__,
-              SocketError::getErrorString().c_str() );
+////////////////////////////////////////////////////////////////////////////////
+bool ServerSocket::isClosed() const {
+    return this->closed;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+Socket* ServerSocket::accept() throw( decaf::io::IOException, decaf::net::SocketTimeoutException ) {
+
+    checkClosed();
+
+    if( !isBound() ) {
+        throw IOException(
+            __FILE__, __LINE__, "The ServerSocket has not yet been bound." );
     }
 
-    // Set the socket to reuse the address and default as blocking
-    apr_socket_opt_set( socketHandle, APR_SO_REUSEADDR, 1 );
-    apr_socket_opt_set( socketHandle, APR_SO_NONBLOCK, 0);
-    apr_socket_timeout_set( socketHandle, -1 );
+    try{
+        ensureCreated();
+        std::auto_ptr<Socket> newSocket( new Socket() );
+        this->implAccept( newSocket.get() );
+        return newSocket.release();
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
 
-    // Bind to the Socket, this may be where we find out if the port is in use.
-    result = apr_socket_bind( socketHandle, socketAddress );
+////////////////////////////////////////////////////////////////////////////////
+void ServerSocket::implAccept( Socket* socket ) throw( decaf::io::IOException ) {
 
-    if( result != APR_SUCCESS ) {
-        close();
-        throw SocketException(
-              __FILE__, __LINE__,
-              "ServerSocket::bind - %s",
-              SocketError::getErrorString().c_str() );
+    try{
+        this->impl->accept( socket->impl );
+        socket->accepted();
     }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
 
-    // Setup the listen for incoming connection requests
-    result = apr_socket_listen( socketHandle, backlog );
+////////////////////////////////////////////////////////////////////////////////
+int ServerSocket::getReceiveBufferSize() const throw( SocketException ) {
 
-    if( result != APR_SUCCESS ) {
-        close();
-        throw SocketException(
-              __FILE__, __LINE__,
-              "ServerSocket::bind - %s",
-              SocketError::getErrorString().c_str() );
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_RCVBUF );
     }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-void ServerSocket::close() throw ( lang::Exception ){
+void ServerSocket::setReceiveBufferSize( int size )
+    throw( SocketException, decaf::lang::exceptions::IllegalArgumentException ) {
 
-    if( isBound() ) {
-        apr_socket_close( socketHandle );
-        socketHandle = NULL;
+    checkClosed();
+
+    if( size <= 0 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Buffer size given was invalid: %d", size );
+    }
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_RCVBUF, size );
     }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-bool ServerSocket::isBound() const {
-    return this->socketHandle != NULL;
+bool ServerSocket::getReuseAddress() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_REUSEADDR ) == 0 ? false : true;
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-Socket* ServerSocket::accept() throw (SocketException)
-{
-    SocketHandle incoming = NULL;
-    apr_status_t result = APR_SUCCESS;
+void ServerSocket::setReuseAddress( bool reuse ) throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_REUSEADDR, reuse ? 1 : 0 );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int ServerSocket::getSoTimeout() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_TIMEOUT );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ServerSocket::setSoTimeout( int timeout )
+    throw( SocketException, decaf::lang::exceptions::IllegalArgumentException ) {
+
+    checkClosed();
 
-    // Loop to ignore any signal interruptions that occur during the operation.
-    do {
-        result = apr_socket_accept( &incoming, socketHandle, apr_pool.getAprPool() );
-    } while( result == APR_EINTR );
+    if( timeout < 0 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Socket timeout given was invalid: %d", timeout );
+    }
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_TIMEOUT, timeout );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
 
-    if( result != APR_SUCCESS ) {
-        std::cout << "Failed to accept New Connection:" << std::endl;
+////////////////////////////////////////////////////////////////////////////////
+void ServerSocket::setSocketImplFactory( SocketImplFactory* factory )
+    throw( decaf::io::IOException,
+           decaf::net::SocketException ) {
+
+    if( Socket::factory != NULL ) {
         throw SocketException(
-              __FILE__, __LINE__,
-              "ServerSocket::accept - %s",
-              SocketError::getErrorString().c_str() );
+            __FILE__, __LINE__, "A SocketInplFactory was already set." );
     }
 
-    return new TcpSocket( incoming );
+    Socket::factory = factory;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+std::string ServerSocket::toString() const {
+
+    std::ostringstream str;
+
+    str << "ServerSocket[";
+
+    if( !isBound() ) {
+        str << "unbound]";
+    } else {
+
+    }
+
+    return str.str();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ServerSocket::checkClosed() const throw( decaf::io::IOException ) {
+    if( this->closed ) {
+        throw IOException( __FILE__, __LINE__, "ServerSocket already closed." );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ServerSocket::ensureCreated() const throw( decaf::io::IOException ) {
+
+    try{
+        if( !this->created ) {
+            this->impl->create();
+            this->created = true;
+        }
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int ServerSocket::getDefaultBacklog() {
+    return 50;
 }

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ServerSocket.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ServerSocket.h?rev=932637&r1=932636&r2=932637&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ServerSocket.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/ServerSocket.h Fri Apr  9 22:17:38 2010
@@ -14,66 +14,174 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef _DECAF_NET_SERVERSOCKETIMPL_H_
-#define _DECAF_NET_SERVERSOCKETIMPL_H_
+#ifndef _DECAF_NET_SERVERSOCKET_H_
+#define _DECAF_NET_SERVERSOCKET_H_
 
-#include <decaf/net/SocketException.h>
 #include <decaf/util/Config.h>
-#include <decaf/internal/AprPool.h>
 
-#include <apr_network_io.h>
+#include <decaf/net/SocketImpl.h>
+#include <decaf/net/SocketImplFactory.h>
+
+#include <decaf/lang/exceptions/NullPointerException.h>
+#include <decaf/lang/exceptions/IllegalArgumentException.h>
+#include <decaf/net/UnknownHostException.h>
+#include <decaf/net/SocketTimeoutException.h>
+#include <decaf/io/IOException.h>
+
+#include <string>
 
 namespace decaf{
 namespace net{
 
     class Socket;
+    class SocketImpl;
 
     /**
-     * A server socket class (for testing purposes).
+     * This class implements server sockets. A server socket waits for requests to come in over
+     * the network.
+     *
+     * The actual work of the server socket is performed by an instance of the SocketImpl class.
+     * An application can change the socket factory that creates the socket implementation to configure
+     * itself to create sockets of a particular type.
+     *
+     * @since 1.0
      */
     class DECAF_API ServerSocket {
-    public:
+    private:
 
-        typedef apr_socket_t* SocketHandle;
-        typedef apr_sockaddr_t* SocketAddress;
+        // Factory for creating sockets, if not set a Plan TCP Socket is created
+        static SocketImplFactory* factory;
 
-    private:
+        // The actual Socket that this Socket represents.
+        mutable SocketImpl* impl;
+        mutable volatile bool created;
+
+        bool closed;
+        bool bound;
 
-        SocketHandle socketHandle;
-        SocketAddress socketAddress;
-        decaf::internal::AprPool apr_pool;
+        int backlog;
+        int port;
 
     public:
 
         /**
-         * Constructor.
          * Creates a non-bound server socket.
          */
         ServerSocket();
 
         /**
-         * Destructor.
+         * Creates a new ServerSocket bound to the specified port, if the value of port is 0, then
+         * any free port is chosen.
+         *
+         * When this constructor is called the size of the backlog queue is set at 50, connections
+         * that arrive after the backlog has been reached are refused.
+         *
+         * If a SocketImplFactory is registered then the createSocketImpl method on the factory
+         * will be called otherwise a default SocketImpl is created.
+         *
+         * @param port
+         *      The port to bind the ServerSocket to.
+         *
+         * @throws IOException if there is an I/O error while performing this operation.
+         * @throws IllegalArgumentException if the port value is negative or greater than 65535.
+         */
+        ServerSocket( int port )
+            throw( decaf::io::IOException,
+                   decaf::lang::exceptions::IllegalArgumentException );
+
+        /**
+         * Creates a new ServerSocket bound to the specified port, if the value of port is 0, then
+         * any free port is chosen.
+         *
+         * When this constructor is called the size of the backlog queue is set at backlog, connections
+         * that arrive after the backlog has been reached are refused.  If backlog is zero or negative
+         * then the default backlog value of 50 is used.
+         *
+         * If a SocketImplFactory is registered then the createSocketImpl method on the factory
+         * will be called otherwise a default SocketImpl is created.
+         *
+         * @param port
+         *      The port to bind the ServerSocket to.
+         * @param backlog
+         *      The the number of incoming connection attempts to queue before connections are refused.
+         *
+         * @throws IOException if there is an I/O error while performing this operation.
+         * @throws IllegalArgumentException if the port value is negative or greater than 65535.
+         */
+        ServerSocket( int port, int backlog )
+            throw( decaf::io::IOException,
+                   decaf::lang::exceptions::IllegalArgumentException );
+
+        /**
+         * Creates a new ServerSocket bound to the specified port, if the value of port is 0, then
+         * any free port is chosen.  If the value of the ipAddress is empty then the ANY address is
+         * used.
+         *
+         * When this constructor is called the size of the backlog queue is set at backlog, connections
+         * that arrive after the backlog has been reached are refused.  If backlog is zero or negative
+         * then the default backlog value of 50 is used.
+         *
+         * If a SocketImplFactory is registered then the createSocketImpl method on the factory
+         * will be called otherwise a default SocketImpl is created.
+         *
+         * @param ipAddress
+         *      The IP Address to bind to on the local machine.
+         * @param port
+         *      The port to bind the ServerSocket to.
+         * @param backlog
+         *      The the number of incoming connection attempts to queue before connections are refused.
+         *
+         * @throws IOException if there is an I/O error while performing this operation.
+         * @throws IllegalArgumentException if the port value is negative or greater than 65535.
+         */
+        ServerSocket( const std::string& ipAddress, int port, int backlog )
+            throw( decaf::io::IOException,
+                   decaf::lang::exceptions::IllegalArgumentException );
+
+        /**
          * Releases socket handle if close() hasn't been called.
          */
         virtual ~ServerSocket();
 
+    protected:
+
+        /**
+         * Creates a ServerSocket wrapping the provided SocketImpl instance, this Socket is
+         * considered unconnected.  The ServerSocket class takes ownership of this SocketImpl
+         * pointer and will delete it when the Socket class is destroyed.
+         *
+         * @param impl
+         *      The SocketImpl instance to wrap.
+         *
+         * @throws NullPointerException if the passed SocketImpl is Null.
+         */
+        ServerSocket( SocketImpl* impl );
+
     public:
 
         /**
-         * Bind and listen to given IP/dns and port.
+         * Bind and listen to given local IPAddress and port, if the address is empty
+         * than a valid local address will be chosen, and if the port of 0 than an
+         * available open port will be chosen.
          *
          * @param host
          *      The IP address or host name.
          * @param port
          *      The TCP port between 1..655535.
          *
-         * @throws SocketException if an I/O error occurs while binding the socket.
+         * @throws IOException if an I/O error occurs while binding the socket.
+         * @throws IllegalArgumentException if the parameters are not valid.
          */
-        virtual void bind( const char* host, int port )
-            throw ( SocketException );
+        void bind( const std::string& host, int port )
+            throw ( decaf::io::IOException, decaf::lang::exceptions::IllegalArgumentException );
 
         /**
-         * Bind and listen to given IP/dns and port.
+         * Bind and listen to given local IPAddress and port, if the address is empty
+         * than a valid local address will be chosen, and if the port of 0 than an
+         * available open port will be chosen.
+         *
+         * If the backlog is greater than zero it will be used instead of the default
+         * value, otherwise the default value is used and no error is generated.
          *
          * @param host
          *      The IP address or host name.
@@ -82,28 +190,169 @@ namespace net{
          * @param backlog
          *      The size of listen backlog.
          *
-         * @throws SocketException if an I/O error occurs while binding the socket.
+         * @throws IOException if an I/O error occurs while binding the socket.
+         * @throws IllegalArgumentException if the parameters are not valid.
          */
-        virtual void bind( const char* host, int port, int backlog )
-            throw ( SocketException );
+        void bind( const std::string& host, int port, int backlog )
+            throw ( decaf::io::IOException, decaf::lang::exceptions::IllegalArgumentException );
 
         /**
-         * Blocks until a client connects to the bound socket.
-         * @return new socket. Never returns NULL.
+         * Listens for a connection request on the bound IPAddress and Port for this ServerSocket, the
+         * caller blocks until a connection is made.  If the SO_TIMEOUT option is set this method could
+         * throw a SocketTimeoutException if the operation times out.
+         *
+         * @return a new Socket object pointer. Never returns NULL, the returned pointer is owned by
+         *         the caller and must be explicitly freed by them.
+         *
+         * @throws IOException if an I/O error occurs while binding the socket.
+         * @throws SocketTimeoutException if the SO_TIMEOUT option was used and the accept timed out.
          */
-        virtual Socket* accept () throw ( SocketException );
+        Socket* accept()
+            throw( decaf::io::IOException, decaf::net::SocketTimeoutException );
 
         /**
-         * Closes the server socket.
+         * Closes the server socket, causing any Threads blocked on an accept call to
+         * throw an Exception.
+         *
+         * @throws IOException if an I/O error occurs while performing this operation.
          */
-        virtual void close() throw( lang::Exception );
+        void close() throw( decaf::io::IOException );
+
+        /**
+         * @returns true if the close method has been called on the ServerSocket.
+         */
+        bool isClosed() const;
 
         /**
          * @return true of the server socket is bound.
          */
-        virtual bool isBound() const;
+        bool isBound() const;
+
+        /**
+         * Gets the receive buffer size for this socket, SO_RCVBUF.  This is the buffer used
+         * by the underlying platform socket to buffer received data.
+         *
+         * @return the receive buffer size in bytes.
+         *
+         * @throws SocketException if the operation fails.
+         */
+        int getReceiveBufferSize() const throw( SocketException );
+
+        /**
+         * Sets the receive buffer size for this socket, SO_RCVBUF.
+         *
+         * @param size
+         *      Number of bytes to set the receive buffer to.
+         *
+         * @throws SocketException if the operation fails.
+         * @throws IllegalArgumentException if the value is zero or negative.
+         */
+        void setReceiveBufferSize( int size )
+            throw( SocketException, decaf::lang::exceptions::IllegalArgumentException );
+
+        /**
+         * Gets the reuse address flag, SO_REUSEADDR.
+         *
+         * @return True if the address can be reused.
+         *
+         * @throws SocketException if the operation fails.
+         */
+        bool getReuseAddress() const throw( SocketException );
+
+        /**
+         * Sets the reuse address flag, SO_REUSEADDR.
+         *
+         * @param reuse
+         *      If true, sets the flag.
+         *
+         * @throws SocketException if the operation fails.
+         */
+        void setReuseAddress( bool reuse ) throw( SocketException );
+
+        /**
+         * Gets the timeout for socket operations, SO_TIMEOUT.
+         *
+         * @return The timeout in milliseconds for socket operations.
+         *
+         * @throws SocketException Thrown if unable to retrieve the information.
+         */
+        int getSoTimeout() const throw( SocketException );
+
+        /**
+         * Sets the timeout for socket operations, SO_TIMEOUT.  A value of zero indicates that timeout
+         * is infinite for operations on this socket.
+         *
+         * @param timeout
+         *      The timeout in milliseconds for socket operations.
+         *
+         * @throws SocketException Thrown if unable to set the information.
+         * @throws IllegalArgumentException if the timeout value is negative.
+         */
+        void setSoTimeout( int timeout )
+            throw( SocketException, decaf::lang::exceptions::IllegalArgumentException );
+
+        /**
+         * Gets the port number on the Local machine that this ServerSocket is bound to.
+         *
+         * @returns the port number of this machine that is bound, if not bound returns -1.
+         */
+        int getLocalPort() const;
+
+        /**
+         * @returns a string representing this ServerSocket.
+         */
+        std::string toString() const;
+
+    public:
+
+        /**
+         * Sets the instance of a SocketImplFactory that the ServerSocket class should use when new
+         * instances of this class are created.  This method is only allowed to be used once
+         * during the lifetime of the application.
+         *
+         * @param factory
+         *      The instance of a SocketImplFactory to use when new SocketImpl objects are created.
+         *
+         * @throws IOException if an I/O error occurs while performing this operation.
+         * @throws SocketException if this method has already been called with a valid factory.
+         */
+        static void setSocketImplFactory( SocketImplFactory* factory )
+            throw( decaf::io::IOException,
+                   decaf::net::SocketException );
+
+    protected:
+
+        /**
+         * Virtual method that allows a ServerSocket subclass to override the accept call and
+         * provide its own SocketImpl for the socket.
+         *
+         * @param socket
+         *      The socket object whose SocketImpl should be used for the accept call.
+         *
+         * @throws IOException if an I/O error occurs while performing this operation.
+         */
+        virtual void implAccept( Socket* socket )
+            throw( decaf::io::IOException );
+
+        /**
+         * Allows a subclass to override what is considered the default backlog.
+         *
+         * @returns the default backlog for connections.
+         */
+        virtual int getDefaultBacklog();
+
+    protected:
+
+        // Check for already closed and throw an error if so.
+        void checkClosed() const throw( decaf::io::IOException );
+
+        // Create but don't connect the underlying OS Socket instance, if not already created.
+        void ensureCreated() const throw( decaf::io::IOException );
+
+        // Binds and sets up the Listen for this Server Socket
+        void setupSocketImpl( const std::string ipAddress, int port, int backlog );
 
-   };
+    };
 
 }}
 

Added: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/Socket.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/Socket.cpp?rev=932637&view=auto
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/Socket.cpp (added)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/Socket.cpp Fri Apr  9 22:17:38 2010
@@ -0,0 +1,686 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Socket.h"
+
+#include <decaf/net/SocketImpl.h>
+#include <decaf/net/SocketImplFactory.h>
+
+#include <decaf/internal/net/tcp/TcpSocket.h>
+
+using namespace decaf;
+using namespace decaf::net;
+using namespace decaf::io;
+using namespace decaf::internal;
+using namespace decaf::internal::net;
+using namespace decaf::internal::net::tcp;
+using namespace decaf::lang;
+using namespace decaf::lang::exceptions;
+
+////////////////////////////////////////////////////////////////////////////////
+SocketImplFactory* Socket::factory = NULL;
+
+////////////////////////////////////////////////////////////////////////////////
+Socket::Socket() : impl(NULL), created(false), connected(false), closed(false),
+                   bound(false), inputShutdown(false), outputShutdown(false) {
+
+    if( this->factory != NULL ) {
+        this->impl = factory->createSocketImpl();
+        return;
+    }
+
+    this->impl = new TcpSocket();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+Socket::Socket( SocketImpl* impl ) : impl(impl), created(false), connected(false), closed(false),
+                                     bound(false), inputShutdown(false), outputShutdown(false) {
+
+    if( impl == NULL ) {
+        throw NullPointerException(
+            __FILE__, __LINE__, "SocketImpl pointer passed was Null." );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+Socket::Socket( const std::string& host, int port ) : impl(NULL), created(false), connected(false),
+                                                      closed(false), bound(false),
+                                                      inputShutdown(false), outputShutdown(false){
+
+    if( port < 0 || port > 65535 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Port specified is out of range: %d", port );
+    }
+
+    try{
+
+        if( this->factory != NULL ) {
+            this->impl = factory->createSocketImpl();
+        } else {
+            this->impl = new TcpSocket();
+        }
+
+        this->initSocketImpl( host, port, "", 0 );
+    }
+    DECAF_CATCH_RETHROW( UnknownHostException )
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+Socket::Socket( const std::string& host, int port, const std::string& localAddress, int localPort ) :
+    impl(NULL), created(false), connected(false), closed(false), bound(false),
+    inputShutdown(false), outputShutdown(false) {
+
+    if( port < 0 || port > 65535 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Port specified is out of range: %d", port );
+    }
+
+    try{
+
+        if( this->factory != NULL ) {
+            this->impl = factory->createSocketImpl();
+        } else {
+            this->impl = new TcpSocket();
+        }
+
+        this->initSocketImpl( host, port, localAddress, localPort );
+    }
+    DECAF_CATCH_RETHROW( UnknownHostException )
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+Socket::~Socket() {
+    try{
+        close();
+        delete this->impl;
+    }
+    DECAF_CATCH_NOTHROW( Exception )
+    DECAF_CATCHALL_NOTHROW()
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::initSocketImpl( const std::string& host, int port, const std::string& localAddress, int localPort )
+    throw( decaf::io::IOException, decaf::net::UnknownHostException ) {
+
+    try{
+
+        ensureCreated();
+
+        try {
+            this->impl->bind( localAddress, localPort );
+            this->bound = true;
+            this->impl->connect( host, port, 0 );
+            this->connected = true;
+        } catch( IOException& ex ) {
+            this->impl->close();
+            throw ex;
+        }
+    }
+    DECAF_CATCH_RETHROW( UnknownHostException )
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int Socket::getPort() const {
+    return this->connected ? this->impl->getPort() : 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int Socket::getLocalPort() const {
+    return this->bound ? this->impl->getLocalPort() : -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+std::string Socket::getInetAddress() const {
+    return this->connected ? this->impl->getInetAddress() : "";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+std::string Socket::getLocalAddress() const {
+    return this->bound ? this->impl->getLocalAddress() : "0.0.0.0";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::bind( const std::string& ipaddress, int port )
+    throw( decaf::io::IOException, decaf::lang::exceptions::IllegalArgumentException ) {
+
+    checkClosed();
+
+    if( isBound() ) {
+        throw IOException(
+            __FILE__, __LINE__, "The Socket is already bound." );
+    }
+
+    try{
+
+        ensureCreated();
+
+        try {
+            this->impl->bind( ipaddress, port );
+            this->bound = true;
+        } catch( IOException& e ) {
+            this->impl->close();
+            throw e;
+        }
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::close() throw( decaf::io::IOException ) {
+    try{
+        this->closed = true;
+        this->impl->close();
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::connect( const std::string& host, int port )
+    throw( decaf::io::IOException,
+           decaf::lang::exceptions::IllegalArgumentException ) {
+
+    if( port < 0 || port > 65535 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Port specified is out of range: %d", port );
+    }
+
+    try{
+        this->connect( host, port, 0 );
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::connect( const std::string& host, int port, int timeout )
+    throw( decaf::io::IOException,
+           decaf::net::SocketTimeoutException,
+           decaf::lang::exceptions::IllegalArgumentException ) {
+
+    checkClosed();
+
+    if( timeout < 0 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Timeout value specified is invalid: %d", timeout );
+    }
+
+    if( isConnected() ) {
+        throw SocketException(
+            __FILE__, __LINE__, "The Socket is already connected." );
+    }
+
+    if( host.empty() ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Host cannot be empty." );
+    }
+
+    try{
+
+        ensureCreated();
+
+        try {
+
+            if( !isBound() ) {
+                this->impl->bind( "", 0 );
+                this->bound = true;
+            }
+
+            this->impl->connect( host, port, timeout );
+            this->connected = true;
+
+        } catch( IOException& ex ) {
+            this->impl->close();
+            throw ex;
+        }
+    }
+    DECAF_CATCH_RETHROW( SocketTimeoutException )
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+InputStream* Socket::getInputStream() throw( decaf::io::IOException ) {
+
+    checkClosed();
+
+    try{
+
+        if( isInputShutdown() ) {
+            throw IOException( __FILE__, __LINE__, "Input was shutdown on this Socket." );
+        }
+
+        return this->impl->getInputStream();
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+OutputStream* Socket::getOutputStream() throw( decaf::io::IOException ) {
+
+    checkClosed();
+
+    try{
+
+        if( isOutputShutdown() ) {
+            throw IOException( __FILE__, __LINE__, "Output was shutdown on this Socket." );
+        }
+
+        return this->impl->getOutputStream();
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::shutdownInput() throw( decaf::io::IOException ) {
+
+    if( isInputShutdown() ) {
+        throw IOException( __FILE__, __LINE__, "Socket input has already been shutdown." );
+    }
+
+    checkClosed();
+
+    try{
+        this->impl->shutdownInput();
+        this->inputShutdown = true;
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::shutdownOutput() throw( decaf::io::IOException ) {
+
+    if( isOutputShutdown() ) {
+        throw IOException( __FILE__, __LINE__, "Socket output has already been shutdown." );
+    }
+
+    checkClosed();
+
+    try{
+        this->impl->shutdownOutput();
+        this->outputShutdown = true;
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int Socket::getSoLinger() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_LINGER );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setSoLinger( bool state, int timeout )
+    throw( SocketException, IllegalArgumentException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+
+        if( state && timeout < 0 ) {
+            throw IllegalArgumentException(
+                __FILE__, __LINE__, "Timeout value passed is invalid: %d", timeout );
+        }
+
+        int value = state ? ( 65535 > timeout ? timeout : 65535 ) : -1;
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_LINGER, value );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool Socket::getKeepAlive() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_KEEPALIVE ) == 0 ? false : true;
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setKeepAlive( bool keepAlive ) throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_KEEPALIVE, keepAlive ? 1 : 0 );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int Socket::getReceiveBufferSize() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_RCVBUF );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setReceiveBufferSize( int size )
+    throw( SocketException, decaf::lang::exceptions::IllegalArgumentException ) {
+
+    checkClosed();
+
+    if( size <= 0 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Buffer size given was invalid: %d", size );
+    }
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_RCVBUF, size );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool Socket::getReuseAddress() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_REUSEADDR ) == 0 ? false : true;
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setReuseAddress( bool reuse ) throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_REUSEADDR, reuse ? 1 : 0 );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int Socket::getSendBufferSize() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_SNDBUF );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setSendBufferSize( int size )
+    throw( SocketException, decaf::lang::exceptions::IllegalArgumentException ) {
+
+    checkClosed();
+
+    if( size <= 0 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Buffer size given was invalid: %d", size );
+    }
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_SNDBUF, size );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int Socket::getSoTimeout() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_TIMEOUT );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setSoTimeout( int timeout )
+    throw( SocketException, decaf::lang::exceptions::IllegalArgumentException ) {
+
+    checkClosed();
+
+    if( timeout < 0 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Socket timeout given was invalid: %d", timeout );
+    }
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_TIMEOUT, timeout );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool Socket::getTcpNoDelay() const throw ( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_TCP_NODELAY ) == 0 ? false : true;
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setTcpNoDelay( bool value ) throw ( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_TCP_NODELAY, value ? 1 : 0 );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int Socket::getTrafficClass() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_IP_TOS );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setTrafficClass( int value )
+    throw( SocketException, decaf::lang::exceptions::IllegalArgumentException ) {
+
+    checkClosed();
+
+    if( value < 0 || value > 255 ) {
+        throw IllegalArgumentException(
+            __FILE__, __LINE__, "Value of the Traffic class option was invalid: %d", value );
+    }
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_IP_TOS, value );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_RETHROW( IllegalArgumentException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool Socket::getOOBInline() const throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        return this->impl->getOption( SocketOptions::SOCKET_OPTION_OOBINLINE ) == 0 ? false : true;
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setOOBInline( bool value ) throw( SocketException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        this->impl->setOption( SocketOptions::SOCKET_OPTION_OOBINLINE, value ? 1 : 0 );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::sendUrgentData( int data ) throw( decaf::io::IOException ) {
+
+    checkClosed();
+
+    try{
+        ensureCreated();
+        this->impl->sendUrgentData( data & 0xFF );
+    }
+    DECAF_CATCH_RETHROW( SocketException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, SocketException )
+    DECAF_CATCHALL_THROW( SocketException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::checkClosed() const throw( decaf::io::IOException ) {
+    if( this->closed ) {
+        throw IOException( __FILE__, __LINE__, "Socket already closed." );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::ensureCreated() const throw( decaf::io::IOException ) {
+
+    try{
+        if( !this->created ) {
+            this->impl->create();
+            this->created = true;
+        }
+    }
+    DECAF_CATCH_RETHROW( IOException )
+    DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
+    DECAF_CATCHALL_THROW( IOException )
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::setSocketImplFactory( SocketImplFactory* factory )
+    throw( decaf::io::IOException,
+           decaf::net::SocketException ) {
+
+    if( Socket::factory != NULL ) {
+        throw SocketException(
+            __FILE__, __LINE__, "A SocketInplFactory was already set." );
+    }
+
+    Socket::factory = factory;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Socket::accepted() {
+
+    this->created = true;
+    this->bound = true;
+    this->connected = true;
+}

Propchange: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/Socket.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/Socket.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/Socket.h?rev=932637&r1=932636&r2=932637&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/Socket.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/Socket.h Fri Apr  9 22:17:38 2010
@@ -17,182 +17,527 @@
 #ifndef _DECAF_NET_SOCKET_H_
 #define _DECAF_NET_SOCKET_H_
 
+#include <decaf/net/SocketImplFactory.h>
 #include <decaf/net/SocketException.h>
 #include <decaf/io/InputStream.h>
 #include <decaf/io/OutputStream.h>
 #include <decaf/io/Closeable.h>
 #include <decaf/util/Config.h>
 
-#include <apr_network_io.h>
+#include <decaf/lang/exceptions/NullPointerException.h>
+#include <decaf/lang/exceptions/IllegalArgumentException.h>
+#include <decaf/net/UnknownHostException.h>
+#include <decaf/net/SocketTimeoutException.h>
+#include <decaf/io/IOException.h>
 
 namespace decaf{
 namespace net{
 
+    class SocketImpl;
+    class ServerSocket;
+
+    /**
+     *
+     * @since 1.0
+     */
     class DECAF_API Socket : public decaf::io::Closeable {
+    private:
+
+        // Factory for creating sockets, if not set a Plan TCP Socket is created
+        static SocketImplFactory* factory;
+
+        // The actual Socket that this Socket represents.
+        mutable SocketImpl* impl;
+        mutable volatile bool created;
+
+        bool connected;
+        bool closed;
+        bool bound;
+        bool inputShutdown;
+        bool outputShutdown;
+
+        friend class ServerSocket;
+
     public:
 
         /**
-         * Define the SocketHandle type.
+         * Creates an unconnected Socket using the set SocketImplFactory or if non is set
+         * than the default SockImpl type is created.
          */
-        typedef apr_socket_t* SocketHandle;
+        Socket();
 
         /**
-         * Define the SocketAddress type
+         * Creates a Socket wrapping the provided SocketImpl instance, this Socket is
+         * considered unconnected.  The Socket class takes ownership of this SocketImpl
+         * pointer and will delete it when the Socket class is destroyed.
+         *
+         * @param impl
+         *      The SocketImpl instance to wrap.
+         *
+         * @throws NullPointerException if the passed SocketImpl is Null.
          */
-        typedef apr_sockaddr_t* SocketAddress;
+        Socket( SocketImpl* impl );
 
-    public:
+        /**
+         * Creates a new Socket instance and connects it to the given host and port.  If
+         * there is a SocketImplFactory set then the SokcetImpl is created using the factory
+         * otherwise the default Socket implementation is used.
+         *
+         * If the host parameter is empty then the loop back address is used.
+         *
+         * @param host
+         *      The host name or IP address to connect to, empty string means loopback.
+         * @param port
+         *      The port number to connect to [0...65535]
+         *
+         * @throws UnknownHostException if the host cannot be resolved.
+         * @throws IOException if an I/O error occurs while connecting the Socket.
+         * @throws IllegalArgumentException if the port if not in range [0...65535]
+         */
+        Socket( const std::string& host, int port );
+
+        /**
+         * Creates a new Socket instance and connects it to the given host and port.  If
+         * there is a SocketImplFactory set then the SokcetImpl is created using the factory
+         * otherwise the default Socket implementation is used.
+         *
+         * If the host parameter is empty then the loop back address is used.
+         *
+         * @param host
+         *      The host name or IP address to connect to, empty string means loopback.
+         * @param port
+         *      The port number to connect to [0...65535]
+         * @param localAddress
+         *      The IP address on the local machine to bind to.
+         * @param localPort
+         *      The port on the local machine to bind to.
+         *
+         * @throws UnknownHostException if the host cannot be resolved.
+         * @throws IOException if an I/O error occurs while connecting the Socket.
+         * @throws IllegalArgumentException if the port if not in range [0...65535]
+         */
+        Socket( const std::string& host, int port, const std::string& localAddress, int localPort );
 
-        virtual ~Socket() {}
+        virtual ~Socket();
 
         /**
-         * Connects to the specified destination. Closes this socket if
-         * connected to another destination.
-         * @param host The host of the server to connect to.
-         * @param port The port of the server to connect to.
+         * Binds this Socket to the given local address and port.  If the SocketAddress
+         * value is NULL then the Socket will be bound to an available local address and
+         * port.
+         *
+         * @param ipaddress
+         *      The local address and port to bind the socket to.
+         * @param port
+         *      The port on the local machine to bind to.
+         *
+         * @throws IOException if an error occurs during the bind operation.
+         * @throws IllegalArgumentException if the Socket can't process the subclass of SocketAddress
+         *         that has been provided.
+         */
+        virtual void bind( const std::string& ipaddress, int port )
+            throw( decaf::io::IOException, decaf::lang::exceptions::IllegalArgumentException );
+
+        /**
+         * Closes the Socket.  Once closed a Socket cannot be connected or otherwise
+         * operated upon, a new Socket instance must be created.
+         *
+         * @throws IOException if an I/O error occurs while closing the Socket.
+         */
+        virtual void close() throw( decaf::io::IOException );
+
+        /**
+         * Connects to the specified destination.
+         *
+         * @param host
+         *      The host name or IP address of the remote host to connect to.
+         * @param port
+         *      The port on the remote host to connect to.
+         *
+         * @throws IOException Thrown if a failure occurred in the connect.
+         * @throws IllegalArguementException if the timeout value is negative or the endpoint is invalid.
+         */
+        virtual void connect( const std::string& host, int port )
+            throw( decaf::io::IOException,
+                   decaf::lang::exceptions::IllegalArgumentException );
+
+        /**
+         * Connects to the specified destination, with a specified timeout value.  If a connection
+         * to the remote host is not established within the specified timeout interval than an
+         * SocketTimeoutException is thrown.  A timeout value of zero is treated as an inifinite
+         * timeout.
+         *
+         * @param host
+         *      The host name or IP address of the remote host to connect to.
+         * @param port
+         *      The port on the remote host to connect to.
+         * @param timeout
+         *      The number of Milliseconds to wait before treating the connection as failed.
+         *
          * @throws IOException Thrown if a failure occurred in the connect.
+         * @throws SocketTimeoutException if the timeout for connection is exceeded.
+         * @throws IllegalArguementException if the timeout value is negative or the endpoint is invalid.
          */
-        virtual void connect( const char* host, int port )
-            throw(SocketException) = 0;
+        virtual void connect( const std::string& host, int port, int timeout )
+            throw( decaf::io::IOException,
+                   decaf::net::SocketTimeoutException,
+                   decaf::lang::exceptions::IllegalArgumentException );
 
         /**
-         * Indicates whether or not this socket is connected to a destination.
-         * @returns true if connected
+         * Indicates whether or not this socket is connected to am end point.
+         *
+         * @returns true if connected, false otherwise.
+         */
+        bool isConnected() const {
+            return connected;
+        }
+
+        /**
+         * @returns true if the Socket has been closed.
+         */
+        bool isClosed() const {
+            return closed;
+        }
+
+        /**
+         * @returns true if this Socket has been bound to a Local address.
          */
-        virtual bool isConnected() const = 0;
+        bool isBound() const {
+            return bound;
+        }
 
         /**
-         * Gets the InputStream for this socket.
-         * @return The InputStream for this socket. NULL if not connected.
+         * @returns true if input on this Socket has been shutdown.
          */
-        virtual io::InputStream* getInputStream() = 0;
+        bool isInputShutdown() const {
+            return inputShutdown;
+        }
 
         /**
-         * Gets the OutputStream for this socket.
-         * @return the OutputStream for this socket.  NULL if not connected.
+         * @returns true if output on this Socket has been shutdown.
          */
-        virtual io::OutputStream* getOutputStream() = 0;
+        bool isOutputShutdown() const {
+            return outputShutdown;
+        }
 
         /**
-         * Gets the set Connect timeout, Socket implementations that support this
-         * setting will throw an SocketException if they cannot connect within the
-         * specified timeout.
+         * Gets the InputStream for this socket if its connected.  The pointer returned is the
+         * property of the associated Socket and should not be deleted by the caller.
          *
-         * @returns The time in Milliseconds to wait for a connection to be made.
+         * When the returned InputStream is performing a blocking operation and the underlying
+         * connection is closed or otherwise broker the read calls will normally throw an exception
+         * to indicate the failure.
          *
-         * @throws SocketException if the operation fails.
+         * Closing the InputStream will also close the underlying Socket.
+         *
+         * @return The InputStream for this socket.
+         *
+         * @throws IOException if an error occurs during creation of the InputStream, also if the
+         *         Socket is not connected or the input has been shutdown previously.
          */
-        virtual int getConnectTimeout() const throw( SocketException ) = 0;
+        virtual decaf::io::InputStream* getInputStream() throw( decaf::io::IOException );
 
         /**
-         * Sets the set Connect timeout, Socket implementations that support this
-         * setting will throw an SocketException if they cannot connect within the
-         * specified timeout.
+         * Gets the OutputStream for this socket if it is connected.  The pointer returned is the
+         * property of the Socket instance and should not be deleted by the caller.
          *
-         * @param timeout
-         *      The time in Milliseconds to wait for a connection to be made.
+         * Closing the returned Socket will also close the underlying Socket.
          *
-         * @throws SocketException if the operation fails.
+         * @return the OutputStream for this socket.
+         *
+         * @throws IOException if an error occurs during the creation of this OutputStream, or
+         *         if the Socket is closed or the output has been shutdown previously.
+         */
+        virtual decaf::io::OutputStream* getOutputStream() throw( decaf::io::IOException );
+
+        /**
+         * Gets the on the remote host this Socket is connected to.
+         *
+         * @return the port on the remote host the socket is connected to, or 0 if not connected.
+         */
+        int getPort() const;
+
+        /**
+         * Gets the local port the socket is bound to.
+         *
+         * @return the local port the socket was bound to, or -1 if the socket is not bound.
+         */
+        int getLocalPort() const;
+
+        /**
+         * Returns the address to which the socket is connected.
+         *
+         * @returns the remote IP address to which this socket is connected, or null if the socket is not connected.
+         */
+        std::string getInetAddress() const;
+
+        /**
+         * Gets the local address to which the socket is bound.
+         *
+         * @returns the local address to which the socket is bound or InetAddress.anyLocalAddress() if the socket is not bound yet.
+         */
+        std::string getLocalAddress() const;
+
+        /**
+         * Shuts down the InputStream for this socket essentially marking it as EOF.  The stream
+         * returns EOF for any calls to read after this method has been called.
+         *
+         * @throws IOException if an I/O error occurs while performing this operation.
+         */
+        void shutdownInput() throw( decaf::io::IOException );
+
+        /**
+         * Shuts down the OutputStream for this socket, any data already written to the socket will
+         * be sent, any further calls to OuputStream::write will throw an IOException.
+         *
+         * @throws IOException if an I/O error occurs while performing this operation.
          */
-        virtual void setConnectTimeout( int timeout ) throw( SocketException ) = 0;
+        void shutdownOutput() throw( decaf::io::IOException );
 
         /**
-         * Gets the linger time.
+         * Gets the linger time for the socket, SO_LINGER.  A return value of -1 indicates that
+         * the option is disabled.
+         *
          * @return The linger time in seconds.
+         *
          * @throws SocketException if the operation fails.
          */
-        virtual int getSoLinger() const throw( SocketException ) = 0;
+        virtual int getSoLinger() const throw( SocketException );
 
         /**
-         * Sets the linger time.
-         * @param linger The linger time in seconds.  If 0, linger is off.
+         * Sets the linger time (SO_LINGER) using a specified time value, this limits of this
+         * value are platform specific.
+         *
+         * @param state
+         *      The state of SO_LINGER, true is on.
+         * @param timeout
+         *      The linger time in seconds, must be non-negative.
+         *
          * @throws SocketException if the operation fails.
+         * @throws IllegalArgumentException if state is true and timeout is negative.
          */
-        virtual void setSoLinger( int linger ) throw( SocketException ) = 0;
+        virtual void setSoLinger( bool state, int timeout )
+            throw( SocketException, decaf::lang::exceptions::IllegalArgumentException );
 
         /**
-         * Gets the keep alive flag.
-         * @return True if keep alive is enabled.
+         * Gets the keep alive flag for this socket, SO_KEEPALIVE.
+         *
+         * @return true if keep alive is enabled for this socket.
+         *
          * @throws SocketException if the operation fails.
          */
-        virtual bool getKeepAlive() const throw( SocketException ) = 0;
+        virtual bool getKeepAlive() const throw( SocketException );
 
         /**
-         * Enables/disables the keep alive flag.
-         * @param keepAlive If true, enables the flag.
+         * Enables/disables the keep alive flag for this socket, SO_KEEPALIVE.
+         *
+         * @param keepAlive
+         *      If true, enables the flag.
+         *
          * @throws SocketException if the operation fails.
          */
-        virtual void setKeepAlive( bool keepAlive ) throw( SocketException ) = 0;
+        virtual void setKeepAlive( bool keepAlive ) throw( SocketException );
 
         /**
-         * Gets the receive buffer size.
+         * Gets the receive buffer size for this socket, SO_RCVBUF.  This is the buffer used
+         * by the underlying platform socket to buffer received data.
+         *
          * @return the receive buffer size in bytes.
+         *
          * @throws SocketException if the operation fails.
          */
-        virtual int getReceiveBufferSize() const throw( SocketException ) = 0;
+        virtual int getReceiveBufferSize() const throw( SocketException );
 
         /**
-         * Sets the receive buffer size.
-         * @param size Number of bytes to set the receive buffer to.
+         * Sets the receive buffer size for this socket, SO_RCVBUF.
+         *
+         * @param size
+         *      Number of bytes to set the receive buffer to.
+         *
          * @throws SocketException if the operation fails.
+         * @throws IllegalArgumentException if the value is zero or negative.
          */
-        virtual void setReceiveBufferSize( int size ) throw( SocketException ) = 0;
+        virtual void setReceiveBufferSize( int size )
+            throw( SocketException, decaf::lang::exceptions::IllegalArgumentException );
 
         /**
-         * Gets the reuse address flag.
+         * Gets the reuse address flag, SO_REUSEADDR.
+         *
          * @return True if the address can be reused.
+         *
          * @throws SocketException if the operation fails.
          */
-        virtual bool getReuseAddress() const throw( SocketException ) = 0;
+        virtual bool getReuseAddress() const throw( SocketException );
 
         /**
-         * Sets the reuse address flag.
-         * @param reuse If true, sets the flag.
+         * Sets the reuse address flag, SO_REUSEADDR.
+         *
+         * @param reuse
+         *      If true, sets the flag.
+         *
          * @throws SocketException if the operation fails.
          */
-        virtual void setReuseAddress( bool reuse ) throw( SocketException ) = 0;
+        virtual void setReuseAddress( bool reuse ) throw( SocketException );
 
         /**
-         * Gets the send buffer size.
+         * Gets the send buffer size for this socket, SO_SNDBUF, this value is used by the platform
+         * socket to buffer data written to the socket.
+         *
          * @return the size in bytes of the send buffer.
+         *
          * @throws SocketException if the operation fails.
          */
-        virtual int getSendBufferSize() const throw( SocketException ) = 0;
+        virtual int getSendBufferSize() const throw( SocketException );
 
         /**
-         * Sets the send buffer size.
-         * @param size The number of bytes to set the send buffer to.
+         * Gets the send buffer size for this socket, SO_SNDBUF, this value is used by the platform
+         * socket to buffer data written to the socket.
+         *
+         * @param size
+         *      The number of bytes to set the send buffer to, must be larger than zero.
+         *
          * @throws SocketException if the operation fails.
+         * @throws IllegalArgumentException if the value is zero or negative.
          */
-        virtual void setSendBufferSize( int size ) throw( SocketException ) = 0;
+        virtual void setSendBufferSize( int size )
+            throw( SocketException, decaf::lang::exceptions::IllegalArgumentException );
 
         /**
-         * Gets the timeout for socket operations.
+         * Gets the timeout for socket operations, SO_TIMEOUT.
+         *
          * @return The timeout in milliseconds for socket operations.
+         *
          * @throws SocketException Thrown if unable to retrieve the information.
          */
-        virtual int getSoTimeout() const throw( SocketException ) = 0;
+        virtual int getSoTimeout() const throw( SocketException );
+
+        /**
+         * Sets the timeout for socket operations, SO_TIMEOUT.  A value of zero indicates that timeout
+         * is infinite for operations on this socket.
+         *
+         * @param timeout
+         *      The timeout in milliseconds for socket operations.
+         *
+         * @throws SocketException Thrown if unable to set the information.
+         * @throws IllegalArgumentException if the timeout value is negative.
+         */
+        virtual void setSoTimeout( int timeout )
+            throw( SocketException, decaf::lang::exceptions::IllegalArgumentException );
 
         /**
-         * Sets the timeout for socket operations.
-         * @param timeout The timeout in milliseconds for socket operations.<p>
+         * Gets the Status of the TCP_NODELAY setting for this socket.
+         *
+         * @returns true if TCP_NODELAY is enabled for the socket.
+         *
+         * @throws SocketException Thrown if unable to set the information.
+         */
+        virtual bool getTcpNoDelay() const throw ( SocketException );
+
+        /**
+         * Sets the Status of the TCP_NODELAY param for this socket., this setting is used
+         * to disable or enable Nagle's algorithm on the Socket.
+         *
+         * @param value
+         *      The setting for the socket's TCP_NODELAY option, true to enable.
+         *
          * @throws SocketException Thrown if unable to set the information.
          */
-        virtual void setSoTimeout( int timeout ) throw( SocketException ) = 0;
+        virtual void setTcpNoDelay( bool value ) throw ( SocketException );
 
         /**
-         * Gets the Status of the TCP_NODELAY param for this socket as a Bool
-         * @returns true if TCP_NODELAY is enabled
-         * @throws Exception
+         * Gets the Traffic Class setting for this Socket, sometimes referred to as Type of
+         * Service setting.  This setting is dependent on the underlying network implementation
+         * for the platform this Socket runs on and is not guaranteed to have any effect.
+         *
+         * Refer to your platforms network documentation regarding support for this setting.
+         *
+         * @returns the bitset result of querying the traffic class setting.
+         *
+         * @throws SocketException if an error is encountered while performing this operation.
          */
-        virtual bool getTcpNoDelay() const throw ( decaf::lang::Exception ) = 0;
+        virtual int getTrafficClass() const throw( SocketException );
 
         /**
-         * Sets the Status of the TCP_NODELAY param for this socket as a Bool
-         * @param value - true if TCP_NODELAY is to be enabled
-         * @throws Exception
+         * Gets the Traffic Class setting for this Socket, sometimes referred to as Type of
+         * Service setting.  This setting is dependent on the underlying network implementation
+         * for the platform this Socket runs on and is not guaranteed to have any effect.
+         *
+         * Refer to your platforms network documentation regarding support for this setting.
+         *
+         * @param value
+         *      The integer value representing the traffic class setting bitset.
+         *
+         * @throws SocketException if an error is encountered while performing this operation.
+         * @throws IllegalArgumentException if the value is not in the range [0..255].
          */
-        virtual void setTcpNoDelay( bool value ) throw ( decaf::lang::Exception ) = 0;
+        virtual void setTrafficClass( int value )
+            throw( SocketException, decaf::lang::exceptions::IllegalArgumentException );
+
+        /**
+         * Gets the value of the OOBINLINE for this socket.
+         *
+         * @return true if OOBINLINE is enabled, false otherwise.
+         *
+         * @throws SocketException if an error is encountered while performing this operation.
+         */
+        bool getOOBInline() const throw( SocketException );
+
+        /**
+         * Sets the value of the OOBINLINE for this socket, by default this option is disabled.  If
+         * enabled the urgent data is read inline on the Socket's InputStream, no notification is give.
+         *
+         * @return true if OOBINLINE is enabled, false otherwise.
+         *
+         * @throws SocketException if an error is encountered while performing this operation.
+         */
+        void setOOBInline( bool value ) throw( SocketException );
+
+        /**
+         * Sends on byte of urgent data to the Socket.
+         *
+         * @param data
+         *      The value to write as urgent data, only the lower eight bits are sent.
+         *
+         * @throws IOException if an I/O error occurs while performing this operation.
+         */
+        void sendUrgentData( int data ) throw( decaf::io::IOException );
+
+        /**
+         * @returns a string representing this Socket.
+         */
+        std::string toString() const;
+
+    public:
+
+        /**
+         * Sets the instance of a SocketImplFactory that the Socket class should use when new
+         * instances of this class are created.  This method is only allowed to be used once
+         * during the lifetime of the application.
+         *
+         * @param factory
+         *      The instance of a SocketImplFactory to use when new Socket objects are created.
+         *
+         * @throws IOException if an I/O error occurs while performing this operation.
+         * @throws SocketException if this method has already been called with a valid factory.
+         */
+        static void setSocketImplFactory( SocketImplFactory* factory )
+            throw( decaf::io::IOException,
+                   decaf::net::SocketException );
+
+    protected:
+
+        // Flags the Socket instance as created, bound and connected when its connected
+        // via a ServerSocket accept call.
+        void accepted();
+
+        // Sets up a connected socket for the constructors that take connection arguments.
+        void initSocketImpl( const std::string& address, int port, const std::string& localAddress, int localPort )
+            throw( decaf::io::IOException, decaf::net::UnknownHostException );
+
+        // Check for already closed and throw an error if so.
+        void checkClosed() const throw( decaf::io::IOException );
+
+        // Create but don't connect the underlying OS Socket instance, if not already created.
+        void ensureCreated() const throw( decaf::io::IOException );
 
     };
 

Added: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/SocketAddress.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/SocketAddress.h?rev=932637&view=auto
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/SocketAddress.h (added)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/SocketAddress.h Fri Apr  9 22:17:38 2010
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DECAF_NET_SOCKETADDRESS_H_
+#define _DECAF_NET_SOCKETADDRESS_H_
+
+#include <decaf/util/Config.h>
+
+namespace decaf {
+namespace net {
+
+    /**
+     * Base class for protocol specific Socket addresses.  These classes provide an
+     * immutable address object that is used by the Socket classes.
+     *
+     * @since 1.0
+     */
+    class DECAF_API SocketAddress {
+    public:
+
+        virtual ~SocketAddress() {}
+
+    };
+
+}}
+
+#endif /* _DECAF_NET_SOCKETADDRESS_H_ */

Propchange: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/SocketAddress.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/SocketImpl.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/SocketImpl.cpp?rev=932637&r1=932636&r2=932637&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/SocketImpl.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/net/SocketImpl.cpp Fri Apr  9 22:17:38 2010
@@ -24,7 +24,7 @@ using namespace decaf::net;
 using namespace decaf::lang;
 
 ////////////////////////////////////////////////////////////////////////////////
-SocketImpl::SocketImpl() {
+SocketImpl::SocketImpl() : port(0), localPort(0), address() {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -34,8 +34,15 @@ SocketImpl::~SocketImpl() {
 ////////////////////////////////////////////////////////////////////////////////
 std::string SocketImpl::toString() const {
 
-    std::string result = std::string( "Socket[addr=" ) + this->hostname +
+    std::string result = std::string( "Socket[addr=" ) + this->address +
                          ",port=" + Integer::toString( this->port ) + "]";
 
     return result;
 }
+
+////////////////////////////////////////////////////////////////////////////////
+void SocketImpl::sendUrgentData( int data ) throw( decaf::io::IOException ) {
+
+    throw decaf::io::IOException(
+        __FILE__, __LINE__, "Urgent Data not supported by this implementation." );
+}



Mime
View raw message