blob: c7622776e391be8ff2ee29f22bb1aa94dc1b775d [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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#if defined(WEBRTC_POSIX)
12#include <sys/file.h>
13#endif // WEBRTC_POSIX
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <errno.h>
andresp@webrtc.orgff689be2015-02-12 11:54:26 +000017
18#include <algorithm>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000019#include <string>
andresp@webrtc.orgff689be2015-02-12 11:54:26 +000020
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/basictypes.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/logging.h"
24#include "rtc_base/messagequeue.h"
25#include "rtc_base/stream.h"
26#include "rtc_base/stringencode.h"
27#include "rtc_base/stringutils.h"
28#include "rtc_base/thread.h"
29#include "rtc_base/timeutils.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000030
31#if defined(WEBRTC_WIN)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "rtc_base/win32.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000033#define fileno _fileno
34#endif
35
36namespace rtc {
37
38///////////////////////////////////////////////////////////////////////////////
39// StreamInterface
40///////////////////////////////////////////////////////////////////////////////
41StreamInterface::~StreamInterface() {
42}
43
44StreamResult StreamInterface::WriteAll(const void* data, size_t data_len,
45 size_t* written, int* error) {
46 StreamResult result = SR_SUCCESS;
47 size_t total_written = 0, current_written;
48 while (total_written < data_len) {
49 result = Write(static_cast<const char*>(data) + total_written,
50 data_len - total_written, &current_written, error);
51 if (result != SR_SUCCESS)
52 break;
53 total_written += current_written;
54 }
55 if (written)
56 *written = total_written;
57 return result;
58}
59
60StreamResult StreamInterface::ReadAll(void* buffer, size_t buffer_len,
61 size_t* read, int* error) {
62 StreamResult result = SR_SUCCESS;
63 size_t total_read = 0, current_read;
64 while (total_read < buffer_len) {
65 result = Read(static_cast<char*>(buffer) + total_read,
66 buffer_len - total_read, &current_read, error);
67 if (result != SR_SUCCESS)
68 break;
69 total_read += current_read;
70 }
71 if (read)
72 *read = total_read;
73 return result;
74}
75
76StreamResult StreamInterface::ReadLine(std::string* line) {
77 line->clear();
78 StreamResult result = SR_SUCCESS;
79 while (true) {
80 char ch;
deadbeef37f5ecf2017-02-27 14:06:41 -080081 result = Read(&ch, sizeof(ch), nullptr, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000082 if (result != SR_SUCCESS) {
83 break;
84 }
85 if (ch == '\n') {
86 break;
87 }
88 line->push_back(ch);
89 }
90 if (!line->empty()) { // give back the line we've collected so far with
91 result = SR_SUCCESS; // a success code. Otherwise return the last code
92 }
93 return result;
94}
95
96void StreamInterface::PostEvent(Thread* t, int events, int err) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070097 t->Post(RTC_FROM_HERE, this, MSG_POST_EVENT,
98 new StreamEventData(events, err));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000099}
100
101void StreamInterface::PostEvent(int events, int err) {
102 PostEvent(Thread::Current(), events, err);
103}
104
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000105const void* StreamInterface::GetReadData(size_t* data_len) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800106 return nullptr;
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000107}
108
109void* StreamInterface::GetWriteBuffer(size_t* buf_len) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800110 return nullptr;
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000111}
112
113bool StreamInterface::SetPosition(size_t position) {
114 return false;
115}
116
117bool StreamInterface::GetPosition(size_t* position) const {
118 return false;
119}
120
121bool StreamInterface::GetSize(size_t* size) const {
122 return false;
123}
124
125bool StreamInterface::GetAvailable(size_t* size) const {
126 return false;
127}
128
129bool StreamInterface::GetWriteRemaining(size_t* size) const {
130 return false;
131}
132
133bool StreamInterface::Flush() {
134 return false;
135}
136
137bool StreamInterface::ReserveSize(size_t size) {
138 return true;
139}
140
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000141StreamInterface::StreamInterface() {
142}
143
144void StreamInterface::OnMessage(Message* msg) {
145 if (MSG_POST_EVENT == msg->message_id) {
146 StreamEventData* pe = static_cast<StreamEventData*>(msg->pdata);
147 SignalEvent(this, pe->events, pe->error);
148 delete msg->pdata;
149 }
150}
151
152///////////////////////////////////////////////////////////////////////////////
153// StreamAdapterInterface
154///////////////////////////////////////////////////////////////////////////////
155
156StreamAdapterInterface::StreamAdapterInterface(StreamInterface* stream,
157 bool owned)
158 : stream_(stream), owned_(owned) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800159 if (nullptr != stream_)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000160 stream_->SignalEvent.connect(this, &StreamAdapterInterface::OnEvent);
161}
162
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000163StreamState StreamAdapterInterface::GetState() const {
164 return stream_->GetState();
165}
166StreamResult StreamAdapterInterface::Read(void* buffer,
167 size_t buffer_len,
168 size_t* read,
169 int* error) {
170 return stream_->Read(buffer, buffer_len, read, error);
171}
172StreamResult StreamAdapterInterface::Write(const void* data,
173 size_t data_len,
174 size_t* written,
175 int* error) {
176 return stream_->Write(data, data_len, written, error);
177}
178void StreamAdapterInterface::Close() {
179 stream_->Close();
180}
181
182bool StreamAdapterInterface::SetPosition(size_t position) {
183 return stream_->SetPosition(position);
184}
185
186bool StreamAdapterInterface::GetPosition(size_t* position) const {
187 return stream_->GetPosition(position);
188}
189
190bool StreamAdapterInterface::GetSize(size_t* size) const {
191 return stream_->GetSize(size);
192}
193
194bool StreamAdapterInterface::GetAvailable(size_t* size) const {
195 return stream_->GetAvailable(size);
196}
197
198bool StreamAdapterInterface::GetWriteRemaining(size_t* size) const {
199 return stream_->GetWriteRemaining(size);
200}
201
202bool StreamAdapterInterface::ReserveSize(size_t size) {
203 return stream_->ReserveSize(size);
204}
205
206bool StreamAdapterInterface::Flush() {
207 return stream_->Flush();
208}
209
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000210void StreamAdapterInterface::Attach(StreamInterface* stream, bool owned) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800211 if (nullptr != stream_)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000212 stream_->SignalEvent.disconnect(this);
213 if (owned_)
214 delete stream_;
215 stream_ = stream;
216 owned_ = owned;
deadbeef37f5ecf2017-02-27 14:06:41 -0800217 if (nullptr != stream_)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000218 stream_->SignalEvent.connect(this, &StreamAdapterInterface::OnEvent);
219}
220
221StreamInterface* StreamAdapterInterface::Detach() {
deadbeef37f5ecf2017-02-27 14:06:41 -0800222 if (nullptr != stream_)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000223 stream_->SignalEvent.disconnect(this);
224 StreamInterface* stream = stream_;
deadbeef37f5ecf2017-02-27 14:06:41 -0800225 stream_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000226 return stream;
227}
228
229StreamAdapterInterface::~StreamAdapterInterface() {
230 if (owned_)
231 delete stream_;
232}
233
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000234void StreamAdapterInterface::OnEvent(StreamInterface* stream,
235 int events,
236 int err) {
237 SignalEvent(this, events, err);
238}
239
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000240///////////////////////////////////////////////////////////////////////////////
deadbeeff137e972017-03-23 15:45:49 -0700241// StreamTap
242///////////////////////////////////////////////////////////////////////////////
243
244StreamTap::StreamTap(StreamInterface* stream, StreamInterface* tap)
245 : StreamAdapterInterface(stream), tap_(), tap_result_(SR_SUCCESS),
246 tap_error_(0) {
247 AttachTap(tap);
248}
249
250StreamTap::~StreamTap() = default;
251
252void StreamTap::AttachTap(StreamInterface* tap) {
253 tap_.reset(tap);
254}
255
256StreamInterface* StreamTap::DetachTap() {
257 return tap_.release();
258}
259
260StreamResult StreamTap::GetTapResult(int* error) {
261 if (error) {
262 *error = tap_error_;
263 }
264 return tap_result_;
265}
266
267StreamResult StreamTap::Read(void* buffer, size_t buffer_len,
268 size_t* read, int* error) {
269 size_t backup_read;
270 if (!read) {
271 read = &backup_read;
272 }
273 StreamResult res = StreamAdapterInterface::Read(buffer, buffer_len,
274 read, error);
275 if ((res == SR_SUCCESS) && (tap_result_ == SR_SUCCESS)) {
276 tap_result_ = tap_->WriteAll(buffer, *read, nullptr, &tap_error_);
277 }
278 return res;
279}
280
281StreamResult StreamTap::Write(const void* data, size_t data_len,
282 size_t* written, int* error) {
283 size_t backup_written;
284 if (!written) {
285 written = &backup_written;
286 }
287 StreamResult res = StreamAdapterInterface::Write(data, data_len,
288 written, error);
289 if ((res == SR_SUCCESS) && (tap_result_ == SR_SUCCESS)) {
290 tap_result_ = tap_->WriteAll(data, *written, nullptr, &tap_error_);
291 }
292 return res;
293}
294
295///////////////////////////////////////////////////////////////////////////////
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000296// NullStream
297///////////////////////////////////////////////////////////////////////////////
298
299NullStream::NullStream() {
300}
301
302NullStream::~NullStream() {
303}
304
305StreamState NullStream::GetState() const {
306 return SS_OPEN;
307}
308
309StreamResult NullStream::Read(void* buffer, size_t buffer_len,
310 size_t* read, int* error) {
311 if (error) *error = -1;
312 return SR_ERROR;
313}
314
315StreamResult NullStream::Write(const void* data, size_t data_len,
316 size_t* written, int* error) {
317 if (written) *written = data_len;
318 return SR_SUCCESS;
319}
320
321void NullStream::Close() {
322}
323
324///////////////////////////////////////////////////////////////////////////////
325// FileStream
326///////////////////////////////////////////////////////////////////////////////
327
deadbeef37f5ecf2017-02-27 14:06:41 -0800328FileStream::FileStream() : file_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000329
330FileStream::~FileStream() {
331 FileStream::Close();
332}
333
334bool FileStream::Open(const std::string& filename, const char* mode,
335 int* error) {
336 Close();
337#if defined(WEBRTC_WIN)
338 std::wstring wfilename;
339 if (Utf8ToWindowsFilename(filename, &wfilename)) {
340 file_ = _wfopen(wfilename.c_str(), ToUtf16(mode).c_str());
341 } else {
342 if (error) {
343 *error = -1;
344 return false;
345 }
346 }
347#else
348 file_ = fopen(filename.c_str(), mode);
349#endif
350 if (!file_ && error) {
351 *error = errno;
352 }
deadbeef37f5ecf2017-02-27 14:06:41 -0800353 return (file_ != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000354}
355
356bool FileStream::OpenShare(const std::string& filename, const char* mode,
357 int shflag, int* error) {
358 Close();
359#if defined(WEBRTC_WIN)
360 std::wstring wfilename;
361 if (Utf8ToWindowsFilename(filename, &wfilename)) {
362 file_ = _wfsopen(wfilename.c_str(), ToUtf16(mode).c_str(), shflag);
363 if (!file_ && error) {
364 *error = errno;
365 return false;
366 }
deadbeef37f5ecf2017-02-27 14:06:41 -0800367 return file_ != nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000368 } else {
369 if (error) {
370 *error = -1;
371 }
372 return false;
373 }
374#else
375 return Open(filename, mode, error);
376#endif
377}
378
379bool FileStream::DisableBuffering() {
380 if (!file_)
381 return false;
deadbeef37f5ecf2017-02-27 14:06:41 -0800382 return (setvbuf(file_, nullptr, _IONBF, 0) == 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000383}
384
385StreamState FileStream::GetState() const {
deadbeef37f5ecf2017-02-27 14:06:41 -0800386 return (file_ == nullptr) ? SS_CLOSED : SS_OPEN;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000387}
388
389StreamResult FileStream::Read(void* buffer, size_t buffer_len,
390 size_t* read, int* error) {
391 if (!file_)
392 return SR_EOS;
393 size_t result = fread(buffer, 1, buffer_len, file_);
394 if ((result == 0) && (buffer_len > 0)) {
395 if (feof(file_))
396 return SR_EOS;
397 if (error)
398 *error = errno;
399 return SR_ERROR;
400 }
401 if (read)
402 *read = result;
403 return SR_SUCCESS;
404}
405
406StreamResult FileStream::Write(const void* data, size_t data_len,
407 size_t* written, int* error) {
408 if (!file_)
409 return SR_EOS;
410 size_t result = fwrite(data, 1, data_len, file_);
411 if ((result == 0) && (data_len > 0)) {
412 if (error)
413 *error = errno;
414 return SR_ERROR;
415 }
416 if (written)
417 *written = result;
418 return SR_SUCCESS;
419}
420
421void FileStream::Close() {
422 if (file_) {
423 DoClose();
deadbeef37f5ecf2017-02-27 14:06:41 -0800424 file_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000425 }
426}
427
428bool FileStream::SetPosition(size_t position) {
429 if (!file_)
430 return false;
431 return (fseek(file_, static_cast<int>(position), SEEK_SET) == 0);
432}
433
434bool FileStream::GetPosition(size_t* position) const {
deadbeef37f5ecf2017-02-27 14:06:41 -0800435 RTC_DCHECK(nullptr != position);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000436 if (!file_)
437 return false;
438 long result = ftell(file_);
439 if (result < 0)
440 return false;
441 if (position)
442 *position = result;
443 return true;
444}
445
446bool FileStream::GetSize(size_t* size) const {
deadbeef37f5ecf2017-02-27 14:06:41 -0800447 RTC_DCHECK(nullptr != size);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000448 if (!file_)
449 return false;
450 struct stat file_stats;
451 if (fstat(fileno(file_), &file_stats) != 0)
452 return false;
453 if (size)
454 *size = file_stats.st_size;
455 return true;
456}
457
458bool FileStream::GetAvailable(size_t* size) const {
deadbeef37f5ecf2017-02-27 14:06:41 -0800459 RTC_DCHECK(nullptr != size);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000460 if (!GetSize(size))
461 return false;
462 long result = ftell(file_);
463 if (result < 0)
464 return false;
465 if (size)
466 *size -= result;
467 return true;
468}
469
470bool FileStream::ReserveSize(size_t size) {
471 // TODO: extend the file to the proper length
472 return true;
473}
474
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000475bool FileStream::Flush() {
476 if (file_) {
477 return (0 == fflush(file_));
478 }
479 // try to flush empty file?
nissec80e7412017-01-11 05:56:46 -0800480 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000481 return false;
482}
483
484#if defined(WEBRTC_POSIX) && !defined(__native_client__)
485
486bool FileStream::TryLock() {
deadbeef37f5ecf2017-02-27 14:06:41 -0800487 if (file_ == nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000488 // Stream not open.
nissec80e7412017-01-11 05:56:46 -0800489 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000490 return false;
491 }
492
493 return flock(fileno(file_), LOCK_EX|LOCK_NB) == 0;
494}
495
496bool FileStream::Unlock() {
deadbeef37f5ecf2017-02-27 14:06:41 -0800497 if (file_ == nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000498 // Stream not open.
nissec80e7412017-01-11 05:56:46 -0800499 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000500 return false;
501 }
502
503 return flock(fileno(file_), LOCK_UN) == 0;
504}
505
506#endif
507
508void FileStream::DoClose() {
509 fclose(file_);
510}
511
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000512///////////////////////////////////////////////////////////////////////////////
513// MemoryStream
514///////////////////////////////////////////////////////////////////////////////
515
516MemoryStreamBase::MemoryStreamBase()
deadbeef37f5ecf2017-02-27 14:06:41 -0800517 : buffer_(nullptr), buffer_length_(0), data_length_(0), seek_position_(0) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000518
519StreamState MemoryStreamBase::GetState() const {
520 return SS_OPEN;
521}
522
523StreamResult MemoryStreamBase::Read(void* buffer, size_t bytes,
524 size_t* bytes_read, int* error) {
525 if (seek_position_ >= data_length_) {
526 return SR_EOS;
527 }
528 size_t available = data_length_ - seek_position_;
529 if (bytes > available) {
530 // Read partial buffer
531 bytes = available;
532 }
533 memcpy(buffer, &buffer_[seek_position_], bytes);
534 seek_position_ += bytes;
535 if (bytes_read) {
536 *bytes_read = bytes;
537 }
538 return SR_SUCCESS;
539}
540
541StreamResult MemoryStreamBase::Write(const void* buffer, size_t bytes,
542 size_t* bytes_written, int* error) {
543 size_t available = buffer_length_ - seek_position_;
544 if (0 == available) {
545 // Increase buffer size to the larger of:
546 // a) new position rounded up to next 256 bytes
547 // b) double the previous length
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000548 size_t new_buffer_length =
549 std::max(((seek_position_ + bytes) | 0xFF) + 1, buffer_length_ * 2);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000550 StreamResult result = DoReserve(new_buffer_length, error);
551 if (SR_SUCCESS != result) {
552 return result;
553 }
nisseede5da42017-01-12 05:15:36 -0800554 RTC_DCHECK(buffer_length_ >= new_buffer_length);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000555 available = buffer_length_ - seek_position_;
556 }
557
558 if (bytes > available) {
559 bytes = available;
560 }
561 memcpy(&buffer_[seek_position_], buffer, bytes);
562 seek_position_ += bytes;
563 if (data_length_ < seek_position_) {
564 data_length_ = seek_position_;
565 }
566 if (bytes_written) {
567 *bytes_written = bytes;
568 }
569 return SR_SUCCESS;
570}
571
572void MemoryStreamBase::Close() {
573 // nothing to do
574}
575
576bool MemoryStreamBase::SetPosition(size_t position) {
577 if (position > data_length_)
578 return false;
579 seek_position_ = position;
580 return true;
581}
582
583bool MemoryStreamBase::GetPosition(size_t* position) const {
584 if (position)
585 *position = seek_position_;
586 return true;
587}
588
589bool MemoryStreamBase::GetSize(size_t* size) const {
590 if (size)
591 *size = data_length_;
592 return true;
593}
594
595bool MemoryStreamBase::GetAvailable(size_t* size) const {
596 if (size)
597 *size = data_length_ - seek_position_;
598 return true;
599}
600
601bool MemoryStreamBase::ReserveSize(size_t size) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800602 return (SR_SUCCESS == DoReserve(size, nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000603}
604
605StreamResult MemoryStreamBase::DoReserve(size_t size, int* error) {
606 return (buffer_length_ >= size) ? SR_SUCCESS : SR_EOS;
607}
608
609///////////////////////////////////////////////////////////////////////////////
610
deadbeef37f5ecf2017-02-27 14:06:41 -0800611MemoryStream::MemoryStream() : buffer_alloc_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000612
deadbeef37f5ecf2017-02-27 14:06:41 -0800613MemoryStream::MemoryStream(const char* data) : buffer_alloc_(nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000614 SetData(data, strlen(data));
615}
616
617MemoryStream::MemoryStream(const void* data, size_t length)
deadbeef37f5ecf2017-02-27 14:06:41 -0800618 : buffer_alloc_(nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000619 SetData(data, length);
620}
621
622MemoryStream::~MemoryStream() {
623 delete [] buffer_alloc_;
624}
625
626void MemoryStream::SetData(const void* data, size_t length) {
627 data_length_ = buffer_length_ = length;
628 delete [] buffer_alloc_;
629 buffer_alloc_ = new char[buffer_length_ + kAlignment];
630 buffer_ = reinterpret_cast<char*>(ALIGNP(buffer_alloc_, kAlignment));
631 memcpy(buffer_, data, data_length_);
632 seek_position_ = 0;
633}
634
635StreamResult MemoryStream::DoReserve(size_t size, int* error) {
636 if (buffer_length_ >= size)
637 return SR_SUCCESS;
638
639 if (char* new_buffer_alloc = new char[size + kAlignment]) {
640 char* new_buffer = reinterpret_cast<char*>(
641 ALIGNP(new_buffer_alloc, kAlignment));
642 memcpy(new_buffer, buffer_, data_length_);
643 delete [] buffer_alloc_;
644 buffer_alloc_ = new_buffer_alloc;
645 buffer_ = new_buffer;
646 buffer_length_ = size;
647 return SR_SUCCESS;
648 }
649
650 if (error) {
651 *error = ENOMEM;
652 }
653 return SR_ERROR;
654}
655
656///////////////////////////////////////////////////////////////////////////////
deadbeeff137e972017-03-23 15:45:49 -0700657
658ExternalMemoryStream::ExternalMemoryStream() {
659}
660
661ExternalMemoryStream::ExternalMemoryStream(void* data, size_t length) {
662 SetData(data, length);
663}
664
665ExternalMemoryStream::~ExternalMemoryStream() {
666}
667
668void ExternalMemoryStream::SetData(void* data, size_t length) {
669 data_length_ = buffer_length_ = length;
670 buffer_ = static_cast<char*>(data);
671 seek_position_ = 0;
672}
673
674///////////////////////////////////////////////////////////////////////////////
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000675// FifoBuffer
676///////////////////////////////////////////////////////////////////////////////
677
678FifoBuffer::FifoBuffer(size_t size)
679 : state_(SS_OPEN), buffer_(new char[size]), buffer_length_(size),
680 data_length_(0), read_position_(0), owner_(Thread::Current()) {
681 // all events are done on the owner_ thread
682}
683
684FifoBuffer::FifoBuffer(size_t size, Thread* owner)
685 : state_(SS_OPEN), buffer_(new char[size]), buffer_length_(size),
686 data_length_(0), read_position_(0), owner_(owner) {
687 // all events are done on the owner_ thread
688}
689
690FifoBuffer::~FifoBuffer() {
691}
692
693bool FifoBuffer::GetBuffered(size_t* size) const {
694 CritScope cs(&crit_);
695 *size = data_length_;
696 return true;
697}
698
699bool FifoBuffer::SetCapacity(size_t size) {
700 CritScope cs(&crit_);
701 if (data_length_ > size) {
702 return false;
703 }
704
705 if (size != buffer_length_) {
706 char* buffer = new char[size];
707 const size_t copy = data_length_;
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000708 const size_t tail_copy = std::min(copy, buffer_length_ - read_position_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000709 memcpy(buffer, &buffer_[read_position_], tail_copy);
710 memcpy(buffer + tail_copy, &buffer_[0], copy - tail_copy);
711 buffer_.reset(buffer);
712 read_position_ = 0;
713 buffer_length_ = size;
714 }
715 return true;
716}
717
718StreamResult FifoBuffer::ReadOffset(void* buffer, size_t bytes,
719 size_t offset, size_t* bytes_read) {
720 CritScope cs(&crit_);
721 return ReadOffsetLocked(buffer, bytes, offset, bytes_read);
722}
723
724StreamResult FifoBuffer::WriteOffset(const void* buffer, size_t bytes,
725 size_t offset, size_t* bytes_written) {
726 CritScope cs(&crit_);
727 return WriteOffsetLocked(buffer, bytes, offset, bytes_written);
728}
729
730StreamState FifoBuffer::GetState() const {
jbauch097d5492016-02-09 02:30:34 -0800731 CritScope cs(&crit_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000732 return state_;
733}
734
735StreamResult FifoBuffer::Read(void* buffer, size_t bytes,
736 size_t* bytes_read, int* error) {
737 CritScope cs(&crit_);
738 const bool was_writable = data_length_ < buffer_length_;
739 size_t copy = 0;
740 StreamResult result = ReadOffsetLocked(buffer, bytes, 0, &copy);
741
742 if (result == SR_SUCCESS) {
743 // If read was successful then adjust the read position and number of
744 // bytes buffered.
745 read_position_ = (read_position_ + copy) % buffer_length_;
746 data_length_ -= copy;
747 if (bytes_read) {
748 *bytes_read = copy;
749 }
750
751 // if we were full before, and now we're not, post an event
752 if (!was_writable && copy > 0) {
753 PostEvent(owner_, SE_WRITE, 0);
754 }
755 }
756 return result;
757}
758
759StreamResult FifoBuffer::Write(const void* buffer, size_t bytes,
760 size_t* bytes_written, int* error) {
761 CritScope cs(&crit_);
762
763 const bool was_readable = (data_length_ > 0);
764 size_t copy = 0;
765 StreamResult result = WriteOffsetLocked(buffer, bytes, 0, &copy);
766
767 if (result == SR_SUCCESS) {
768 // If write was successful then adjust the number of readable bytes.
769 data_length_ += copy;
770 if (bytes_written) {
771 *bytes_written = copy;
772 }
773
774 // if we didn't have any data to read before, and now we do, post an event
775 if (!was_readable && copy > 0) {
776 PostEvent(owner_, SE_READ, 0);
777 }
778 }
779 return result;
780}
781
782void FifoBuffer::Close() {
783 CritScope cs(&crit_);
784 state_ = SS_CLOSED;
785}
786
787const void* FifoBuffer::GetReadData(size_t* size) {
788 CritScope cs(&crit_);
789 *size = (read_position_ + data_length_ <= buffer_length_) ?
790 data_length_ : buffer_length_ - read_position_;
791 return &buffer_[read_position_];
792}
793
794void FifoBuffer::ConsumeReadData(size_t size) {
795 CritScope cs(&crit_);
nisseede5da42017-01-12 05:15:36 -0800796 RTC_DCHECK(size <= data_length_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000797 const bool was_writable = data_length_ < buffer_length_;
798 read_position_ = (read_position_ + size) % buffer_length_;
799 data_length_ -= size;
800 if (!was_writable && size > 0) {
801 PostEvent(owner_, SE_WRITE, 0);
802 }
803}
804
805void* FifoBuffer::GetWriteBuffer(size_t* size) {
806 CritScope cs(&crit_);
807 if (state_ == SS_CLOSED) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800808 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000809 }
810
811 // if empty, reset the write position to the beginning, so we can get
812 // the biggest possible block
813 if (data_length_ == 0) {
814 read_position_ = 0;
815 }
816
817 const size_t write_position = (read_position_ + data_length_)
818 % buffer_length_;
819 *size = (write_position > read_position_ || data_length_ == 0) ?
820 buffer_length_ - write_position : read_position_ - write_position;
821 return &buffer_[write_position];
822}
823
824void FifoBuffer::ConsumeWriteBuffer(size_t size) {
825 CritScope cs(&crit_);
nisseede5da42017-01-12 05:15:36 -0800826 RTC_DCHECK(size <= buffer_length_ - data_length_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000827 const bool was_readable = (data_length_ > 0);
828 data_length_ += size;
829 if (!was_readable && size > 0) {
830 PostEvent(owner_, SE_READ, 0);
831 }
832}
833
834bool FifoBuffer::GetWriteRemaining(size_t* size) const {
835 CritScope cs(&crit_);
836 *size = buffer_length_ - data_length_;
837 return true;
838}
839
840StreamResult FifoBuffer::ReadOffsetLocked(void* buffer,
841 size_t bytes,
842 size_t offset,
843 size_t* bytes_read) {
844 if (offset >= data_length_) {
845 return (state_ != SS_CLOSED) ? SR_BLOCK : SR_EOS;
846 }
847
848 const size_t available = data_length_ - offset;
849 const size_t read_position = (read_position_ + offset) % buffer_length_;
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000850 const size_t copy = std::min(bytes, available);
851 const size_t tail_copy = std::min(copy, buffer_length_ - read_position);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000852 char* const p = static_cast<char*>(buffer);
853 memcpy(p, &buffer_[read_position], tail_copy);
854 memcpy(p + tail_copy, &buffer_[0], copy - tail_copy);
855
856 if (bytes_read) {
857 *bytes_read = copy;
858 }
859 return SR_SUCCESS;
860}
861
862StreamResult FifoBuffer::WriteOffsetLocked(const void* buffer,
863 size_t bytes,
864 size_t offset,
865 size_t* bytes_written) {
866 if (state_ == SS_CLOSED) {
867 return SR_EOS;
868 }
869
870 if (data_length_ + offset >= buffer_length_) {
871 return SR_BLOCK;
872 }
873
874 const size_t available = buffer_length_ - data_length_ - offset;
875 const size_t write_position = (read_position_ + data_length_ + offset)
876 % buffer_length_;
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000877 const size_t copy = std::min(bytes, available);
878 const size_t tail_copy = std::min(copy, buffer_length_ - write_position);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000879 const char* const p = static_cast<const char*>(buffer);
880 memcpy(&buffer_[write_position], p, tail_copy);
881 memcpy(&buffer_[0], p + tail_copy, copy - tail_copy);
882
883 if (bytes_written) {
884 *bytes_written = copy;
885 }
886 return SR_SUCCESS;
887}
888
deadbeeff137e972017-03-23 15:45:49 -0700889
890
891///////////////////////////////////////////////////////////////////////////////
892// LoggingAdapter
893///////////////////////////////////////////////////////////////////////////////
894
895LoggingAdapter::LoggingAdapter(StreamInterface* stream, LoggingSeverity level,
896 const std::string& label, bool hex_mode)
897 : StreamAdapterInterface(stream), level_(level), hex_mode_(hex_mode) {
898 set_label(label);
899}
900
901void LoggingAdapter::set_label(const std::string& label) {
902 label_.assign("[");
903 label_.append(label);
904 label_.append("]");
905}
906
907StreamResult LoggingAdapter::Read(void* buffer, size_t buffer_len,
908 size_t* read, int* error) {
909 size_t local_read; if (!read) read = &local_read;
910 StreamResult result = StreamAdapterInterface::Read(buffer, buffer_len, read,
911 error);
912 if (result == SR_SUCCESS) {
913 LogMultiline(level_, label_.c_str(), true, buffer, *read, hex_mode_, &lms_);
914 }
915 return result;
916}
917
918StreamResult LoggingAdapter::Write(const void* data, size_t data_len,
919 size_t* written, int* error) {
920 size_t local_written;
921 if (!written) written = &local_written;
922 StreamResult result = StreamAdapterInterface::Write(data, data_len, written,
923 error);
924 if (result == SR_SUCCESS) {
925 LogMultiline(level_, label_.c_str(), false, data, *written, hex_mode_,
926 &lms_);
927 }
928 return result;
929}
930
931void LoggingAdapter::Close() {
932 LogMultiline(level_, label_.c_str(), false, nullptr, 0, hex_mode_, &lms_);
933 LogMultiline(level_, label_.c_str(), true, nullptr, 0, hex_mode_, &lms_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100934 RTC_LOG_V(level_) << label_ << " Closed locally";
deadbeeff137e972017-03-23 15:45:49 -0700935 StreamAdapterInterface::Close();
936}
937
938void LoggingAdapter::OnEvent(StreamInterface* stream, int events, int err) {
939 if (events & SE_OPEN) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100940 RTC_LOG_V(level_) << label_ << " Open";
deadbeeff137e972017-03-23 15:45:49 -0700941 } else if (events & SE_CLOSE) {
942 LogMultiline(level_, label_.c_str(), false, nullptr, 0, hex_mode_, &lms_);
943 LogMultiline(level_, label_.c_str(), true, nullptr, 0, hex_mode_, &lms_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100944 RTC_LOG_V(level_) << label_ << " Closed with error: " << err;
deadbeeff137e972017-03-23 15:45:49 -0700945 }
946 StreamAdapterInterface::OnEvent(stream, events, err);
947}
948
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000949///////////////////////////////////////////////////////////////////////////////
950// StringStream - Reads/Writes to an external std::string
951///////////////////////////////////////////////////////////////////////////////
952
Tommi00aac5a2015-05-25 11:25:59 +0200953StringStream::StringStream(std::string* str)
954 : str_(*str), read_pos_(0), read_only_(false) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000955}
956
957StringStream::StringStream(const std::string& str)
958 : str_(const_cast<std::string&>(str)), read_pos_(0), read_only_(true) {
959}
960
961StreamState StringStream::GetState() const {
962 return SS_OPEN;
963}
964
965StreamResult StringStream::Read(void* buffer, size_t buffer_len,
966 size_t* read, int* error) {
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000967 size_t available = std::min(buffer_len, str_.size() - read_pos_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000968 if (!available)
969 return SR_EOS;
970 memcpy(buffer, str_.data() + read_pos_, available);
971 read_pos_ += available;
972 if (read)
973 *read = available;
974 return SR_SUCCESS;
975}
976
977StreamResult StringStream::Write(const void* data, size_t data_len,
978 size_t* written, int* error) {
979 if (read_only_) {
980 if (error) {
981 *error = -1;
982 }
983 return SR_ERROR;
984 }
985 str_.append(static_cast<const char*>(data),
986 static_cast<const char*>(data) + data_len);
987 if (written)
988 *written = data_len;
989 return SR_SUCCESS;
990}
991
992void StringStream::Close() {
993}
994
995bool StringStream::SetPosition(size_t position) {
996 if (position > str_.size())
997 return false;
998 read_pos_ = position;
999 return true;
1000}
1001
1002bool StringStream::GetPosition(size_t* position) const {
1003 if (position)
1004 *position = read_pos_;
1005 return true;
1006}
1007
1008bool StringStream::GetSize(size_t* size) const {
1009 if (size)
1010 *size = str_.size();
1011 return true;
1012}
1013
1014bool StringStream::GetAvailable(size_t* size) const {
1015 if (size)
1016 *size = str_.size() - read_pos_;
1017 return true;
1018}
1019
1020bool StringStream::ReserveSize(size_t size) {
1021 if (read_only_)
1022 return false;
1023 str_.reserve(size);
1024 return true;
1025}
1026
1027///////////////////////////////////////////////////////////////////////////////
deadbeeff137e972017-03-23 15:45:49 -07001028// StreamReference
1029///////////////////////////////////////////////////////////////////////////////
1030
1031StreamReference::StreamReference(StreamInterface* stream)
1032 : StreamAdapterInterface(stream, false) {
1033 // owner set to false so the destructor does not free the stream.
1034 stream_ref_count_ = new StreamRefCount(stream);
1035}
1036
1037StreamInterface* StreamReference::NewReference() {
1038 stream_ref_count_->AddReference();
1039 return new StreamReference(stream_ref_count_, stream());
1040}
1041
1042StreamReference::~StreamReference() {
1043 stream_ref_count_->Release();
1044}
1045
1046StreamReference::StreamReference(StreamRefCount* stream_ref_count,
1047 StreamInterface* stream)
1048 : StreamAdapterInterface(stream, false),
1049 stream_ref_count_(stream_ref_count) {
1050}
1051
1052///////////////////////////////////////////////////////////////////////////////
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001053
1054StreamResult Flow(StreamInterface* source,
deadbeef37f5ecf2017-02-27 14:06:41 -08001055 char* buffer,
1056 size_t buffer_len,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001057 StreamInterface* sink,
deadbeef37f5ecf2017-02-27 14:06:41 -08001058 size_t* data_len /* = nullptr */) {
nisseede5da42017-01-12 05:15:36 -08001059 RTC_DCHECK(buffer_len > 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001060
1061 StreamResult result;
1062 size_t count, read_pos, write_pos;
1063 if (data_len) {
1064 read_pos = *data_len;
1065 } else {
1066 read_pos = 0;
1067 }
1068
1069 bool end_of_stream = false;
1070 do {
1071 // Read until buffer is full, end of stream, or error
1072 while (!end_of_stream && (read_pos < buffer_len)) {
deadbeef37f5ecf2017-02-27 14:06:41 -08001073 result = source->Read(buffer + read_pos, buffer_len - read_pos, &count,
1074 nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001075 if (result == SR_EOS) {
1076 end_of_stream = true;
1077 } else if (result != SR_SUCCESS) {
1078 if (data_len) {
1079 *data_len = read_pos;
1080 }
1081 return result;
1082 } else {
1083 read_pos += count;
1084 }
1085 }
1086
1087 // Write until buffer is empty, or error (including end of stream)
1088 write_pos = 0;
1089 while (write_pos < read_pos) {
deadbeef37f5ecf2017-02-27 14:06:41 -08001090 result = sink->Write(buffer + write_pos, read_pos - write_pos, &count,
1091 nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001092 if (result != SR_SUCCESS) {
1093 if (data_len) {
1094 *data_len = read_pos - write_pos;
1095 if (write_pos > 0) {
1096 memmove(buffer, buffer + write_pos, *data_len);
1097 }
1098 }
1099 return result;
1100 }
1101 write_pos += count;
1102 }
1103
1104 read_pos = 0;
1105 } while (!end_of_stream);
1106
1107 if (data_len) {
1108 *data_len = 0;
1109 }
1110 return SR_SUCCESS;
1111}
1112
1113///////////////////////////////////////////////////////////////////////////////
1114
1115} // namespace rtc