xref: /haiku/src/kits/network/libnetapi/NetBuffer.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
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 
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 
30 BNetBuffer::~BNetBuffer()
31 {
32 	delete fImpl;
33 }
34 
35 
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 
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 			status_t result = fImpl->Insert(bufferPtr, bufferSize);
58 			if (result == B_OK)
59 				fInit = fImpl->InitCheck();
60 			else
61 				fInit = result;
62 		}
63 	}
64 }
65 
66 BNetBuffer&
67 BNetBuffer::operator=(const BNetBuffer& buffer)
68 {
69 	delete fImpl;
70 
71 	fImpl = new (std::nothrow) DynamicBuffer(*buffer.GetImpl());
72 	if (fImpl != NULL)
73 		fInit = fImpl->InitCheck();
74 
75 	return *this;
76 }
77 
78 
79 status_t
80 BNetBuffer::Archive(BMessage* into, bool deep) const
81 {
82 	if (fInit != B_OK)
83 		return B_NO_INIT;
84 
85 	status_t result = into->AddData("buffer", B_RAW_TYPE, fImpl->Data(),
86 		fImpl->BytesRemaining());
87 
88 	return result;
89 }
90 
91 
92 BArchivable*
93 BNetBuffer::Instantiate(BMessage* archive)
94 {
95     if (!validate_instantiation(archive, "BNetBuffer")) {
96         return NULL;
97     }
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
113 BNetBuffer::InitCheck()
114 {
115 	return fInit;
116 }
117 
118 
119 status_t
120 BNetBuffer::AppendInt8(int8 data)
121 {
122 	return AppendData((const void*)&data, sizeof(int8));
123 }
124 
125 
126 status_t
127 BNetBuffer::AppendUint8(uint8 data)
128 {
129 	return AppendData((const void*)&data, sizeof(int8));
130 }
131 
132 
133 status_t
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
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
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
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
166 BNetBuffer::AppendFloat(float data)
167 {
168 	return AppendData((const void*)&data, sizeof(float));
169 }
170 
171 
172 status_t
173 BNetBuffer::AppendDouble(double data)
174 {
175 	return AppendData((const void*)&data, sizeof(double));
176 }
177 
178 
179 status_t
180 BNetBuffer::AppendString(const char* data)
181 {
182 	return AppendData((const void*)data, strlen(data) + 1);
183 }
184 
185 
186 status_t
187 BNetBuffer::AppendData(const void* data, size_t size)
188 {
189 	return fImpl->Insert(data, size);
190 }
191 
192 
193 #define STACK_BUFFER_SIZE 2048
194 
195 status_t
196 BNetBuffer::AppendMessage(const BMessage& data)
197 {
198 	char stackFlattenedData[STACK_BUFFER_SIZE];
199 
200 	size_t dataSize = data.FlattenedSize();
201 	if (dataSize == 0)
202 		return B_ERROR;
203 
204 	status_t result = B_OK;
205 
206 	if (dataSize > STACK_BUFFER_SIZE) {
207 		char* flattenedData = new (std::nothrow) char[dataSize];
208 		if (flattenedData == NULL)
209 			return B_NO_MEMORY;
210 
211 		if (data.Flatten(flattenedData, dataSize) == B_OK)
212 			result = AppendData((const void*)&flattenedData, dataSize);
213 
214 		delete[] flattenedData;
215 	} else {
216 		if (data.Flatten(stackFlattenedData, dataSize) == B_OK)
217 			result = AppendData((const void*)&stackFlattenedData, dataSize);
218 	}
219 
220 	return result;
221 }
222 
223 
224 status_t
225 BNetBuffer::AppendInt64(int64 data)
226 {
227 	int64 be_data = B_HOST_TO_BENDIAN_INT64(data);
228 	return AppendData((const void*)&be_data, sizeof(int64));
229 }
230 
231 
232 status_t
233 BNetBuffer::AppendUint64(uint64 data)
234 {
235 	uint64 be_data = B_HOST_TO_BENDIAN_INT64(data);
236 	return AppendData((const void*)&be_data, sizeof(uint64));
237 }
238 
239 
240 status_t
241 BNetBuffer::RemoveInt8(int8& data)
242 {
243 	return RemoveData((void*)&data, sizeof(int8));
244 }
245 
246 
247 status_t
248 BNetBuffer::RemoveUint8(uint8& data)
249 {
250 	return RemoveData((void*)&data, sizeof(uint8));
251 }
252 
253 
254 status_t
255 BNetBuffer::RemoveInt16(int16& data)
256 {
257 	int16 be_data;
258 	status_t result = RemoveData((void*)&be_data, sizeof(int16));
259 	if (result != B_OK)
260 		return result;
261 
262 	data = B_BENDIAN_TO_HOST_INT16(be_data);
263 
264 	return B_OK;
265 }
266 
267 
268 status_t
269 BNetBuffer::RemoveUint16(uint16& data)
270 {
271 	uint16 be_data;
272 	status_t result = RemoveData((void*)&be_data, sizeof(uint16));
273 	if (result != B_OK)
274 		return result;
275 
276 	data = B_BENDIAN_TO_HOST_INT16(be_data);
277 
278 	return B_OK;
279 }
280 
281 
282 status_t
283 BNetBuffer::RemoveInt32(int32& data)
284 {
285 	int32 be_data;
286 	status_t result = RemoveData((void*)&be_data, sizeof(int32));
287 	if (result != B_OK)
288 		return result;
289 
290 	data = B_BENDIAN_TO_HOST_INT32(be_data);
291 
292 	return B_OK;
293 }
294 
295 
296 status_t
297 BNetBuffer::RemoveUint32(uint32& data)
298 {
299 	uint32 be_data;
300 	status_t result = RemoveData((void*)&be_data, sizeof(uint32));
301 	if (result != B_OK)
302 		return result;
303 
304 	data = B_BENDIAN_TO_HOST_INT32(be_data);
305 
306 	return B_OK;
307 }
308 
309 
310 status_t
311 BNetBuffer::RemoveFloat(float& data)
312 {
313 	return RemoveData((void*)&data, sizeof(float));
314 }
315 
316 
317 status_t
318 BNetBuffer::RemoveDouble(double& data)
319 {
320 	return RemoveData((void*)&data, sizeof(double));
321 }
322 
323 
324 status_t
325 BNetBuffer::RemoveString(char* data, size_t size)
326 {
327 	// TODO(bga): Should we do anything specific to handle the terminating
328 	// NULL byte?
329 	return RemoveData((void*)data, size);
330 }
331 
332 
333 status_t
334 BNetBuffer::RemoveData(void* data, size_t size)
335 {
336 	return fImpl->Remove(data, size);
337 }
338 
339 
340 status_t
341 BNetBuffer::RemoveMessage(BMessage& data)
342 {
343 	unsigned char* bufferPtr = fImpl->Data();
344 
345 	if (*(int32*)bufferPtr != B_MESSAGE_TYPE)
346 		return B_ERROR;
347 
348 
349 	bufferPtr += sizeof(int32);
350 	int32 dataSize = *(int32*)bufferPtr;
351 
352 	char* flattenedData = new (std::nothrow) char[dataSize];
353 	if (flattenedData == NULL)
354 		return B_NO_MEMORY;
355 
356 	status_t result = RemoveData(flattenedData, dataSize);
357 	if (result == B_OK)
358 		result = data.Unflatten(flattenedData);
359 
360 	delete[] flattenedData;
361 
362 	return result;
363 }
364 
365 
366 status_t
367 BNetBuffer::RemoveInt64(int64& data)
368 {
369 	int64 be_data;
370 	status_t result = RemoveData((void*)&be_data, sizeof(int64));
371 	if (result != B_OK)
372 		return result;
373 
374 	data = B_BENDIAN_TO_HOST_INT64(be_data);
375 
376 	return B_OK;
377 }
378 
379 
380 status_t
381 BNetBuffer::RemoveUint64(uint64& data)
382 {
383 	uint64 be_data;
384 	status_t result = RemoveData((void*)&be_data, sizeof(uint64));
385 	if (result != B_OK)
386 		return result;
387 
388 	data = B_BENDIAN_TO_HOST_INT64(be_data);
389 
390 	return B_OK;
391 }
392 
393 
394 unsigned char*
395 BNetBuffer::Data() const
396 {
397 	return fImpl->Data();
398 }
399 
400 
401 size_t
402 BNetBuffer::Size() const
403 {
404 	return fImpl->Size();
405 }
406 
407 
408 size_t
409 BNetBuffer::BytesRemaining() const
410 {
411 	return fImpl->BytesRemaining();
412 }
413 
414 
415 void
416 BNetBuffer::_ReservedBNetBufferFBCCruft1()
417 {
418 }
419 
420 
421 void
422 BNetBuffer::_ReservedBNetBufferFBCCruft2()
423 {
424 }
425 
426 
427 void
428 BNetBuffer::_ReservedBNetBufferFBCCruft3()
429 {
430 }
431 
432 
433 void
434 BNetBuffer::_ReservedBNetBufferFBCCruft4()
435 {
436 }
437 
438 
439 void
440 BNetBuffer::_ReservedBNetBufferFBCCruft5()
441 {
442 }
443 
444 
445 void
446 BNetBuffer::_ReservedBNetBufferFBCCruft6()
447 {
448 }
449