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