1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.spdy;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.ByteBufAllocator;
20 import io.netty.buffer.ByteBufUtil;
21 import io.netty.buffer.Unpooled;
22 import io.netty.util.internal.ObjectUtil;
23
24 import java.util.Set;
25
26 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_MAX_NV_LENGTH;
27
28 public class SpdyHeaderBlockRawEncoder extends SpdyHeaderBlockEncoder {
29
30 private final int version;
31
32 public SpdyHeaderBlockRawEncoder(SpdyVersion version) {
33 this.version = ObjectUtil.checkNotNull(version, "version").getVersion();
34 }
35
36 private static void setLengthField(ByteBuf buffer, int writerIndex, int length) {
37 buffer.setInt(writerIndex, length);
38 }
39
40 private static void writeLengthField(ByteBuf buffer, int length) {
41 buffer.writeInt(length);
42 }
43
44 @Override
45 public ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception {
46 Set<CharSequence> names = frame.headers().names();
47 int numHeaders = names.size();
48 if (numHeaders == 0) {
49 return Unpooled.EMPTY_BUFFER;
50 }
51 if (numHeaders > SPDY_MAX_NV_LENGTH) {
52 throw new IllegalArgumentException(
53 "header block contains too many headers");
54 }
55 ByteBuf headerBlock = alloc.heapBuffer();
56 writeLengthField(headerBlock, numHeaders);
57 for (CharSequence name: names) {
58 writeLengthField(headerBlock, name.length());
59 ByteBufUtil.writeAscii(headerBlock, name);
60 int savedIndex = headerBlock.writerIndex();
61 int valueLength = 0;
62 writeLengthField(headerBlock, valueLength);
63 for (CharSequence value: frame.headers().getAll(name)) {
64 int length = value.length();
65 if (length > 0) {
66 ByteBufUtil.writeAscii(headerBlock, value);
67 headerBlock.writeByte(0);
68 valueLength += length + 1;
69 }
70 }
71 if (valueLength != 0) {
72 valueLength --;
73 }
74 if (valueLength > SPDY_MAX_NV_LENGTH) {
75 throw new IllegalArgumentException(
76 "header exceeds allowable length: " + name);
77 }
78 if (valueLength > 0) {
79 setLengthField(headerBlock, savedIndex, valueLength);
80 headerBlock.writerIndex(headerBlock.writerIndex() - 1);
81 }
82 }
83 return headerBlock;
84 }
85
86 @Override
87 void end() {
88 }
89 }