1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/quic/quic_spdy_compressor.h"
6
7#include "base/basictypes.h"
8#include "base/memory/scoped_ptr.h"
9
10using std::string;
11
12namespace net {
13
14QuicSpdyCompressor::QuicSpdyCompressor()
15    : spdy_framer_(SPDY3),
16      header_sequence_id_(1) {
17  spdy_framer_.set_enable_compression(true);
18}
19
20QuicSpdyCompressor::~QuicSpdyCompressor() {
21}
22
23string QuicSpdyCompressor::CompressHeadersWithPriority(
24    QuicPriority priority,
25    const SpdyHeaderBlock& headers) {
26  return CompressHeadersInternal(priority, headers, true);
27}
28
29string QuicSpdyCompressor::CompressHeaders(
30    const SpdyHeaderBlock& headers) {
31  // CompressHeadersInternal ignores priority when write_priority is false.
32  return CompressHeadersInternal(0 /* ignored */, headers, false);
33}
34
35string QuicSpdyCompressor::CompressHeadersInternal(
36    QuicPriority priority,
37    const SpdyHeaderBlock& headers,
38    bool write_priority) {
39  // TODO(rch): Modify the SpdyFramer to expose a
40  // CreateCompressedHeaderBlock method, or some such.
41  SpdyStreamId stream_id = 3;    // unused.
42  scoped_ptr<SpdyFrame> frame(spdy_framer_.CreateHeaders(
43      stream_id, CONTROL_FLAG_NONE, &headers));
44
45  // The size of the spdy HEADER frame's fixed prefix which
46  // needs to be stripped off from the resulting frame.
47  const size_t header_frame_prefix_len = 12;
48  string serialized = string(frame->data() + header_frame_prefix_len,
49                             frame->size() - header_frame_prefix_len);
50  uint32 serialized_len = serialized.length();
51  char priority_str[sizeof(priority)];
52  memcpy(&priority_str, &priority, sizeof(priority));
53  char id_str[sizeof(header_sequence_id_)];
54  memcpy(&id_str, &header_sequence_id_, sizeof(header_sequence_id_));
55  char len_str[sizeof(serialized_len)];
56  memcpy(&len_str, &serialized_len, sizeof(serialized_len));
57  string compressed;
58  int priority_len = write_priority ? arraysize(priority_str) : 0;
59  compressed.reserve(
60      priority_len + arraysize(id_str) + arraysize(len_str) + serialized_len);
61  if (write_priority) {
62    compressed.append(priority_str, arraysize(priority_str));
63  }
64  compressed.append(id_str, arraysize(id_str));
65  compressed.append(len_str, arraysize(len_str));
66  compressed.append(serialized);
67  ++header_sequence_id_;
68  return compressed;
69}
70
71}  // namespace net
72