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