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