View Javadoc

1   /*
2    * Copyright (c) 2012 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.eclipse.jetty.spdy.generator;
18  
19  import java.nio.ByteBuffer;
20  
21  import org.eclipse.jetty.spdy.ByteBufferPool;
22  import org.eclipse.jetty.spdy.SessionException;
23  import org.eclipse.jetty.spdy.api.SPDY;
24  import org.eclipse.jetty.spdy.api.SessionStatus;
25  import org.eclipse.jetty.spdy.frames.ControlFrame;
26  import org.eclipse.jetty.spdy.frames.SynReplyFrame;
27  
28  public class SynReplyGenerator extends ControlFrameGenerator
29  {
30      private final HeadersBlockGenerator headersBlockGenerator;
31  
32      public SynReplyGenerator(ByteBufferPool bufferPool, HeadersBlockGenerator headersBlockGenerator)
33      {
34          super(bufferPool);
35          this.headersBlockGenerator = headersBlockGenerator;
36      }
37  
38      @Override
39      public ByteBuffer generate(ControlFrame frame)
40      {
41          SynReplyFrame synReply = (SynReplyFrame)frame;
42          short version = synReply.getVersion();
43  
44          ByteBuffer headersBuffer = headersBlockGenerator.generate(version, synReply.getHeaders());
45  
46          int frameBodyLength = getFrameDataLength(version);
47  
48          int frameLength = frameBodyLength + headersBuffer.remaining();
49          if (frameLength > 0xFF_FF_FF)
50          {
51              // Too many headers, but unfortunately we have already modified the compression
52              // context, so we have no other choice than tear down the connection.
53              throw new SessionException(SessionStatus.PROTOCOL_ERROR, "Too many headers");
54          }
55  
56          int totalLength = ControlFrame.HEADER_LENGTH + frameLength;
57  
58          ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
59          generateControlFrameHeader(synReply, frameLength, buffer);
60  
61          buffer.putInt(synReply.getStreamId() & 0x7F_FF_FF_FF);
62          writeAdditional(version, buffer);
63  
64          buffer.put(headersBuffer);
65  
66          buffer.flip();
67          return buffer;
68      }
69  
70      private int getFrameDataLength(short version)
71      {
72          switch (version)
73          {
74              case SPDY.V2:
75                  return 6;
76              case SPDY.V3:
77                  return 4;
78              default:
79                  // Here the version is trusted to be correct; if it's not
80                  // then it's a bug rather than an application error
81                  throw new IllegalStateException();
82          }
83      }
84  
85      private void writeAdditional(short version, ByteBuffer buffer)
86      {
87          switch (version)
88          {
89              case SPDY.V2:
90                  buffer.putShort((short)0);
91                  break;
92              case SPDY.V3:
93                  break;
94              default:
95                  // Here the version is trusted to be correct; if it's not
96                  // then it's a bug rather than an application error
97                  throw new IllegalStateException();
98          }
99      }
100 }