xref: /haiku/src/kits/network/libnetapi/NetBuffer.cpp (revision c237c4ce593ee823d9867fd997e51e4c447f5623)
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 	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
81 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*
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
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 	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
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
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
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
251 BNetBuffer::RemoveInt8(int8& data)
252 {
253 	return RemoveData((void*)&data, sizeof(int8));
254 }
255 
256 
257 status_t
258 BNetBuffer::RemoveUint8(uint8& data)
259 {
260 	return RemoveData((void*)&data, sizeof(uint8));
261 }
262 
263 
264 status_t
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
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
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
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
321 BNetBuffer::RemoveFloat(float& data)
322 {
323 	return RemoveData((void*)&data, sizeof(float));
324 }
325 
326 
327 status_t
328 BNetBuffer::RemoveDouble(double& data)
329 {
330 	return RemoveData((void*)&data, sizeof(double));
331 }
332 
333 
334 status_t
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
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
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
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
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*
413 BNetBuffer::Data() const
414 {
415 	if (fInit != B_OK)
416 		return NULL;
417 
418 	return fImpl->Data();
419 }
420 
421 
422 size_t
423 BNetBuffer::Size() const
424 {
425 	if (fInit != B_OK)
426 		return 0;
427 
428 	return fImpl->Size();
429 }
430 
431 
432 size_t
433 BNetBuffer::BytesRemaining() const
434 {
435 	if (fInit != B_OK)
436 		return 0;
437 
438 	return fImpl->BytesRemaining();
439 }
440 
441 
442 void
443 BNetBuffer::_ReservedBNetBufferFBCCruft1()
444 {
445 }
446 
447 
448 void
449 BNetBuffer::_ReservedBNetBufferFBCCruft2()
450 {
451 }
452 
453 
454 void
455 BNetBuffer::_ReservedBNetBufferFBCCruft3()
456 {
457 }
458 
459 
460 void
461 BNetBuffer::_ReservedBNetBufferFBCCruft4()
462 {
463 }
464 
465 
466 void
467 BNetBuffer::_ReservedBNetBufferFBCCruft5()
468 {
469 }
470 
471 
472 void
473 BNetBuffer::_ReservedBNetBufferFBCCruft6()
474 {
475 }
476