Stun Server  Compliant with the latest RFCs including 5389, 5769, and 5780
discover the local host's own external IP address
datastream.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2011 John Selbie
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 
18 
19 #include "commonincludes.hpp"
20 #include "datastream.h"
21 
22 
23 
25 _pBuffer(NULL),
26 _pos(0),
27 _fNoGrow(false)
28 {
29  // _spBuffer is null
30 }
31 
32 
34 _spBuffer(spBuffer),
35 _pos(0),
36 _fNoGrow(false)
37 {
38  _pBuffer = spBuffer.get();
39 }
40 
42 {
43  return Grow(size);
44 }
45 
46 
48 {
49  _spBuffer.reset();
50  _pBuffer = NULL;
51  _pos = 0;
52  _fNoGrow = false;
53 }
54 
55 void CDataStream::Attach(CRefCountedBuffer& buf, bool fForWriting)
56 {
57  Reset();
58  _spBuffer = buf;
59  _pBuffer = _spBuffer.get();
60 
61  if (_spBuffer && fForWriting)
62  {
63  _spBuffer->SetSize(0);
64  }
65 }
66 
67 HRESULT CDataStream::Read(void* data, size_t size)
68 {
69  size_t newpos = size + _pos;
70  size_t currentSize = GetSize();
71 
72  ASSERT(newpos <= currentSize);
73 
74  if (newpos > currentSize)
75  {
76  return E_INVALIDARG;
77  }
78 
79  memcpy(data, _pBuffer->GetData() + _pos, size);
80  _pos = newpos;
81  return S_OK;
82 }
83 
85 {
86  size_t currentAllocated = (_pBuffer ? _pBuffer->GetAllocatedSize() : 0);
87  size_t currentSize = GetSize();
88  size_t newallocationsize=0;
89 
90  if (size <= currentAllocated)
91  {
92  return S_OK;
93  }
94 
95  if (_fNoGrow)
96  {
97  return E_FAIL;
98  }
99 
100  if (size > (currentAllocated*2))
101  {
102  newallocationsize = size;
103  }
104  else
105  {
106  newallocationsize = currentAllocated*2;
107  }
108 
109  ASSERT(newallocationsize > 0);
110 
111  CRefCountedBuffer spNewBuffer(new CBuffer(newallocationsize));
112 
113 
114  if (spNewBuffer->IsValid() == false)
115  {
116  return E_OUTOFMEMORY;
117  }
118 
119  // Grow only increases allocated size. It doesn't influence the actual data stream size
120  spNewBuffer->SetSize(currentSize);
121 
122  if (_pBuffer && (currentSize > 0))
123  {
124  memcpy(spNewBuffer->GetData(), _pBuffer->GetData(), currentSize);
125  }
126 
127  _spBuffer = spNewBuffer;
128  _pBuffer = _spBuffer.get();
129 
130  return S_OK;
131 }
132 
133 void CDataStream::SetNoGrow(bool fNoGrow)
134 {
135  _fNoGrow = fNoGrow;
136 }
137 
138 HRESULT CDataStream::Write(const void* data, size_t size)
139 {
140 
141  size_t newposition = size + _pos;
142  size_t currentSize = GetSize();
143  HRESULT hr = S_OK;
144 
145  if ((size == 0) || (data == NULL))
146  {
147  return E_FAIL;
148  }
149 
150  hr = Grow(newposition); // make sure we have enough buffer to write into
151 
152  if (FAILED(hr))
153  {
154  return hr;
155  }
156 
157  memcpy(_pBuffer->GetData()+_pos, data, size);
158  _pos = newposition;
159 
160  if (newposition > currentSize)
161  {
162  hr = _pBuffer->SetSize(newposition);
163  ASSERT(SUCCEEDED(hr));
164  }
165 
166  return hr;
167 }
168 
169 
170 
172 {
173  size_t currentSize = GetSize();
174  return (_pos >= currentSize);
175 }
176 
178 {
179  return _pos;
180 }
181 
183 {
184  return (_pBuffer ? _pBuffer->GetSize() : 0);
185 }
186 
188 {
189  HRESULT hr = S_OK;
190  size_t currentSize = (_pBuffer ? _pBuffer->GetSize() : 0);
191 
192  // seeking is allowed anywhere between 0 and stream size
193 
194  if (pos <= currentSize)
195  {
196  _pos = pos;
197  }
198  else
199  {
200  ASSERT(false); // likely a programmer error if we seek out of the stream
201  hr = E_FAIL;
202  }
203 
204  return hr;
205 }
206 
208 {
209  // todo: there might be some math overflow to check here.
210  return SeekDirect(offset + _pos);
211 }
212 
214 {
215  HRESULT hr;
216 
217  if (pBuffer)
218  {
219  *pBuffer = _spBuffer;
220  hr = S_OK;
221  }
222  else
223  {
224  hr = E_FAIL;
225  }
226 
227  return hr;
228 }
229 
230 // unsafe because the pointer is not guaranteed to be valid after subsequent writes. Could also be NULL if nothing has been written
232 {
233  uint8_t* pRet = NULL;
234 
235  if (_pBuffer)
236  {
237  pRet = _pBuffer->GetData();
238  }
239 
240  return pRet;
241 }
242 
243 
244 
245 
246 
247 
#define S_OK
Definition: hresult.h:46
size_t GetPos()
Definition: datastream.cpp:177
#define ASSERT(expr)
uint8_t * GetData()
Definition: buffer.h:60
CRefCountedBuffer _spBuffer
Definition: datastream.h:26
void Reset()
Definition: datastream.cpp:47
HRESULT SeekRelative(int nOffset)
Definition: datastream.cpp:207
HRESULT Read(void *data, size_t size)
Definition: datastream.cpp:67
size_t _pos
Definition: datastream.h:28
HRESULT GetBuffer(CRefCountedBuffer *pRefCountedBuffer)
Definition: datastream.cpp:213
bool IsEOF()
Definition: datastream.cpp:171
CBuffer * _pBuffer
Definition: datastream.h:27
void SetNoGrow(bool fDisableGrow)
Definition: datastream.cpp:133
size_t GetSize()
Definition: buffer.h:54
bool _fNoGrow
Definition: datastream.h:29
Definition: buffer.h:27
#define SUCCEEDED(hr)
Definition: hresult.h:28
HRESULT Grow(size_t newsize)
Definition: datastream.cpp:84
int32_t HRESULT
Definition: hresult.h:22
HRESULT SetSize(size_t size)
Definition: buffer.cpp:126
uint8_t * GetDataPointerUnsafe()
Definition: datastream.cpp:231
size_t GetAllocatedSize()
Definition: buffer.h:55
HRESULT Write(const void *data, size_t size)
Definition: datastream.cpp:138
#define E_INVALIDARG
Definition: hresult.h:51
HRESULT SeekDirect(size_t pos)
Definition: datastream.cpp:187
#define E_FAIL
Definition: hresult.h:56
#define FAILED(hr)
Definition: hresult.h:29
#define E_OUTOFMEMORY
Definition: hresult.h:50
HRESULT SetSizeHint(size_t size)
Definition: datastream.cpp:41
size_t GetSize()
Definition: datastream.cpp:182
boost::shared_ptr< CBuffer > CRefCountedBuffer
Definition: buffer.h:65
void Attach(CRefCountedBuffer &buffer, bool fForWriting)
Definition: datastream.cpp:55