View Javadoc

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