SocketImpl.java revision dd828f42a5c83b4270d4fbf6fce2da1878f1e84a
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.net; 19 20import java.io.FileDescriptor; 21import java.io.IOException; 22import java.io.InputStream; 23import java.io.InterruptedIOException; 24import java.io.OutputStream; 25 26import org.apache.harmony.luni.platform.INetworkSystem; 27import org.apache.harmony.luni.platform.Platform; 28import org.apache.harmony.luni.util.Msg; 29 30/** 31 * This class is the base of all streaming socket implementation classes. 32 * Streaming sockets are wrapped by two classes, {@code ServerSocket} and 33 * {@code Socket} at the server and client end of a connection. At the server, 34 * there are two types of sockets engaged in communication, the {@code 35 * ServerSocket} on a well known port (referred to as listener) used to 36 * establish a connection and the resulting {@code Socket} (referred to as 37 * host). 38 * 39 * @since Android 1.0 40 */ 41public abstract class SocketImpl implements SocketOptions { 42 43 /** 44 * The remote address this socket is connected to. 45 * 46 * @since Android 1.0 47 */ 48 protected InetAddress address; 49 50 /** 51 * The remote port this socket is connected to. 52 * 53 * @since Android 1.0 54 */ 55 protected int port; 56 57 /** 58 * The file descriptor of this socket. 59 * 60 * @since Android 1.0 61 */ 62 protected FileDescriptor fd; 63 64 /** 65 * The local port this socket is connected to. 66 * 67 * @since Android 1.0 68 */ 69 protected int localport; 70 71 INetworkSystem netImpl; 72 73 // BEGIN android-removed 74 // int receiveTimeout; 75 // END android-removed 76 77 boolean streaming = true; 78 79 boolean shutdownInput; 80 81 /** 82 * Creates a new connection-oriented socket implementation. 83 * 84 * @see SocketImplFactory 85 * @since Android 1.0 86 */ 87 public SocketImpl() { 88 this.netImpl = Platform.getNetworkSystem(); 89 } 90 91 /** 92 * Waits for an incoming request and blocks until the connection is opened 93 * on the given socket. 94 * 95 * @param newSocket 96 * the socket to accept connections on. 97 * @throws IOException 98 * if an error occurs while accepting a new connection. 99 * @since Android 1.0 100 */ 101 protected abstract void accept(SocketImpl newSocket) throws IOException; 102 103 /** 104 * Returns the available number of bytes which are readable from this socket 105 * without blocking. 106 * 107 * @return the number of bytes that may be read without blocking. 108 * @throws IOException 109 * if an error occurs while reading the number of bytes. 110 * @since Android 1.0 111 */ 112 protected abstract int available() throws IOException; 113 114 /** 115 * Binds this socket to the specified local host address and port number. 116 * 117 * @param address 118 * the local machine address to bind this socket to. 119 * @param port 120 * the port on the local machine to bind this socket to. 121 * @throws IOException 122 * if an error occurs while binding this socket. 123 * @since Android 1.0 124 */ 125 protected abstract void bind(InetAddress address, int port) 126 throws IOException; 127 128 /** 129 * Closes this socket. This makes later access invalid. 130 * 131 * @throws IOException 132 * if an error occurs while closing this socket. 133 * @since Android 1.0 134 */ 135 protected abstract void close() throws IOException; 136 137 /** 138 * Connects this socket to the specified remote host and port number. 139 * 140 * @param host 141 * the remote host this socket has to be connected to. 142 * @param port 143 * the remote port on which this socket has to be connected. 144 * @throws IOException 145 * if an error occurs while connecting to the remote host. 146 * @since Android 1.0 147 */ 148 protected abstract void connect(String host, int port) throws IOException; 149 150 /** 151 * Connects this socket to the specified remote host address and port 152 * number. 153 * 154 * @param address 155 * the remote host address this socket has to be connected to. 156 * @param port 157 * the remote port on which this socket has to be connected. 158 * @throws IOException 159 * if an error occurs while connecting to the remote host. 160 * @since Android 1.0 161 */ 162 protected abstract void connect(InetAddress address, int port) 163 throws IOException; 164 165 /** 166 * Creates a new unconnected socket. The argument {@code isStreaming} 167 * defines whether the new socket is a streaming or a datagram socket. 168 * 169 * @param isStreaming 170 * defines whether the type of the new socket is streaming or 171 * datagram. 172 * @throws IOException 173 * if an error occurs while creating the socket. 174 * @since Android 1.0 175 */ 176 protected abstract void create(boolean isStreaming) throws IOException; 177 178 /** 179 * Gets the file descriptor of this socket. 180 * 181 * @return the file descriptor of this socket. 182 * @since Android 1.0 183 */ 184 protected FileDescriptor getFileDescriptor() { 185 return fd; 186 } 187 188 /** 189 * Gets the remote address this socket is connected to. 190 * 191 * @return the remote address of this socket. 192 * @since Android 1.0 193 */ 194 protected InetAddress getInetAddress() { 195 return address; 196 } 197 198 /** 199 * Gets the input stream of this socket. 200 * 201 * @return the input stream of this socket. 202 * @throws IOException 203 * if an error occurs while accessing the input stream. 204 * @since Android 1.0 205 */ 206 protected abstract InputStream getInputStream() throws IOException; 207 208 /** 209 * Gets the local port number of this socket. The field is initialized to 210 * {@code -1} and upon demand will go to the IP stack to get the bound 211 * value. See the class comment for the context of the local port. 212 * 213 * @return the local port number this socket is bound to. 214 * @since Android 1.0 215 */ 216 protected int getLocalPort() { 217 return localport; 218 } 219 220 /** 221 * Gets the value of the given socket option. 222 * 223 * @param optID 224 * the socket option to retrieve. 225 * @return the option value. 226 * @throws SocketException 227 * if an error occurs while accessing the option. 228 * @since Android 1.0 229 */ 230 public abstract Object getOption(int optID) throws SocketException; 231 232 /** 233 * Gets the output stream of this socket. 234 * 235 * @return the output stream of this socket. 236 * @throws IOException 237 * if an error occurs while accessing the output stream. 238 * @since Android 1.0 239 */ 240 protected abstract OutputStream getOutputStream() throws IOException; 241 242 /** 243 * Gets the remote port number of this socket. This value is not meaningful 244 * when this instance is wrapped by a {@code ServerSocket}. 245 * 246 * @return the remote port this socket is connected to. 247 * @since Android 1.0 248 */ 249 protected int getPort() { 250 return port; 251 } 252 253 /** 254 * Listens for connection requests on this streaming socket. Incoming 255 * connection requests are queued up to the limit specified by {@code 256 * backlog}. Additional requests are rejected. The method {@code listen()} 257 * may only be invoked on streaming sockets. 258 * 259 * @param backlog 260 * the maximum number of outstanding connection requests. 261 * @throws IOException 262 * if an error occurs while listening. 263 * @since Android 1.0 264 */ 265 protected abstract void listen(int backlog) throws IOException; 266 267 /** 268 * In the IP stack, read at most {@code count} bytes off the socket 269 * into the {@code buffer}, at the {@code offset}. If the timeout 270 * is zero, block indefinitely waiting for data, otherwise wait the 271 * specified period (in milliseconds). 272 * 273 * @param buffer 274 * the buffer to read into 275 * @param offset 276 * the offset into the buffer 277 * @param count 278 * the max number of bytes to read 279 * @return int the actual number of bytes read 280 * @exception IOException 281 * thrown if an error occurs while reading 282 */ 283 int read(byte[] buffer, int offset, int count) throws IOException { 284 if (shutdownInput) { 285 return -1; 286 } 287 try { 288 // BEGIN android-added 289 int receiveTimeout = (Integer)getOption(SocketOptions.SO_TIMEOUT); 290 // END android-added 291 int read = this.netImpl.receiveStream(fd, buffer, offset, count, 292 receiveTimeout); 293 if (read == -1) { 294 shutdownInput = true; 295 } 296 return read; 297 } catch (InterruptedIOException e) { 298 throw new SocketTimeoutException(e.getMessage()); 299 } 300 } 301 302 /** 303 * Sets the value for the specified socket option. 304 * 305 * @param optID 306 * the socket option to be set. 307 * @param val 308 * the option value. 309 * @throws SocketException 310 * if an error occurs while setting the option. 311 * @since Android 1.0 312 */ 313 public abstract void setOption(int optID, Object val) 314 throws SocketException; 315 316 /** 317 * Returns a string containing a concise, human-readable description of the 318 * socket. 319 * 320 * @return the textual representation of this socket. 321 * @since Android 1.0 322 */ 323 @SuppressWarnings("nls") 324 @Override 325 public String toString() { 326 return new StringBuffer(100).append("Socket[addr=").append( 327 getInetAddress()).append(",port=").append(port).append( 328 ",localport=").append(getLocalPort()).append("]").toString(); 329 } 330 331 /** 332 * In the IP stack, write at most {@code count} bytes on the socket 333 * from the {@code buffer}, from the {@code offset}. 334 * 335 * @param buffer 336 * the buffer to read into 337 * @param offset 338 * the offset into the buffer 339 * @param count 340 * the number of bytes to write 341 * @return int the actual number of bytes written 342 * @exception IOException 343 * thrown if an error occurs while writing 344 */ 345 int write(byte[] buffer, int offset, int count) throws IOException { 346 if (!streaming) { 347 // BEGIN android-changed 348 // copied from newer harmony version 349 return this.netImpl 350 .sendDatagram2(fd, buffer, offset, count, port, address); 351 // END android-changed 352 } 353 return this.netImpl.sendStream(fd, buffer, offset, count); 354 } 355 356 /** 357 * Closes the input channel of this socket. 358 * <p> 359 * This default implementation always throws an {@link IOException} to 360 * indicate that the subclass should have overridden this method. 361 * </p> 362 * 363 * @throws IOException 364 * always because this method should be overridden. 365 * @since Android 1.0 366 */ 367 protected void shutdownInput() throws IOException { 368 // KA025=Method has not been implemented 369 throw new IOException(Msg.getString("KA025"));//$NON-NLS-1$ 370 } 371 372 /** 373 * Closes the output channel of this socket. 374 * <p> 375 * This default implementation always throws an {@link IOException} to 376 * indicate that the subclass should have overridden this method. 377 * </p> 378 * 379 * @throws IOException 380 * always because this method should be overridden. 381 * @since Android 1.0 382 */ 383 protected void shutdownOutput() throws IOException { 384 // KA025=Method has not been implemented 385 throw new IOException(Msg.getString("KA025"));//$NON-NLS-1$ 386 } 387 388 /** 389 * Connects this socket to the remote host address and port number specified 390 * by the {@code SocketAddress} object with the given timeout. This method 391 * will block indefinitely if the timeout is set to zero. 392 * 393 * @param remoteAddr 394 * the remote host address and port number to connect to. 395 * @param timeout 396 * the timeout value in milliseconds. 397 * @throws IOException 398 * if an error occurs while connecting. 399 * @since Android 1.0 400 */ 401 protected abstract void connect(SocketAddress remoteAddr, int timeout) 402 throws IOException; 403 404 /** 405 * Returns whether the socket supports urgent data or not. Subclasses should 406 * override this method. 407 * 408 * @return {@code false} because subclasses must override this method. 409 * @since Android 1.0 410 */ 411 protected boolean supportsUrgentData() { 412 return false; 413 } 414 415 /** 416 * Sends the single byte of urgent data on the socket. 417 * 418 * @param value 419 * the byte of urgent data. 420 * @throws IOException 421 * if an error occurs sending urgent data. 422 * @since Android 1.0 423 */ 424 protected abstract void sendUrgentData(int value) throws IOException; 425 426 /** 427 * Sets performance preference for connection time, latency and bandwidth. 428 * Does nothing by default. 429 * 430 * @param connectionTime 431 * the importance of connect time. 432 * @param latency 433 * the importance of latency. 434 * @param bandwidth 435 * the importance of bandwidth. 436 * @since Android 1.0 437 */ 438 protected void setPerformancePreferences(int connectionTime, int latency, 439 int bandwidth) { 440 // Our socket implementation only provide one protocol: TCP/IP, so 441 // we do nothing for this method 442 } 443} 444