1 4 package com.tc.net.protocol; 5 6 import com.tc.async.api.Sink; 7 import com.tc.bytes.TCByteBuffer; 8 import com.tc.bytes.TCByteBufferFactory; 9 import com.tc.net.core.TCConnection; 10 import com.tc.util.Assert; 11 12 import java.io.IOException ; 13 import java.net.Socket ; 14 import java.util.Arrays ; 15 import java.util.HashSet ; 16 import java.util.Set ; 17 18 23 public class ProtocolSwitch implements TCProtocolAdaptor { 24 25 private static final String [] HTTP_METHODS = new String [] { "GET", "POST", "HEAD", "PUT", "OPTIONS", "DELETE", 26 "TRACE", "CONNECT" }; 27 28 private static final Set METHODS = new HashSet (Arrays.asList(HTTP_METHODS)); 29 30 private static final int INSPECT = 8; 32 33 private static final int PROTOCOL_UNKNOWN = 0; 34 private static final int PROTOCOL_NOT_HTTP = 1; 35 private static final int PROTOCOL_HTTP = 2; 36 37 private volatile int protocol = PROTOCOL_UNKNOWN; 38 private final TCByteBuffer[] buffer = new TCByteBuffer[] { TCByteBufferFactory.wrap(new byte[INSPECT]) }; 39 private final TCProtocolAdaptor delegate; 40 private final Sink httpSink; 41 42 public ProtocolSwitch(TCProtocolAdaptor delegate, Sink httpSink) { 43 this.delegate = delegate; 44 this.httpSink = httpSink; 45 } 46 47 public void addReadData(TCConnection source, TCByteBuffer[] data, int length) throws TCProtocolException { 48 switch (protocol) { 49 case PROTOCOL_NOT_HTTP: { 50 delegate.addReadData(source, data, length); 51 return; 52 } 53 case PROTOCOL_UNKNOWN: { 54 Assert.assertEquals(1, data.length); 55 TCByteBuffer buf = data[0]; 56 if (buf.hasRemaining()) { 57 return; 59 } 60 61 buf.flip(); 62 boolean isHttp = isHttp(buf); 63 buf.rewind(); 64 65 if (isHttp) { 66 protocol = PROTOCOL_HTTP; 67 final Socket socket; 68 try { 69 socket = source.detach(); 70 } catch (IOException e) { 71 throw new TCProtocolException(e); 72 } 73 httpSink.add(new HttpConnectionContext(socket, buf)); 74 return; 75 } else { 76 protocol = PROTOCOL_NOT_HTTP; 77 feedDataToDelegate(source, buf); 78 return; 79 } 80 } 81 default: 82 throw new AssertionError ("Protocol is " + protocol); 83 } 84 85 } 87 88 private void feedDataToDelegate(TCConnection source, TCByteBuffer src) throws TCProtocolException { 89 while (src.hasRemaining()) { 90 int count = 0; 91 92 TCByteBuffer[] readBuffers = delegate.getReadBuffers(); 93 for (int i = 0; i < readBuffers.length; i++) { 94 TCByteBuffer dest = readBuffers[i]; 95 int len = Math.min(src.remaining(), dest.remaining()); 96 count += len; 97 for (int j = 0; j < len; j++) { 98 dest.put(src.get()); 99 } 100 if (!src.hasRemaining()) { 101 break; 102 } 103 } 104 105 delegate.addReadData(source, readBuffers, count); 106 } 107 } 108 109 private static boolean isHttp(TCByteBuffer buf) { 110 Assert.assertEquals(INSPECT, buf.limit()); 111 byte[] bytes = new byte[buf.limit()]; 112 buf.get(bytes); 113 114 final String s; 115 try { 116 s = new String (bytes); 117 } catch (Exception e) { 118 return false; 119 } 120 121 int spaceIndex = s.indexOf(' '); 122 if (spaceIndex < 0) { return false; } 123 124 String token = s.substring(0, spaceIndex); 125 126 return METHODS.contains(token); 128 } 129 130 public TCByteBuffer[] getReadBuffers() { 131 switch (protocol) { 132 case PROTOCOL_NOT_HTTP: { 133 return delegate.getReadBuffers(); 134 } 135 case PROTOCOL_UNKNOWN: { 136 return buffer; 137 } 138 default: 139 throw new AssertionError ("Protocol is " + protocol); 140 } 141 142 } 144 } 145 | Popular Tags |