xref: /aosp_15_r20/external/cronet/components/cronet/cronet_upload_data_stream.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/cronet/cronet_upload_data_stream.h"
6 
7 #include "net/base/io_buffer.h"
8 #include "net/base/net_errors.h"
9 
10 namespace cronet {
11 
CronetUploadDataStream(Delegate * delegate,int64_t size)12 CronetUploadDataStream::CronetUploadDataStream(Delegate* delegate, int64_t size)
13     : UploadDataStream(size < 0, 0),
14       size_(size),
15       waiting_on_read_(false),
16       read_in_progress_(false),
17       waiting_on_rewind_(false),
18       rewind_in_progress_(false),
19       at_front_of_stream_(true),
20       delegate_(delegate) {}
21 
~CronetUploadDataStream()22 CronetUploadDataStream::~CronetUploadDataStream() {
23   delegate_->OnUploadDataStreamDestroyed();
24 }
25 
InitInternal(const net::NetLogWithSource & net_log)26 int CronetUploadDataStream::InitInternal(const net::NetLogWithSource& net_log) {
27   // ResetInternal should have been called before init, if the stream was in
28   // use.
29   DCHECK(!waiting_on_read_);
30   DCHECK(!waiting_on_rewind_);
31 
32   if (!weak_factory_.HasWeakPtrs())
33     delegate_->InitializeOnNetworkThread(weak_factory_.GetWeakPtr());
34 
35   // Set size of non-chunked uploads.
36   if (size_ >= 0)
37     SetSize(static_cast<uint64_t>(size_));
38 
39   // If already at the front of the stream, nothing to do.
40   if (at_front_of_stream_) {
41     // Being at the front of the stream implies there's no read or rewind in
42     // progress.
43     DCHECK(!read_in_progress_);
44     DCHECK(!rewind_in_progress_);
45     return net::OK;
46   }
47 
48   // Otherwise, the request is now waiting for the stream to be rewound.
49   waiting_on_rewind_ = true;
50 
51   // Start rewinding the stream if no operation is in progress.
52   if (!read_in_progress_ && !rewind_in_progress_)
53     StartRewind();
54   return net::ERR_IO_PENDING;
55 }
56 
ReadInternal(net::IOBuffer * buf,int buf_len)57 int CronetUploadDataStream::ReadInternal(net::IOBuffer* buf, int buf_len) {
58   // All pending operations should have completed before a read can start.
59   DCHECK(!waiting_on_read_);
60   DCHECK(!read_in_progress_);
61   DCHECK(!waiting_on_rewind_);
62   DCHECK(!rewind_in_progress_);
63 
64   DCHECK(buf);
65   DCHECK_GT(buf_len, 0);
66 
67   read_in_progress_ = true;
68   waiting_on_read_ = true;
69   at_front_of_stream_ = false;
70   scoped_refptr<net::IOBuffer> buffer(base::WrapRefCounted(buf));
71   delegate_->Read(std::move(buffer), buf_len);
72   return net::ERR_IO_PENDING;
73 }
74 
ResetInternal()75 void CronetUploadDataStream::ResetInternal() {
76   // Consumer is not waiting on any operation.  Note that the active operation,
77   // if any, will continue.
78   waiting_on_read_ = false;
79   waiting_on_rewind_ = false;
80 }
81 
OnReadSuccess(int bytes_read,bool final_chunk)82 void CronetUploadDataStream::OnReadSuccess(int bytes_read, bool final_chunk) {
83   DCHECK(read_in_progress_);
84   DCHECK(!rewind_in_progress_);
85   DCHECK(bytes_read > 0 || (final_chunk && bytes_read == 0));
86   if (!is_chunked()) {
87     DCHECK(!final_chunk);
88   }
89 
90   read_in_progress_ = false;
91 
92   if (waiting_on_rewind_) {
93     DCHECK(!waiting_on_read_);
94     // Since a read just completed, can't be at the front of the stream.
95     StartRewind();
96     return;
97   }
98   // ResetInternal has been called, but still waiting on InitInternal.
99   if (!waiting_on_read_)
100     return;
101 
102   waiting_on_read_ = false;
103   if (final_chunk)
104     SetIsFinalChunk();
105   OnReadCompleted(bytes_read);
106 }
107 
OnRewindSuccess()108 void CronetUploadDataStream::OnRewindSuccess() {
109   DCHECK(!waiting_on_read_);
110   DCHECK(!read_in_progress_);
111   DCHECK(rewind_in_progress_);
112   DCHECK(!at_front_of_stream_);
113 
114   rewind_in_progress_ = false;
115   at_front_of_stream_ = true;
116 
117   // Possible that ResetInternal was called since the rewind was started, but
118   // InitInternal has not been.
119   if (!waiting_on_rewind_)
120     return;
121 
122   waiting_on_rewind_ = false;
123   OnInitCompleted(net::OK);
124 }
125 
StartRewind()126 void CronetUploadDataStream::StartRewind() {
127   DCHECK(!waiting_on_read_);
128   DCHECK(!read_in_progress_);
129   DCHECK(waiting_on_rewind_);
130   DCHECK(!rewind_in_progress_);
131   DCHECK(!at_front_of_stream_);
132 
133   rewind_in_progress_ = true;
134   delegate_->Rewind();
135 }
136 
137 }  // namespace cronet
138