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