1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.spdy.generator;
20
21 import java.nio.ByteBuffer;
22
23 import org.eclipse.jetty.io.ByteBufferPool;
24 import org.eclipse.jetty.spdy.SessionException;
25 import org.eclipse.jetty.spdy.StreamException;
26 import org.eclipse.jetty.spdy.api.SPDY;
27 import org.eclipse.jetty.spdy.api.SessionStatus;
28 import org.eclipse.jetty.spdy.api.StreamStatus;
29 import org.eclipse.jetty.spdy.frames.ControlFrame;
30 import org.eclipse.jetty.spdy.frames.SynStreamFrame;
31 import org.eclipse.jetty.util.BufferUtil;
32
33 public class SynStreamGenerator extends ControlFrameGenerator
34 {
35 private final HeadersBlockGenerator headersBlockGenerator;
36
37 public SynStreamGenerator(ByteBufferPool bufferPool, HeadersBlockGenerator headersBlockGenerator)
38 {
39 super(bufferPool);
40 this.headersBlockGenerator = headersBlockGenerator;
41 }
42
43 @Override
44 public ByteBuffer generate(ControlFrame frame)
45 {
46 SynStreamFrame synStream = (SynStreamFrame)frame;
47 short version = synStream.getVersion();
48
49 ByteBuffer headersBuffer = headersBlockGenerator.generate(version, synStream.getHeaders());
50
51 int frameBodyLength = 10;
52
53 int frameLength = frameBodyLength + headersBuffer.remaining();
54 if (frameLength > 0xFF_FF_FF)
55 {
56
57
58 throw new SessionException(SessionStatus.PROTOCOL_ERROR, "Too many headers");
59 }
60
61 int totalLength = ControlFrame.HEADER_LENGTH + frameLength;
62
63 ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
64 BufferUtil.clearToFill(buffer);
65 generateControlFrameHeader(synStream, frameLength, buffer);
66
67 int streamId = synStream.getStreamId();
68 buffer.putInt(streamId & 0x7F_FF_FF_FF);
69 buffer.putInt(synStream.getAssociatedStreamId() & 0x7F_FF_FF_FF);
70 writePriority(streamId, version, synStream.getPriority(), buffer);
71 buffer.put((byte)synStream.getSlot());
72
73 buffer.put(headersBuffer);
74
75 buffer.flip();
76 return buffer;
77 }
78
79 private void writePriority(int streamId, short version, byte priority, ByteBuffer buffer)
80 {
81 switch (version)
82 {
83 case SPDY.V2:
84 priority <<= 6;
85 break;
86 case SPDY.V3:
87 priority <<= 5;
88 break;
89 default:
90 throw new StreamException(streamId, StreamStatus.UNSUPPORTED_VERSION);
91 }
92 buffer.put(priority);
93 }
94 }