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 20BNetBuffer::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 30BNetBuffer::~BNetBuffer() 31{ 32 delete fImpl; 33} 34 35 36BNetBuffer::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 46BNetBuffer::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 66BNetBuffer& 67BNetBuffer::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 80status_t 81BNetBuffer::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 93BArchivable* 94BNetBuffer::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 112status_t 113BNetBuffer::InitCheck() 114{ 115 return fInit; 116} 117 118 119status_t 120BNetBuffer::AppendInt8(int8 data) 121{ 122 return AppendData((const void*)&data, sizeof(int8)); 123} 124 125 126status_t 127BNetBuffer::AppendUint8(uint8 data) 128{ 129 return AppendData((const void*)&data, sizeof(int8)); 130} 131 132 133status_t 134BNetBuffer::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 141status_t 142BNetBuffer::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 149status_t 150BNetBuffer::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 157status_t 158BNetBuffer::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 165status_t 166BNetBuffer::AppendFloat(float data) 167{ 168 return AppendData((const void*)&data, sizeof(float)); 169} 170 171 172status_t 173BNetBuffer::AppendDouble(double data) 174{ 175 return AppendData((const void*)&data, sizeof(double)); 176} 177 178 179status_t 180BNetBuffer::AppendString(const char* data) 181{ 182 return AppendData((const void*)data, strlen(data) + 1); 183} 184 185 186status_t 187BNetBuffer::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 201status_t 202BNetBuffer::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 234status_t 235BNetBuffer::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 242status_t 243BNetBuffer::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 250status_t 251BNetBuffer::RemoveInt8(int8& data) 252{ 253 return RemoveData((void*)&data, sizeof(int8)); 254} 255 256 257status_t 258BNetBuffer::RemoveUint8(uint8& data) 259{ 260 return RemoveData((void*)&data, sizeof(uint8)); 261} 262 263 264status_t 265BNetBuffer::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 278status_t 279BNetBuffer::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 292status_t 293BNetBuffer::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 306status_t 307BNetBuffer::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 320status_t 321BNetBuffer::RemoveFloat(float& data) 322{ 323 return RemoveData((void*)&data, sizeof(float)); 324} 325 326 327status_t 328BNetBuffer::RemoveDouble(double& data) 329{ 330 return RemoveData((void*)&data, sizeof(double)); 331} 332 333 334status_t 335BNetBuffer::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 343status_t 344BNetBuffer::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 356status_t 357BNetBuffer::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 384status_t 385BNetBuffer::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 398status_t 399BNetBuffer::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 412unsigned char* 413BNetBuffer::Data() const 414{ 415 if (fInit != B_OK) 416 return NULL; 417 418 return fImpl->Data(); 419} 420 421 422size_t 423BNetBuffer::Size() const 424{ 425 if (fInit != B_OK) 426 return 0; 427 428 return fImpl->Size(); 429} 430 431 432size_t 433BNetBuffer::BytesRemaining() const 434{ 435 if (fInit != B_OK) 436 return 0; 437 438 return fImpl->BytesRemaining(); 439} 440 441 442void 443BNetBuffer::_ReservedBNetBufferFBCCruft1() 444{ 445} 446 447 448void 449BNetBuffer::_ReservedBNetBufferFBCCruft2() 450{ 451} 452 453 454void 455BNetBuffer::_ReservedBNetBufferFBCCruft3() 456{ 457} 458 459 460void 461BNetBuffer::_ReservedBNetBufferFBCCruft4() 462{ 463} 464 465 466void 467BNetBuffer::_ReservedBNetBufferFBCCruft5() 468{ 469} 470 471 472void 473BNetBuffer::_ReservedBNetBufferFBCCruft6() 474{ 475} 476