I must admit MesageList was pain in the ass. Instead of forcing a handler always loop over the list of messages, this commit splits messageReceived(ctx, list) into two event handlers: - messageReceived(ctx, msg) - mmessageReceivedLast(ctx) When Netty reads one or more messages, messageReceived(ctx, msg) event is triggered for each message. Once the current read operation is finished, messageReceivedLast() is triggered to tell the handler that the last messageReceived() was the last message in the current batch. Similarly, for outbound, write(ctx, list) has been split into two: - write(ctx, msg) - flush(ctx, promise) Instead of writing a list of message with a promise, a user is now supposed to call write(msg) multiple times and then call flush() to actually flush the buffered messages. Please note that write() doesn't have a promise with it. You must call flush() to get notified on completion. (or you can use writeAndFlush()) Other changes: - Because MessageList is completely hidden, codec framework uses List<Object> instead of MessageList as an output parameter.
68 lines
2.5 KiB
Java
68 lines
2.5 KiB
Java
/*
|
|
* Copyright 2012 The Netty Project
|
|
*
|
|
* The Netty Project licenses this file to you under the Apache License,
|
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
package io.netty.handler.codec.spdy;
|
|
|
|
import io.netty.channel.ChannelHandlerContext;
|
|
import io.netty.handler.codec.MessageToMessageCodec;
|
|
import io.netty.handler.codec.http.HttpMessage;
|
|
import io.netty.util.ReferenceCountUtil;
|
|
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Queue;
|
|
|
|
/**
|
|
* {@link MessageToMessageCodec} that takes care of adding the right {@link SpdyHttpHeaders.Names#STREAM_ID} to the
|
|
* {@link HttpMessage} if one is not present. This makes it possible to just re-use plan handlers current used
|
|
* for HTTP.
|
|
*/
|
|
public class SpdyHttpResponseStreamIdHandler extends
|
|
MessageToMessageCodec<Object, HttpMessage> {
|
|
private static final Integer NO_ID = -1;
|
|
private final Queue<Integer> ids = new LinkedList<Integer>();
|
|
|
|
@Override
|
|
public boolean acceptInboundMessage(Object msg) throws Exception {
|
|
return msg instanceof HttpMessage || msg instanceof SpdyRstStreamFrame;
|
|
}
|
|
|
|
@Override
|
|
protected void encode(ChannelHandlerContext ctx, HttpMessage msg, List<Object> out) throws Exception {
|
|
Integer id = ids.poll();
|
|
if (id != null && id.intValue() != NO_ID && !msg.headers().contains(SpdyHttpHeaders.Names.STREAM_ID)) {
|
|
SpdyHttpHeaders.setStreamId(msg, id);
|
|
}
|
|
|
|
out.add(ReferenceCountUtil.retain(msg));
|
|
}
|
|
|
|
@Override
|
|
protected void decode(ChannelHandlerContext ctx, Object msg, List<Object> out) throws Exception {
|
|
if (msg instanceof HttpMessage) {
|
|
boolean contains = ((HttpMessage) msg).headers().contains(SpdyHttpHeaders.Names.STREAM_ID);
|
|
if (!contains) {
|
|
ids.add(NO_ID);
|
|
} else {
|
|
ids.add(SpdyHttpHeaders.getStreamId((HttpMessage) msg));
|
|
}
|
|
} else if (msg instanceof SpdyRstStreamFrame) {
|
|
ids.remove(((SpdyRstStreamFrame) msg).getStreamId());
|
|
}
|
|
|
|
out.add(ReferenceCountUtil.retain(msg));
|
|
}
|
|
}
|