1 /*
2  * ====================================================================
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  * ====================================================================
20  *
21  * This software consists of voluntary contributions made by many
22  * individuals on behalf of the Apache Software Foundation.  For more
23  * information on the Apache Software Foundation, please see
24  * <http://www.apache.org/>.
25  *
26  */
27 
28 package ch.boye.httpclientandroidlib.impl;
29 
30 import java.io.IOException;
31 import java.net.InetAddress;
32 import java.net.InetSocketAddress;
33 import java.net.Socket;
34 import java.net.SocketAddress;
35 import java.net.SocketException;
36 
37 import ch.boye.httpclientandroidlib.HttpInetConnection;
38 import ch.boye.httpclientandroidlib.impl.io.SocketInputBuffer;
39 import ch.boye.httpclientandroidlib.impl.io.SocketOutputBuffer;
40 import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
41 import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
42 import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
43 import ch.boye.httpclientandroidlib.params.HttpParams;
44 import ch.boye.httpclientandroidlib.util.Args;
45 import ch.boye.httpclientandroidlib.util.Asserts;
46 
47 @Deprecated
48 public class SocketHttpServerConnection extends
49         AbstractHttpServerConnection implements HttpInetConnection {
50 
51     private volatile boolean open;
52     private volatile Socket socket = null;
53 
SocketHttpServerConnection()54     public SocketHttpServerConnection() {
55         super();
56     }
57 
assertNotOpen()58     protected void assertNotOpen() {
59         Asserts.check(!this.open, "Connection is already open");
60     }
61 
62     @Override
assertOpen()63     protected void assertOpen() {
64         Asserts.check(this.open, "Connection is not open");
65     }
66 
67     /**
68      * Creates an instance of {@link SocketInputBuffer} to be used for
69      * receiving data from the given {@link Socket}.
70      * <p>
71      * This method can be overridden in a super class in order to provide
72      * a custom implementation of {@link SessionInputBuffer} interface.
73      *
74      * @see SocketInputBuffer#SocketInputBuffer(Socket, int, HttpParams)
75      *
76      * @param socket the socket.
77      * @param buffersize the buffer size.
78      * @param params HTTP parameters.
79      * @return session input buffer.
80      * @throws IOException in case of an I/O error.
81      */
createSessionInputBuffer( final Socket socket, final int buffersize, final HttpParams params)82     protected SessionInputBuffer createSessionInputBuffer(
83             final Socket socket,
84             final int buffersize,
85             final HttpParams params) throws IOException {
86         return new SocketInputBuffer(socket, buffersize, params);
87     }
88 
89     /**
90      * Creates an instance of {@link SessionOutputBuffer} to be used for
91      * sending data to the given {@link Socket}.
92      * <p>
93      * This method can be overridden in a super class in order to provide
94      * a custom implementation of {@link SocketOutputBuffer} interface.
95      *
96      * @see SocketOutputBuffer#SocketOutputBuffer(Socket, int, HttpParams)
97      *
98      * @param socket the socket.
99      * @param buffersize the buffer size.
100      * @param params HTTP parameters.
101      * @return session output buffer.
102      * @throws IOException in case of an I/O error.
103      */
createSessionOutputBuffer( final Socket socket, final int buffersize, final HttpParams params)104     protected SessionOutputBuffer createSessionOutputBuffer(
105             final Socket socket,
106             final int buffersize,
107             final HttpParams params) throws IOException {
108         return new SocketOutputBuffer(socket, buffersize, params);
109     }
110 
111     /**
112      * Binds this connection to the given {@link Socket}. This socket will be
113      * used by the connection to send and receive data.
114      * <p>
115      * This method will invoke {@link #createSessionInputBuffer(Socket, int, HttpParams)}
116      * and {@link #createSessionOutputBuffer(Socket, int, HttpParams)} methods
117      * to create session input / output buffers bound to this socket and then
118      * will invoke {@link #init(SessionInputBuffer, SessionOutputBuffer, HttpParams)}
119      * method to pass references to those buffers to the underlying HTTP message
120      * parser and formatter.
121      * <p>
122      * After this method's execution the connection status will be reported
123      * as open and the {@link #isOpen()} will return <code>true</code>.
124      *
125      * @param socket the socket.
126      * @param params HTTP parameters.
127      * @throws IOException in case of an I/O error.
128      */
bind(final Socket socket, final HttpParams params)129     protected void bind(final Socket socket, final HttpParams params) throws IOException {
130         Args.notNull(socket, "Socket");
131         Args.notNull(params, "HTTP parameters");
132         this.socket = socket;
133 
134         final int buffersize = params.getIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, -1);
135         init(
136                 createSessionInputBuffer(socket, buffersize, params),
137                 createSessionOutputBuffer(socket, buffersize, params),
138                 params);
139 
140         this.open = true;
141     }
142 
getSocket()143     protected Socket getSocket() {
144         return this.socket;
145     }
146 
isOpen()147     public boolean isOpen() {
148         return this.open;
149     }
150 
getLocalAddress()151     public InetAddress getLocalAddress() {
152         if (this.socket != null) {
153             return this.socket.getLocalAddress();
154         } else {
155             return null;
156         }
157     }
158 
getLocalPort()159     public int getLocalPort() {
160         if (this.socket != null) {
161             return this.socket.getLocalPort();
162         } else {
163             return -1;
164         }
165     }
166 
getRemoteAddress()167     public InetAddress getRemoteAddress() {
168         if (this.socket != null) {
169             return this.socket.getInetAddress();
170         } else {
171             return null;
172         }
173     }
174 
getRemotePort()175     public int getRemotePort() {
176         if (this.socket != null) {
177             return this.socket.getPort();
178         } else {
179             return -1;
180         }
181     }
182 
setSocketTimeout(final int timeout)183     public void setSocketTimeout(final int timeout) {
184         assertOpen();
185         if (this.socket != null) {
186             try {
187                 this.socket.setSoTimeout(timeout);
188             } catch (final SocketException ignore) {
189                 // It is not quite clear from the Sun's documentation if there are any
190                 // other legitimate cases for a socket exception to be thrown when setting
191                 // SO_TIMEOUT besides the socket being already closed
192             }
193         }
194     }
195 
getSocketTimeout()196     public int getSocketTimeout() {
197         if (this.socket != null) {
198             try {
199                 return this.socket.getSoTimeout();
200             } catch (final SocketException ignore) {
201                 return -1;
202             }
203         } else {
204             return -1;
205         }
206     }
207 
shutdown()208     public void shutdown() throws IOException {
209         this.open = false;
210         final Socket tmpsocket = this.socket;
211         if (tmpsocket != null) {
212             tmpsocket.close();
213         }
214     }
215 
close()216     public void close() throws IOException {
217         if (!this.open) {
218             return;
219         }
220         this.open = false;
221         this.open = false;
222         final Socket sock = this.socket;
223         try {
224             doFlush();
225             try {
226                 try {
227                     sock.shutdownOutput();
228                 } catch (final IOException ignore) {
229                 }
230                 try {
231                     sock.shutdownInput();
232                 } catch (final IOException ignore) {
233                 }
234             } catch (final UnsupportedOperationException ignore) {
235                 // if one isn't supported, the other one isn't either
236             }
237         } finally {
238             sock.close();
239         }
240     }
241 
formatAddress(final StringBuilder buffer, final SocketAddress socketAddress)242     private static void formatAddress(final StringBuilder buffer, final SocketAddress socketAddress) {
243         if (socketAddress instanceof InetSocketAddress) {
244             final InetSocketAddress addr = ((InetSocketAddress) socketAddress);
245             buffer.append(addr.getAddress() != null ? addr.getAddress().getHostAddress() :
246                 addr.getAddress())
247             .append(':')
248             .append(addr.getPort());
249         } else {
250             buffer.append(socketAddress);
251         }
252     }
253 
254     @Override
toString()255     public String toString() {
256         if (this.socket != null) {
257             final StringBuilder buffer = new StringBuilder();
258             final SocketAddress remoteAddress = this.socket.getRemoteSocketAddress();
259             final SocketAddress localAddress = this.socket.getLocalSocketAddress();
260             if (remoteAddress != null && localAddress != null) {
261                 formatAddress(buffer, localAddress);
262                 buffer.append("<->");
263                 formatAddress(buffer, remoteAddress);
264             }
265             return buffer.toString();
266         } else {
267             return super.toString();
268         }
269     }
270 
271 }
272