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