/**************************************************************************
* Copyright (c) 2007, 2009, 2015, 2016 by Chris Gray, KIFFER Ltd. *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* 1. Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* 3. Neither the name of KIFFER Ltd nor the names of other contributors *
* may be used to endorse or promote products derived from this *
* software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
* IN NO EVENT SHALL KIFFER LTD OR OTHER CONTRIBUTORS BE LIABLE FOR ANY *
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS *
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) *
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, *
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING *
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
**************************************************************************/
package java.net;
import java.io.*;
public class Socket {
private static SocketImplFactory factory=null;
SocketImpl socket;
private InetAddress local;
boolean bound;
boolean inputShut;
boolean outputShut;
public Socket(){
socket = getImpl();
}
protected Socket(SocketImpl impl) throws SocketException {
if (impl == null) {
throw new NullPointerException();
}
socket = impl;
}
public Socket(String host, int port) throws UnknownHostException, IOException {
this(InetAddress.getByName(host), port, null, 0);
}
public Socket (InetAddress address, int port) throws IOException {
this(address, port, null, 0);
}
public Socket(String host, int port, InetAddress localAddr, int localPort) throws UnknownHostException, IOException {
this(InetAddress.getByName(host), port, localAddr, localPort);
}
public Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException {
if(port < 0 || port > 65535 || localPort < 0 || localPort > 65535){
throw new IllegalArgumentException();
}
if(localAddr == null){
if(address instanceof Inet6Address) {
localAddr = new Inet6Address("::0");
}
else {
localAddr = InetAddress.allZeroAddress;
}
}
InetAddress.connectCheck(address.getHostAddress(),port);
socket = getImpl();
socket.create(true);
socket.bind(localAddr, localPort);
socket.connect(address,port);
}
private SocketImpl getImpl() {
return factory == null ? new PlainSocketImpl() : factory.createSocketImpl();
}
/**
** will always create a Stream Socket ...
**
*/
public Socket(InetAddress host, int port, boolean stream) throws IOException {
this(host, port);
}
/**
** will always create a Stream Socket ...
**
*/
public Socket(String host, int port, boolean stream) throws IOException {
this(host, port);
}
public void connect(SocketAddress sa, int timeout) throws IOException {
if (socket == null) {
throw new SocketException();
}
if (!isBound()) {
bind(null);
}
socket.connect(sa, timeout);
}
public void connect(SocketAddress sa) throws IOException {
connect(sa, 0);
}
public void bind(SocketAddress sa) throws IOException {
if (socket == null) {
throw new SocketException();
}
if (sa == null) {
sa = new InetSocketAddress(InetAddress.getByAddress(new byte[4]), 0);
}
try {
InetSocketAddress isa = (InetSocketAddress)sa;
socket.bind(isa.getAddress(), isa.getPort());
bound = true;
}
catch (ClassCastException cce) {
throw new IllegalArgumentException();
}
finally {
if (!bound) {
close();
}
}
}
public boolean isBound() {
try {
// TODO: how is this supposed to work for non-Plain SocketImpl?
PlainSocketImpl psi = (PlainSocketImpl)socket;
return psi != null && psi.localAddress != null && psi.localAddress.getAddress() != null || bound;
}
catch (ClassCastException cce) {
return false;
}
}
public boolean isConnected() {
return socket != null && socket.getInetAddress() != null;
}
public boolean isClosed() {
return socket == null;
}
public synchronized void close() throws IOException {
if (socket == null) {
return;
}
socket.close();
local = InetAddress.allZeroAddress;
socket = null;
}
public InetAddress getInetAddress() {
return socket.address;
}
public SocketAddress getRemoteSocketAddress() {
if(socket == null || socket.address == null) {
return null;
}
return new InetSocketAddress(socket.address, socket.port);
}
public InputStream getInputStream() throws IOException {
if (socket == null) {
throw new SocketException();
}
return socket.getInputStream();
}
public InetAddress getLocalAddress() {
if (!isBound()) {
try {
return InetAddress.getByAddress(new byte[4]);
}
catch(UnknownHostException e){
e.printStackTrace();
return null;
}
}
if (local == null) {
try {
local = (InetAddress) socket.getOption(SocketOptions.SO_BINDADDR);
}
catch(SocketException e){
e.printStackTrace();
}
}
return local;
}
public int getLocalPort() {
if (!isBound()) {
return -1;
}
return socket.localport;
}
public SocketAddress getLocalSocketAddress() {
if (!isBound()) {
return null;
}
return new InetSocketAddress(getLocalAddress(), socket.localport);
}
public OutputStream getOutputStream() throws IOException {
if (socket == null) {
throw new SocketException();
}
return socket.getOutputStream();
}
public int getPort(){
return socket.port;
}
public int getReceiveBufferSize() throws SocketException {
if (socket == null) {
throw new SocketException();
}
return ((Integer)socket.getOption(SocketOptions.SO_RCVBUF)).intValue();
}
public int getSendBufferSize() throws SocketException {
if (socket == null) {
throw new SocketException();
}
return ((Integer)socket.getOption(SocketOptions.SO_SNDBUF)).intValue();
}
public int getSoLinger() throws SocketException {
try {
return ((Integer)socket.getOption(SocketOptions.SO_LINGER)).intValue();
}
catch(ClassCastException cce) {
return -1;
}
}
public int getSoTimeout() throws SocketException {
if (socket == null) {
throw new SocketException();
}
if (socket == null) {
throw new SocketException();
}
return ((Integer)socket.getOption(SocketOptions.SO_TIMEOUT)).intValue();
}
public boolean getTcpNoDelay() throws SocketException {
if (socket == null) {
throw new SocketException();
}
return ((Boolean)socket.getOption(SocketOptions.TCP_NODELAY)).booleanValue();
}
public void setReceiveBufferSize(int size) throws SocketException {
if (socket == null) {
throw new SocketException();
}
if (size <= 0) {
throw new IllegalArgumentException();
}
socket.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
}
public void setSendBufferSize(int size) throws SocketException {
if (socket == null) {
throw new SocketException();
}
if (size <= 0) {
throw new IllegalArgumentException();
}
socket.setOption(SocketOptions.SO_SNDBUF, new Integer(size));
}
public void setSoLinger(boolean on, int linger) throws SocketException {
if (socket == null) {
throw new SocketException();
}
if (on) {
if (linger < 0) {
throw new IllegalArgumentException();
}
socket.setOption(SocketOptions.SO_LINGER, new Integer(linger));
}
else {
socket.setOption(SocketOptions.SO_LINGER, new Boolean(false));
}
}
public void setSoTimeout(int timeout) throws SocketException {
if (socket == null) {
throw new SocketException();
}
if (timeout < 0) {
throw new IllegalArgumentException();
}
socket.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
}
public void setTcpNoDelay(boolean on) throws SocketException {
if (socket == null) {
throw new SocketException();
}
socket.setOption(SocketOptions.TCP_NODELAY, new Boolean(on));
}
public String toString() {
return "Socket to "+socket;
}
/**
** @remark the socketImplFactory can only be set once !
*/
public static synchronized void setSocketImplFactory(SocketImplFactory fact) throws IOException {
if (factory != null) {
throw new SocketException();
}
InetAddress.factoryCheck();
factory = fact;
}
public void shutdownInput() throws IOException {
if (socket == null) {
throw new SocketException();
}
if (!inputShut) {
inputShut = true;
socket.shutdownInput();
}
}
public boolean isInputShutdown() {
return inputShut;
}
public void shutdownOutput() throws IOException {
if (socket == null) {
throw new SocketException();
}
if (!outputShut) {
outputShut = true;
socket.shutdownOutput();
}
}
public boolean isOutputShutdown() {
return outputShut;
}
public void setKeepAlive(boolean on) throws SocketException {
if (socket == null) {
throw new SocketException();
}
socket.setOption(SocketOptions.SO_KEEPALIVE, new Boolean(on));
}
public boolean getKeepAlive() throws SocketException {
if (socket == null) {
throw new SocketException();
}
return ((Boolean)socket.getOption(SocketOptions.SO_KEEPALIVE)).booleanValue();
}
public void sendUrgentData(int udata) throws IOException {
if (socket == null) {
throw new SocketException();
}
socket.sendUrgentData(udata);
}
public void setOOBInline(boolean on) throws SocketException {
if (socket == null) {
throw new SocketException();
}
socket.setOption(SocketOptions.SO_OOBINLINE, new Boolean(on));
}
public boolean getOOBInline() throws SocketException {
if (socket == null) {
throw new SocketException();
}
return ((Boolean)socket.getOption(SocketOptions.SO_OOBINLINE)).booleanValue();
}
public void setTrafficClass(int tcl) throws SocketException {
if (socket == null) {
throw new SocketException();
}
socket.setOption(SocketOptions.IP_TOS, new Integer(tcl));
}
public int getTrafficClass() throws SocketException {
if (socket == null) {
throw new SocketException();
}
return ((Integer)socket.getOption(SocketOptions.IP_TOS)).intValue();
}
public void setReuseAddress(boolean on) throws SocketException {
if (socket == null) {
throw new SocketException();
}
socket.setOption(SocketOptions.SO_REUSEADDR, new Boolean(on));
}
public boolean getReuseAddress() throws SocketException {
if (socket == null) {
throw new SocketException();
}
return ((Boolean)socket.getOption(SocketOptions.SO_REUSEADDR)).booleanValue();
}
}