1//
2//  ========================================================================
3//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4//  ------------------------------------------------------------------------
5//  All rights reserved. This program and the accompanying materials
6//  are made available under the terms of the Eclipse Public License v1.0
7//  and Apache License v2.0 which accompanies this distribution.
8//
9//      The Eclipse Public License is available at
10//      http://www.eclipse.org/legal/epl-v10.html
11//
12//      The Apache License v2.0 is available at
13//      http://www.opensource.org/licenses/apache2.0.php
14//
15//  You may elect to redistribute this code under either of these licenses.
16//  ========================================================================
17//
18
19package org.eclipse.jetty.io.bio;
20
21import java.io.IOException;
22import java.net.InetAddress;
23import java.net.InetSocketAddress;
24import java.net.Socket;
25
26import javax.net.ssl.SSLSocket;
27
28import org.eclipse.jetty.util.StringUtil;
29import org.eclipse.jetty.util.log.Log;
30import org.eclipse.jetty.util.log.Logger;
31
32public class SocketEndPoint extends StreamEndPoint
33{
34    private static final Logger LOG = Log.getLogger(SocketEndPoint.class);
35
36    final Socket _socket;
37    final InetSocketAddress _local;
38    final InetSocketAddress _remote;
39
40    /* ------------------------------------------------------------ */
41    /**
42     *
43     */
44    public SocketEndPoint(Socket socket)
45    	throws IOException
46    {
47        super(socket.getInputStream(),socket.getOutputStream());
48        _socket=socket;
49        _local=(InetSocketAddress)_socket.getLocalSocketAddress();
50        _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();
51        super.setMaxIdleTime(_socket.getSoTimeout());
52    }
53
54    /* ------------------------------------------------------------ */
55    /**
56     *
57     */
58    protected SocketEndPoint(Socket socket, int maxIdleTime)
59        throws IOException
60    {
61        super(socket.getInputStream(),socket.getOutputStream());
62        _socket=socket;
63        _local=(InetSocketAddress)_socket.getLocalSocketAddress();
64        _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();
65        _socket.setSoTimeout(maxIdleTime>0?maxIdleTime:0);
66        super.setMaxIdleTime(maxIdleTime);
67    }
68
69    /* ------------------------------------------------------------ */
70    /* (non-Javadoc)
71     * @see org.eclipse.io.BufferIO#isClosed()
72     */
73    @Override
74    public boolean isOpen()
75    {
76        return super.isOpen() && _socket!=null && !_socket.isClosed();
77    }
78
79    /* ------------------------------------------------------------ */
80    @Override
81    public boolean isInputShutdown()
82    {
83        if (_socket instanceof SSLSocket)
84            return super.isInputShutdown();
85        return _socket.isClosed() || _socket.isInputShutdown();
86    }
87
88    /* ------------------------------------------------------------ */
89    @Override
90    public boolean isOutputShutdown()
91    {
92        if (_socket instanceof SSLSocket)
93            return super.isOutputShutdown();
94
95        return _socket.isClosed() || _socket.isOutputShutdown();
96    }
97
98
99    /* ------------------------------------------------------------ */
100    /*
101     */
102    protected final void shutdownSocketOutput() throws IOException
103    {
104        if (!_socket.isClosed())
105        {
106            if (!_socket.isOutputShutdown())
107                _socket.shutdownOutput();
108            if (_socket.isInputShutdown())
109                _socket.close();
110        }
111    }
112
113    /* ------------------------------------------------------------ */
114    /*
115     * @see org.eclipse.jetty.io.bio.StreamEndPoint#shutdownOutput()
116     */
117    @Override
118    public void shutdownOutput() throws IOException
119    {
120        if (_socket instanceof SSLSocket)
121            super.shutdownOutput();
122        else
123            shutdownSocketOutput();
124    }
125
126
127    /* ------------------------------------------------------------ */
128    /*
129     */
130    public void shutdownSocketInput() throws IOException
131    {
132        if (!_socket.isClosed())
133        {
134            if (!_socket.isInputShutdown())
135                _socket.shutdownInput();
136            if (_socket.isOutputShutdown())
137                _socket.close();
138        }
139    }
140
141    /* ------------------------------------------------------------ */
142    /*
143     * @see org.eclipse.jetty.io.bio.StreamEndPoint#shutdownOutput()
144     */
145    @Override
146    public void shutdownInput() throws IOException
147    {
148        if (_socket instanceof SSLSocket)
149            super.shutdownInput();
150        else
151            shutdownSocketInput();
152    }
153
154    /* ------------------------------------------------------------ */
155    /* (non-Javadoc)
156     * @see org.eclipse.io.BufferIO#close()
157     */
158    @Override
159    public void close() throws IOException
160    {
161        _socket.close();
162        _in=null;
163        _out=null;
164    }
165
166
167    /* ------------------------------------------------------------ */
168    /*
169     * @see org.eclipse.io.EndPoint#getLocalAddr()
170     */
171    @Override
172    public String getLocalAddr()
173    {
174       if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
175           return StringUtil.ALL_INTERFACES;
176
177        return _local.getAddress().getHostAddress();
178    }
179
180    /* ------------------------------------------------------------ */
181    /*
182     * @see org.eclipse.io.EndPoint#getLocalHost()
183     */
184    @Override
185    public String getLocalHost()
186    {
187       if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
188           return StringUtil.ALL_INTERFACES;
189
190        return _local.getAddress().getCanonicalHostName();
191    }
192
193    /* ------------------------------------------------------------ */
194    /*
195     * @see org.eclipse.io.EndPoint#getLocalPort()
196     */
197    @Override
198    public int getLocalPort()
199    {
200        if (_local==null)
201            return -1;
202        return _local.getPort();
203    }
204
205    /* ------------------------------------------------------------ */
206    /*
207     * @see org.eclipse.io.EndPoint#getRemoteAddr()
208     */
209    @Override
210    public String getRemoteAddr()
211    {
212        if (_remote==null)
213            return null;
214        InetAddress addr = _remote.getAddress();
215        return ( addr == null ? null : addr.getHostAddress() );
216    }
217
218    /* ------------------------------------------------------------ */
219    /*
220     * @see org.eclipse.io.EndPoint#getRemoteHost()
221     */
222    @Override
223    public String getRemoteHost()
224    {
225        if (_remote==null)
226            return null;
227        return _remote.getAddress().getCanonicalHostName();
228    }
229
230    /* ------------------------------------------------------------ */
231    /*
232     * @see org.eclipse.io.EndPoint#getRemotePort()
233     */
234    @Override
235    public int getRemotePort()
236    {
237        if (_remote==null)
238            return -1;
239        return _remote.getPort();
240    }
241
242    /* ------------------------------------------------------------ */
243    /*
244     * @see org.eclipse.io.EndPoint#getConnection()
245     */
246    @Override
247    public Object getTransport()
248    {
249        return _socket;
250    }
251
252    /* ------------------------------------------------------------ */
253    /**
254     * @see org.eclipse.jetty.io.bio.StreamEndPoint#setMaxIdleTime(int)
255     */
256    @Override
257    public void setMaxIdleTime(int timeMs) throws IOException
258    {
259        if (timeMs!=getMaxIdleTime())
260            _socket.setSoTimeout(timeMs>0?timeMs:0);
261        super.setMaxIdleTime(timeMs);
262    }
263
264
265    /* ------------------------------------------------------------ */
266    @Override
267    protected void idleExpired() throws IOException
268    {
269        try
270        {
271            if (!isInputShutdown())
272                shutdownInput();
273        }
274        catch(IOException e)
275        {
276            LOG.ignore(e);
277            _socket.close();
278        }
279    }
280
281    @Override
282    public String toString()
283    {
284        return _local + " <--> " + _remote;
285    }
286}
287