151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
3e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.net;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InputStream;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.OutputStream;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.FileDescriptor;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
353a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong * The abstract class {@code SocketImpl} is a common superclass
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of all classes that actually implement sockets. It is used to
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * create both client and server sockets.
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A "plain" socket implements these methods exactly as
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * described, without attempting to go through a firewall or proxy.
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author  unascribed
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since   JDK1.0
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic abstract class SocketImpl implements SocketOptions {
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The actual Socket object.
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    Socket socket = null;
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    ServerSocket serverSocket = null;
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The file descriptor object for this socket.
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected FileDescriptor fd;
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The IP address of the remote end of this socket.
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected InetAddress address;
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The port number on the remote host to which this socket is connected.
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected int port;
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The local port number to which this socket is connected.
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected int localport;
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates either a stream or a datagram socket.
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
753a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @param      stream   if {@code true}, create a stream socket;
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                      otherwise, create a datagram socket.
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs while creating the
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               socket.
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract void create(boolean stream) throws IOException;
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Connects this socket to the specified port on the named host.
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      host   the name of the remote host.
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      port   the port number.
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when connecting to the
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               remote host.
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract void connect(String host, int port) throws IOException;
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Connects this socket to the specified port number on the specified host.
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      address   the IP address of the remote host.
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      port      the port number.
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when attempting a
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               connection.
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract void connect(InetAddress address, int port) throws IOException;
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Connects this socket to the specified port number on the specified host.
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * A timeout of zero is interpreted as an infinite timeout. The connection
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * will then block until established or an error occurs.
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      address   the Socket address of the remote host.
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param     timeout  the timeout value, in milliseconds, or zero for no timeout.
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when attempting a
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               connection.
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.4
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract void connect(SocketAddress address, int timeout) throws IOException;
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Binds this socket to the specified local IP address and port number.
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      host   an IP address that belongs to a local interface.
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      port   the port number.
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when binding this socket.
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract void bind(InetAddress host, int port) throws IOException;
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Sets the maximum queue length for incoming connection indications
1263a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * (a request to connect) to the {@code count} argument. If a
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * connection indication arrives when the queue is full, the
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * connection is refused.
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      backlog   the maximum length of the queue.
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when creating the queue.
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract void listen(int backlog) throws IOException;
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Accepts a connection.
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      s   the accepted connection.
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when accepting the
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               connection.
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract void accept(SocketImpl s) throws IOException;
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns an input stream for this socket.
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     a stream for reading from this socket.
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when creating the
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               input stream.
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    */
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract InputStream getInputStream() throws IOException;
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns an output stream for this socket.
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     an output stream for writing to this socket.
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when creating the
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               output stream.
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract OutputStream getOutputStream() throws IOException;
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the number of bytes that can be read from this socket
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * without blocking.
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     the number of bytes that can be read from this socket
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             without blocking.
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when determining the
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               number of bytes available.
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract int available() throws IOException;
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Closes this socket.
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs when closing this socket.
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract void close() throws IOException;
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Places the input stream for this socket at "end of stream".
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Any data sent to this socket is acknowledged and then
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * silently discarded.
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
185402988a2c41b244ba5d5977fe790af1803567ca6Victor Chang     * If you read from a socket input stream after invoking this method on the
186402988a2c41b244ba5d5977fe790af1803567ca6Victor Chang     * socket, the stream's {@code available} method will return 0, and its
187402988a2c41b244ba5d5977fe790af1803567ca6Victor Chang     * {@code read} methods will return {@code -1} (end of stream).
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException if an I/O error occurs when shutting down this
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * socket.
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.net.Socket#shutdownOutput()
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.net.Socket#close()
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.net.Socket#setSoLinger(boolean, int)
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void shutdownInput() throws IOException {
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski      throw new IOException("Method not implemented!");
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Disables the output stream for this socket.
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * For a TCP socket, any previously written data will be sent
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * followed by TCP's normal connection termination sequence.
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If you write to a socket output stream after invoking
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * shutdownOutput() on the socket, the stream will throw
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * an IOException.
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException if an I/O error occurs when shutting down this
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * socket.
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.net.Socket#shutdownInput()
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.net.Socket#close()
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.net.Socket#setSoLinger(boolean, int)
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void shutdownOutput() throws IOException {
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski      throw new IOException("Method not implemented!");
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
2213a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Returns the value of this socket's {@code fd} field.
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
2233a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return  the value of this socket's {@code fd} field.
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.SocketImpl#fd
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
226b0ff23bbf588d76541eed5f98be94785dcba6b98Przemyslaw Szczepaniak    protected FileDescriptor getFileDescriptor() {
227b0ff23bbf588d76541eed5f98be94785dcba6b98Przemyslaw Szczepaniak        return fd;
228b0ff23bbf588d76541eed5f98be94785dcba6b98Przemyslaw Szczepaniak    }
229b0ff23bbf588d76541eed5f98be94785dcba6b98Przemyslaw Szczepaniak
230bfa68df087738325b250e7b9e7c88273a21962baVictor Chang    // Android-added: getFD$() for testing.
231b0ff23bbf588d76541eed5f98be94785dcba6b98Przemyslaw Szczepaniak    /**
232b0ff23bbf588d76541eed5f98be94785dcba6b98Przemyslaw Szczepaniak     * @hide used by java.nio tests
233b0ff23bbf588d76541eed5f98be94785dcba6b98Przemyslaw Szczepaniak     */
234b0ff23bbf588d76541eed5f98be94785dcba6b98Przemyslaw Szczepaniak    public FileDescriptor getFD$() {
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return fd;
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
2393a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Returns the value of this socket's {@code address} field.
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
2413a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return  the value of this socket's {@code address} field.
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.SocketImpl#address
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected InetAddress getInetAddress() {
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return address;
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
2493a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Returns the value of this socket's {@code port} field.
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
2513a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return  the value of this socket's {@code port} field.
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.SocketImpl#port
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected int getPort() {
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return port;
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns whether or not this SocketImpl supports sending
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * urgent data. By default, false is returned
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * unless the method is overridden in a sub-class
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  true if urgent data supported
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.SocketImpl#address
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.4
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected boolean supportsUrgentData () {
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false; // must be overridden in sub-class
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Send one byte of urgent data on the socket.
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The byte to be sent is the low eight bits of the parameter
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param data The byte of data to send
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException if there is an error
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  sending the data.
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.4
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected abstract void sendUrgentData (int data) throws IOException;
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
2823a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Returns the value of this socket's {@code localport} field.
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
2843a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return  the value of this socket's {@code localport} field.
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.SocketImpl#localport
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected int getLocalPort() {
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return localport;
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void setSocket(Socket soc) {
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.socket = soc;
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    Socket getSocket() {
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return socket;
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void setServerSocket(ServerSocket soc) {
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.serverSocket = soc;
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    ServerSocket getServerSocket() {
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return serverSocket;
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
3083a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Returns the address and port of this socket as a {@code String}.
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  a string representation of this socket.
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String toString() {
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return "Socket[addr=" + getInetAddress() +
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ",port=" + getPort() + ",localport=" + getLocalPort()  + "]";
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void reset() throws IOException {
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        address = null;
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        port = 0;
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        localport = 0;
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Sets performance preferences for this socket.
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> Sockets use the TCP/IP protocol by default.  Some implementations
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * may offer alternative protocols which have different performance
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * characteristics than TCP/IP.  This method allows the application to
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * express its own preferences as to how these tradeoffs should be made
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * when the implementation chooses from the available protocols.
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> Performance preferences are described by three integers
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * whose values indicate the relative importance of short connection time,
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * low latency, and high bandwidth.  The absolute values of the integers
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * are irrelevant; in order to choose a protocol the values are simply
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * compared, with larger values indicating stronger preferences. Negative
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * values represent a lower priority than positive values. If the
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * application prefers short connection time over both low latency and high
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * bandwidth, for example, then it could invoke this method with the values
3403a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * {@code (1, 0, 0)}.  If the application prefers high bandwidth above low
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * latency, and low latency above short connection time, then it could
3423a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * invoke this method with the values {@code (0, 1, 2)}.
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * By default, this method does nothing, unless it is overridden in a
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * a sub-class.
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param  connectionTime
3483a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     *         An {@code int} expressing the relative importance of a short
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         connection time
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param  latency
3523a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     *         An {@code int} expressing the relative importance of low
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         latency
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param  bandwidth
3563a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     *         An {@code int} expressing the relative importance of high
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         bandwidth
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.5
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void setPerformancePreferences(int connectionTime,
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                          int latency,
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                          int bandwidth)
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* Not implemented yet */
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
367e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
368e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    <T> void setOption(SocketOption<T> name, T value) throws IOException {
369e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (name == StandardSocketOptions.SO_KEEPALIVE) {
370e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            setOption(SocketOptions.SO_KEEPALIVE, value);
371e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.SO_SNDBUF) {
372e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            setOption(SocketOptions.SO_SNDBUF, value);
373e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.SO_RCVBUF) {
374e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            setOption(SocketOptions.SO_RCVBUF, value);
375e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.SO_REUSEADDR) {
376e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            setOption(SocketOptions.SO_REUSEADDR, value);
377e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.SO_LINGER) {
378e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            setOption(SocketOptions.SO_LINGER, value);
379e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.IP_TOS) {
380e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            setOption(SocketOptions.IP_TOS, value);
381e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.TCP_NODELAY) {
382e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            setOption(SocketOptions.TCP_NODELAY, value);
383e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else {
384e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new UnsupportedOperationException("unsupported option");
385e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
386e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
387e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
388e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    <T> T getOption(SocketOption<T> name) throws IOException {
389e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (name == StandardSocketOptions.SO_KEEPALIVE) {
390e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            return (T)getOption(SocketOptions.SO_KEEPALIVE);
391e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.SO_SNDBUF) {
392e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            return (T)getOption(SocketOptions.SO_SNDBUF);
393e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.SO_RCVBUF) {
394e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            return (T)getOption(SocketOptions.SO_RCVBUF);
395e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.SO_REUSEADDR) {
396e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            return (T)getOption(SocketOptions.SO_REUSEADDR);
397e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.SO_LINGER) {
398e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            return (T)getOption(SocketOptions.SO_LINGER);
399e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.IP_TOS) {
400e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            return (T)getOption(SocketOptions.IP_TOS);
401e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else if (name == StandardSocketOptions.TCP_NODELAY) {
402e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            return (T)getOption(SocketOptions.TCP_NODELAY);
403e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } else {
404e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new UnsupportedOperationException("unsupported option");
405e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
406e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
408