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.Unpooled;
21
22 import java.util.Set;
23
24 import static io.netty.handler.codec.spdy.SpdyCodecUtil.*;
25
26 public class SpdyHeaderBlockRawEncoder extends SpdyHeaderBlockEncoder {
27
28 private final int version;
29
30 public SpdyHeaderBlockRawEncoder(SpdyVersion version) {
31 if (version == null) {
32 throw new NullPointerException("version");
33 }
34 this.version = version.getVersion();
35 }
36
37 private static void setLengthField(ByteBuf buffer, int writerIndex, int length) {
38 buffer.setInt(writerIndex, length);
39 }
40
41 private static void writeLengthField(ByteBuf buffer, int length) {
42 buffer.writeInt(length);
43 }
44
45 @Override
46 public ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception {
47 Set<String> names = frame.headers().names();
48 int numHeaders = names.size();
49 if (numHeaders == 0) {
50 return Unpooled.EMPTY_BUFFER;
51 }
52 if (numHeaders > SPDY_MAX_NV_LENGTH) {
53 throw new IllegalArgumentException(
54 "header block contains too many headers");
55 }
56 ByteBuf headerBlock = alloc.heapBuffer();
57 writeLengthField(headerBlock, numHeaders);
58 for (String name: names) {
59 byte[] nameBytes = name.getBytes("UTF-8");
60 writeLengthField(headerBlock, nameBytes.length);
61 headerBlock.writeBytes(nameBytes);
62 int savedIndex = headerBlock.writerIndex();
63 int valueLength = 0;
64 writeLengthField(headerBlock, valueLength);
65 for (String value: frame.headers().getAll(name)) {
66 byte[] valueBytes = value.getBytes("UTF-8");
67 if (valueBytes.length > 0) {
68 headerBlock.writeBytes(valueBytes);
69 headerBlock.writeByte(0);
70 valueLength += valueBytes.length + 1;
71 }
72 }
73 if (valueLength != 0) {
74 valueLength --;
75 }
76 if (valueLength > SPDY_MAX_NV_LENGTH) {
77 throw new IllegalArgumentException(
78 "header exceeds allowable length: " + name);
79 }
80 if (valueLength > 0) {
81 setLengthField(headerBlock, savedIndex, valueLength);
82 headerBlock.writerIndex(headerBlock.writerIndex() - 1);
83 }
84 }
85 return headerBlock;
86 }
87
88 @Override
89 void end() {
90 }
91 }