下面列出了 io.netty.handler.codec.http.websocketx.ContinuationWebSocketFrame #io.netty.handler.codec.CodecException 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private static void printAggregatedRedisResponse(RedisMessage msg) {
if (msg instanceof SimpleStringRedisMessage) {
System.out.println(((SimpleStringRedisMessage) msg).content());
} else if (msg instanceof ErrorRedisMessage) {
System.out.println(((ErrorRedisMessage) msg).content());
} else if (msg instanceof IntegerRedisMessage) {
System.out.println(((IntegerRedisMessage) msg).value());
} else if (msg instanceof FullBulkStringRedisMessage) {
System.out.println(getString((FullBulkStringRedisMessage) msg));
} else if (msg instanceof ArrayRedisMessage) {
for (RedisMessage child : ((ArrayRedisMessage) msg).children()) {
printAggregatedRedisResponse(child);
}
} else {
throw new CodecException("unknown message type: " + msg);
}
}
private RedisMessage decodeRedisArrayHeader(ArrayHeaderRedisMessage header) {
if (header.isNull()) {
return ArrayRedisMessage.NULL_INSTANCE;
} else if (header.length() == 0L) {
return ArrayRedisMessage.EMPTY_INSTANCE;
} else if (header.length() > 0L) {
// Currently, this codec doesn't support `long` length for arrays because Java's List.size() is int.
if (header.length() > Integer.MAX_VALUE) {
throw new CodecException("this codec doesn't support longer length than " + Integer.MAX_VALUE);
}
// start aggregating array
depths.push(new AggregateState((int) header.length()));
return null;
} else {
throw new CodecException("bad length: " + header.length());
}
}
private void writeRedisMessage(ByteBufAllocator allocator, RedisMessage msg, List<Object> out) {
if (msg instanceof SimpleStringRedisMessage) {
writeSimpleStringMessage(allocator, (SimpleStringRedisMessage) msg, out);
} else if (msg instanceof ErrorRedisMessage) {
writeErrorMessage(allocator, (ErrorRedisMessage) msg, out);
} else if (msg instanceof IntegerRedisMessage) {
writeIntegerMessage(allocator, (IntegerRedisMessage) msg, out);
} else if (msg instanceof FullBulkStringRedisMessage) {
writeFullBulkStringMessage(allocator, (FullBulkStringRedisMessage) msg, out);
} else if (msg instanceof BulkStringRedisContent) {
writeBulkStringContent(allocator, (BulkStringRedisContent) msg, out);
} else if (msg instanceof BulkStringHeaderRedisMessage) {
writeBulkStringHeader(allocator, (BulkStringHeaderRedisMessage) msg, out);
} else if (msg instanceof ArrayHeaderRedisMessage) {
writeArrayHeader(allocator, (ArrayHeaderRedisMessage) msg, out);
} else if (msg instanceof ArrayRedisMessage) {
writeArrayMessage(allocator, (ArrayRedisMessage) msg, out);
} else {
throw new CodecException("unknown message type: " + msg);
}
}
@Test
public void testFailsOnMissingResponse() {
HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true);
EmbeddedChannel ch = new EmbeddedChannel(codec);
assertTrue(ch.writeOutbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,
"http://localhost/")));
ByteBuf buffer = ch.readOutbound();
assertNotNull(buffer);
buffer.release();
try {
ch.finish();
fail();
} catch (CodecException e) {
assertTrue(e instanceof PrematureChannelClosureException);
}
}
@Test
public void testFailsOnIncompleteChunkedResponse() {
HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true);
EmbeddedChannel ch = new EmbeddedChannel(codec);
ch.writeOutbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/"));
ByteBuf buffer = ch.readOutbound();
assertNotNull(buffer);
buffer.release();
assertNull(ch.readInbound());
ch.writeInbound(Unpooled.copiedBuffer(INCOMPLETE_CHUNKED_RESPONSE, CharsetUtil.ISO_8859_1));
assertThat(ch.readInbound(), instanceOf(HttpResponse.class));
((HttpContent) ch.readInbound()).release(); // Chunk 'first'
((HttpContent) ch.readInbound()).release(); // Chunk 'second'
assertNull(ch.readInbound());
try {
ch.finish();
fail();
} catch (CodecException e) {
assertTrue(e instanceof PrematureChannelClosureException);
}
}
public static long readLengthEncodedInteger(ByteBuf buf, int firstByte) {
firstByte = firstByte & 0xff;
if (firstByte < NULL_VALUE) {
return firstByte;
}
if (firstByte == NULL_VALUE) {
return -1;
}
if (firstByte == SHORT_VALUE) {
return buf.readUnsignedShortLE();
}
if (firstByte == MEDIUM_VALUE) {
return buf.readUnsignedMediumLE();
}
if (firstByte == LONG_VALUE) {
long length = buf.readLongLE();
if (length < 0) {
throw new CodecException("Received a length value too large to handle: " + Long.toHexString(length));
}
return length;
}
throw new CodecException("Received an invalid length value " + firstByte);
}
private void processTRAILER ( final ChannelHandlerContext ctx, final byte b, final ByteBuf msg )
{
if ( b != Constants.LF )
{
throw new CodecException ( String.format ( "Expected trailer byte (LF) but found 0x%02X: Remaining buffer: %s", b, ByteBufUtil.hexDump ( msg, msg.readerIndex (), msg.readableBytes () ) ) );
}
final int length = ctx.attr ( ATTR_EXPECTED_LENGTH ).get ();
final long txnr = Long.parseLong ( ctx.attr ( ATTR_TXNR_BUFFER ).get ().toString ( TXNR_CHARSET ) );
final String command = ctx.attr ( ATTR_COMMAND_BUFFER ).get ().toString ( COMMAND_CHARSET );
final ByteBuf data = ctx.attr ( ATTR_DATA_BUFFER ).get ().readSlice ( length );
final Frame frame = new Frame ( txnr, command, data );
ctx.fireChannelRead ( frame );
ctx.attr ( ATTR_STATE ).set ( State.TXNR );
ctx.attr ( ATTR_TXNR_BUFFER ).get ().clear ();
ctx.attr ( ATTR_COMMAND_BUFFER ).get ().clear ();
ctx.attr ( ATTR_LENGTH_BUFFER ).get ().clear ();
ctx.attr ( ATTR_DATA_BUFFER ).get ().clear ();
}
protected void processMessage ( final ChannelHandlerContext ctx, final ByteBuf msg )
{
if ( msg.readByte () != PRI_START )
{
throw new CodecException ( "PRI start not found" );
}
final int prival = decodePrival ( msg );
final Severity severity = Severity.values ()[prival % 8];
final Facility facility = Facility.values ()[prival / 8];
final Calendar timestamp = this.timestampParser.parseTimestamp ( msg );
final String hostname = decodeHostname ( msg );
final String[] process = decodeProcess ( msg );
final String processName = process[0];
final Long processId = process.length > 1 ? Long.parseLong ( process[1] ) : null;
final String message = decodeMessage ( msg );
ctx.fireChannelRead ( new SyslogMessage ( facility, severity, timestamp, hostname, processName, processId, message ) );
}
private String[] decodeProcess ( final ByteBuf msg )
{
// split by colon
final int spaceIndex = msg.bytesBefore ( COLON );
if ( spaceIndex < 0 )
{
throw new CodecException ( "Unable to find process name" );
}
final String process = msg.readSlice ( spaceIndex ).toString ( StandardCharsets.US_ASCII );
msg.skipBytes ( 1 ); // COLON
if ( msg.isReadable () )
{
msg.skipBytes ( 1 ); // SPACE
}
final Matcher m = PROCESS_PATTERN.matcher ( process );
if ( m.matches () )
{
return new String[] { m.group ( 1 ), m.group ( 2 ) };
}
return new String[] { process };
}
private int decodePrival ( final ByteBuf msg )
{
final ByteBuffer privalBuffer = ByteBuffer.wrap ( new byte[3] );
byte b;
do
{
b = msg.readByte ();
if ( b == PRI_END )
{
break;
}
if ( !privalBuffer.hasRemaining () )
{
throw new CodecException ( "PRI value must be <=3 bytes" );
}
privalBuffer.put ( b );
} while ( true );
privalBuffer.flip ();
final int prival = Integer.parseInt ( StandardCharsets.US_ASCII.decode ( privalBuffer ).toString () );
return prival;
}
@Test
public void testFailsOnIncompleteChunkedResponse() {
HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true);
EmbeddedChannel ch = new EmbeddedChannel(codec);
ch.writeOutbound(releaseLater(
new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/")));
assertNotNull(releaseLater(ch.readOutbound()));
assertNull(ch.readInbound());
ch.writeInbound(releaseLater(
Unpooled.copiedBuffer(INCOMPLETE_CHUNKED_RESPONSE, CharsetUtil.ISO_8859_1)));
assertThat(releaseLater(ch.readInbound()), instanceOf(HttpResponse.class));
assertThat(releaseLater(ch.readInbound()), instanceOf(HttpContent.class)); // Chunk 'first'
assertThat(releaseLater(ch.readInbound()), instanceOf(HttpContent.class)); // Chunk 'second'
assertNull(ch.readInbound());
try {
ch.finish();
fail();
} catch (CodecException e) {
assertTrue(e instanceof PrematureChannelClosureException);
}
}
@Override
protected void decode(ChannelHandlerContext ctx, SctpMessage msg, List<Object> out) throws Exception {
if (!msg.isComplete()) {
throw new CodecException(String.format("Received SctpMessage is not complete, please add %s in the " +
"pipeline before this handler", SctpMessageCompletionHandler.class.getSimpleName()));
}
out.add(msg.content().retain());
}
@Override
public boolean acceptInboundMessage(Object msg) throws Exception {
if (msg instanceof SctpMessage) {
SctpMessage sctpMsg = (SctpMessage) msg;
if (sctpMsg.isComplete()) {
return true;
}
throw new CodecException(String.format("Received SctpMessage is not complete, please add %s in " +
"the pipeline before this handler", SctpMessageCompletionHandler.class.getSimpleName()));
} else {
return false;
}
}
@Override
protected void onTooBigFrame(EmbeddedChannel ch, ByteBuf input) {
try {
ch.writeInbound(input);
fail();
} catch (CodecException e) {
assertEquals(TooLongFrameException.class, e.getClass());
}
}
@Override
protected void onTooBigFrame(EmbeddedChannel ch, ByteBuf input) {
try {
ch.writeInbound(input);
fail();
} catch (CodecException e) {
assertEquals(TooLongFrameException.class, e.getClass());
}
}
private void processTXNR ( final ChannelHandlerContext ctx, final byte b )
{
if ( b == Constants.SP )
{
ctx.attr ( ATTR_STATE ).set ( State.COMMAND );
}
else
{
if ( b < 0x30 || b > 0x39 )
{
throw new CodecException ( String.format ( "Invalid character found: 0x%1$02x (%1$s)", b, (char)b ) );
}
ctx.attr ( ATTR_TXNR_BUFFER ).get ().writeByte ( b );
}
}
private String decodeHostname ( final ByteBuf msg )
{
// split by first space
final int spaceIndex = msg.bytesBefore ( Constants.SP );
if ( spaceIndex < 0 )
{
throw new CodecException ( "Unable to find hostname" );
}
final String hostname = msg.readSlice ( spaceIndex ).toString ( StandardCharsets.US_ASCII );
msg.skipBytes ( 1 ); // SPACE
return hostname;
}
@Test
public void testFailsOnMissingResponse() {
HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true);
EmbeddedChannel ch = new EmbeddedChannel(codec);
assertTrue(ch.writeOutbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,
"http://localhost/")));
assertNotNull(releaseLater(ch.readOutbound()));
try {
ch.finish();
fail();
} catch (CodecException e) {
assertTrue(e instanceof PrematureChannelClosureException);
}
}
@Override
protected void decode(ChannelHandlerContext ctx, SctpMessage msg, List<Object> out) throws Exception {
if (!msg.isComplete()) {
throw new CodecException(String.format("Received SctpMessage is not complete, please add %s in the " +
"pipeline before this handler", SctpMessageCompletionHandler.class.getSimpleName()));
}
out.add(msg.content().retain());
}
@Override
public boolean acceptInboundMessage(Object msg) throws Exception {
if (msg instanceof SctpMessage) {
SctpMessage sctpMsg = (SctpMessage) msg;
if (sctpMsg.isComplete()) {
return true;
}
throw new CodecException(String.format("Received SctpMessage is not complete, please add %s in " +
"the pipeline before this handler", SctpMessageCompletionHandler.class.getSimpleName()));
} else {
return false;
}
}
@Override
protected void onTooBigFrame(EmbeddedChannel ch, ByteBuf input) {
try {
ch.writeInbound(input);
fail();
} catch (CodecException e) {
assertEquals(TooLongFrameException.class, e.getClass());
}
}
@Override
protected void onTooBigFrame(EmbeddedChannel ch, ByteBuf input) {
try {
ch.writeInbound(input);
fail();
} catch (CodecException e) {
assertEquals(TooLongFrameException.class, e.getClass());
}
}
/**
* @param e the exception
* @param unexpectedExceptionHandler a callback for handling unexpected exceptions. If null, or if this
* returns false, the error is logged at ERROR level via sl4fj
*/
public static ErrorMessage fromException(Throwable e, Predicate<Throwable> unexpectedExceptionHandler)
{
int streamId = 0;
// Netty will wrap exceptions during decoding in a CodecException. If the cause was one of our ProtocolExceptions
// or some other internal exception, extract that and use it.
if (e instanceof CodecException)
{
Throwable cause = e.getCause();
if (cause != null && cause instanceof WrappedException)
{
streamId = ((WrappedException)cause).streamId;
e = cause.getCause();
}
}
else if (e instanceof WrappedException)
{
streamId = ((WrappedException)e).streamId;
e = e.getCause();
}
if (e instanceof TransportException)
return new ErrorMessage((TransportException)e, streamId);
// Unexpected exception
if (unexpectedExceptionHandler == null || !unexpectedExceptionHandler.apply(e))
logger.error("Unexpected exception during request", e);
return new ErrorMessage(new ServerError(e), streamId);
}
@Test(expected = CodecException.class)
public void testIfMainAndFallbackUseRSV1WillFail() {
// initialize
when(mainHandshakerMock.newRequestData()).
thenReturn(new WebSocketExtensionData("main", Collections.<String, String>emptyMap()));
when(mainHandshakerMock.handshakeExtension(
webSocketExtensionDataMatcher("main"))).thenReturn(mainExtensionMock);
when(mainHandshakerMock.handshakeExtension(
webSocketExtensionDataMatcher("fallback"))).thenReturn(null);
when(fallbackHandshakerMock.newRequestData()).
thenReturn(new WebSocketExtensionData("fallback", Collections.<String, String>emptyMap()));
when(fallbackHandshakerMock.handshakeExtension(
webSocketExtensionDataMatcher("main"))).thenReturn(null);
when(fallbackHandshakerMock.handshakeExtension(
webSocketExtensionDataMatcher("fallback"))).thenReturn(fallbackExtensionMock);
when(mainExtensionMock.rsv()).thenReturn(WebSocketExtension.RSV1);
when(fallbackExtensionMock.rsv()).thenReturn(WebSocketExtension.RSV1);
// execute
EmbeddedChannel ch = new EmbeddedChannel(new WebSocketClientExtensionHandler(
mainHandshakerMock, fallbackHandshakerMock));
HttpRequest req = newUpgradeRequest(null);
ch.writeOutbound(req);
HttpRequest req2 = ch.readOutbound();
List<WebSocketExtensionData> reqExts = WebSocketExtensionUtil.extractExtensions(
req2.headers().get(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
HttpResponse res = newUpgradeResponse("main, fallback");
ch.writeInbound(res);
// test
assertEquals(2, reqExts.size());
assertEquals("main", reqExts.get(0).name());
assertEquals("fallback", reqExts.get(1).name());
verify(mainHandshakerMock).newRequestData();
verify(mainHandshakerMock, atLeastOnce()).handshakeExtension(webSocketExtensionDataMatcher("main"));
verify(mainHandshakerMock, atLeastOnce()).handshakeExtension(webSocketExtensionDataMatcher("fallback"));
verify(fallbackHandshakerMock).newRequestData();
verify(fallbackHandshakerMock, atLeastOnce()).handshakeExtension(webSocketExtensionDataMatcher("main"));
verify(fallbackHandshakerMock, atLeastOnce()).handshakeExtension(webSocketExtensionDataMatcher("fallback"));
verify(mainExtensionMock, atLeastOnce()).rsv();
verify(fallbackExtensionMock, atLeastOnce()).rsv();
}
private void decodeHandshake(ChannelHandlerContext ctx,ByteBuf packet, int sequenceId,List<Object> out, int protocolVersion) {
if (protocolVersion < MINIMUM_SUPPORTED_PROTOCOL_VERSION) {
throw new CodecException("Unsupported version of MySQL");
}
ServerHandshakePacket.Builder builder = ServerHandshakePacket.builder();
builder.sequenceId(sequenceId)
.protocolVersion(protocolVersion)
.serverVersion(CodecUtils.readNullTerminatedString(packet))
.connectionId(packet.readIntLE())
.addAuthData(packet, Constants.AUTH_PLUGIN_DATA_PART1_LEN);
packet.skipBytes(1); // Skip auth plugin data terminator
builder.addCapabilities(CodecUtils.toEnumSet(CapabilityFlags.class, packet.readUnsignedShortLE()));
if (packet.isReadable()) {
MysqlCharacterSet characterSet = MysqlCharacterSet.findById(packet.readByte());
builder.characterSet(characterSet)
.addServerStatus(CodecUtils.readShortEnumSet(packet, ServerStatusFlag.class))
.addCapabilities(
CodecUtils.toEnumSet(CapabilityFlags.class, packet.readUnsignedShortLE() << Short.SIZE));
if (builder.hasCapability(CapabilityFlags.CLIENT_SECURE_CONNECTION)) {
int authDataLen = packet.readByte();
packet.skipBytes(Constants.HANDSHAKE_RESERVED_BYTES); // Skip reserved bytes
int readableBytes =
Math.max(Constants.AUTH_PLUGIN_DATA_PART2_MIN_LEN,
authDataLen - Constants.AUTH_PLUGIN_DATA_PART1_LEN);
builder.addAuthData(packet, readableBytes);
if (builder.hasCapability(CapabilityFlags.CLIENT_PLUGIN_AUTH) && packet.isReadable()) {
int len = packet.readableBytes();
if (packet.getByte(packet.readerIndex() + len - 1) == 0) {
len--;
}
builder.authPluginName(CodecUtils.readFixedLengthString(packet, len, CharsetUtil.UTF_8));
packet.skipBytes(1);
}
}
}
ServerHandshakePacket handshake = builder.build();
out.add(handshake);
}
@Override
public Calendar parseTimestamp ( final ByteBuf data )
{
final int index = data.bytesBefore ( this.endMarker );
if ( index < 0 )
{
throw new CodecException ( "Unable to find timestamp" );
}
final String timestampString = data.readSlice ( index ).toString ( this.charset );
logger.debug ( "Timestamp string: '{}'", timestampString );
final Matcher m = this.pattern.matcher ( timestampString );
if ( !m.matches () )
{
throw new CodecException ( "Timestamp string does not match pattern: " + this.pattern.pattern () );
}
final int year = Integer.parseInt ( m.group ( "year" ) );
final int month = Integer.parseInt ( m.group ( "month" ) ) - 1;
final int day = Integer.parseInt ( m.group ( "day" ) );
final int hour = Integer.parseInt ( m.group ( "hour" ) );
final int minute = Integer.parseInt ( m.group ( "minute" ) );
final int second = Integer.parseInt ( m.group ( "second" ) );
final int ms = Integer.parseInt ( m.group ( "subsec" ) ) / 1000;
TimeZone timezone = TimeZone.getDefault ();
final String tz = m.group ( "tz" );
if ( !tz.isEmpty () )
{
// FIXME: implement
if ( "Z".equals ( tz ) )
{
timezone = TimeZone.getTimeZone ( "UTC" );
}
else
{
timezone = TimeZone.getTimeZone ( "GMT" + tz );
}
}
final Calendar c = new GregorianCalendar ( year, month, day, hour, minute, second );
c.setTimeZone ( timezone );
c.set ( Calendar.MILLISECOND, ms );
// skip marker byte
data.skipBytes ( 1 );
return c;
}