• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 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 #ifndef NET_FLIP_FRAME_BUILDER_H_
6 #define NET_FLIP_FRAME_BUILDER_H_
7 
8 #ifdef WIN32
9 #include <winsock2.h>  // for htonl() functions
10 #else
11 #include <arpa/inet.h>
12 #endif
13 
14 #include <string>
15 
16 #include "base/logging.h"
17 #include "flip_protocol.h"  // cross-google3 directory naming.
18 
19 namespace flip {
20 
21 // This class provides facilities for basic binary value packing and unpacking
22 // into Flip frames.
23 //
24 // The FlipFrameBuilder supports appending primitive values (int, string, etc)
25 // to a frame instance.  The FlipFrameBuilder grows its internal memory buffer
26 // dynamically to hold the sequence of primitive values.   The internal memory
27 // buffer is exposed as the "data" of the FlipFrameBuilder.
28 //
29 // When reading from a FlipFrameBuilder the consumer must know what value types
30 // to read and in what order to read them as the FlipFrameBuilder does not keep
31 // track of the type of data written to it.
32 class FlipFrameBuilder {
33  public:
34   FlipFrameBuilder();
35   ~FlipFrameBuilder();
36 
37   // Initializes a FlipFrameBuilder from a const block of data.  The data is
38   // not copied; instead the data is merely referenced by this
39   // FlipFrameBuilder.  Only const methods should be used when initialized
40   // this way.
41   FlipFrameBuilder(const char* data, int data_len);
42 
43   // Returns the size of the FlipFrameBuilder's data.
length()44   int length() const { return length_; }
45 
46   // Takes the buffer from the FlipFrameBuilder.
take()47   FlipFrame* take() {
48     FlipFrame* rv = new FlipFrame(buffer_, true);
49     buffer_ = NULL;
50     capacity_ = 0;
51     length_ = 0;
52     return rv;
53   }
54 
55   // Methods for reading the payload of the FlipFrameBuilder.  To read from the
56   // start of the FlipFrameBuilder, initialize *iter to NULL.  If successful,
57   // these methods return true.  Otherwise, false is returned to indicate that
58   // the result could not be extracted.
59   bool ReadUInt16(void** iter, uint16* result) const;
60   bool ReadUInt32(void** iter, uint32* result) const;
61   bool ReadString(void** iter, std::string* result) const;
62   bool ReadBytes(void** iter, const char** data, uint16 length) const;
63   bool ReadData(void** iter, const char** data, uint16* length) const;
64 
65   // Methods for adding to the payload.  These values are appended to the end
66   // of the FlipFrameBuilder payload.  When reading values, you must read them
67   // in the order they were added.  Note - binary integers are converted from
68   // host to network form.
WriteUInt16(uint16 value)69   bool WriteUInt16(uint16 value) {
70     value = htons(value);
71     return WriteBytes(&value, sizeof(value));
72   }
WriteUInt32(uint32 value)73   bool WriteUInt32(uint32 value) {
74     value = htonl(value);
75     return WriteBytes(&value, sizeof(value));
76   }
77   bool WriteString(const std::string& value);
78   bool WriteBytes(const void* data, uint16 data_len);
79 
80   // Write an integer to a particular offset in the data buffer.
WriteUInt32ToOffset(int offset,uint32 value)81   bool WriteUInt32ToOffset(int offset, uint32 value) {
82     value = htonl(value);
83     return WriteBytesToOffset(offset, &value, sizeof(value));
84   }
85 
86   // Write to a particular offset in the data buffer.
WriteBytesToOffset(int offset,const void * data,uint32 data_len)87   bool WriteBytesToOffset(int offset, const void* data, uint32 data_len) {
88     if (offset + data_len > length_)
89       return false;
90     char *ptr = buffer_ + offset;
91     memcpy(ptr, data, data_len);
92     return true;
93   }
94 
95   // Allows the caller to write data directly into the FlipFrameBuilder.
96   // This saves a copy when the data is not already available in a buffer.
97   // The caller must not write more than the length it declares it will.
98   // Use ReadData to get the data.
99   // Returns NULL on failure.
100   //
101   // The returned pointer will only be valid until the next write operation
102   // on this FlipFrameBuilder.
103   char* BeginWriteData(uint16 length);
104 
105   // Returns true if the given iterator could point to data with the given
106   // length. If there is no room for the given data before the end of the
107   // payload, returns false.
IteratorHasRoomFor(const void * iter,int len)108   bool IteratorHasRoomFor(const void* iter, int len) const {
109     const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
110     if (len < 0 ||
111         iter < buffer_ ||
112         iter > end_of_payload() ||
113         iter > end_of_region ||
114         end_of_region > end_of_payload())
115       return false;
116 
117     // Watch out for overflow in pointer calculation, which wraps.
118     return (iter <= end_of_region) && (end_of_region <= end_of_payload());
119   }
120 
121  protected:
capacity()122   size_t capacity() const {
123     return capacity_;
124   }
125 
end_of_payload()126   const char* end_of_payload() const { return buffer_ + length_; }
127 
128   // Resizes the buffer for use when writing the specified amount of data. The
129   // location that the data should be written at is returned, or NULL if there
130   // was an error. Call EndWrite with the returned offset and the given length
131   // to pad out for the next write.
132   char* BeginWrite(size_t length);
133 
134   // Completes the write operation by padding the data with NULL bytes until it
135   // is padded. Should be paired with BeginWrite, but it does not necessarily
136   // have to be called after the data is written.
137   void EndWrite(char* dest, int length);
138 
139   // Resize the capacity, note that the input value should include the size of
140   // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
141   // A new failure will cause a Resize failure... and caller should check
142   // the return result for true (i.e., successful resizing).
143   bool Resize(size_t new_capacity);
144 
145   // Moves the iterator by the given number of bytes.
UpdateIter(void ** iter,int bytes)146   static void UpdateIter(void** iter, int bytes) {
147     *iter = static_cast<char*>(*iter) + bytes;
148   }
149 
150   // Initial size of the payload.
151   static const int kInitialPayload = 1024;
152 
153  private:
154   char* buffer_;
155   size_t capacity_;  // Allocation size of payload (or -1 if buffer is const).
156   size_t length_;    // current length of the buffer
157   size_t variable_buffer_offset_;  // IF non-zero, then offset to a buffer.
158 };
159 
160 }  // namespace flip
161 
162 #endif  // NET_FLIP_FRAME_BUILDER_H_
163 
164