|
16 | 16 | import com.ning.http.client.AsyncHandler;
|
17 | 17 | import com.ning.http.client.AsyncHttpClientConfig;
|
18 | 18 | import com.ning.http.client.AsyncHttpProvider;
|
| 19 | +import com.ning.http.client.AsyncHttpProviderConfig; |
19 | 20 | import com.ning.http.client.Body;
|
20 | 21 | import com.ning.http.client.BodyGenerator;
|
21 | 22 | import com.ning.http.client.ConnectionPoolKeyStrategy;
|
|
112 | 113 | import org.slf4j.LoggerFactory;
|
113 | 114 |
|
114 | 115 | import javax.net.ssl.SSLContext;
|
| 116 | +import java.io.ByteArrayOutputStream; |
115 | 117 | import java.io.EOFException;
|
116 | 118 | import java.io.File;
|
117 | 119 | import java.io.FileInputStream;
|
|
136 | 138 | import java.util.concurrent.atomic.AtomicInteger;
|
137 | 139 | import java.util.concurrent.atomic.AtomicLong;
|
138 | 140 |
|
| 141 | +import static com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProviderConfig.Property.BUFFER_WEBSOCKET_FRAGMENTS; |
139 | 142 | import static com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProviderConfig.Property.MAX_HTTP_PACKET_HEADER_SIZE;
|
140 | 143 | import static com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProviderConfig.Property.TRANSPORT_CUSTOMIZER;
|
141 | 144 |
|
@@ -1328,17 +1331,19 @@ protected void onHttpHeadersParsed(HttpHeader httpHeader,
|
1328 | 1331 | }
|
1329 | 1332 | if (context.isWSRequest) {
|
1330 | 1333 | try {
|
1331 |
| - //in case of DIGEST auth protocol handler is null and just returning here is working |
1332 |
| - if(context.protocolHandler == null) |
1333 |
| - { |
1334 |
| - return; |
1335 |
| - //context.protocolHandler = Version.DRAFT17.createHandler(true); |
1336 |
| - //context.currentState = AsyncHandler.STATE.UPGRADE; |
1337 |
| - } |
1338 |
| - |
| 1334 | + //in case of DIGEST auth protocol handler is null and just returning here is working |
| 1335 | + if(context.protocolHandler == null) |
| 1336 | + { |
| 1337 | + return; |
| 1338 | + //context.protocolHandler = Version.DRAFT17.createHandler(true); |
| 1339 | + //context.currentState = AsyncHandler.STATE.UPGRADE; |
| 1340 | + } |
| 1341 | + |
1339 | 1342 | context.protocolHandler.setConnection(ctx.getConnection());
|
1340 |
| - DefaultWebSocket ws = new DefaultWebSocket(context.protocolHandler); |
1341 |
| - context.webSocket = new GrizzlyWebSocketAdapter(ws); |
| 1343 | + |
| 1344 | + final GrizzlyWebSocketAdapter webSocketAdapter = createWebSocketAdapter(context); |
| 1345 | + context.webSocket = webSocketAdapter; |
| 1346 | + DefaultWebSocket ws = webSocketAdapter.gWebSocket; |
1342 | 1347 | if (context.currentState == AsyncHandler.STATE.UPGRADE) {
|
1343 | 1348 | httpHeader.setChunked(false);
|
1344 | 1349 | ws.onConnect();
|
@@ -1429,6 +1434,16 @@ protected boolean onHttpPacketParsed(HttpHeader httpHeader, FilterChainContext c
|
1429 | 1434 |
|
1430 | 1435 | // ----------------------------------------------------- Private Methods
|
1431 | 1436 |
|
| 1437 | + private static GrizzlyWebSocketAdapter createWebSocketAdapter(final HttpTransactionContext context) { |
| 1438 | + DefaultWebSocket ws = new DefaultWebSocket(context.protocolHandler); |
| 1439 | + AsyncHttpProviderConfig config = context.provider.clientConfig.getAsyncHttpProviderConfig(); |
| 1440 | + boolean bufferFragments = true; |
| 1441 | + if (config instanceof GrizzlyAsyncHttpProviderConfig) { |
| 1442 | + bufferFragments = (Boolean) ((GrizzlyAsyncHttpProviderConfig) config).getProperty(BUFFER_WEBSOCKET_FRAGMENTS); |
| 1443 | + } |
| 1444 | + |
| 1445 | + return new GrizzlyWebSocketAdapter(ws, bufferFragments); |
| 1446 | + } |
1432 | 1447 |
|
1433 | 1448 | private static boolean isRedirectAllowed(final HttpTransactionContext ctx) {
|
1434 | 1449 | boolean allowed = ctx.request.isRedirectEnabled();
|
@@ -2724,13 +2739,16 @@ public void getBytes(byte[] bytes) {
|
2724 | 2739 |
|
2725 | 2740 | private static final class GrizzlyWebSocketAdapter implements WebSocket {
|
2726 | 2741 |
|
2727 |
| - private final org.glassfish.grizzly.websockets.WebSocket gWebSocket; |
| 2742 | + private final DefaultWebSocket gWebSocket; |
| 2743 | + private final boolean bufferFragments; |
2728 | 2744 |
|
2729 | 2745 | // -------------------------------------------------------- Constructors
|
2730 | 2746 |
|
2731 | 2747 |
|
2732 |
| - GrizzlyWebSocketAdapter(final org.glassfish.grizzly.websockets.WebSocket gWebSocket) { |
2733 |
| - this.gWebSocket = gWebSocket; |
| 2748 | + GrizzlyWebSocketAdapter(final DefaultWebSocket gWebSocket, |
| 2749 | + final boolean bufferFragements) { |
| 2750 | + this.gWebSocket = gWebSocket; |
| 2751 | + this.bufferFragments = bufferFragements; |
2734 | 2752 | }
|
2735 | 2753 |
|
2736 | 2754 |
|
@@ -2811,14 +2829,24 @@ public void close() {
|
2811 | 2829 | private static final class AHCWebSocketListenerAdapter implements org.glassfish.grizzly.websockets.WebSocketListener {
|
2812 | 2830 |
|
2813 | 2831 | private final WebSocketListener ahcListener;
|
2814 |
| - private final WebSocket webSocket; |
| 2832 | + private final GrizzlyWebSocketAdapter webSocket; |
| 2833 | + private final StringBuilder stringBuffer; |
| 2834 | + private final ByteArrayOutputStream byteArrayOutputStream; |
2815 | 2835 |
|
2816 | 2836 | // -------------------------------------------------------- Constructors
|
2817 | 2837 |
|
2818 | 2838 |
|
2819 |
| - AHCWebSocketListenerAdapter(final WebSocketListener ahcListener, WebSocket webSocket) { |
| 2839 | + AHCWebSocketListenerAdapter(final WebSocketListener ahcListener, |
| 2840 | + final GrizzlyWebSocketAdapter webSocket) { |
2820 | 2841 | this.ahcListener = ahcListener;
|
2821 | 2842 | this.webSocket = webSocket;
|
| 2843 | + if (webSocket.bufferFragments) { |
| 2844 | + stringBuffer = new StringBuilder(); |
| 2845 | + byteArrayOutputStream = new ByteArrayOutputStream(); |
| 2846 | + } else { |
| 2847 | + stringBuffer = null; |
| 2848 | + byteArrayOutputStream = null; |
| 2849 | + } |
2822 | 2850 | }
|
2823 | 2851 |
|
2824 | 2852 |
|
@@ -2893,21 +2921,47 @@ public void onPong(org.glassfish.grizzly.websockets.WebSocket webSocket, byte[]
|
2893 | 2921 | }
|
2894 | 2922 |
|
2895 | 2923 | @Override
|
2896 |
| - public void onFragment(org.glassfish.grizzly.websockets.WebSocket webSocket, String s, boolean b) { |
| 2924 | + public void onFragment(org.glassfish.grizzly.websockets.WebSocket webSocket, String s, boolean last) { |
2897 | 2925 | try {
|
2898 |
| - if (WebSocketTextListener.class.isAssignableFrom(ahcListener.getClass())) { |
2899 |
| - WebSocketTextListener.class.cast(ahcListener).onFragment(s, b); |
| 2926 | + if (this.webSocket.bufferFragments) { |
| 2927 | + synchronized (this.webSocket) { |
| 2928 | + stringBuffer.append(s); |
| 2929 | + if (last) { |
| 2930 | + if (WebSocketTextListener.class.isAssignableFrom(ahcListener.getClass())) { |
| 2931 | + final String message = stringBuffer.toString(); |
| 2932 | + stringBuffer.setLength(0); |
| 2933 | + WebSocketTextListener.class.cast(ahcListener).onMessage(message); |
| 2934 | + } |
| 2935 | + } |
| 2936 | + } |
| 2937 | + } else { |
| 2938 | + if (WebSocketTextListener.class.isAssignableFrom(ahcListener.getClass())) { |
| 2939 | + WebSocketTextListener.class.cast(ahcListener).onFragment(s, last); |
| 2940 | + } |
2900 | 2941 | }
|
2901 | 2942 | } catch (Throwable e) {
|
2902 | 2943 | ahcListener.onError(e);
|
2903 | 2944 | }
|
2904 | 2945 | }
|
2905 | 2946 |
|
2906 | 2947 | @Override
|
2907 |
| - public void onFragment(org.glassfish.grizzly.websockets.WebSocket webSocket, byte[] bytes, boolean b) { |
| 2948 | + public void onFragment(org.glassfish.grizzly.websockets.WebSocket webSocket, byte[] bytes, boolean last) { |
2908 | 2949 | try {
|
2909 |
| - if (WebSocketByteListener.class.isAssignableFrom(ahcListener.getClass())) { |
2910 |
| - WebSocketByteListener.class.cast(ahcListener).onFragment(bytes, b); |
| 2950 | + if (this.webSocket.bufferFragments) { |
| 2951 | + synchronized (this.webSocket) { |
| 2952 | + byteArrayOutputStream.write(bytes); |
| 2953 | + if (last) { |
| 2954 | + if (WebSocketByteListener.class.isAssignableFrom(ahcListener.getClass())) { |
| 2955 | + final byte[] bytesLocal = byteArrayOutputStream.toByteArray(); |
| 2956 | + byteArrayOutputStream.reset(); |
| 2957 | + WebSocketByteListener.class.cast(ahcListener).onMessage(bytesLocal); |
| 2958 | + } |
| 2959 | + } |
| 2960 | + } |
| 2961 | + } else { |
| 2962 | + if (WebSocketByteListener.class.isAssignableFrom(ahcListener.getClass())) { |
| 2963 | + WebSocketByteListener.class.cast(ahcListener).onFragment(bytes, last); |
| 2964 | + } |
2911 | 2965 | }
|
2912 | 2966 | } catch (Throwable e) {
|
2913 | 2967 | ahcListener.onError(e);
|
|
0 commit comments