001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.net;
019:
020: import java.io.FileDescriptor;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024:
025: import org.apache.harmony.luni.platform.INetworkSystem;
026: import org.apache.harmony.luni.platform.Platform;
027: import org.apache.harmony.luni.util.Msg;
028:
029: /**
030: * The abstract superclass of all classes that implement streaming sockets.
031: *
032: * Streaming sockets are wrapped by two classes, ServerSocket and Socket at the
033: * server and client end of a connection respectively. At the server there are
034: * two types of sockets engaged in communication, the <code>ServerSocket</code>
035: * on a well known port (hereafter referred to as the listener) used to
036: * establish a connection and the resulting <code>Socket</code> (hereafter
037: * referred to as host).
038: *
039: * Some of the <code>SocketImpl</code> instance variable values must be
040: * interpreted in the context of the wrapper. See the getter methods for these
041: * details.
042: */
043: public abstract class SocketImpl implements SocketOptions {
044:
045: protected InetAddress address;
046:
047: protected int port;
048:
049: protected FileDescriptor fd;
050:
051: protected int localport;
052:
053: INetworkSystem netImpl;
054:
055: int receiveTimeout;
056:
057: boolean streaming = true;
058:
059: boolean shutdownInput;
060:
061: /**
062: * Construct a connection-oriented SocketImpl.
063: *
064: * @see SocketImplFactory
065: */
066: public SocketImpl() {
067: this .netImpl = Platform.getNetworkSystem();
068: }
069:
070: /**
071: * Accepts a connection on the provided socket.
072: *
073: * @param newSocket
074: * the socket to accept connections on
075: * @exception SocketException
076: * if an error occurs while accepting
077: */
078: protected abstract void accept(SocketImpl newSocket)
079: throws IOException;
080:
081: /**
082: * Answer the number of bytes that may be read from this socket without
083: * blocking. This call does not block.
084: *
085: * @return the number of bytes that may be read without blocking
086: * @exception SocketException
087: * if an error occurs while peeking
088: */
089: protected abstract int available() throws IOException;
090:
091: /**
092: * Binds this socket to the specified local host/port.
093: *
094: * @param address
095: * the local machine address to bind the socket to
096: * @param port
097: * the port on the local machine to bind the socket to
098: * @exception IOException
099: * if an error occurs while binding
100: */
101: protected abstract void bind(InetAddress address, int port)
102: throws IOException;
103:
104: /**
105: * Close the socket. Usage thereafter is invalid.
106: *
107: * @exception IOException
108: * if an error occurs while closing
109: */
110: protected abstract void close() throws IOException;
111:
112: /**
113: * Connects this socket to the specified remote host/port.
114: *
115: * @param host
116: * the remote host to connect to
117: * @param port
118: * the remote port to connect to
119: * @exception IOException
120: * if an error occurs while connecting
121: */
122: protected abstract void connect(String host, int port)
123: throws IOException;
124:
125: /**
126: * Connects this socket to the specified remote host address/port.
127: *
128: * @param address
129: * the remote host address to connect to
130: * @param port
131: * the remote port to connect to
132: * @exception IOException
133: * if an error occurs while connecting
134: */
135: protected abstract void connect(InetAddress address, int port)
136: throws IOException;
137:
138: /**
139: * Creates a new unconnected socket. If streaming is true, create a stream
140: * socket, else a datagram socket.
141: *
142: * @param isStreaming
143: * true, if the socket is type streaming
144: * @exception SocketException
145: * if an error occurs while creating the socket
146: */
147: protected abstract void create(boolean isStreaming)
148: throws IOException;
149:
150: /**
151: * Answer the socket's file descriptor.
152: *
153: * @return FileDescriptor the socket FileDescriptor
154: */
155: protected FileDescriptor getFileDescriptor() {
156: return fd;
157: }
158:
159: /**
160: * Answer the socket's address. Referring to the class comment: Listener:
161: * The local machines IP address to which this socket is bound. Host: The
162: * client machine, to which this socket is connected. Client: The host
163: * machine, to which this socket is connected.
164: *
165: * @return InetAddress the socket address
166: */
167: protected InetAddress getInetAddress() {
168: return address;
169: }
170:
171: /**
172: * Answer the socket input stream.
173: *
174: * @return InputStream an InputStream on the socket
175: * @exception IOException
176: * thrown if an error occurs while accessing the stream
177: */
178: protected abstract InputStream getInputStream() throws IOException;
179:
180: /**
181: * Answer the socket's localport. The field is initialized to -1 and upon
182: * demand will go to the IP stack to get the bound value. See the class
183: * comment for the context of the local port.
184: *
185: * @return the socket localport
186: */
187:
188: protected int getLocalPort() {
189: return localport;
190: }
191:
192: /**
193: * Answer the nominated socket option.
194: *
195: * @param optID
196: * the socket option to retrieve
197: * @return Object the option value
198: * @exception SocketException
199: * thrown if an error occurs while accessing the option
200: */
201: public abstract Object getOption(int optID) throws SocketException;
202:
203: /**
204: * Answer the socket output stream.
205: *
206: * @return OutputStream an OutputStream on the socket
207: * @exception IOException
208: * thrown if an error occurs while accessing the stream
209: */
210: protected abstract OutputStream getOutputStream()
211: throws IOException;
212:
213: /**
214: * Answer the socket's remote port. This value is not meaningful when the
215: * socketImpl is wrapped by a ServerSocket.
216: *
217: * @return the remote port the socket is connected to
218: */
219: protected int getPort() {
220: return port;
221: }
222:
223: /**
224: * Listen for connection requests on this stream socket. Incoming connection
225: * requests are queued, up to the limit nominated by backlog. Additional
226: * requests are rejected. listen() may only be invoked on stream sockets.
227: *
228: * @param backlog
229: * the max number of outstanding connection requests
230: * @exception IOException
231: * thrown if an error occurs while listening
232: */
233: protected abstract void listen(int backlog) throws IOException;
234:
235: /**
236: * Set the nominated socket option.
237: *
238: * @param optID
239: * the socket option to set
240: * @param val
241: * the option value
242: * @exception SocketException
243: * thrown if an error occurs while setting the option
244: */
245: public abstract void setOption(int optID, Object val)
246: throws SocketException;
247:
248: /**
249: * Answers a string containing a concise, human-readable description of the
250: * socket.
251: *
252: * @return the description
253: */
254: @SuppressWarnings("nls")
255: @Override
256: public String toString() {
257: return new StringBuffer(100).append("Socket[addr=").append(
258: getInetAddress()).append(",port=").append(port).append(
259: ",localport=").append(getLocalPort()).append("]")
260: .toString();
261: }
262:
263: /**
264: * In the IP stack, write at most <code>count</code> bytes on the socket
265: * from the <code>buffer</code>, from the <code>offset</code>.
266: *
267: * @param buffer
268: * the buffer to read into
269: * @param offset
270: * the offset into the buffer
271: * @param count
272: * the number of bytes to write
273: * @return the actual number of bytes written
274: * @exception IOException
275: * thrown if an error occurs while writing
276: */
277: int write(byte[] buffer, int offset, int count) throws IOException {
278: if (!streaming) {
279: return this .netImpl.sendDatagram2(fd, buffer, offset,
280: count, port, address);
281: }
282: return this .netImpl.sendStream(fd, buffer, offset, count);
283: }
284:
285: /**
286: * Shutdown the input portion of the socket.
287: *
288: * The default implementation always throws an {@link IOException} to
289: * indicate that the subclass should have overridden this method.
290: *
291: * @throws IOException
292: * Always. Designed to be subclassed.
293: */
294: protected void shutdownInput() throws IOException {
295: // KA025=Method has not been implemented
296: throw new IOException(Msg.getString("KA025"));//$NON-NLS-1$
297: }
298:
299: /**
300: * Shutdown the output portion of the socket.
301: *
302: * The default implementation always throws an {@link IOException} to
303: * indicate that the subclass should have overridden this method.
304: *
305: * @throws IOException
306: * Always. Designed to be subclassed.
307: */
308: protected void shutdownOutput() throws IOException {
309: // KA025=Method has not been implemented
310: throw new IOException(Msg.getString("KA025"));//$NON-NLS-1$
311: }
312:
313: /**
314: * Connect the socket to the host/port specified by the SocketAddress with a
315: * specified timeout.
316: *
317: * @param remoteAddr
318: * the remote machine address and port to connect to
319: * @param timeout
320: * the millisecond timeout value, the connect will block
321: * indefinitely for a zero value.
322: *
323: * @exception IOException
324: * if a problem occurs during the connect
325: */
326: protected abstract void connect(SocketAddress remoteAddr,
327: int timeout) throws IOException;
328:
329: /**
330: * Answer if the socket supports urgent data. Subclasses should override
331: * this method.
332: *
333: * @return false, subclasses must override
334: */
335: protected boolean supportsUrgentData() {
336: return false;
337: }
338:
339: /**
340: * Send the single byte of urgent data on the socket.
341: *
342: * @param value
343: * the byte of urgent data
344: *
345: * @exception IOException
346: * when an error occurs sending urgent data
347: */
348: protected abstract void sendUrgentData(int value)
349: throws IOException;
350:
351: /**
352: * Sets performance preference for connectionTime, latency and bandwidth.
353: * Does nothing by default.
354: *
355: * @param connectionTime
356: * the importance of connect time
357: * @param latency
358: * the importance of latency
359: * @param bandwidth
360: * the importance of bandwidth
361: */
362: protected void setPerformancePreferences(int connectionTime,
363: int latency, int bandwidth) {
364: // Our socket implementation only provide one protocol: TCP/IP, so
365: // we do nothing for this method
366: }
367: }
|