blob: b3e651f17fee11899452332d52b281cea09b5524 [file] [log] [blame]
/*
* 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_SOCKET_H_
#define _DECAF_NET_SOCKET_H_
#include <decaf/net/InetAddress.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 <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 {
protected:
// The actual Socket that this Socket represents.
mutable SocketImpl* impl;
private:
// Factory for creating sockets, if not set a Plan TCP Socket is created
static SocketImplFactory* factory;
mutable volatile bool created;
bool connected;
bool closed;
bool bound;
bool inputShutdown;
bool outputShutdown;
friend class ServerSocket;
private:
Socket( const Socket& );
Socket& operator= ( const Socket& );
public:
/**
* Creates an unconnected Socket using the set SocketImplFactory or if non is set
* than the default SockImpl type is created.
*/
Socket();
/**
* 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.
*/
Socket( SocketImpl* impl );
/**
* Creates a new Socket instance and connects it to the given address 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 address
* The address to connect to.
* @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 NullPointerException if the InetAddress instance in NULL.
* @throws IllegalArgumentException if the port if not in range [0...65535]
*/
Socket( const InetAddress* address, int port );
/**
* Creates a new Socket instance and connects it to the given address and port. If
* there is a SocketImplFactory set then the SokcetImpl is created using the factory
* otherwise the default Socket implementation is used. The Socket will also bind
* to the local address and port specified.
*
* @param address
* The address to connect to.
* @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 NullPointerException if the InetAddress instance in NULL.
* @throws IllegalArgumentException if the port if not in range [0...65535]
*/
Socket( const InetAddress* address, int port, const InetAddress* localAddress, int localPort );
/**
* 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 InetAddress* localAddress, int localPort );
virtual ~Socket();
/**
* 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 );
/**
* 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();
/**
* 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);
/**
* 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 std::string& host, int port, int timeout);
/**
* Indicates whether or not this socket is connected to am end point.
*
* @return true if connected, false otherwise.
*/
bool isConnected() const {
return connected;
}
/**
* @return true if the Socket has been closed.
*/
bool isClosed() const {
return closed;
}
/**
* @return true if this Socket has been bound to a Local address.
*/
bool isBound() const {
return bound;
}
/**
* @return true if input on this Socket has been shutdown.
*/
bool isInputShutdown() const {
return inputShutdown;
}
/**
* @return true if output on this Socket has been shutdown.
*/
bool isOutputShutdown() const {
return outputShutdown;
}
/**
* 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.
*
* 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.
*
* 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 decaf::io::InputStream* getInputStream();
/**
* 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.
*
* Closing the returned Socket will also close the underlying Socket.
*
* @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();
/**
* 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.
*
* @return 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.
*
* @return 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.
*/
virtual void shutdownInput();
/**
* 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 shutdownOutput();
/**
* 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;
/**
* 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(bool state, int timeout);
/**
* 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;
/**
* 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);
/**
* 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;
/**
* 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);
/**
* 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;
/**
* 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);
/**
* 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;
/**
* 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);
/**
* 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;
/**
* 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);
/**
* Gets the Status of the TCP_NODELAY setting for this socket.
*
* @return true if TCP_NODELAY is enabled for the socket.
*
* @throws SocketException Thrown if unable to set the information.
*/
virtual bool getTcpNoDelay() const;
/**
* 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 setTcpNoDelay(bool value);
/**
* 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.
*
* @return the bitset result of querying the traffic class setting.
*
* @throws SocketException if an error is encountered while performing this operation.
*/
virtual int getTrafficClass() const;
/**
* 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 setTrafficClass(int value);
/**
* 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.
*/
virtual bool getOOBInline() const;
/**
* 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.
*/
virtual void setOOBInline(bool value);
/**
* 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.
*/
virtual void sendUrgentData(int data);
/**
* @return a string representing this Socket.
*/
virtual 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 );
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 InetAddress* localAddress, int localPort );
// Check for already closed and throw an error if so.
void checkClosed() const;
// Create but don't connect the underlying OS Socket instance, if not already created.
void ensureCreated() const;
};
}}
#endif /*_DECAF_NET_SOCKET_H_*/