blob: 56c848a139fefa1f31e0ef542e8e8eb70b782e0e [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
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000014#include <errno.h>
Yves Gerey665174f2018-06-19 15:03:05 +020015#include <sys/stat.h>
16#include <sys/types.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/checks.h"
22#include "rtc_base/logging.h"
23#include "rtc_base/messagequeue.h"
24#include "rtc_base/stream.h"
25#include "rtc_base/stringencode.h"
26#include "rtc_base/stringutils.h"
27#include "rtc_base/thread.h"
28#include "rtc_base/timeutils.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000029
30#if defined(WEBRTC_WIN)
Patrik Höglunda8005cf2017-12-13 16:05:42 +010031#include <windows.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032#define fileno _fileno
33#endif
34
35namespace rtc {
36
37///////////////////////////////////////////////////////////////////////////////
38// StreamInterface
39///////////////////////////////////////////////////////////////////////////////
Yves Gerey665174f2018-06-19 15:03:05 +020040StreamInterface::~StreamInterface() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000041
Yves Gerey665174f2018-06-19 15:03:05 +020042StreamResult StreamInterface::WriteAll(const void* data,
43 size_t data_len,
44 size_t* written,
45 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000046 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
Yves Gerey665174f2018-06-19 15:03:05 +020060StreamResult StreamInterface::ReadAll(void* buffer,
61 size_t buffer_len,
62 size_t* read,
63 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000064 StreamResult result = SR_SUCCESS;
65 size_t total_read = 0, current_read;
66 while (total_read < buffer_len) {
67 result = Read(static_cast<char*>(buffer) + total_read,
68 buffer_len - total_read, &current_read, error);
69 if (result != SR_SUCCESS)
70 break;
71 total_read += current_read;
72 }
73 if (read)
74 *read = total_read;
75 return result;
76}
77
78StreamResult StreamInterface::ReadLine(std::string* line) {
79 line->clear();
80 StreamResult result = SR_SUCCESS;
81 while (true) {
82 char ch;
deadbeef37f5ecf2017-02-27 14:06:41 -080083 result = Read(&ch, sizeof(ch), nullptr, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000084 if (result != SR_SUCCESS) {
85 break;
86 }
87 if (ch == '\n') {
88 break;
89 }
90 line->push_back(ch);
91 }
92 if (!line->empty()) { // give back the line we've collected so far with
93 result = SR_SUCCESS; // a success code. Otherwise return the last code
94 }
95 return result;
96}
97
98void StreamInterface::PostEvent(Thread* t, int events, int err) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070099 t->Post(RTC_FROM_HERE, this, MSG_POST_EVENT,
100 new StreamEventData(events, err));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000101}
102
103void StreamInterface::PostEvent(int events, int err) {
104 PostEvent(Thread::Current(), events, err);
105}
106
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000107const void* StreamInterface::GetReadData(size_t* data_len) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800108 return nullptr;
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000109}
110
111void* StreamInterface::GetWriteBuffer(size_t* buf_len) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800112 return nullptr;
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000113}
114
115bool StreamInterface::SetPosition(size_t position) {
116 return false;
117}
118
119bool StreamInterface::GetPosition(size_t* position) const {
120 return false;
121}
122
123bool StreamInterface::GetSize(size_t* size) const {
124 return false;
125}
126
127bool StreamInterface::GetAvailable(size_t* size) const {
128 return false;
129}
130
131bool StreamInterface::GetWriteRemaining(size_t* size) const {
132 return false;
133}
134
135bool StreamInterface::Flush() {
136 return false;
137}
138
139bool StreamInterface::ReserveSize(size_t size) {
140 return true;
141}
142
Yves Gerey665174f2018-06-19 15:03:05 +0200143StreamInterface::StreamInterface() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000144
145void StreamInterface::OnMessage(Message* msg) {
146 if (MSG_POST_EVENT == msg->message_id) {
147 StreamEventData* pe = static_cast<StreamEventData*>(msg->pdata);
148 SignalEvent(this, pe->events, pe->error);
149 delete msg->pdata;
150 }
151}
152
153///////////////////////////////////////////////////////////////////////////////
154// StreamAdapterInterface
155///////////////////////////////////////////////////////////////////////////////
156
157StreamAdapterInterface::StreamAdapterInterface(StreamInterface* stream,
158 bool owned)
159 : stream_(stream), owned_(owned) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800160 if (nullptr != stream_)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000161 stream_->SignalEvent.connect(this, &StreamAdapterInterface::OnEvent);
162}
163
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000164StreamState StreamAdapterInterface::GetState() const {
165 return stream_->GetState();
166}
167StreamResult StreamAdapterInterface::Read(void* buffer,
168 size_t buffer_len,
169 size_t* read,
170 int* error) {
171 return stream_->Read(buffer, buffer_len, read, error);
172}
173StreamResult StreamAdapterInterface::Write(const void* data,
174 size_t data_len,
175 size_t* written,
176 int* error) {
177 return stream_->Write(data, data_len, written, error);
178}
179void StreamAdapterInterface::Close() {
180 stream_->Close();
181}
182
183bool StreamAdapterInterface::SetPosition(size_t position) {
184 return stream_->SetPosition(position);
185}
186
187bool StreamAdapterInterface::GetPosition(size_t* position) const {
188 return stream_->GetPosition(position);
189}
190
191bool StreamAdapterInterface::GetSize(size_t* size) const {
192 return stream_->GetSize(size);
193}
194
195bool StreamAdapterInterface::GetAvailable(size_t* size) const {
196 return stream_->GetAvailable(size);
197}
198
199bool StreamAdapterInterface::GetWriteRemaining(size_t* size) const {
200 return stream_->GetWriteRemaining(size);
201}
202
203bool StreamAdapterInterface::ReserveSize(size_t size) {
204 return stream_->ReserveSize(size);
205}
206
207bool StreamAdapterInterface::Flush() {
208 return stream_->Flush();
209}
210
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000211void StreamAdapterInterface::Attach(StreamInterface* stream, bool owned) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800212 if (nullptr != stream_)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000213 stream_->SignalEvent.disconnect(this);
214 if (owned_)
215 delete stream_;
216 stream_ = stream;
217 owned_ = owned;
deadbeef37f5ecf2017-02-27 14:06:41 -0800218 if (nullptr != stream_)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000219 stream_->SignalEvent.connect(this, &StreamAdapterInterface::OnEvent);
220}
221
222StreamInterface* StreamAdapterInterface::Detach() {
deadbeef37f5ecf2017-02-27 14:06:41 -0800223 if (nullptr != stream_)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000224 stream_->SignalEvent.disconnect(this);
225 StreamInterface* stream = stream_;
deadbeef37f5ecf2017-02-27 14:06:41 -0800226 stream_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000227 return stream;
228}
229
230StreamAdapterInterface::~StreamAdapterInterface() {
231 if (owned_)
232 delete stream_;
233}
234
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000235void StreamAdapterInterface::OnEvent(StreamInterface* stream,
236 int events,
237 int err) {
238 SignalEvent(this, events, err);
239}
240
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000241///////////////////////////////////////////////////////////////////////////////
deadbeeff137e972017-03-23 15:45:49 -0700242// StreamTap
243///////////////////////////////////////////////////////////////////////////////
244
245StreamTap::StreamTap(StreamInterface* stream, StreamInterface* tap)
Yves Gerey665174f2018-06-19 15:03:05 +0200246 : StreamAdapterInterface(stream),
247 tap_(),
248 tap_result_(SR_SUCCESS),
249 tap_error_(0) {
deadbeeff137e972017-03-23 15:45:49 -0700250 AttachTap(tap);
251}
252
253StreamTap::~StreamTap() = default;
254
255void StreamTap::AttachTap(StreamInterface* tap) {
256 tap_.reset(tap);
257}
258
259StreamInterface* StreamTap::DetachTap() {
260 return tap_.release();
261}
262
263StreamResult StreamTap::GetTapResult(int* error) {
264 if (error) {
265 *error = tap_error_;
266 }
267 return tap_result_;
268}
269
Yves Gerey665174f2018-06-19 15:03:05 +0200270StreamResult StreamTap::Read(void* buffer,
271 size_t buffer_len,
272 size_t* read,
273 int* error) {
deadbeeff137e972017-03-23 15:45:49 -0700274 size_t backup_read;
275 if (!read) {
276 read = &backup_read;
277 }
Yves Gerey665174f2018-06-19 15:03:05 +0200278 StreamResult res =
279 StreamAdapterInterface::Read(buffer, buffer_len, read, error);
deadbeeff137e972017-03-23 15:45:49 -0700280 if ((res == SR_SUCCESS) && (tap_result_ == SR_SUCCESS)) {
281 tap_result_ = tap_->WriteAll(buffer, *read, nullptr, &tap_error_);
282 }
283 return res;
284}
285
Yves Gerey665174f2018-06-19 15:03:05 +0200286StreamResult StreamTap::Write(const void* data,
287 size_t data_len,
288 size_t* written,
289 int* error) {
deadbeeff137e972017-03-23 15:45:49 -0700290 size_t backup_written;
291 if (!written) {
292 written = &backup_written;
293 }
Yves Gerey665174f2018-06-19 15:03:05 +0200294 StreamResult res =
295 StreamAdapterInterface::Write(data, data_len, written, error);
deadbeeff137e972017-03-23 15:45:49 -0700296 if ((res == SR_SUCCESS) && (tap_result_ == SR_SUCCESS)) {
297 tap_result_ = tap_->WriteAll(data, *written, nullptr, &tap_error_);
298 }
299 return res;
300}
301
302///////////////////////////////////////////////////////////////////////////////
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000303// NullStream
304///////////////////////////////////////////////////////////////////////////////
305
Yves Gerey665174f2018-06-19 15:03:05 +0200306NullStream::NullStream() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000307
Yves Gerey665174f2018-06-19 15:03:05 +0200308NullStream::~NullStream() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000309
310StreamState NullStream::GetState() const {
311 return SS_OPEN;
312}
313
Yves Gerey665174f2018-06-19 15:03:05 +0200314StreamResult NullStream::Read(void* buffer,
315 size_t buffer_len,
316 size_t* read,
317 int* error) {
318 if (error)
319 *error = -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000320 return SR_ERROR;
321}
322
Yves Gerey665174f2018-06-19 15:03:05 +0200323StreamResult NullStream::Write(const void* data,
324 size_t data_len,
325 size_t* written,
326 int* error) {
327 if (written)
328 *written = data_len;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000329 return SR_SUCCESS;
330}
331
Yves Gerey665174f2018-06-19 15:03:05 +0200332void NullStream::Close() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000333
334///////////////////////////////////////////////////////////////////////////////
335// FileStream
336///////////////////////////////////////////////////////////////////////////////
337
deadbeef37f5ecf2017-02-27 14:06:41 -0800338FileStream::FileStream() : file_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000339
340FileStream::~FileStream() {
341 FileStream::Close();
342}
343
Yves Gerey665174f2018-06-19 15:03:05 +0200344bool FileStream::Open(const std::string& filename,
345 const char* mode,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000346 int* error) {
347 Close();
348#if defined(WEBRTC_WIN)
349 std::wstring wfilename;
350 if (Utf8ToWindowsFilename(filename, &wfilename)) {
351 file_ = _wfopen(wfilename.c_str(), ToUtf16(mode).c_str());
352 } else {
353 if (error) {
354 *error = -1;
355 return false;
356 }
357 }
358#else
359 file_ = fopen(filename.c_str(), mode);
360#endif
361 if (!file_ && error) {
362 *error = errno;
363 }
deadbeef37f5ecf2017-02-27 14:06:41 -0800364 return (file_ != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000365}
366
Yves Gerey665174f2018-06-19 15:03:05 +0200367bool FileStream::OpenShare(const std::string& filename,
368 const char* mode,
369 int shflag,
370 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000371 Close();
372#if defined(WEBRTC_WIN)
373 std::wstring wfilename;
374 if (Utf8ToWindowsFilename(filename, &wfilename)) {
375 file_ = _wfsopen(wfilename.c_str(), ToUtf16(mode).c_str(), shflag);
376 if (!file_ && error) {
377 *error = errno;
378 return false;
379 }
deadbeef37f5ecf2017-02-27 14:06:41 -0800380 return file_ != nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000381 } else {
382 if (error) {
383 *error = -1;
384 }
385 return false;
386 }
387#else
388 return Open(filename, mode, error);
389#endif
390}
391
392bool FileStream::DisableBuffering() {
393 if (!file_)
394 return false;
deadbeef37f5ecf2017-02-27 14:06:41 -0800395 return (setvbuf(file_, nullptr, _IONBF, 0) == 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000396}
397
398StreamState FileStream::GetState() const {
deadbeef37f5ecf2017-02-27 14:06:41 -0800399 return (file_ == nullptr) ? SS_CLOSED : SS_OPEN;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000400}
401
Yves Gerey665174f2018-06-19 15:03:05 +0200402StreamResult FileStream::Read(void* buffer,
403 size_t buffer_len,
404 size_t* read,
405 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000406 if (!file_)
407 return SR_EOS;
408 size_t result = fread(buffer, 1, buffer_len, file_);
409 if ((result == 0) && (buffer_len > 0)) {
410 if (feof(file_))
411 return SR_EOS;
412 if (error)
413 *error = errno;
414 return SR_ERROR;
415 }
416 if (read)
417 *read = result;
418 return SR_SUCCESS;
419}
420
Yves Gerey665174f2018-06-19 15:03:05 +0200421StreamResult FileStream::Write(const void* data,
422 size_t data_len,
423 size_t* written,
424 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000425 if (!file_)
426 return SR_EOS;
427 size_t result = fwrite(data, 1, data_len, file_);
428 if ((result == 0) && (data_len > 0)) {
429 if (error)
430 *error = errno;
431 return SR_ERROR;
432 }
433 if (written)
434 *written = result;
435 return SR_SUCCESS;
436}
437
438void FileStream::Close() {
439 if (file_) {
440 DoClose();
deadbeef37f5ecf2017-02-27 14:06:41 -0800441 file_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000442 }
443}
444
445bool FileStream::SetPosition(size_t position) {
446 if (!file_)
447 return false;
448 return (fseek(file_, static_cast<int>(position), SEEK_SET) == 0);
449}
450
451bool FileStream::GetPosition(size_t* position) const {
deadbeef37f5ecf2017-02-27 14:06:41 -0800452 RTC_DCHECK(nullptr != position);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000453 if (!file_)
454 return false;
455 long result = ftell(file_);
456 if (result < 0)
457 return false;
458 if (position)
459 *position = result;
460 return true;
461}
462
463bool FileStream::GetSize(size_t* size) const {
deadbeef37f5ecf2017-02-27 14:06:41 -0800464 RTC_DCHECK(nullptr != size);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000465 if (!file_)
466 return false;
467 struct stat file_stats;
468 if (fstat(fileno(file_), &file_stats) != 0)
469 return false;
470 if (size)
471 *size = file_stats.st_size;
472 return true;
473}
474
475bool FileStream::GetAvailable(size_t* size) const {
deadbeef37f5ecf2017-02-27 14:06:41 -0800476 RTC_DCHECK(nullptr != size);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000477 if (!GetSize(size))
478 return false;
479 long result = ftell(file_);
480 if (result < 0)
481 return false;
482 if (size)
483 *size -= result;
484 return true;
485}
486
487bool FileStream::ReserveSize(size_t size) {
488 // TODO: extend the file to the proper length
489 return true;
490}
491
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000492bool FileStream::Flush() {
493 if (file_) {
494 return (0 == fflush(file_));
495 }
496 // try to flush empty file?
nissec80e7412017-01-11 05:56:46 -0800497 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000498 return false;
499}
500
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000501void FileStream::DoClose() {
502 fclose(file_);
503}
504
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000505///////////////////////////////////////////////////////////////////////////////
506// MemoryStream
507///////////////////////////////////////////////////////////////////////////////
508
509MemoryStreamBase::MemoryStreamBase()
deadbeef37f5ecf2017-02-27 14:06:41 -0800510 : buffer_(nullptr), buffer_length_(0), data_length_(0), seek_position_(0) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000511
512StreamState MemoryStreamBase::GetState() const {
513 return SS_OPEN;
514}
515
Yves Gerey665174f2018-06-19 15:03:05 +0200516StreamResult MemoryStreamBase::Read(void* buffer,
517 size_t bytes,
518 size_t* bytes_read,
519 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000520 if (seek_position_ >= data_length_) {
521 return SR_EOS;
522 }
523 size_t available = data_length_ - seek_position_;
524 if (bytes > available) {
525 // Read partial buffer
526 bytes = available;
527 }
528 memcpy(buffer, &buffer_[seek_position_], bytes);
529 seek_position_ += bytes;
530 if (bytes_read) {
531 *bytes_read = bytes;
532 }
533 return SR_SUCCESS;
534}
535
Yves Gerey665174f2018-06-19 15:03:05 +0200536StreamResult MemoryStreamBase::Write(const void* buffer,
537 size_t bytes,
538 size_t* bytes_written,
539 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000540 size_t available = buffer_length_ - seek_position_;
541 if (0 == available) {
542 // Increase buffer size to the larger of:
543 // a) new position rounded up to next 256 bytes
544 // b) double the previous length
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000545 size_t new_buffer_length =
546 std::max(((seek_position_ + bytes) | 0xFF) + 1, buffer_length_ * 2);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000547 StreamResult result = DoReserve(new_buffer_length, error);
548 if (SR_SUCCESS != result) {
549 return result;
550 }
nisseede5da42017-01-12 05:15:36 -0800551 RTC_DCHECK(buffer_length_ >= new_buffer_length);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000552 available = buffer_length_ - seek_position_;
553 }
554
555 if (bytes > available) {
556 bytes = available;
557 }
558 memcpy(&buffer_[seek_position_], buffer, bytes);
559 seek_position_ += bytes;
560 if (data_length_ < seek_position_) {
561 data_length_ = seek_position_;
562 }
563 if (bytes_written) {
564 *bytes_written = bytes;
565 }
566 return SR_SUCCESS;
567}
568
569void MemoryStreamBase::Close() {
570 // nothing to do
571}
572
573bool MemoryStreamBase::SetPosition(size_t position) {
574 if (position > data_length_)
575 return false;
576 seek_position_ = position;
577 return true;
578}
579
580bool MemoryStreamBase::GetPosition(size_t* position) const {
581 if (position)
582 *position = seek_position_;
583 return true;
584}
585
586bool MemoryStreamBase::GetSize(size_t* size) const {
587 if (size)
588 *size = data_length_;
589 return true;
590}
591
592bool MemoryStreamBase::GetAvailable(size_t* size) const {
593 if (size)
594 *size = data_length_ - seek_position_;
595 return true;
596}
597
598bool MemoryStreamBase::ReserveSize(size_t size) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800599 return (SR_SUCCESS == DoReserve(size, nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000600}
601
602StreamResult MemoryStreamBase::DoReserve(size_t size, int* error) {
603 return (buffer_length_ >= size) ? SR_SUCCESS : SR_EOS;
604}
605
606///////////////////////////////////////////////////////////////////////////////
607
Niels Möller7502a9e2018-05-21 16:11:34 +0200608MemoryStream::MemoryStream() {}
609
610MemoryStream::MemoryStream(const char* data) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000611 SetData(data, strlen(data));
612}
613
Niels Möller7502a9e2018-05-21 16:11:34 +0200614MemoryStream::MemoryStream(const void* data, size_t length) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000615 SetData(data, length);
616}
617
618MemoryStream::~MemoryStream() {
Yves Gerey665174f2018-06-19 15:03:05 +0200619 delete[] buffer_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000620}
621
622void MemoryStream::SetData(const void* data, size_t length) {
623 data_length_ = buffer_length_ = length;
Yves Gerey665174f2018-06-19 15:03:05 +0200624 delete[] buffer_;
Niels Möller7502a9e2018-05-21 16:11:34 +0200625 buffer_ = new char[buffer_length_];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000626 memcpy(buffer_, data, data_length_);
627 seek_position_ = 0;
628}
629
630StreamResult MemoryStream::DoReserve(size_t size, int* error) {
631 if (buffer_length_ >= size)
632 return SR_SUCCESS;
633
Niels Möller7502a9e2018-05-21 16:11:34 +0200634 if (char* new_buffer = new char[size]) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000635 memcpy(new_buffer, buffer_, data_length_);
Yves Gerey665174f2018-06-19 15:03:05 +0200636 delete[] buffer_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000637 buffer_ = new_buffer;
638 buffer_length_ = size;
639 return SR_SUCCESS;
640 }
641
642 if (error) {
643 *error = ENOMEM;
644 }
645 return SR_ERROR;
646}
647
648///////////////////////////////////////////////////////////////////////////////
deadbeeff137e972017-03-23 15:45:49 -0700649
Yves Gerey665174f2018-06-19 15:03:05 +0200650ExternalMemoryStream::ExternalMemoryStream() {}
deadbeeff137e972017-03-23 15:45:49 -0700651
652ExternalMemoryStream::ExternalMemoryStream(void* data, size_t length) {
653 SetData(data, length);
654}
655
Yves Gerey665174f2018-06-19 15:03:05 +0200656ExternalMemoryStream::~ExternalMemoryStream() {}
deadbeeff137e972017-03-23 15:45:49 -0700657
658void ExternalMemoryStream::SetData(void* data, size_t length) {
659 data_length_ = buffer_length_ = length;
660 buffer_ = static_cast<char*>(data);
661 seek_position_ = 0;
662}
663
664///////////////////////////////////////////////////////////////////////////////
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000665// FifoBuffer
666///////////////////////////////////////////////////////////////////////////////
667
668FifoBuffer::FifoBuffer(size_t size)
Yves Gerey665174f2018-06-19 15:03:05 +0200669 : state_(SS_OPEN),
670 buffer_(new char[size]),
671 buffer_length_(size),
672 data_length_(0),
673 read_position_(0),
674 owner_(Thread::Current()) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000675 // all events are done on the owner_ thread
676}
677
678FifoBuffer::FifoBuffer(size_t size, Thread* owner)
Yves Gerey665174f2018-06-19 15:03:05 +0200679 : state_(SS_OPEN),
680 buffer_(new char[size]),
681 buffer_length_(size),
682 data_length_(0),
683 read_position_(0),
684 owner_(owner) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000685 // all events are done on the owner_ thread
686}
687
Yves Gerey665174f2018-06-19 15:03:05 +0200688FifoBuffer::~FifoBuffer() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000689
690bool FifoBuffer::GetBuffered(size_t* size) const {
691 CritScope cs(&crit_);
692 *size = data_length_;
693 return true;
694}
695
696bool FifoBuffer::SetCapacity(size_t size) {
697 CritScope cs(&crit_);
698 if (data_length_ > size) {
699 return false;
700 }
701
702 if (size != buffer_length_) {
703 char* buffer = new char[size];
704 const size_t copy = data_length_;
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000705 const size_t tail_copy = std::min(copy, buffer_length_ - read_position_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000706 memcpy(buffer, &buffer_[read_position_], tail_copy);
707 memcpy(buffer + tail_copy, &buffer_[0], copy - tail_copy);
708 buffer_.reset(buffer);
709 read_position_ = 0;
710 buffer_length_ = size;
711 }
712 return true;
713}
714
Yves Gerey665174f2018-06-19 15:03:05 +0200715StreamResult FifoBuffer::ReadOffset(void* buffer,
716 size_t bytes,
717 size_t offset,
718 size_t* bytes_read) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000719 CritScope cs(&crit_);
720 return ReadOffsetLocked(buffer, bytes, offset, bytes_read);
721}
722
Yves Gerey665174f2018-06-19 15:03:05 +0200723StreamResult FifoBuffer::WriteOffset(const void* buffer,
724 size_t bytes,
725 size_t offset,
726 size_t* bytes_written) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000727 CritScope cs(&crit_);
728 return WriteOffsetLocked(buffer, bytes, offset, bytes_written);
729}
730
731StreamState FifoBuffer::GetState() const {
jbauch097d5492016-02-09 02:30:34 -0800732 CritScope cs(&crit_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000733 return state_;
734}
735
Yves Gerey665174f2018-06-19 15:03:05 +0200736StreamResult FifoBuffer::Read(void* buffer,
737 size_t bytes,
738 size_t* bytes_read,
739 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000740 CritScope cs(&crit_);
741 const bool was_writable = data_length_ < buffer_length_;
742 size_t copy = 0;
743 StreamResult result = ReadOffsetLocked(buffer, bytes, 0, &copy);
744
745 if (result == SR_SUCCESS) {
746 // If read was successful then adjust the read position and number of
747 // bytes buffered.
748 read_position_ = (read_position_ + copy) % buffer_length_;
749 data_length_ -= copy;
750 if (bytes_read) {
751 *bytes_read = copy;
752 }
753
754 // if we were full before, and now we're not, post an event
755 if (!was_writable && copy > 0) {
756 PostEvent(owner_, SE_WRITE, 0);
757 }
758 }
759 return result;
760}
761
Yves Gerey665174f2018-06-19 15:03:05 +0200762StreamResult FifoBuffer::Write(const void* buffer,
763 size_t bytes,
764 size_t* bytes_written,
765 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000766 CritScope cs(&crit_);
767
768 const bool was_readable = (data_length_ > 0);
769 size_t copy = 0;
770 StreamResult result = WriteOffsetLocked(buffer, bytes, 0, &copy);
771
772 if (result == SR_SUCCESS) {
773 // If write was successful then adjust the number of readable bytes.
774 data_length_ += copy;
775 if (bytes_written) {
776 *bytes_written = copy;
777 }
778
779 // if we didn't have any data to read before, and now we do, post an event
780 if (!was_readable && copy > 0) {
781 PostEvent(owner_, SE_READ, 0);
782 }
783 }
784 return result;
785}
786
787void FifoBuffer::Close() {
788 CritScope cs(&crit_);
789 state_ = SS_CLOSED;
790}
791
792const void* FifoBuffer::GetReadData(size_t* size) {
793 CritScope cs(&crit_);
Yves Gerey665174f2018-06-19 15:03:05 +0200794 *size = (read_position_ + data_length_ <= buffer_length_)
795 ? data_length_
796 : buffer_length_ - read_position_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000797 return &buffer_[read_position_];
798}
799
800void FifoBuffer::ConsumeReadData(size_t size) {
801 CritScope cs(&crit_);
nisseede5da42017-01-12 05:15:36 -0800802 RTC_DCHECK(size <= data_length_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000803 const bool was_writable = data_length_ < buffer_length_;
804 read_position_ = (read_position_ + size) % buffer_length_;
805 data_length_ -= size;
806 if (!was_writable && size > 0) {
807 PostEvent(owner_, SE_WRITE, 0);
808 }
809}
810
811void* FifoBuffer::GetWriteBuffer(size_t* size) {
812 CritScope cs(&crit_);
813 if (state_ == SS_CLOSED) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800814 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000815 }
816
817 // if empty, reset the write position to the beginning, so we can get
818 // the biggest possible block
819 if (data_length_ == 0) {
820 read_position_ = 0;
821 }
822
Yves Gerey665174f2018-06-19 15:03:05 +0200823 const size_t write_position =
824 (read_position_ + data_length_) % buffer_length_;
825 *size = (write_position > read_position_ || data_length_ == 0)
826 ? buffer_length_ - write_position
827 : read_position_ - write_position;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000828 return &buffer_[write_position];
829}
830
831void FifoBuffer::ConsumeWriteBuffer(size_t size) {
832 CritScope cs(&crit_);
nisseede5da42017-01-12 05:15:36 -0800833 RTC_DCHECK(size <= buffer_length_ - data_length_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000834 const bool was_readable = (data_length_ > 0);
835 data_length_ += size;
836 if (!was_readable && size > 0) {
837 PostEvent(owner_, SE_READ, 0);
838 }
839}
840
841bool FifoBuffer::GetWriteRemaining(size_t* size) const {
842 CritScope cs(&crit_);
843 *size = buffer_length_ - data_length_;
844 return true;
845}
846
847StreamResult FifoBuffer::ReadOffsetLocked(void* buffer,
848 size_t bytes,
849 size_t offset,
850 size_t* bytes_read) {
851 if (offset >= data_length_) {
852 return (state_ != SS_CLOSED) ? SR_BLOCK : SR_EOS;
853 }
854
855 const size_t available = data_length_ - offset;
856 const size_t read_position = (read_position_ + offset) % buffer_length_;
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000857 const size_t copy = std::min(bytes, available);
858 const size_t tail_copy = std::min(copy, buffer_length_ - read_position);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000859 char* const p = static_cast<char*>(buffer);
860 memcpy(p, &buffer_[read_position], tail_copy);
861 memcpy(p + tail_copy, &buffer_[0], copy - tail_copy);
862
863 if (bytes_read) {
864 *bytes_read = copy;
865 }
866 return SR_SUCCESS;
867}
868
869StreamResult FifoBuffer::WriteOffsetLocked(const void* buffer,
870 size_t bytes,
871 size_t offset,
872 size_t* bytes_written) {
873 if (state_ == SS_CLOSED) {
874 return SR_EOS;
875 }
876
877 if (data_length_ + offset >= buffer_length_) {
878 return SR_BLOCK;
879 }
880
881 const size_t available = buffer_length_ - data_length_ - offset;
Yves Gerey665174f2018-06-19 15:03:05 +0200882 const size_t write_position =
883 (read_position_ + data_length_ + offset) % buffer_length_;
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000884 const size_t copy = std::min(bytes, available);
885 const size_t tail_copy = std::min(copy, buffer_length_ - write_position);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000886 const char* const p = static_cast<const char*>(buffer);
887 memcpy(&buffer_[write_position], p, tail_copy);
888 memcpy(&buffer_[0], p + tail_copy, copy - tail_copy);
889
890 if (bytes_written) {
891 *bytes_written = copy;
892 }
893 return SR_SUCCESS;
894}
895
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000896///////////////////////////////////////////////////////////////////////////////
897// StringStream - Reads/Writes to an external std::string
898///////////////////////////////////////////////////////////////////////////////
899
Tommi00aac5a2015-05-25 11:25:59 +0200900StringStream::StringStream(std::string* str)
Yves Gerey665174f2018-06-19 15:03:05 +0200901 : str_(*str), read_pos_(0), read_only_(false) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000902
903StringStream::StringStream(const std::string& str)
Yves Gerey665174f2018-06-19 15:03:05 +0200904 : str_(const_cast<std::string&>(str)), read_pos_(0), read_only_(true) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000905
906StreamState StringStream::GetState() const {
907 return SS_OPEN;
908}
909
Yves Gerey665174f2018-06-19 15:03:05 +0200910StreamResult StringStream::Read(void* buffer,
911 size_t buffer_len,
912 size_t* read,
913 int* error) {
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000914 size_t available = std::min(buffer_len, str_.size() - read_pos_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000915 if (!available)
916 return SR_EOS;
917 memcpy(buffer, str_.data() + read_pos_, available);
918 read_pos_ += available;
919 if (read)
920 *read = available;
921 return SR_SUCCESS;
922}
923
Yves Gerey665174f2018-06-19 15:03:05 +0200924StreamResult StringStream::Write(const void* data,
925 size_t data_len,
926 size_t* written,
927 int* error) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000928 if (read_only_) {
929 if (error) {
930 *error = -1;
931 }
932 return SR_ERROR;
933 }
934 str_.append(static_cast<const char*>(data),
935 static_cast<const char*>(data) + data_len);
936 if (written)
937 *written = data_len;
938 return SR_SUCCESS;
939}
940
Yves Gerey665174f2018-06-19 15:03:05 +0200941void StringStream::Close() {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000942
943bool StringStream::SetPosition(size_t position) {
944 if (position > str_.size())
945 return false;
946 read_pos_ = position;
947 return true;
948}
949
950bool StringStream::GetPosition(size_t* position) const {
951 if (position)
952 *position = read_pos_;
953 return true;
954}
955
956bool StringStream::GetSize(size_t* size) const {
957 if (size)
958 *size = str_.size();
959 return true;
960}
961
962bool StringStream::GetAvailable(size_t* size) const {
963 if (size)
964 *size = str_.size() - read_pos_;
965 return true;
966}
967
968bool StringStream::ReserveSize(size_t size) {
969 if (read_only_)
970 return false;
971 str_.reserve(size);
972 return true;
973}
974
975///////////////////////////////////////////////////////////////////////////////
deadbeeff137e972017-03-23 15:45:49 -0700976// StreamReference
977///////////////////////////////////////////////////////////////////////////////
978
979StreamReference::StreamReference(StreamInterface* stream)
980 : StreamAdapterInterface(stream, false) {
981 // owner set to false so the destructor does not free the stream.
982 stream_ref_count_ = new StreamRefCount(stream);
983}
984
985StreamInterface* StreamReference::NewReference() {
986 stream_ref_count_->AddReference();
987 return new StreamReference(stream_ref_count_, stream());
988}
989
990StreamReference::~StreamReference() {
991 stream_ref_count_->Release();
992}
993
994StreamReference::StreamReference(StreamRefCount* stream_ref_count,
995 StreamInterface* stream)
996 : StreamAdapterInterface(stream, false),
Yves Gerey665174f2018-06-19 15:03:05 +0200997 stream_ref_count_(stream_ref_count) {}
deadbeeff137e972017-03-23 15:45:49 -0700998
999///////////////////////////////////////////////////////////////////////////////
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001000
1001StreamResult Flow(StreamInterface* source,
deadbeef37f5ecf2017-02-27 14:06:41 -08001002 char* buffer,
1003 size_t buffer_len,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001004 StreamInterface* sink,
deadbeef37f5ecf2017-02-27 14:06:41 -08001005 size_t* data_len /* = nullptr */) {
nisseede5da42017-01-12 05:15:36 -08001006 RTC_DCHECK(buffer_len > 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001007
1008 StreamResult result;
1009 size_t count, read_pos, write_pos;
1010 if (data_len) {
1011 read_pos = *data_len;
1012 } else {
1013 read_pos = 0;
1014 }
1015
1016 bool end_of_stream = false;
1017 do {
1018 // Read until buffer is full, end of stream, or error
1019 while (!end_of_stream && (read_pos < buffer_len)) {
deadbeef37f5ecf2017-02-27 14:06:41 -08001020 result = source->Read(buffer + read_pos, buffer_len - read_pos, &count,
1021 nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001022 if (result == SR_EOS) {
1023 end_of_stream = true;
1024 } else if (result != SR_SUCCESS) {
1025 if (data_len) {
1026 *data_len = read_pos;
1027 }
1028 return result;
1029 } else {
1030 read_pos += count;
1031 }
1032 }
1033
1034 // Write until buffer is empty, or error (including end of stream)
1035 write_pos = 0;
1036 while (write_pos < read_pos) {
deadbeef37f5ecf2017-02-27 14:06:41 -08001037 result = sink->Write(buffer + write_pos, read_pos - write_pos, &count,
1038 nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001039 if (result != SR_SUCCESS) {
1040 if (data_len) {
1041 *data_len = read_pos - write_pos;
1042 if (write_pos > 0) {
1043 memmove(buffer, buffer + write_pos, *data_len);
1044 }
1045 }
1046 return result;
1047 }
1048 write_pos += count;
1049 }
1050
1051 read_pos = 0;
1052 } while (!end_of_stream);
1053
1054 if (data_len) {
1055 *data_len = 0;
1056 }
1057 return SR_SUCCESS;
1058}
1059
1060///////////////////////////////////////////////////////////////////////////////
1061
1062} // namespace rtc