blob: affdbe40b1f1c1273ea2c7e0aebd311538d8c857 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_SPDY_SPDY_FRAME_BUILDER_H_
#define NET_SPDY_SPDY_FRAME_BUILDER_H_
#include <string>
#include "base/basictypes.h"
#include "base/string_piece.h"
#include "base/sys_byteorder.h"
#include "net/base/net_export.h"
#include "net/spdy/spdy_protocol.h"
namespace net {
// This class provides facilities for basic binary value packing and unpacking
// into Spdy frames.
//
// The SpdyFrameBuilder supports appending primitive values (int, string, etc)
// to a frame instance. The SpdyFrameBuilder grows its internal memory buffer
// dynamically to hold the sequence of primitive values. The internal memory
// buffer is exposed as the "data" of the SpdyFrameBuilder.
class NET_EXPORT_PRIVATE SpdyFrameBuilder {
public:
~SpdyFrameBuilder();
// Initializes a SpdyFrameBuilder with a buffer of given size,
// populate with a SPDY control frame header based on
// |type|, |flags|, and |spdy_version|.
SpdyFrameBuilder(SpdyControlType type, SpdyControlFlags flags,
int spdy_version, size_t size);
// Initiailizes a SpdyFrameBuilder with a buffer of given size,
// populated with a SPDY data frame header based on
// |stream_id| and |flags|.
SpdyFrameBuilder(SpdyStreamId stream_id, SpdyDataFlags flags, size_t size);
// Returns the size of the SpdyFrameBuilder's data.
size_t length() const { return length_; }
// Takes the buffer from the SpdyFrameBuilder.
SpdyFrame* take() {
SpdyFrame* rv = new SpdyFrame(buffer_, true);
buffer_ = NULL;
capacity_ = 0;
length_ = 0;
return rv;
}
// Methods for adding to the payload. These values are appended to the end
// of the SpdyFrameBuilder payload. Note - binary integers are converted from
// host to network form.
bool WriteUInt8(uint8 value) {
return WriteBytes(&value, sizeof(value));
}
bool WriteUInt16(uint16 value) {
value = htons(value);
return WriteBytes(&value, sizeof(value));
}
bool WriteUInt32(uint32 value) {
value = htonl(value);
return WriteBytes(&value, sizeof(value));
}
// TODO(hkhalil) Rename to WriteStringPiece16().
bool WriteString(const std::string& value);
bool WriteStringPiece32(const base::StringPiece& value);
bool WriteBytes(const void* data, uint32 data_len);
// Write an integer to a particular offset in the data buffer.
bool WriteUInt32ToOffset(int offset, uint32 value) {
value = htonl(value);
return WriteBytesToOffset(offset, &value, sizeof(value));
}
// Write to a particular offset in the data buffer.
bool WriteBytesToOffset(int offset, const void* data, uint32 data_len) {
if (offset + data_len > length_)
return false;
char *ptr = buffer_ + offset;
memcpy(ptr, data, data_len);
return true;
}
// Returns true if the given iterator could point to data with the given
// length. If there is no room for the given data before the end of the
// payload, returns false.
bool IteratorHasRoomFor(const void* iter, int len) const {
const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
if (len < 0 ||
iter < buffer_ ||
iter > end_of_payload() ||
iter > end_of_region ||
end_of_region > end_of_payload())
return false;
// Watch out for overflow in pointer calculation, which wraps.
return (iter <= end_of_region) && (end_of_region <= end_of_payload());
}
protected:
size_t capacity() const {
return capacity_;
}
const char* end_of_payload() const { return buffer_ + length_; }
// Completes the write operation by padding the data with NULL bytes until it
// is padded. Should be paired with BeginWrite, but it does not necessarily
// have to be called after the data is written.
void EndWrite(char* dest, int length);
// Moves the iterator by the given number of bytes.
static void UpdateIter(void** iter, int bytes) {
*iter = static_cast<char*>(*iter) + bytes;
}
private:
// Returns the location that the data should be written at, or NULL if there
// is not enough room. Call EndWrite with the returned offset and the given
// length to pad out for the next write.
char* BeginWrite(size_t length);
char* buffer_;
size_t capacity_; // Allocation size of payload (or -1 if buffer is const).
size_t length_; // current length of the buffer
};
} // namespace net
#endif // NET_SPDY_SPDY_FRAME_BUILDER_H_