xref: /haiku/src/kits/network/libnetapi/NetBuffer.cpp (revision 97dfeb96704e5dbc5bec32ad7b21379d0125e031)
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 			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&
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     BNetBuffer* buffer = new (std::nothrow) BNetBuffer(archive);
99     if (buffer == NULL)
100         return NULL;
101 
102     if (buffer->InitCheck() != B_OK) {
103         delete buffer;
104         return NULL;
105     }
106 
107     return buffer;
108 }
109 
110 
111 status_t
112 BNetBuffer::InitCheck()
113 {
114 	return fInit;
115 }
116 
117 
118 status_t
119 BNetBuffer::AppendInt8(int8 data)
120 {
121 	return AppendData((const void*)&data, sizeof(int8));
122 }
123 
124 
125 status_t
126 BNetBuffer::AppendUint8(uint8 data)
127 {
128 	return AppendData((const void*)&data, sizeof(int8));
129 }
130 
131 
132 status_t
133 BNetBuffer::AppendInt16(int16 data)
134 {
135 	int16 be_data = B_HOST_TO_BENDIAN_INT16(data);
136 	return AppendData((const void*)&be_data, sizeof(int16));
137 }
138 
139 
140 status_t
141 BNetBuffer::AppendUint16(uint16 data)
142 {
143 	uint16 be_data = B_HOST_TO_BENDIAN_INT16(data);
144 	return AppendData((const void*)&be_data, sizeof(uint16));
145 }
146 
147 
148 status_t
149 BNetBuffer::AppendInt32(int32 data)
150 {
151 	int32 be_data = B_HOST_TO_BENDIAN_INT32(data);
152 	return AppendData((const void*)&be_data, sizeof(int32));
153 }
154 
155 
156 status_t
157 BNetBuffer::AppendUint32(uint32 data)
158 {
159 	uint32 be_data = B_HOST_TO_BENDIAN_INT32(data);
160 	return AppendData((const void*)&be_data, sizeof(uint32));
161 }
162 
163 
164 status_t
165 BNetBuffer::AppendFloat(float data)
166 {
167 	return AppendData((const void*)&data, sizeof(float));
168 }
169 
170 
171 status_t
172 BNetBuffer::AppendDouble(double data)
173 {
174 	return AppendData((const void*)&data, sizeof(double));
175 }
176 
177 
178 status_t
179 BNetBuffer::AppendString(const char* data)
180 {
181 	return AppendData((const void*)data, strlen(data) + 1);
182 }
183 
184 
185 status_t
186 BNetBuffer::AppendData(const void* data, size_t size)
187 {
188 	if (fInit != B_OK)
189 		return B_NO_INIT;
190 
191 	ssize_t bytesWritten = fImpl->Write(data, size);
192 	if (bytesWritten < 0)
193 		return (status_t)bytesWritten;
194 	return (size_t)bytesWritten == size ? B_OK : B_ERROR;
195 }
196 
197 
198 #define STACK_BUFFER_SIZE 2048
199 
200 status_t
201 BNetBuffer::AppendMessage(const BMessage& data)
202 {
203 	char stackFlattenedData[STACK_BUFFER_SIZE];
204 
205 	ssize_t dataSize = data.FlattenedSize();
206 
207 	if (dataSize < 0)
208 		return dataSize;
209 
210 	if (dataSize == 0)
211 		return B_ERROR;
212 
213 	status_t result = B_OK;
214 
215 	if (dataSize > STACK_BUFFER_SIZE) {
216 		char* flattenedData = new (std::nothrow) char[dataSize];
217 		if (flattenedData == NULL)
218 			return B_NO_MEMORY;
219 
220 		if (data.Flatten(flattenedData, dataSize) == B_OK)
221 			result = AppendData((const void*)&flattenedData, dataSize);
222 
223 		delete[] flattenedData;
224 	} else {
225 		if (data.Flatten(stackFlattenedData, dataSize) == B_OK)
226 			result = AppendData((const void*)&stackFlattenedData, dataSize);
227 	}
228 
229 	return result;
230 }
231 
232 
233 status_t
234 BNetBuffer::AppendInt64(int64 data)
235 {
236 	int64 be_data = B_HOST_TO_BENDIAN_INT64(data);
237 	return AppendData((const void*)&be_data, sizeof(int64));
238 }
239 
240 
241 status_t
242 BNetBuffer::AppendUint64(uint64 data)
243 {
244 	uint64 be_data = B_HOST_TO_BENDIAN_INT64(data);
245 	return AppendData((const void*)&be_data, sizeof(uint64));
246 }
247 
248 
249 status_t
250 BNetBuffer::RemoveInt8(int8& data)
251 {
252 	return RemoveData((void*)&data, sizeof(int8));
253 }
254 
255 
256 status_t
257 BNetBuffer::RemoveUint8(uint8& data)
258 {
259 	return RemoveData((void*)&data, sizeof(uint8));
260 }
261 
262 
263 status_t
264 BNetBuffer::RemoveInt16(int16& data)
265 {
266 	int16 be_data;
267 	status_t result = RemoveData((void*)&be_data, sizeof(int16));
268 	if (result != B_OK)
269 		return result;
270 
271 	data = B_BENDIAN_TO_HOST_INT16(be_data);
272 
273 	return B_OK;
274 }
275 
276 
277 status_t
278 BNetBuffer::RemoveUint16(uint16& data)
279 {
280 	uint16 be_data;
281 	status_t result = RemoveData((void*)&be_data, sizeof(uint16));
282 	if (result != B_OK)
283 		return result;
284 
285 	data = B_BENDIAN_TO_HOST_INT16(be_data);
286 
287 	return B_OK;
288 }
289 
290 
291 status_t
292 BNetBuffer::RemoveInt32(int32& data)
293 {
294 	int32 be_data;
295 	status_t result = RemoveData((void*)&be_data, sizeof(int32));
296 	if (result != B_OK)
297 		return result;
298 
299 	data = B_BENDIAN_TO_HOST_INT32(be_data);
300 
301 	return B_OK;
302 }
303 
304 
305 status_t
306 BNetBuffer::RemoveUint32(uint32& data)
307 {
308 	uint32 be_data;
309 	status_t result = RemoveData((void*)&be_data, sizeof(uint32));
310 	if (result != B_OK)
311 		return result;
312 
313 	data = B_BENDIAN_TO_HOST_INT32(be_data);
314 
315 	return B_OK;
316 }
317 
318 
319 status_t
320 BNetBuffer::RemoveFloat(float& data)
321 {
322 	return RemoveData((void*)&data, sizeof(float));
323 }
324 
325 
326 status_t
327 BNetBuffer::RemoveDouble(double& data)
328 {
329 	return RemoveData((void*)&data, sizeof(double));
330 }
331 
332 
333 status_t
334 BNetBuffer::RemoveString(char* data, size_t size)
335 {
336 	// TODO(bga): Should we do anything specific to handle the terminating
337 	// NULL byte?
338 	return RemoveData((void*)data, size);
339 }
340 
341 
342 status_t
343 BNetBuffer::RemoveData(void* data, size_t size)
344 {
345 	if (fInit != B_OK)
346 		return B_NO_INIT;
347 
348 	ssize_t bytesRead = fImpl->Read(data, size);
349 	if (bytesRead < 0)
350 		return (status_t)bytesRead;
351 	return (size_t)bytesRead == size ? B_OK : B_BUFFER_OVERFLOW;
352 }
353 
354 
355 status_t
356 BNetBuffer::RemoveMessage(BMessage& data)
357 {
358 	if (fInit != B_OK)
359 		return B_NO_INIT;
360 
361 	unsigned char* bufferPtr = fImpl->Data();
362 
363 	if (*(int32*)bufferPtr != B_MESSAGE_TYPE)
364 		return B_ERROR;
365 
366 	bufferPtr += sizeof(int32);
367 	int32 dataSize = *(int32*)bufferPtr;
368 
369 	char* flattenedData = new (std::nothrow) char[dataSize];
370 	if (flattenedData == NULL)
371 		return B_NO_MEMORY;
372 
373 	status_t result = RemoveData(flattenedData, dataSize);
374 	if (result == B_OK)
375 		result = data.Unflatten(flattenedData);
376 
377 	delete[] flattenedData;
378 
379 	return result;
380 }
381 
382 
383 status_t
384 BNetBuffer::RemoveInt64(int64& data)
385 {
386 	int64 be_data;
387 	status_t result = RemoveData((void*)&be_data, sizeof(int64));
388 	if (result != B_OK)
389 		return result;
390 
391 	data = B_BENDIAN_TO_HOST_INT64(be_data);
392 
393 	return B_OK;
394 }
395 
396 
397 status_t
398 BNetBuffer::RemoveUint64(uint64& data)
399 {
400 	uint64 be_data;
401 	status_t result = RemoveData((void*)&be_data, sizeof(uint64));
402 	if (result != B_OK)
403 		return result;
404 
405 	data = B_BENDIAN_TO_HOST_INT64(be_data);
406 
407 	return B_OK;
408 }
409 
410 
411 unsigned char*
412 BNetBuffer::Data() const
413 {
414 	if (fInit != B_OK)
415 		return NULL;
416 
417 	return fImpl->Data();
418 }
419 
420 
421 size_t
422 BNetBuffer::Size() const
423 {
424 	if (fInit != B_OK)
425 		return 0;
426 
427 	return fImpl->Size();
428 }
429 
430 
431 size_t
432 BNetBuffer::BytesRemaining() const
433 {
434 	if (fInit != B_OK)
435 		return 0;
436 
437 	return fImpl->BytesRemaining();
438 }
439 
440 
441 void
442 BNetBuffer::_ReservedBNetBufferFBCCruft1()
443 {
444 }
445 
446 
447 void
448 BNetBuffer::_ReservedBNetBufferFBCCruft2()
449 {
450 }
451 
452 
453 void
454 BNetBuffer::_ReservedBNetBufferFBCCruft3()
455 {
456 }
457 
458 
459 void
460 BNetBuffer::_ReservedBNetBufferFBCCruft4()
461 {
462 }
463 
464 
465 void
466 BNetBuffer::_ReservedBNetBufferFBCCruft5()
467 {
468 }
469 
470 
471 void
472 BNetBuffer::_ReservedBNetBufferFBCCruft6()
473 {
474 }
475