1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef WEBRTC_BASE_STREAM_H_ 12 #define WEBRTC_BASE_STREAM_H_ 13 14 #include <stdio.h> 15 16 #include "webrtc/base/basictypes.h" 17 #include "webrtc/base/buffer.h" 18 #include "webrtc/base/criticalsection.h" 19 #include "webrtc/base/logging.h" 20 #include "webrtc/base/messagehandler.h" 21 #include "webrtc/base/messagequeue.h" 22 #include "webrtc/base/scoped_ptr.h" 23 #include "webrtc/base/sigslot.h" 24 25 namespace rtc { 26 27 /////////////////////////////////////////////////////////////////////////////// 28 // StreamInterface is a generic asynchronous stream interface, supporting read, 29 // write, and close operations, and asynchronous signalling of state changes. 30 // The interface is designed with file, memory, and socket implementations in 31 // mind. Some implementations offer extended operations, such as seeking. 32 /////////////////////////////////////////////////////////////////////////////// 33 34 // The following enumerations are declared outside of the StreamInterface 35 // class for brevity in use. 36 37 // The SS_OPENING state indicates that the stream will signal open or closed 38 // in the future. 39 enum StreamState { SS_CLOSED, SS_OPENING, SS_OPEN }; 40 41 // Stream read/write methods return this value to indicate various success 42 // and failure conditions described below. 43 enum StreamResult { SR_ERROR, SR_SUCCESS, SR_BLOCK, SR_EOS }; 44 45 // StreamEvents are used to asynchronously signal state transitionss. The flags 46 // may be combined. 47 // SE_OPEN: The stream has transitioned to the SS_OPEN state 48 // SE_CLOSE: The stream has transitioned to the SS_CLOSED state 49 // SE_READ: Data is available, so Read is likely to not return SR_BLOCK 50 // SE_WRITE: Data can be written, so Write is likely to not return SR_BLOCK 51 enum StreamEvent { SE_OPEN = 1, SE_READ = 2, SE_WRITE = 4, SE_CLOSE = 8 }; 52 53 class Thread; 54 55 struct StreamEventData : public MessageData { 56 int events, error; StreamEventDataStreamEventData57 StreamEventData(int ev, int er) : events(ev), error(er) { } 58 }; 59 60 class StreamInterface : public MessageHandler { 61 public: 62 enum { 63 MSG_POST_EVENT = 0xF1F1, MSG_MAX = MSG_POST_EVENT 64 }; 65 66 virtual ~StreamInterface(); 67 68 virtual StreamState GetState() const = 0; 69 70 // Read attempts to fill buffer of size buffer_len. Write attempts to send 71 // data_len bytes stored in data. The variables read and write are set only 72 // on SR_SUCCESS (see below). Likewise, error is only set on SR_ERROR. 73 // Read and Write return a value indicating: 74 // SR_ERROR: an error occurred, which is returned in a non-null error 75 // argument. Interpretation of the error requires knowledge of the 76 // stream's concrete type, which limits its usefulness. 77 // SR_SUCCESS: some number of bytes were successfully written, which is 78 // returned in a non-null read/write argument. 79 // SR_BLOCK: the stream is in non-blocking mode, and the operation would 80 // block, or the stream is in SS_OPENING state. 81 // SR_EOS: the end-of-stream has been reached, or the stream is in the 82 // SS_CLOSED state. 83 virtual StreamResult Read(void* buffer, size_t buffer_len, 84 size_t* read, int* error) = 0; 85 virtual StreamResult Write(const void* data, size_t data_len, 86 size_t* written, int* error) = 0; 87 // Attempt to transition to the SS_CLOSED state. SE_CLOSE will not be 88 // signalled as a result of this call. 89 virtual void Close() = 0; 90 91 // Streams may signal one or more StreamEvents to indicate state changes. 92 // The first argument identifies the stream on which the state change occured. 93 // The second argument is a bit-wise combination of StreamEvents. 94 // If SE_CLOSE is signalled, then the third argument is the associated error 95 // code. Otherwise, the value is undefined. 96 // Note: Not all streams will support asynchronous event signalling. However, 97 // SS_OPENING and SR_BLOCK returned from stream member functions imply that 98 // certain events will be raised in the future. 99 sigslot::signal3<StreamInterface*, int, int> SignalEvent; 100 101 // Like calling SignalEvent, but posts a message to the specified thread, 102 // which will call SignalEvent. This helps unroll the stack and prevent 103 // re-entrancy. 104 void PostEvent(Thread* t, int events, int err); 105 // Like the aforementioned method, but posts to the current thread. 106 void PostEvent(int events, int err); 107 108 // 109 // OPTIONAL OPERATIONS 110 // 111 // Not all implementations will support the following operations. In general, 112 // a stream will only support an operation if it reasonably efficient to do 113 // so. For example, while a socket could buffer incoming data to support 114 // seeking, it will not do so. Instead, a buffering stream adapter should 115 // be used. 116 // 117 // Even though several of these operations are related, you should 118 // always use whichever operation is most relevant. For example, you may 119 // be tempted to use GetSize() and GetPosition() to deduce the result of 120 // GetAvailable(). However, a stream which is read-once may support the 121 // latter operation but not the former. 122 // 123 124 // The following four methods are used to avoid copying data multiple times. 125 126 // GetReadData returns a pointer to a buffer which is owned by the stream. 127 // The buffer contains data_len bytes. NULL is returned if no data is 128 // available, or if the method fails. If the caller processes the data, it 129 // must call ConsumeReadData with the number of processed bytes. GetReadData 130 // does not require a matching call to ConsumeReadData if the data is not 131 // processed. Read and ConsumeReadData invalidate the buffer returned by 132 // GetReadData. GetReadData(size_t * data_len)133 virtual const void* GetReadData(size_t* data_len) { return NULL; } ConsumeReadData(size_t used)134 virtual void ConsumeReadData(size_t used) {} 135 136 // GetWriteBuffer returns a pointer to a buffer which is owned by the stream. 137 // The buffer has a capacity of buf_len bytes. NULL is returned if there is 138 // no buffer available, or if the method fails. The call may write data to 139 // the buffer, and then call ConsumeWriteBuffer with the number of bytes 140 // written. GetWriteBuffer does not require a matching call to 141 // ConsumeWriteData if no data is written. Write, ForceWrite, and 142 // ConsumeWriteData invalidate the buffer returned by GetWriteBuffer. 143 // TODO: Allow the caller to specify a minimum buffer size. If the specified 144 // amount of buffer is not yet available, return NULL and Signal SE_WRITE 145 // when it is available. If the requested amount is too large, return an 146 // error. GetWriteBuffer(size_t * buf_len)147 virtual void* GetWriteBuffer(size_t* buf_len) { return NULL; } ConsumeWriteBuffer(size_t used)148 virtual void ConsumeWriteBuffer(size_t used) {} 149 150 // Write data_len bytes found in data, circumventing any throttling which 151 // would could cause SR_BLOCK to be returned. Returns true if all the data 152 // was written. Otherwise, the method is unsupported, or an unrecoverable 153 // error occurred, and the error value is set. This method should be used 154 // sparingly to write critical data which should not be throttled. A stream 155 // which cannot circumvent its blocking constraints should not implement this 156 // method. 157 // NOTE: This interface is being considered experimentally at the moment. It 158 // would be used by JUDP and BandwidthStream as a way to circumvent certain 159 // soft limits in writing. 160 //virtual bool ForceWrite(const void* data, size_t data_len, int* error) { 161 // if (error) *error = -1; 162 // return false; 163 //} 164 165 // Seek to a byte offset from the beginning of the stream. Returns false if 166 // the stream does not support seeking, or cannot seek to the specified 167 // position. SetPosition(size_t position)168 virtual bool SetPosition(size_t position) { return false; } 169 170 // Get the byte offset of the current position from the start of the stream. 171 // Returns false if the position is not known. GetPosition(size_t * position)172 virtual bool GetPosition(size_t* position) const { return false; } 173 174 // Get the byte length of the entire stream. Returns false if the length 175 // is not known. GetSize(size_t * size)176 virtual bool GetSize(size_t* size) const { return false; } 177 178 // Return the number of Read()-able bytes remaining before end-of-stream. 179 // Returns false if not known. GetAvailable(size_t * size)180 virtual bool GetAvailable(size_t* size) const { return false; } 181 182 // Return the number of Write()-able bytes remaining before end-of-stream. 183 // Returns false if not known. GetWriteRemaining(size_t * size)184 virtual bool GetWriteRemaining(size_t* size) const { return false; } 185 186 // Return true if flush is successful. Flush()187 virtual bool Flush() { return false; } 188 189 // Communicates the amount of data which will be written to the stream. The 190 // stream may choose to preallocate memory to accomodate this data. The 191 // stream may return false to indicate that there is not enough room (ie, 192 // Write will return SR_EOS/SR_ERROR at some point). Note that calling this 193 // function should not affect the existing state of data in the stream. ReserveSize(size_t size)194 virtual bool ReserveSize(size_t size) { return true; } 195 196 // 197 // CONVENIENCE METHODS 198 // 199 // These methods are implemented in terms of other methods, for convenience. 200 // 201 202 // Seek to the start of the stream. Rewind()203 inline bool Rewind() { return SetPosition(0); } 204 205 // WriteAll is a helper function which repeatedly calls Write until all the 206 // data is written, or something other than SR_SUCCESS is returned. Note that 207 // unlike Write, the argument 'written' is always set, and may be non-zero 208 // on results other than SR_SUCCESS. The remaining arguments have the 209 // same semantics as Write. 210 StreamResult WriteAll(const void* data, size_t data_len, 211 size_t* written, int* error); 212 213 // Similar to ReadAll. Calls Read until buffer_len bytes have been read, or 214 // until a non-SR_SUCCESS result is returned. 'read' is always set. 215 StreamResult ReadAll(void* buffer, size_t buffer_len, 216 size_t* read, int* error); 217 218 // ReadLine is a helper function which repeatedly calls Read until it hits 219 // the end-of-line character, or something other than SR_SUCCESS. 220 // TODO: this is too inefficient to keep here. Break this out into a buffered 221 // readline object or adapter 222 StreamResult ReadLine(std::string* line); 223 224 protected: 225 StreamInterface(); 226 227 // MessageHandler Interface 228 virtual void OnMessage(Message* msg); 229 230 private: 231 DISALLOW_EVIL_CONSTRUCTORS(StreamInterface); 232 }; 233 234 /////////////////////////////////////////////////////////////////////////////// 235 // StreamAdapterInterface is a convenient base-class for adapting a stream. 236 // By default, all operations are pass-through. Override the methods that you 237 // require adaptation. Streams should really be upgraded to reference-counted. 238 // In the meantime, use the owned flag to indicate whether the adapter should 239 // own the adapted stream. 240 /////////////////////////////////////////////////////////////////////////////// 241 242 class StreamAdapterInterface : public StreamInterface, 243 public sigslot::has_slots<> { 244 public: 245 explicit StreamAdapterInterface(StreamInterface* stream, bool owned = true); 246 247 // Core Stream Interface GetState()248 virtual StreamState GetState() const { 249 return stream_->GetState(); 250 } Read(void * buffer,size_t buffer_len,size_t * read,int * error)251 virtual StreamResult Read(void* buffer, size_t buffer_len, 252 size_t* read, int* error) { 253 return stream_->Read(buffer, buffer_len, read, error); 254 } Write(const void * data,size_t data_len,size_t * written,int * error)255 virtual StreamResult Write(const void* data, size_t data_len, 256 size_t* written, int* error) { 257 return stream_->Write(data, data_len, written, error); 258 } Close()259 virtual void Close() { 260 stream_->Close(); 261 } 262 263 // Optional Stream Interface 264 /* Note: Many stream adapters were implemented prior to this Read/Write 265 interface. Therefore, a simple pass through of data in those cases may 266 be broken. At a later time, we should do a once-over pass of all 267 adapters, and make them compliant with these interfaces, after which this 268 code can be uncommented. 269 virtual const void* GetReadData(size_t* data_len) { 270 return stream_->GetReadData(data_len); 271 } 272 virtual void ConsumeReadData(size_t used) { 273 stream_->ConsumeReadData(used); 274 } 275 276 virtual void* GetWriteBuffer(size_t* buf_len) { 277 return stream_->GetWriteBuffer(buf_len); 278 } 279 virtual void ConsumeWriteBuffer(size_t used) { 280 stream_->ConsumeWriteBuffer(used); 281 } 282 */ 283 284 /* Note: This interface is currently undergoing evaluation. 285 virtual bool ForceWrite(const void* data, size_t data_len, int* error) { 286 return stream_->ForceWrite(data, data_len, error); 287 } 288 */ 289 SetPosition(size_t position)290 virtual bool SetPosition(size_t position) { 291 return stream_->SetPosition(position); 292 } GetPosition(size_t * position)293 virtual bool GetPosition(size_t* position) const { 294 return stream_->GetPosition(position); 295 } GetSize(size_t * size)296 virtual bool GetSize(size_t* size) const { 297 return stream_->GetSize(size); 298 } GetAvailable(size_t * size)299 virtual bool GetAvailable(size_t* size) const { 300 return stream_->GetAvailable(size); 301 } GetWriteRemaining(size_t * size)302 virtual bool GetWriteRemaining(size_t* size) const { 303 return stream_->GetWriteRemaining(size); 304 } ReserveSize(size_t size)305 virtual bool ReserveSize(size_t size) { 306 return stream_->ReserveSize(size); 307 } Flush()308 virtual bool Flush() { 309 return stream_->Flush(); 310 } 311 312 void Attach(StreamInterface* stream, bool owned = true); 313 StreamInterface* Detach(); 314 315 protected: 316 virtual ~StreamAdapterInterface(); 317 318 // Note that the adapter presents itself as the origin of the stream events, 319 // since users of the adapter may not recognize the adapted object. OnEvent(StreamInterface * stream,int events,int err)320 virtual void OnEvent(StreamInterface* stream, int events, int err) { 321 SignalEvent(this, events, err); 322 } stream()323 StreamInterface* stream() { return stream_; } 324 325 private: 326 StreamInterface* stream_; 327 bool owned_; 328 DISALLOW_EVIL_CONSTRUCTORS(StreamAdapterInterface); 329 }; 330 331 /////////////////////////////////////////////////////////////////////////////// 332 // StreamTap is a non-modifying, pass-through adapter, which copies all data 333 // in either direction to the tap. Note that errors or blocking on writing to 334 // the tap will prevent further tap writes from occurring. 335 /////////////////////////////////////////////////////////////////////////////// 336 337 class StreamTap : public StreamAdapterInterface { 338 public: 339 explicit StreamTap(StreamInterface* stream, StreamInterface* tap); 340 341 void AttachTap(StreamInterface* tap); 342 StreamInterface* DetachTap(); 343 StreamResult GetTapResult(int* error); 344 345 // StreamAdapterInterface Interface 346 virtual StreamResult Read(void* buffer, size_t buffer_len, 347 size_t* read, int* error); 348 virtual StreamResult Write(const void* data, size_t data_len, 349 size_t* written, int* error); 350 351 private: 352 scoped_ptr<StreamInterface> tap_; 353 StreamResult tap_result_; 354 int tap_error_; 355 DISALLOW_EVIL_CONSTRUCTORS(StreamTap); 356 }; 357 358 /////////////////////////////////////////////////////////////////////////////// 359 // StreamSegment adapts a read stream, to expose a subset of the adapted 360 // stream's data. This is useful for cases where a stream contains multiple 361 // documents concatenated together. StreamSegment can expose a subset of 362 // the data as an independent stream, including support for rewinding and 363 // seeking. 364 /////////////////////////////////////////////////////////////////////////////// 365 366 class StreamSegment : public StreamAdapterInterface { 367 public: 368 // The current position of the adapted stream becomes the beginning of the 369 // segment. If a length is specified, it bounds the length of the segment. 370 explicit StreamSegment(StreamInterface* stream); 371 explicit StreamSegment(StreamInterface* stream, size_t length); 372 373 // StreamAdapterInterface Interface 374 virtual StreamResult Read(void* buffer, size_t buffer_len, 375 size_t* read, int* error); 376 virtual bool SetPosition(size_t position); 377 virtual bool GetPosition(size_t* position) const; 378 virtual bool GetSize(size_t* size) const; 379 virtual bool GetAvailable(size_t* size) const; 380 381 private: 382 size_t start_, pos_, length_; 383 DISALLOW_EVIL_CONSTRUCTORS(StreamSegment); 384 }; 385 386 /////////////////////////////////////////////////////////////////////////////// 387 // NullStream gives errors on read, and silently discards all written data. 388 /////////////////////////////////////////////////////////////////////////////// 389 390 class NullStream : public StreamInterface { 391 public: 392 NullStream(); 393 virtual ~NullStream(); 394 395 // StreamInterface Interface 396 virtual StreamState GetState() const; 397 virtual StreamResult Read(void* buffer, size_t buffer_len, 398 size_t* read, int* error); 399 virtual StreamResult Write(const void* data, size_t data_len, 400 size_t* written, int* error); 401 virtual void Close(); 402 }; 403 404 /////////////////////////////////////////////////////////////////////////////// 405 // FileStream is a simple implementation of a StreamInterface, which does not 406 // support asynchronous notification. 407 /////////////////////////////////////////////////////////////////////////////// 408 409 class FileStream : public StreamInterface { 410 public: 411 FileStream(); 412 virtual ~FileStream(); 413 414 // The semantics of filename and mode are the same as stdio's fopen 415 virtual bool Open(const std::string& filename, const char* mode, int* error); 416 virtual bool OpenShare(const std::string& filename, const char* mode, 417 int shflag, int* error); 418 419 // By default, reads and writes are buffered for efficiency. Disabling 420 // buffering causes writes to block until the bytes on disk are updated. 421 virtual bool DisableBuffering(); 422 423 virtual StreamState GetState() const; 424 virtual StreamResult Read(void* buffer, size_t buffer_len, 425 size_t* read, int* error); 426 virtual StreamResult Write(const void* data, size_t data_len, 427 size_t* written, int* error); 428 virtual void Close(); 429 virtual bool SetPosition(size_t position); 430 virtual bool GetPosition(size_t* position) const; 431 virtual bool GetSize(size_t* size) const; 432 virtual bool GetAvailable(size_t* size) const; 433 virtual bool ReserveSize(size_t size); 434 435 virtual bool Flush(); 436 437 #if defined(WEBRTC_POSIX) && !defined(__native_client__) 438 // Tries to aquire an exclusive lock on the file. 439 // Use OpenShare(...) on win32 to get similar functionality. 440 bool TryLock(); 441 bool Unlock(); 442 #endif 443 444 // Note: Deprecated in favor of Filesystem::GetFileSize(). 445 static bool GetSize(const std::string& filename, size_t* size); 446 447 protected: 448 virtual void DoClose(); 449 450 FILE* file_; 451 452 private: 453 DISALLOW_EVIL_CONSTRUCTORS(FileStream); 454 }; 455 456 // A stream that caps the output at a certain size, dropping content from the 457 // middle of the logical stream and maintaining equal parts of the start/end of 458 // the logical stream. 459 class CircularFileStream : public FileStream { 460 public: 461 explicit CircularFileStream(size_t max_size); 462 463 virtual bool Open(const std::string& filename, const char* mode, int* error); 464 virtual StreamResult Read(void* buffer, size_t buffer_len, 465 size_t* read, int* error); 466 virtual StreamResult Write(const void* data, size_t data_len, 467 size_t* written, int* error); 468 469 private: 470 enum ReadSegment { 471 READ_MARKED, // Read 0 .. marked_position_ 472 READ_MIDDLE, // Read position_ .. file_size 473 READ_LATEST, // Read marked_position_ .. position_ if the buffer was 474 // overwritten or 0 .. position_ otherwise. 475 }; 476 477 size_t max_write_size_; 478 size_t position_; 479 size_t marked_position_; 480 size_t last_write_position_; 481 ReadSegment read_segment_; 482 size_t read_segment_available_; 483 }; 484 485 // A stream which pushes writes onto a separate thread and 486 // returns from the write call immediately. 487 class AsyncWriteStream : public StreamInterface { 488 public: 489 // Takes ownership of the stream, but not the thread. AsyncWriteStream(StreamInterface * stream,rtc::Thread * write_thread)490 AsyncWriteStream(StreamInterface* stream, rtc::Thread* write_thread) 491 : stream_(stream), 492 write_thread_(write_thread), 493 state_(stream ? stream->GetState() : SS_CLOSED) { 494 } 495 496 virtual ~AsyncWriteStream(); 497 498 // StreamInterface Interface GetState()499 virtual StreamState GetState() const { return state_; } 500 // This is needed by some stream writers, such as RtpDumpWriter. 501 virtual bool GetPosition(size_t* position) const; 502 virtual StreamResult Read(void* buffer, size_t buffer_len, 503 size_t* read, int* error); 504 virtual StreamResult Write(const void* data, size_t data_len, 505 size_t* written, int* error); 506 virtual void Close(); 507 virtual bool Flush(); 508 509 protected: 510 // From MessageHandler 511 virtual void OnMessage(rtc::Message* pmsg); 512 virtual void ClearBufferAndWrite(); 513 514 private: 515 rtc::scoped_ptr<StreamInterface> stream_; 516 Thread* write_thread_; 517 StreamState state_; 518 Buffer buffer_; 519 mutable CriticalSection crit_stream_; 520 CriticalSection crit_buffer_; 521 522 DISALLOW_EVIL_CONSTRUCTORS(AsyncWriteStream); 523 }; 524 525 526 #if defined(WEBRTC_POSIX) && !defined(__native_client__) 527 // A FileStream that is actually not a file, but the output or input of a 528 // sub-command. See "man 3 popen" for documentation of the underlying OS popen() 529 // function. 530 class POpenStream : public FileStream { 531 public: POpenStream()532 POpenStream() : wait_status_(-1) {} 533 virtual ~POpenStream(); 534 535 virtual bool Open(const std::string& subcommand, const char* mode, 536 int* error); 537 // Same as Open(). shflag is ignored. 538 virtual bool OpenShare(const std::string& subcommand, const char* mode, 539 int shflag, int* error); 540 541 // Returns the wait status from the last Close() of an Open()'ed stream, or 542 // -1 if no Open()+Close() has been done on this object. Meaning of the number 543 // is documented in "man 2 wait". GetWaitStatus()544 int GetWaitStatus() const { return wait_status_; } 545 546 protected: 547 virtual void DoClose(); 548 549 private: 550 int wait_status_; 551 }; 552 #endif // WEBRTC_POSIX 553 554 /////////////////////////////////////////////////////////////////////////////// 555 // MemoryStream is a simple implementation of a StreamInterface over in-memory 556 // data. Data is read and written at the current seek position. Reads return 557 // end-of-stream when they reach the end of data. Writes actually extend the 558 // end of data mark. 559 /////////////////////////////////////////////////////////////////////////////// 560 561 class MemoryStreamBase : public StreamInterface { 562 public: 563 virtual StreamState GetState() const; 564 virtual StreamResult Read(void* buffer, size_t bytes, size_t* bytes_read, 565 int* error); 566 virtual StreamResult Write(const void* buffer, size_t bytes, 567 size_t* bytes_written, int* error); 568 virtual void Close(); 569 virtual bool SetPosition(size_t position); 570 virtual bool GetPosition(size_t* position) const; 571 virtual bool GetSize(size_t* size) const; 572 virtual bool GetAvailable(size_t* size) const; 573 virtual bool ReserveSize(size_t size); 574 GetBuffer()575 char* GetBuffer() { return buffer_; } GetBuffer()576 const char* GetBuffer() const { return buffer_; } 577 578 protected: 579 MemoryStreamBase(); 580 581 virtual StreamResult DoReserve(size_t size, int* error); 582 583 // Invariant: 0 <= seek_position <= data_length_ <= buffer_length_ 584 char* buffer_; 585 size_t buffer_length_; 586 size_t data_length_; 587 size_t seek_position_; 588 589 private: 590 DISALLOW_EVIL_CONSTRUCTORS(MemoryStreamBase); 591 }; 592 593 // MemoryStream dynamically resizes to accomodate written data. 594 595 class MemoryStream : public MemoryStreamBase { 596 public: 597 MemoryStream(); 598 explicit MemoryStream(const char* data); // Calls SetData(data, strlen(data)) 599 MemoryStream(const void* data, size_t length); // Calls SetData(data, length) 600 virtual ~MemoryStream(); 601 602 void SetData(const void* data, size_t length); 603 604 protected: 605 virtual StreamResult DoReserve(size_t size, int* error); 606 // Memory Streams are aligned for efficiency. 607 static const int kAlignment = 16; 608 char* buffer_alloc_; 609 }; 610 611 // ExternalMemoryStream adapts an external memory buffer, so writes which would 612 // extend past the end of the buffer will return end-of-stream. 613 614 class ExternalMemoryStream : public MemoryStreamBase { 615 public: 616 ExternalMemoryStream(); 617 ExternalMemoryStream(void* data, size_t length); 618 virtual ~ExternalMemoryStream(); 619 620 void SetData(void* data, size_t length); 621 }; 622 623 // FifoBuffer allows for efficient, thread-safe buffering of data between 624 // writer and reader. As the data can wrap around the end of the buffer, 625 // MemoryStreamBase can't help us here. 626 627 class FifoBuffer : public StreamInterface { 628 public: 629 // Creates a FIFO buffer with the specified capacity. 630 explicit FifoBuffer(size_t length); 631 // Creates a FIFO buffer with the specified capacity and owner 632 FifoBuffer(size_t length, Thread* owner); 633 virtual ~FifoBuffer(); 634 // Gets the amount of data currently readable from the buffer. 635 bool GetBuffered(size_t* data_len) const; 636 // Resizes the buffer to the specified capacity. Fails if data_length_ > size 637 bool SetCapacity(size_t length); 638 639 // Read into |buffer| with an offset from the current read position, offset 640 // is specified in number of bytes. 641 // This method doesn't adjust read position nor the number of available 642 // bytes, user has to call ConsumeReadData() to do this. 643 StreamResult ReadOffset(void* buffer, size_t bytes, size_t offset, 644 size_t* bytes_read); 645 646 // Write |buffer| with an offset from the current write position, offset is 647 // specified in number of bytes. 648 // This method doesn't adjust the number of buffered bytes, user has to call 649 // ConsumeWriteBuffer() to do this. 650 StreamResult WriteOffset(const void* buffer, size_t bytes, size_t offset, 651 size_t* bytes_written); 652 653 // StreamInterface methods 654 virtual StreamState GetState() const; 655 virtual StreamResult Read(void* buffer, size_t bytes, 656 size_t* bytes_read, int* error); 657 virtual StreamResult Write(const void* buffer, size_t bytes, 658 size_t* bytes_written, int* error); 659 virtual void Close(); 660 virtual const void* GetReadData(size_t* data_len); 661 virtual void ConsumeReadData(size_t used); 662 virtual void* GetWriteBuffer(size_t* buf_len); 663 virtual void ConsumeWriteBuffer(size_t used); 664 virtual bool GetWriteRemaining(size_t* size) const; 665 666 private: 667 // Helper method that implements ReadOffset. Caller must acquire a lock 668 // when calling this method. 669 StreamResult ReadOffsetLocked(void* buffer, size_t bytes, size_t offset, 670 size_t* bytes_read); 671 672 // Helper method that implements WriteOffset. Caller must acquire a lock 673 // when calling this method. 674 StreamResult WriteOffsetLocked(const void* buffer, size_t bytes, 675 size_t offset, size_t* bytes_written); 676 677 StreamState state_; // keeps the opened/closed state of the stream 678 scoped_ptr<char[]> buffer_; // the allocated buffer 679 size_t buffer_length_; // size of the allocated buffer 680 size_t data_length_; // amount of readable data in the buffer 681 size_t read_position_; // offset to the readable data 682 Thread* owner_; // stream callbacks are dispatched on this thread 683 mutable CriticalSection crit_; // object lock 684 DISALLOW_EVIL_CONSTRUCTORS(FifoBuffer); 685 }; 686 687 /////////////////////////////////////////////////////////////////////////////// 688 689 class LoggingAdapter : public StreamAdapterInterface { 690 public: 691 LoggingAdapter(StreamInterface* stream, LoggingSeverity level, 692 const std::string& label, bool hex_mode = false); 693 694 void set_label(const std::string& label); 695 696 virtual StreamResult Read(void* buffer, size_t buffer_len, 697 size_t* read, int* error); 698 virtual StreamResult Write(const void* data, size_t data_len, 699 size_t* written, int* error); 700 virtual void Close(); 701 702 protected: 703 virtual void OnEvent(StreamInterface* stream, int events, int err); 704 705 private: 706 LoggingSeverity level_; 707 std::string label_; 708 bool hex_mode_; 709 LogMultilineState lms_; 710 711 DISALLOW_EVIL_CONSTRUCTORS(LoggingAdapter); 712 }; 713 714 /////////////////////////////////////////////////////////////////////////////// 715 // StringStream - Reads/Writes to an external std::string 716 /////////////////////////////////////////////////////////////////////////////// 717 718 class StringStream : public StreamInterface { 719 public: 720 explicit StringStream(std::string& str); 721 explicit StringStream(const std::string& str); 722 723 virtual StreamState GetState() const; 724 virtual StreamResult Read(void* buffer, size_t buffer_len, 725 size_t* read, int* error); 726 virtual StreamResult Write(const void* data, size_t data_len, 727 size_t* written, int* error); 728 virtual void Close(); 729 virtual bool SetPosition(size_t position); 730 virtual bool GetPosition(size_t* position) const; 731 virtual bool GetSize(size_t* size) const; 732 virtual bool GetAvailable(size_t* size) const; 733 virtual bool ReserveSize(size_t size); 734 735 private: 736 std::string& str_; 737 size_t read_pos_; 738 bool read_only_; 739 }; 740 741 /////////////////////////////////////////////////////////////////////////////// 742 // StreamReference - A reference counting stream adapter 743 /////////////////////////////////////////////////////////////////////////////// 744 745 // Keep in mind that the streams and adapters defined in this file are 746 // not thread-safe, so this has limited uses. 747 748 // A StreamRefCount holds the reference count and a pointer to the 749 // wrapped stream. It deletes the wrapped stream when there are no 750 // more references. We can then have multiple StreamReference 751 // instances pointing to one StreamRefCount, all wrapping the same 752 // stream. 753 754 class StreamReference : public StreamAdapterInterface { 755 class StreamRefCount; 756 public: 757 // Constructor for the first reference to a stream 758 // Note: get more references through NewReference(). Use this 759 // constructor only once on a given stream. 760 explicit StreamReference(StreamInterface* stream); GetStream()761 StreamInterface* GetStream() { return stream(); } 762 StreamInterface* NewReference(); 763 virtual ~StreamReference(); 764 765 private: 766 class StreamRefCount { 767 public: StreamRefCount(StreamInterface * stream)768 explicit StreamRefCount(StreamInterface* stream) 769 : stream_(stream), ref_count_(1) { 770 } AddReference()771 void AddReference() { 772 CritScope lock(&cs_); 773 ++ref_count_; 774 } Release()775 void Release() { 776 int ref_count; 777 { // Atomic ops would have been a better fit here. 778 CritScope lock(&cs_); 779 ref_count = --ref_count_; 780 } 781 if (ref_count == 0) { 782 delete stream_; 783 delete this; 784 } 785 } 786 private: 787 StreamInterface* stream_; 788 int ref_count_; 789 CriticalSection cs_; 790 DISALLOW_EVIL_CONSTRUCTORS(StreamRefCount); 791 }; 792 793 // Constructor for adding references 794 explicit StreamReference(StreamRefCount* stream_ref_count, 795 StreamInterface* stream); 796 797 StreamRefCount* stream_ref_count_; 798 DISALLOW_EVIL_CONSTRUCTORS(StreamReference); 799 }; 800 801 /////////////////////////////////////////////////////////////////////////////// 802 803 // Flow attempts to move bytes from source to sink via buffer of size 804 // buffer_len. The function returns SR_SUCCESS when source reaches 805 // end-of-stream (returns SR_EOS), and all the data has been written successful 806 // to sink. Alternately, if source returns SR_BLOCK or SR_ERROR, or if sink 807 // returns SR_BLOCK, SR_ERROR, or SR_EOS, then the function immediately returns 808 // with the unexpected StreamResult value. 809 // data_len is the length of the valid data in buffer. in case of error 810 // this is the data that read from source but can't move to destination. 811 // as a pass in parameter, it indicates data in buffer that should move to sink 812 StreamResult Flow(StreamInterface* source, 813 char* buffer, size_t buffer_len, 814 StreamInterface* sink, size_t* data_len = NULL); 815 816 /////////////////////////////////////////////////////////////////////////////// 817 818 } // namespace rtc 819 820 #endif // WEBRTC_BASE_STREAM_H_ 821