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