blob: be13eca233ff1680eebb0bb9e8227adc791d53d7 [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.
*/
package java.net;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.harmony.luni.platform.INetworkSystem;
import org.apache.harmony.luni.platform.Platform;
import org.apache.harmony.luni.util.Msg;
/**
* This class is the base of all streaming socket implementation classes.
* Streaming sockets are wrapped by two classes, {@code ServerSocket} and
* {@code Socket} at the server and client end of a connection. At the server,
* there are two types of sockets engaged in communication, the {@code
* ServerSocket} on a well known port (referred to as listener) used to
* establish a connection and the resulting {@code Socket} (referred to as
* host).
*/
public abstract class SocketImpl implements SocketOptions {
/**
* The remote address this socket is connected to.
*/
protected InetAddress address;
/**
* The remote port this socket is connected to.
*/
protected int port;
/**
* The file descriptor of this socket.
*/
protected FileDescriptor fd;
/**
* The local port this socket is connected to.
*/
protected int localport;
INetworkSystem netImpl;
// BEGIN android-removed
// int receiveTimeout;
// END android-removed
boolean streaming = true;
boolean shutdownInput;
/**
* Creates a new connection-oriented socket implementation.
*
* @see SocketImplFactory
*/
public SocketImpl() {
this.netImpl = Platform.getNetworkSystem();
}
/**
* Waits for an incoming request and blocks until the connection is opened
* on the given socket.
*
* @param newSocket
* the socket to accept connections on.
* @throws IOException
* if an error occurs while accepting a new connection.
*/
protected abstract void accept(SocketImpl newSocket) throws IOException;
/**
* Returns the available number of bytes which are readable from this socket
* without blocking.
*
* @return the number of bytes that may be read without blocking.
* @throws IOException
* if an error occurs while reading the number of bytes.
*/
protected abstract int available() throws IOException;
/**
* Binds this socket to the specified local host address and port number.
*
* @param address
* the local machine address to bind this socket to.
* @param port
* the port on the local machine to bind this socket to.
* @throws IOException
* if an error occurs while binding this socket.
*/
protected abstract void bind(InetAddress address, int port)
throws IOException;
/**
* Closes this socket. This makes later access invalid.
*
* @throws IOException
* if an error occurs while closing this socket.
*/
protected abstract void close() throws IOException;
/**
* Connects this socket to the specified remote host and port number.
*
* @param host
* the remote host this socket has to be connected to.
* @param port
* the remote port on which this socket has to be connected.
* @throws IOException
* if an error occurs while connecting to the remote host.
*/
protected abstract void connect(String host, int port) throws IOException;
/**
* Connects this socket to the specified remote host address and port
* number.
*
* @param address
* the remote host address this socket has to be connected to.
* @param port
* the remote port on which this socket has to be connected.
* @throws IOException
* if an error occurs while connecting to the remote host.
*/
protected abstract void connect(InetAddress address, int port)
throws IOException;
/**
* Creates a new unconnected socket. The argument {@code isStreaming}
* defines whether the new socket is a streaming or a datagram socket.
*
* @param isStreaming
* defines whether the type of the new socket is streaming or
* datagram.
* @throws IOException
* if an error occurs while creating the socket.
*/
protected abstract void create(boolean isStreaming) throws IOException;
/**
* Gets the file descriptor of this socket.
*
* @return the file descriptor of this socket.
*/
protected FileDescriptor getFileDescriptor() {
return fd;
}
/**
* Gets the remote address this socket is connected to.
*
* @return the remote address of this socket.
*/
protected InetAddress getInetAddress() {
return address;
}
/**
* Gets the input stream of this socket.
*
* @return the input stream of this socket.
* @throws IOException
* if an error occurs while accessing the input stream.
*/
protected abstract InputStream getInputStream() throws IOException;
/**
* Gets the local port number of this socket. The field is initialized to
* {@code -1} and upon demand will go to the IP stack to get the bound
* value. See the class comment for the context of the local port.
*
* @return the local port number this socket is bound to.
*/
protected int getLocalPort() {
return localport;
}
/**
* Gets the value of the given socket option.
*
* @param optID
* the socket option to retrieve.
* @return the option value.
* @throws SocketException
* if an error occurs while accessing the option.
*/
public abstract Object getOption(int optID) throws SocketException;
/**
* Gets the output stream of this socket.
*
* @return the output stream of this socket.
* @throws IOException
* if an error occurs while accessing the output stream.
*/
protected abstract OutputStream getOutputStream() throws IOException;
/**
* Gets the remote port number of this socket. This value is not meaningful
* when this instance is wrapped by a {@code ServerSocket}.
*
* @return the remote port this socket is connected to.
*/
protected int getPort() {
return port;
}
/**
* Listens for connection requests on this streaming socket. Incoming
* connection requests are queued up to the limit specified by {@code
* backlog}. Additional requests are rejected. The method {@code listen()}
* may only be invoked on streaming sockets.
*
* @param backlog
* the maximum number of outstanding connection requests.
* @throws IOException
* if an error occurs while listening.
*/
protected abstract void listen(int backlog) throws IOException;
/**
* Sets the value for the specified socket option.
*
* @param optID
* the socket option to be set.
* @param val
* the option value.
* @throws SocketException
* if an error occurs while setting the option.
*/
public abstract void setOption(int optID, Object val)
throws SocketException;
/**
* Returns a string containing a concise, human-readable description of the
* socket.
*
* @return the textual representation of this socket.
*/
@SuppressWarnings("nls")
@Override
public String toString() {
return new StringBuffer(100).append("Socket[addr=").append(
getInetAddress()).append(",port=").append(port).append(
",localport=").append(getLocalPort()).append("]").toString();
}
/**
* In the IP stack, write at most {@code count} bytes on the socket
* from the {@code buffer}, from the {@code offset}.
*
* @param buffer
* the buffer to read into
* @param offset
* the offset into the buffer
* @param count
* the number of bytes to write
* @return int the actual number of bytes written
* @throws IOException
* thrown if an error occurs while writing
*/
int write(byte[] buffer, int offset, int count) throws IOException {
if (!streaming) {
return this.netImpl.sendDatagram2(fd, buffer, offset, count, port,
address);
}
return this.netImpl.write(fd, buffer, offset, count);
}
/**
* Closes the input channel of this socket.
* <p>
* This default implementation always throws an {@link IOException} to
* indicate that the subclass should have overridden this method.
*
* @throws IOException
* always because this method should be overridden.
*/
protected void shutdownInput() throws IOException {
// KA025=Method has not been implemented
throw new IOException(Msg.getString("KA025"));//$NON-NLS-1$
}
/**
* Closes the output channel of this socket.
* <p>
* This default implementation always throws an {@link IOException} to
* indicate that the subclass should have overridden this method.
*
* @throws IOException
* always because this method should be overridden.
*/
protected void shutdownOutput() throws IOException {
// KA025=Method has not been implemented
throw new IOException(Msg.getString("KA025"));//$NON-NLS-1$
}
/**
* Connects this socket to the remote host address and port number specified
* by the {@code SocketAddress} object with the given timeout. This method
* will block indefinitely if the timeout is set to zero.
*
* @param remoteAddr
* the remote host address and port number to connect to.
* @param timeout
* the timeout value in milliseconds.
* @throws IOException
* if an error occurs while connecting.
*/
protected abstract void connect(SocketAddress remoteAddr, int timeout)
throws IOException;
/**
* Returns whether the socket supports urgent data or not. Subclasses should
* override this method.
*
* @return {@code false} because subclasses must override this method.
*/
protected boolean supportsUrgentData() {
return false;
}
/**
* Sends the single byte of urgent data on the socket.
*
* @param value
* the byte of urgent data.
* @throws IOException
* if an error occurs sending urgent data.
*/
protected abstract void sendUrgentData(int value) throws IOException;
/**
* Sets performance preference for connection time, latency and bandwidth.
* Does nothing by default.
*
* @param connectionTime
* the importance of connect time.
* @param latency
* the importance of latency.
* @param bandwidth
* the importance of bandwidth.
*/
protected void setPerformancePreferences(int connectionTime, int latency,
int bandwidth) {
// Our socket implementation only provide one protocol: TCP/IP, so
// we do nothing for this method
}
}