1 /*
2 * Copyright 2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Scott T. Mansfield, thephantom@mac.com
7 * Bruno Albuquerque, bga@bug-br.org.br
8 */
9
10 #include <ByteOrder.h>
11 #include <Message.h>
12 #include <TypeConstants.h>
13
14 #include "DynamicBuffer.h"
15 #include "NetBuffer.h"
16
17 #include <new>
18 #include <string.h>
19
BNetBuffer(size_t size)20 BNetBuffer::BNetBuffer(size_t size) :
21 BArchivable(),
22 fInit(B_NO_INIT)
23 {
24 fImpl = new (std::nothrow) DynamicBuffer(size);
25 if (fImpl != NULL)
26 fInit = fImpl->InitCheck();
27 }
28
29
~BNetBuffer()30 BNetBuffer::~BNetBuffer()
31 {
32 delete fImpl;
33 }
34
35
BNetBuffer(const BNetBuffer & buffer)36 BNetBuffer::BNetBuffer(const BNetBuffer& buffer) :
37 BArchivable(),
38 fInit(B_NO_INIT)
39 {
40 fImpl = new (std::nothrow) DynamicBuffer(*buffer.GetImpl());
41 if (fImpl != NULL)
42 fInit = fImpl->InitCheck();
43 }
44
45
BNetBuffer(BMessage * archive)46 BNetBuffer::BNetBuffer(BMessage* archive) :
47 BArchivable(),
48 fInit(B_NO_INIT)
49 {
50 const unsigned char* bufferPtr;
51 ssize_t bufferSize;
52
53 if (archive->FindData("buffer", B_RAW_TYPE, (const void**)&bufferPtr,
54 &bufferSize) == B_OK) {
55 fImpl = new (std::nothrow) DynamicBuffer(bufferSize);
56 if (fImpl != NULL) {
57 ssize_t result = fImpl->Write(bufferPtr, bufferSize);
58 if (result >= 0)
59 fInit = fImpl->InitCheck();
60 else
61 fInit = result;
62 }
63 }
64 }
65
66 BNetBuffer&
operator =(const BNetBuffer & buffer)67 BNetBuffer::operator=(const BNetBuffer& buffer)
68 {
69 if (&buffer != this) {
70 delete fImpl;
71
72 fImpl = new (std::nothrow) DynamicBuffer(*buffer.GetImpl());
73 if (fImpl != NULL)
74 fInit = fImpl->InitCheck();
75 }
76 return *this;
77 }
78
79
80 status_t
Archive(BMessage * into,bool deep) const81 BNetBuffer::Archive(BMessage* into, bool deep) const
82 {
83 if (fInit != B_OK)
84 return B_NO_INIT;
85
86 status_t result = into->AddData("buffer", B_RAW_TYPE, fImpl->Data(),
87 fImpl->BytesRemaining());
88
89 return result;
90 }
91
92
93 BArchivable*
Instantiate(BMessage * archive)94 BNetBuffer::Instantiate(BMessage* archive)
95 {
96 if (!validate_instantiation(archive, "BNetBuffer"))
97 return NULL;
98
99 BNetBuffer* buffer = new (std::nothrow) BNetBuffer(archive);
100 if (buffer == NULL)
101 return NULL;
102
103 if (buffer->InitCheck() != B_OK) {
104 delete buffer;
105 return NULL;
106 }
107
108 return buffer;
109 }
110
111
112 status_t
InitCheck()113 BNetBuffer::InitCheck()
114 {
115 return fInit;
116 }
117
118
119 status_t
AppendInt8(int8 data)120 BNetBuffer::AppendInt8(int8 data)
121 {
122 return AppendData((const void*)&data, sizeof(int8));
123 }
124
125
126 status_t
AppendUint8(uint8 data)127 BNetBuffer::AppendUint8(uint8 data)
128 {
129 return AppendData((const void*)&data, sizeof(int8));
130 }
131
132
133 status_t
AppendInt16(int16 data)134 BNetBuffer::AppendInt16(int16 data)
135 {
136 int16 be_data = B_HOST_TO_BENDIAN_INT16(data);
137 return AppendData((const void*)&be_data, sizeof(int16));
138 }
139
140
141 status_t
AppendUint16(uint16 data)142 BNetBuffer::AppendUint16(uint16 data)
143 {
144 uint16 be_data = B_HOST_TO_BENDIAN_INT16(data);
145 return AppendData((const void*)&be_data, sizeof(uint16));
146 }
147
148
149 status_t
AppendInt32(int32 data)150 BNetBuffer::AppendInt32(int32 data)
151 {
152 int32 be_data = B_HOST_TO_BENDIAN_INT32(data);
153 return AppendData((const void*)&be_data, sizeof(int32));
154 }
155
156
157 status_t
AppendUint32(uint32 data)158 BNetBuffer::AppendUint32(uint32 data)
159 {
160 uint32 be_data = B_HOST_TO_BENDIAN_INT32(data);
161 return AppendData((const void*)&be_data, sizeof(uint32));
162 }
163
164
165 status_t
AppendFloat(float data)166 BNetBuffer::AppendFloat(float data)
167 {
168 return AppendData((const void*)&data, sizeof(float));
169 }
170
171
172 status_t
AppendDouble(double data)173 BNetBuffer::AppendDouble(double data)
174 {
175 return AppendData((const void*)&data, sizeof(double));
176 }
177
178
179 status_t
AppendString(const char * data)180 BNetBuffer::AppendString(const char* data)
181 {
182 return AppendData((const void*)data, strlen(data) + 1);
183 }
184
185
186 status_t
AppendData(const void * data,size_t size)187 BNetBuffer::AppendData(const void* data, size_t size)
188 {
189 if (fInit != B_OK)
190 return B_NO_INIT;
191
192 ssize_t bytesWritten = fImpl->Write(data, size);
193 if (bytesWritten < 0)
194 return (status_t)bytesWritten;
195 return (size_t)bytesWritten == size ? B_OK : B_ERROR;
196 }
197
198
199 #define STACK_BUFFER_SIZE 2048
200
201 status_t
AppendMessage(const BMessage & data)202 BNetBuffer::AppendMessage(const BMessage& data)
203 {
204 char stackFlattenedData[STACK_BUFFER_SIZE];
205
206 ssize_t dataSize = data.FlattenedSize();
207
208 if (dataSize < 0)
209 return dataSize;
210
211 if (dataSize == 0)
212 return B_ERROR;
213
214 status_t result = B_OK;
215
216 if (dataSize > STACK_BUFFER_SIZE) {
217 char* flattenedData = new (std::nothrow) char[dataSize];
218 if (flattenedData == NULL)
219 return B_NO_MEMORY;
220
221 if (data.Flatten(flattenedData, dataSize) == B_OK)
222 result = AppendData((const void*)&flattenedData, dataSize);
223
224 delete[] flattenedData;
225 } else {
226 if (data.Flatten(stackFlattenedData, dataSize) == B_OK)
227 result = AppendData((const void*)&stackFlattenedData, dataSize);
228 }
229
230 return result;
231 }
232
233
234 status_t
AppendInt64(int64 data)235 BNetBuffer::AppendInt64(int64 data)
236 {
237 int64 be_data = B_HOST_TO_BENDIAN_INT64(data);
238 return AppendData((const void*)&be_data, sizeof(int64));
239 }
240
241
242 status_t
AppendUint64(uint64 data)243 BNetBuffer::AppendUint64(uint64 data)
244 {
245 uint64 be_data = B_HOST_TO_BENDIAN_INT64(data);
246 return AppendData((const void*)&be_data, sizeof(uint64));
247 }
248
249
250 status_t
RemoveInt8(int8 & data)251 BNetBuffer::RemoveInt8(int8& data)
252 {
253 return RemoveData((void*)&data, sizeof(int8));
254 }
255
256
257 status_t
RemoveUint8(uint8 & data)258 BNetBuffer::RemoveUint8(uint8& data)
259 {
260 return RemoveData((void*)&data, sizeof(uint8));
261 }
262
263
264 status_t
RemoveInt16(int16 & data)265 BNetBuffer::RemoveInt16(int16& data)
266 {
267 int16 be_data;
268 status_t result = RemoveData((void*)&be_data, sizeof(int16));
269 if (result != B_OK)
270 return result;
271
272 data = B_BENDIAN_TO_HOST_INT16(be_data);
273
274 return B_OK;
275 }
276
277
278 status_t
RemoveUint16(uint16 & data)279 BNetBuffer::RemoveUint16(uint16& data)
280 {
281 uint16 be_data;
282 status_t result = RemoveData((void*)&be_data, sizeof(uint16));
283 if (result != B_OK)
284 return result;
285
286 data = B_BENDIAN_TO_HOST_INT16(be_data);
287
288 return B_OK;
289 }
290
291
292 status_t
RemoveInt32(int32 & data)293 BNetBuffer::RemoveInt32(int32& data)
294 {
295 int32 be_data;
296 status_t result = RemoveData((void*)&be_data, sizeof(int32));
297 if (result != B_OK)
298 return result;
299
300 data = B_BENDIAN_TO_HOST_INT32(be_data);
301
302 return B_OK;
303 }
304
305
306 status_t
RemoveUint32(uint32 & data)307 BNetBuffer::RemoveUint32(uint32& data)
308 {
309 uint32 be_data;
310 status_t result = RemoveData((void*)&be_data, sizeof(uint32));
311 if (result != B_OK)
312 return result;
313
314 data = B_BENDIAN_TO_HOST_INT32(be_data);
315
316 return B_OK;
317 }
318
319
320 status_t
RemoveFloat(float & data)321 BNetBuffer::RemoveFloat(float& data)
322 {
323 return RemoveData((void*)&data, sizeof(float));
324 }
325
326
327 status_t
RemoveDouble(double & data)328 BNetBuffer::RemoveDouble(double& data)
329 {
330 return RemoveData((void*)&data, sizeof(double));
331 }
332
333
334 status_t
RemoveString(char * data,size_t size)335 BNetBuffer::RemoveString(char* data, size_t size)
336 {
337 // TODO(bga): Should we do anything specific to handle the terminating
338 // NULL byte?
339 return RemoveData((void*)data, size);
340 }
341
342
343 status_t
RemoveData(void * data,size_t size)344 BNetBuffer::RemoveData(void* data, size_t size)
345 {
346 if (fInit != B_OK)
347 return B_NO_INIT;
348
349 ssize_t bytesRead = fImpl->Read(data, size);
350 if (bytesRead < 0)
351 return (status_t)bytesRead;
352 return (size_t)bytesRead == size ? B_OK : B_BUFFER_OVERFLOW;
353 }
354
355
356 status_t
RemoveMessage(BMessage & data)357 BNetBuffer::RemoveMessage(BMessage& data)
358 {
359 if (fInit != B_OK)
360 return B_NO_INIT;
361
362 unsigned char* bufferPtr = fImpl->Data();
363
364 if (*(int32*)bufferPtr != B_MESSAGE_TYPE)
365 return B_ERROR;
366
367 bufferPtr += sizeof(int32);
368 int32 dataSize = *(int32*)bufferPtr;
369
370 char* flattenedData = new (std::nothrow) char[dataSize];
371 if (flattenedData == NULL)
372 return B_NO_MEMORY;
373
374 status_t result = RemoveData(flattenedData, dataSize);
375 if (result == B_OK)
376 result = data.Unflatten(flattenedData);
377
378 delete[] flattenedData;
379
380 return result;
381 }
382
383
384 status_t
RemoveInt64(int64 & data)385 BNetBuffer::RemoveInt64(int64& data)
386 {
387 int64 be_data;
388 status_t result = RemoveData((void*)&be_data, sizeof(int64));
389 if (result != B_OK)
390 return result;
391
392 data = B_BENDIAN_TO_HOST_INT64(be_data);
393
394 return B_OK;
395 }
396
397
398 status_t
RemoveUint64(uint64 & data)399 BNetBuffer::RemoveUint64(uint64& data)
400 {
401 uint64 be_data;
402 status_t result = RemoveData((void*)&be_data, sizeof(uint64));
403 if (result != B_OK)
404 return result;
405
406 data = B_BENDIAN_TO_HOST_INT64(be_data);
407
408 return B_OK;
409 }
410
411
412 unsigned char*
Data() const413 BNetBuffer::Data() const
414 {
415 if (fInit != B_OK)
416 return NULL;
417
418 return fImpl->Data();
419 }
420
421
422 size_t
Size() const423 BNetBuffer::Size() const
424 {
425 if (fInit != B_OK)
426 return 0;
427
428 return fImpl->Size();
429 }
430
431
432 size_t
BytesRemaining() const433 BNetBuffer::BytesRemaining() const
434 {
435 if (fInit != B_OK)
436 return 0;
437
438 return fImpl->BytesRemaining();
439 }
440
441
442 void
_ReservedBNetBufferFBCCruft1()443 BNetBuffer::_ReservedBNetBufferFBCCruft1()
444 {
445 }
446
447
448 void
_ReservedBNetBufferFBCCruft2()449 BNetBuffer::_ReservedBNetBufferFBCCruft2()
450 {
451 }
452
453
454 void
_ReservedBNetBufferFBCCruft3()455 BNetBuffer::_ReservedBNetBufferFBCCruft3()
456 {
457 }
458
459
460 void
_ReservedBNetBufferFBCCruft4()461 BNetBuffer::_ReservedBNetBufferFBCCruft4()
462 {
463 }
464
465
466 void
_ReservedBNetBufferFBCCruft5()467 BNetBuffer::_ReservedBNetBufferFBCCruft5()
468 {
469 }
470
471
472 void
_ReservedBNetBufferFBCCruft6()473 BNetBuffer::_ReservedBNetBufferFBCCruft6()
474 {
475 }
476