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.io.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  import org.eclipse.jetty.util.BufferUtil;
29  
30  public class SettingsGenerator extends ControlFrameGenerator
31  {
32      public SettingsGenerator(ByteBufferPool bufferPool)
33      {
34          super(bufferPool);
35      }
36  
37      @Override
38      public ByteBuffer generate(ControlFrame frame)
39      {
40          SettingsFrame settingsFrame = (SettingsFrame)frame;
41  
42          Settings settings = settingsFrame.getSettings();
43          int size = settings.size();
44          int frameBodyLength = 4 + 8 * size;
45          int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
46          ByteBuffer buffer = getByteBufferPool().acquire(totalLength, Generator.useDirectBuffers);
47          BufferUtil.clearToFill(buffer);
48          generateControlFrameHeader(settingsFrame, frameBodyLength, buffer);
49  
50          buffer.putInt(size);
51  
52          for (Settings.Setting setting : settings)
53          {
54              int id = setting.id().code();
55              byte flags = setting.flag().code();
56              int idAndFlags = convertIdAndFlags(frame.getVersion(), id, flags);
57              buffer.putInt(idAndFlags);
58              buffer.putInt(setting.value());
59          }
60  
61          buffer.flip();
62          return buffer;
63      }
64  
65      private int convertIdAndFlags(short version, int id, byte flags)
66      {
67          switch (version)
68          {
69              case SPDY.V2:
70              {
71                  // In v2 the format is 24 bits of ID + 8 bits of flag
72                  int idAndFlags = (id << 8) + (flags & 0xFF);
73                  // A bug in the Chromium implementation forces v2 to have
74                  // the 3 ID bytes little endian, so we swap first and third
75                  int result = idAndFlags & 0x00_FF_00_FF;
76                  result += (idAndFlags & 0xFF_00_00_00) >>> 16;
77                  result += (idAndFlags & 0x00_00_FF_00) << 16;
78                  return result;
79              }
80              case SPDY.V3:
81              {
82                  // In v3 the format is 8 bits of flags + 24 bits of ID
83                  return (flags << 24) + (id & 0xFF_FF_FF);
84              }
85              default:
86              {
87                  throw new IllegalStateException();
88              }
89          }
90      }
91  }