xref: /haiku/src/kits/network/libnetapi/NetBuffer.cpp (revision bf57c148f7787f0df15980976997c6dfb70ee067)
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 	size_t dataSize = data.FlattenedSize();
206 	if (dataSize == 0)
207 		return B_ERROR;
208 
209 	status_t result = B_OK;
210 
211 	if (dataSize > STACK_BUFFER_SIZE) {
212 		char* flattenedData = new (std::nothrow) char[dataSize];
213 		if (flattenedData == NULL)
214 			return B_NO_MEMORY;
215 
216 		if (data.Flatten(flattenedData, dataSize) == B_OK)
217 			result = AppendData((const void*)&flattenedData, dataSize);
218 
219 		delete[] flattenedData;
220 	} else {
221 		if (data.Flatten(stackFlattenedData, dataSize) == B_OK)
222 			result = AppendData((const void*)&stackFlattenedData, dataSize);
223 	}
224 
225 	return result;
226 }
227 
228 
229 status_t
230 BNetBuffer::AppendInt64(int64 data)
231 {
232 	int64 be_data = B_HOST_TO_BENDIAN_INT64(data);
233 	return AppendData((const void*)&be_data, sizeof(int64));
234 }
235 
236 
237 status_t
238 BNetBuffer::AppendUint64(uint64 data)
239 {
240 	uint64 be_data = B_HOST_TO_BENDIAN_INT64(data);
241 	return AppendData((const void*)&be_data, sizeof(uint64));
242 }
243 
244 
245 status_t
246 BNetBuffer::RemoveInt8(int8& data)
247 {
248 	return RemoveData((void*)&data, sizeof(int8));
249 }
250 
251 
252 status_t
253 BNetBuffer::RemoveUint8(uint8& data)
254 {
255 	return RemoveData((void*)&data, sizeof(uint8));
256 }
257 
258 
259 status_t
260 BNetBuffer::RemoveInt16(int16& data)
261 {
262 	int16 be_data;
263 	status_t result = RemoveData((void*)&be_data, sizeof(int16));
264 	if (result != B_OK)
265 		return result;
266 
267 	data = B_BENDIAN_TO_HOST_INT16(be_data);
268 
269 	return B_OK;
270 }
271 
272 
273 status_t
274 BNetBuffer::RemoveUint16(uint16& data)
275 {
276 	uint16 be_data;
277 	status_t result = RemoveData((void*)&be_data, sizeof(uint16));
278 	if (result != B_OK)
279 		return result;
280 
281 	data = B_BENDIAN_TO_HOST_INT16(be_data);
282 
283 	return B_OK;
284 }
285 
286 
287 status_t
288 BNetBuffer::RemoveInt32(int32& data)
289 {
290 	int32 be_data;
291 	status_t result = RemoveData((void*)&be_data, sizeof(int32));
292 	if (result != B_OK)
293 		return result;
294 
295 	data = B_BENDIAN_TO_HOST_INT32(be_data);
296 
297 	return B_OK;
298 }
299 
300 
301 status_t
302 BNetBuffer::RemoveUint32(uint32& data)
303 {
304 	uint32 be_data;
305 	status_t result = RemoveData((void*)&be_data, sizeof(uint32));
306 	if (result != B_OK)
307 		return result;
308 
309 	data = B_BENDIAN_TO_HOST_INT32(be_data);
310 
311 	return B_OK;
312 }
313 
314 
315 status_t
316 BNetBuffer::RemoveFloat(float& data)
317 {
318 	return RemoveData((void*)&data, sizeof(float));
319 }
320 
321 
322 status_t
323 BNetBuffer::RemoveDouble(double& data)
324 {
325 	return RemoveData((void*)&data, sizeof(double));
326 }
327 
328 
329 status_t
330 BNetBuffer::RemoveString(char* data, size_t size)
331 {
332 	// TODO(bga): Should we do anything specific to handle the terminating
333 	// NULL byte?
334 	return RemoveData((void*)data, size);
335 }
336 
337 
338 status_t
339 BNetBuffer::RemoveData(void* data, size_t size)
340 {
341 	if (fInit != B_OK)
342 		return B_NO_INIT;
343 
344 	ssize_t bytesRead = fImpl->Read(data, size);
345 	if (bytesRead < 0)
346 		return (status_t)bytesRead;
347 	return (size_t)bytesRead == size ? B_OK : B_BUFFER_OVERFLOW;
348 }
349 
350 
351 status_t
352 BNetBuffer::RemoveMessage(BMessage& data)
353 {
354 	if (fInit != B_OK)
355 		return B_NO_INIT;
356 
357 	unsigned char* bufferPtr = fImpl->Data();
358 
359 	if (*(int32*)bufferPtr != B_MESSAGE_TYPE)
360 		return B_ERROR;
361 
362 	bufferPtr += sizeof(int32);
363 	int32 dataSize = *(int32*)bufferPtr;
364 
365 	char* flattenedData = new (std::nothrow) char[dataSize];
366 	if (flattenedData == NULL)
367 		return B_NO_MEMORY;
368 
369 	status_t result = RemoveData(flattenedData, dataSize);
370 	if (result == B_OK)
371 		result = data.Unflatten(flattenedData);
372 
373 	delete[] flattenedData;
374 
375 	return result;
376 }
377 
378 
379 status_t
380 BNetBuffer::RemoveInt64(int64& data)
381 {
382 	int64 be_data;
383 	status_t result = RemoveData((void*)&be_data, sizeof(int64));
384 	if (result != B_OK)
385 		return result;
386 
387 	data = B_BENDIAN_TO_HOST_INT64(be_data);
388 
389 	return B_OK;
390 }
391 
392 
393 status_t
394 BNetBuffer::RemoveUint64(uint64& data)
395 {
396 	uint64 be_data;
397 	status_t result = RemoveData((void*)&be_data, sizeof(uint64));
398 	if (result != B_OK)
399 		return result;
400 
401 	data = B_BENDIAN_TO_HOST_INT64(be_data);
402 
403 	return B_OK;
404 }
405 
406 
407 unsigned char*
408 BNetBuffer::Data() const
409 {
410 	if (fInit != B_OK)
411 		return NULL;
412 
413 	return fImpl->Data();
414 }
415 
416 
417 size_t
418 BNetBuffer::Size() const
419 {
420 	if (fInit != B_OK)
421 		return 0;
422 
423 	return fImpl->Size();
424 }
425 
426 
427 size_t
428 BNetBuffer::BytesRemaining() const
429 {
430 	if (fInit != B_OK)
431 		return 0;
432 
433 	return fImpl->BytesRemaining();
434 }
435 
436 
437 void
438 BNetBuffer::_ReservedBNetBufferFBCCruft1()
439 {
440 }
441 
442 
443 void
444 BNetBuffer::_ReservedBNetBufferFBCCruft2()
445 {
446 }
447 
448 
449 void
450 BNetBuffer::_ReservedBNetBufferFBCCruft3()
451 {
452 }
453 
454 
455 void
456 BNetBuffer::_ReservedBNetBufferFBCCruft4()
457 {
458 }
459 
460 
461 void
462 BNetBuffer::_ReservedBNetBufferFBCCruft5()
463 {
464 }
465 
466 
467 void
468 BNetBuffer::_ReservedBNetBufferFBCCruft6()
469 {
470 }
471