View Javadoc

1   //========================================================================
2   //Copyright 2011-2012 Mort Bay Consulting Pty. Ltd.
3   //------------------------------------------------------------------------
4   //All rights reserved. This program and the accompanying materials
5   //are made available under the terms of the Eclipse Public License v1.0
6   //and Apache License v2.0 which accompanies this distribution.
7   //The Eclipse Public License is available at
8   //http://www.eclipse.org/legal/epl-v10.html
9   //The Apache License v2.0 is available at
10  //http://www.opensource.org/licenses/apache2.0.php
11  //You may elect to redistribute this code under either of these licenses.
12  //========================================================================
13  
14  package org.eclipse.jetty.spdy.generator;
15  
16  import java.nio.ByteBuffer;
17  
18  import org.eclipse.jetty.spdy.ByteBufferPool;
19  import org.eclipse.jetty.spdy.api.SPDY;
20  import org.eclipse.jetty.spdy.api.Settings;
21  import org.eclipse.jetty.spdy.frames.ControlFrame;
22  import org.eclipse.jetty.spdy.frames.SettingsFrame;
23  
24  public class SettingsGenerator extends ControlFrameGenerator
25  {
26      public SettingsGenerator(ByteBufferPool bufferPool)
27      {
28          super(bufferPool);
29      }
30  
31      @Override
32      public ByteBuffer generate(ControlFrame frame)
33      {
34          SettingsFrame settingsFrame = (SettingsFrame)frame;
35  
36          Settings settings = settingsFrame.getSettings();
37          int size = settings.size();
38          int frameBodyLength = 4 + 8 * size;
39          int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
40          ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
41          generateControlFrameHeader(settingsFrame, frameBodyLength, buffer);
42  
43          buffer.putInt(size);
44  
45          for (Settings.Setting setting : settings)
46          {
47              int id = setting.id().code();
48              byte flags = setting.flag().code();
49              int idAndFlags = convertIdAndFlags(frame.getVersion(), id, flags);
50              buffer.putInt(idAndFlags);
51              buffer.putInt(setting.value());
52          }
53  
54          buffer.flip();
55          return buffer;
56      }
57  
58      private int convertIdAndFlags(short version, int id, byte flags)
59      {
60          switch (version)
61          {
62              case SPDY.V2:
63              {
64                  // In v2 the format is 24 bits of ID + 8 bits of flag
65                  int idAndFlags = (id << 8) + (flags & 0xFF);
66                  // A bug in the Chromium implementation forces v2 to have
67                  // the 3 ID bytes little endian, so we swap first and third
68                  int result = idAndFlags & 0x00_FF_00_FF;
69                  result += (idAndFlags & 0xFF_00_00_00) >>> 16;
70                  result += (idAndFlags & 0x00_00_FF_00) << 16;
71                  return result;
72              }
73              case SPDY.V3:
74              {
75                  // In v3 the format is 8 bits of flags + 24 bits of ID
76                  return (flags << 24) + (id & 0xFF_FF_FF);
77              }
78              default:
79              {
80                  throw new IllegalStateException();
81              }
82          }
83      }
84  }