1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker * Copyright (c) 2020, The OpenThread Authors.
3*4a64e381SAndroid Build Coastguard Worker * All rights reserved.
4*4a64e381SAndroid Build Coastguard Worker *
5*4a64e381SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*4a64e381SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
7*4a64e381SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
8*4a64e381SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
9*4a64e381SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
10*4a64e381SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
11*4a64e381SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
12*4a64e381SAndroid Build Coastguard Worker * 3. Neither the name of the copyright holder nor the
13*4a64e381SAndroid Build Coastguard Worker * names of its contributors may be used to endorse or promote products
14*4a64e381SAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
15*4a64e381SAndroid Build Coastguard Worker *
16*4a64e381SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*4a64e381SAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*4a64e381SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*4a64e381SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*4a64e381SAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*4a64e381SAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*4a64e381SAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*4a64e381SAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*4a64e381SAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*4a64e381SAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*4a64e381SAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE.
27*4a64e381SAndroid Build Coastguard Worker */
28*4a64e381SAndroid Build Coastguard Worker
29*4a64e381SAndroid Build Coastguard Worker #include "rest/connection.hpp"
30*4a64e381SAndroid Build Coastguard Worker
31*4a64e381SAndroid Build Coastguard Worker #include <cerrno>
32*4a64e381SAndroid Build Coastguard Worker
33*4a64e381SAndroid Build Coastguard Worker #include <assert.h>
34*4a64e381SAndroid Build Coastguard Worker
35*4a64e381SAndroid Build Coastguard Worker #include <sys/socket.h>
36*4a64e381SAndroid Build Coastguard Worker #include <sys/time.h>
37*4a64e381SAndroid Build Coastguard Worker
38*4a64e381SAndroid Build Coastguard Worker using std::chrono::duration_cast;
39*4a64e381SAndroid Build Coastguard Worker using std::chrono::microseconds;
40*4a64e381SAndroid Build Coastguard Worker using std::chrono::seconds;
41*4a64e381SAndroid Build Coastguard Worker using std::chrono::steady_clock;
42*4a64e381SAndroid Build Coastguard Worker
43*4a64e381SAndroid Build Coastguard Worker namespace otbr {
44*4a64e381SAndroid Build Coastguard Worker namespace rest {
45*4a64e381SAndroid Build Coastguard Worker
46*4a64e381SAndroid Build Coastguard Worker // The timeout (in microseconds) since a connection is in wait callback state
47*4a64e381SAndroid Build Coastguard Worker static const uint32_t kCallbackTimeout = 10000000;
48*4a64e381SAndroid Build Coastguard Worker
49*4a64e381SAndroid Build Coastguard Worker // The time interval (in microseconds) for checking again if there is a connection need callback.
50*4a64e381SAndroid Build Coastguard Worker static const uint32_t kCallbackCheckInterval = 500000;
51*4a64e381SAndroid Build Coastguard Worker
52*4a64e381SAndroid Build Coastguard Worker // The timeout (in microseconds) since a connection is in wait write state
53*4a64e381SAndroid Build Coastguard Worker static const uint32_t kWriteTimeout = 10000000;
54*4a64e381SAndroid Build Coastguard Worker
55*4a64e381SAndroid Build Coastguard Worker // The timeout (in microseconds) since a connection is in wait read state
56*4a64e381SAndroid Build Coastguard Worker static const uint32_t kReadTimeout = 1000000;
57*4a64e381SAndroid Build Coastguard Worker
Connection(steady_clock::time_point aStartTime,Resource * aResource,int aFd)58*4a64e381SAndroid Build Coastguard Worker Connection::Connection(steady_clock::time_point aStartTime, Resource *aResource, int aFd)
59*4a64e381SAndroid Build Coastguard Worker : mTimeStamp(aStartTime)
60*4a64e381SAndroid Build Coastguard Worker , mFd(aFd)
61*4a64e381SAndroid Build Coastguard Worker , mState(ConnectionState::kInit)
62*4a64e381SAndroid Build Coastguard Worker , mParser(&mRequest)
63*4a64e381SAndroid Build Coastguard Worker , mResource(aResource)
64*4a64e381SAndroid Build Coastguard Worker {
65*4a64e381SAndroid Build Coastguard Worker }
66*4a64e381SAndroid Build Coastguard Worker
~Connection(void)67*4a64e381SAndroid Build Coastguard Worker Connection::~Connection(void)
68*4a64e381SAndroid Build Coastguard Worker {
69*4a64e381SAndroid Build Coastguard Worker Disconnect();
70*4a64e381SAndroid Build Coastguard Worker }
71*4a64e381SAndroid Build Coastguard Worker
Init(void)72*4a64e381SAndroid Build Coastguard Worker void Connection::Init(void)
73*4a64e381SAndroid Build Coastguard Worker {
74*4a64e381SAndroid Build Coastguard Worker mParser.Init();
75*4a64e381SAndroid Build Coastguard Worker }
76*4a64e381SAndroid Build Coastguard Worker
UpdateReadFdSet(fd_set & aReadFdSet,int & aMaxFd) const77*4a64e381SAndroid Build Coastguard Worker void Connection::UpdateReadFdSet(fd_set &aReadFdSet, int &aMaxFd) const
78*4a64e381SAndroid Build Coastguard Worker {
79*4a64e381SAndroid Build Coastguard Worker if (mState == ConnectionState::kReadWait || mState == ConnectionState::kInit)
80*4a64e381SAndroid Build Coastguard Worker {
81*4a64e381SAndroid Build Coastguard Worker FD_SET(mFd, &aReadFdSet);
82*4a64e381SAndroid Build Coastguard Worker aMaxFd = aMaxFd < mFd ? mFd : aMaxFd;
83*4a64e381SAndroid Build Coastguard Worker }
84*4a64e381SAndroid Build Coastguard Worker }
85*4a64e381SAndroid Build Coastguard Worker
UpdateWriteFdSet(fd_set & aWriteFdSet,int & aMaxFd) const86*4a64e381SAndroid Build Coastguard Worker void Connection::UpdateWriteFdSet(fd_set &aWriteFdSet, int &aMaxFd) const
87*4a64e381SAndroid Build Coastguard Worker {
88*4a64e381SAndroid Build Coastguard Worker if (mState == ConnectionState::kWriteWait)
89*4a64e381SAndroid Build Coastguard Worker {
90*4a64e381SAndroid Build Coastguard Worker FD_SET(mFd, &aWriteFdSet);
91*4a64e381SAndroid Build Coastguard Worker aMaxFd = aMaxFd < mFd ? mFd : aMaxFd;
92*4a64e381SAndroid Build Coastguard Worker }
93*4a64e381SAndroid Build Coastguard Worker }
94*4a64e381SAndroid Build Coastguard Worker
UpdateTimeout(timeval & aTimeout) const95*4a64e381SAndroid Build Coastguard Worker void Connection::UpdateTimeout(timeval &aTimeout) const
96*4a64e381SAndroid Build Coastguard Worker {
97*4a64e381SAndroid Build Coastguard Worker struct timeval timeout;
98*4a64e381SAndroid Build Coastguard Worker uint32_t timeoutLen = kReadTimeout;
99*4a64e381SAndroid Build Coastguard Worker auto duration = duration_cast<microseconds>(steady_clock::now() - mTimeStamp).count();
100*4a64e381SAndroid Build Coastguard Worker
101*4a64e381SAndroid Build Coastguard Worker switch (mState)
102*4a64e381SAndroid Build Coastguard Worker {
103*4a64e381SAndroid Build Coastguard Worker case ConnectionState::kReadWait:
104*4a64e381SAndroid Build Coastguard Worker timeoutLen = kReadTimeout;
105*4a64e381SAndroid Build Coastguard Worker break;
106*4a64e381SAndroid Build Coastguard Worker case ConnectionState::kCallbackWait:
107*4a64e381SAndroid Build Coastguard Worker timeoutLen = kCallbackCheckInterval;
108*4a64e381SAndroid Build Coastguard Worker break;
109*4a64e381SAndroid Build Coastguard Worker case ConnectionState::kWriteWait:
110*4a64e381SAndroid Build Coastguard Worker timeoutLen = kWriteTimeout;
111*4a64e381SAndroid Build Coastguard Worker break;
112*4a64e381SAndroid Build Coastguard Worker case ConnectionState::kComplete:
113*4a64e381SAndroid Build Coastguard Worker timeoutLen = 0;
114*4a64e381SAndroid Build Coastguard Worker break;
115*4a64e381SAndroid Build Coastguard Worker default:
116*4a64e381SAndroid Build Coastguard Worker break;
117*4a64e381SAndroid Build Coastguard Worker }
118*4a64e381SAndroid Build Coastguard Worker
119*4a64e381SAndroid Build Coastguard Worker if (duration <= timeoutLen)
120*4a64e381SAndroid Build Coastguard Worker {
121*4a64e381SAndroid Build Coastguard Worker timeout.tv_sec = 0;
122*4a64e381SAndroid Build Coastguard Worker timeout.tv_usec = timeoutLen - duration;
123*4a64e381SAndroid Build Coastguard Worker }
124*4a64e381SAndroid Build Coastguard Worker else
125*4a64e381SAndroid Build Coastguard Worker {
126*4a64e381SAndroid Build Coastguard Worker timeout.tv_sec = 0;
127*4a64e381SAndroid Build Coastguard Worker timeout.tv_usec = 0;
128*4a64e381SAndroid Build Coastguard Worker }
129*4a64e381SAndroid Build Coastguard Worker
130*4a64e381SAndroid Build Coastguard Worker if (timercmp(&timeout, &aTimeout, <))
131*4a64e381SAndroid Build Coastguard Worker {
132*4a64e381SAndroid Build Coastguard Worker aTimeout = timeout;
133*4a64e381SAndroid Build Coastguard Worker }
134*4a64e381SAndroid Build Coastguard Worker }
135*4a64e381SAndroid Build Coastguard Worker
Update(MainloopContext & aMainloop)136*4a64e381SAndroid Build Coastguard Worker void Connection::Update(MainloopContext &aMainloop)
137*4a64e381SAndroid Build Coastguard Worker {
138*4a64e381SAndroid Build Coastguard Worker UpdateTimeout(aMainloop.mTimeout);
139*4a64e381SAndroid Build Coastguard Worker UpdateReadFdSet(aMainloop.mReadFdSet, aMainloop.mMaxFd);
140*4a64e381SAndroid Build Coastguard Worker UpdateWriteFdSet(aMainloop.mWriteFdSet, aMainloop.mMaxFd);
141*4a64e381SAndroid Build Coastguard Worker }
142*4a64e381SAndroid Build Coastguard Worker
Disconnect(void)143*4a64e381SAndroid Build Coastguard Worker void Connection::Disconnect(void)
144*4a64e381SAndroid Build Coastguard Worker {
145*4a64e381SAndroid Build Coastguard Worker mState = ConnectionState::kComplete;
146*4a64e381SAndroid Build Coastguard Worker
147*4a64e381SAndroid Build Coastguard Worker if (mFd != -1)
148*4a64e381SAndroid Build Coastguard Worker {
149*4a64e381SAndroid Build Coastguard Worker close(mFd);
150*4a64e381SAndroid Build Coastguard Worker mFd = -1;
151*4a64e381SAndroid Build Coastguard Worker }
152*4a64e381SAndroid Build Coastguard Worker }
153*4a64e381SAndroid Build Coastguard Worker
Process(const MainloopContext & aMainloop)154*4a64e381SAndroid Build Coastguard Worker void Connection::Process(const MainloopContext &aMainloop)
155*4a64e381SAndroid Build Coastguard Worker {
156*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
157*4a64e381SAndroid Build Coastguard Worker
158*4a64e381SAndroid Build Coastguard Worker switch (mState)
159*4a64e381SAndroid Build Coastguard Worker {
160*4a64e381SAndroid Build Coastguard Worker // Initial state, directly read for the first time.
161*4a64e381SAndroid Build Coastguard Worker case ConnectionState::kInit:
162*4a64e381SAndroid Build Coastguard Worker case ConnectionState::kReadWait:
163*4a64e381SAndroid Build Coastguard Worker ProcessWaitRead(aMainloop.mReadFdSet);
164*4a64e381SAndroid Build Coastguard Worker break;
165*4a64e381SAndroid Build Coastguard Worker case ConnectionState::kCallbackWait:
166*4a64e381SAndroid Build Coastguard Worker // Wait for Callback process.
167*4a64e381SAndroid Build Coastguard Worker ProcessWaitCallback();
168*4a64e381SAndroid Build Coastguard Worker break;
169*4a64e381SAndroid Build Coastguard Worker case ConnectionState::kWriteWait:
170*4a64e381SAndroid Build Coastguard Worker ProcessWaitWrite(aMainloop.mWriteFdSet);
171*4a64e381SAndroid Build Coastguard Worker break;
172*4a64e381SAndroid Build Coastguard Worker default:
173*4a64e381SAndroid Build Coastguard Worker assert(false);
174*4a64e381SAndroid Build Coastguard Worker }
175*4a64e381SAndroid Build Coastguard Worker
176*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
177*4a64e381SAndroid Build Coastguard Worker {
178*4a64e381SAndroid Build Coastguard Worker Disconnect();
179*4a64e381SAndroid Build Coastguard Worker }
180*4a64e381SAndroid Build Coastguard Worker }
181*4a64e381SAndroid Build Coastguard Worker
ProcessWaitRead(const fd_set & aReadFdSet)182*4a64e381SAndroid Build Coastguard Worker void Connection::ProcessWaitRead(const fd_set &aReadFdSet)
183*4a64e381SAndroid Build Coastguard Worker {
184*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
185*4a64e381SAndroid Build Coastguard Worker int32_t received = 0, err;
186*4a64e381SAndroid Build Coastguard Worker char buf[2048];
187*4a64e381SAndroid Build Coastguard Worker auto duration = duration_cast<microseconds>(steady_clock::now() - mTimeStamp).count();
188*4a64e381SAndroid Build Coastguard Worker
189*4a64e381SAndroid Build Coastguard Worker // Reach a read timeout, will send response about this timeout later.
190*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(duration <= kReadTimeout, error = OTBR_ERROR_REST);
191*4a64e381SAndroid Build Coastguard Worker
192*4a64e381SAndroid Build Coastguard Worker // It will succeed either fd is set or it is in kInit state.
193*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(FD_ISSET(mFd, &aReadFdSet) || mState == ConnectionState::kInit);
194*4a64e381SAndroid Build Coastguard Worker
195*4a64e381SAndroid Build Coastguard Worker do
196*4a64e381SAndroid Build Coastguard Worker {
197*4a64e381SAndroid Build Coastguard Worker mState = ConnectionState::kReadWait;
198*4a64e381SAndroid Build Coastguard Worker received = read(mFd, buf, sizeof(buf));
199*4a64e381SAndroid Build Coastguard Worker err = errno;
200*4a64e381SAndroid Build Coastguard Worker if (received > 0)
201*4a64e381SAndroid Build Coastguard Worker {
202*4a64e381SAndroid Build Coastguard Worker mParser.Process(buf, received);
203*4a64e381SAndroid Build Coastguard Worker }
204*4a64e381SAndroid Build Coastguard Worker } while ((received > 0 && !mRequest.IsComplete()) || err == EINTR);
205*4a64e381SAndroid Build Coastguard Worker
206*4a64e381SAndroid Build Coastguard Worker if (mRequest.IsComplete())
207*4a64e381SAndroid Build Coastguard Worker {
208*4a64e381SAndroid Build Coastguard Worker Handle();
209*4a64e381SAndroid Build Coastguard Worker }
210*4a64e381SAndroid Build Coastguard Worker
211*4a64e381SAndroid Build Coastguard Worker // Check first failure situation: received == 0 (indicate another side at least has closes its write side )
212*4a64e381SAndroid Build Coastguard Worker // and at the same time, the request has not been parsed completely.
213*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(received != 0 || mRequest.IsComplete(), error = OTBR_ERROR_REST);
214*4a64e381SAndroid Build Coastguard Worker
215*4a64e381SAndroid Build Coastguard Worker // Check second failure situation : received = -1 error(indicates that our system call read raise an error )
216*4a64e381SAndroid Build Coastguard Worker // then try to send back a response that there is an internal error.
217*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(received > 0 || (received == -1 && (err == EAGAIN || err == EWOULDBLOCK)), error = OTBR_ERROR_REST);
218*4a64e381SAndroid Build Coastguard Worker
219*4a64e381SAndroid Build Coastguard Worker exit:
220*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
221*4a64e381SAndroid Build Coastguard Worker {
222*4a64e381SAndroid Build Coastguard Worker if (received < 0)
223*4a64e381SAndroid Build Coastguard Worker {
224*4a64e381SAndroid Build Coastguard Worker mResource->ErrorHandler(mResponse, HttpStatusCode::kStatusInternalServerError);
225*4a64e381SAndroid Build Coastguard Worker Write();
226*4a64e381SAndroid Build Coastguard Worker }
227*4a64e381SAndroid Build Coastguard Worker else
228*4a64e381SAndroid Build Coastguard Worker {
229*4a64e381SAndroid Build Coastguard Worker mResource->ErrorHandler(mResponse, HttpStatusCode::kStatusRequestTimeout);
230*4a64e381SAndroid Build Coastguard Worker Write();
231*4a64e381SAndroid Build Coastguard Worker }
232*4a64e381SAndroid Build Coastguard Worker }
233*4a64e381SAndroid Build Coastguard Worker }
234*4a64e381SAndroid Build Coastguard Worker
Handle(void)235*4a64e381SAndroid Build Coastguard Worker void Connection::Handle(void)
236*4a64e381SAndroid Build Coastguard Worker {
237*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
238*4a64e381SAndroid Build Coastguard Worker
239*4a64e381SAndroid Build Coastguard Worker // Try to close server read side here, because we have started to handle the request and no longler read from
240*4a64e381SAndroid Build Coastguard Worker // socket.
241*4a64e381SAndroid Build Coastguard Worker VerifyOrExit((shutdown(mFd, SHUT_RD) == 0), error = OTBR_ERROR_REST);
242*4a64e381SAndroid Build Coastguard Worker
243*4a64e381SAndroid Build Coastguard Worker mResource->Handle(mRequest, mResponse);
244*4a64e381SAndroid Build Coastguard Worker
245*4a64e381SAndroid Build Coastguard Worker if (mResponse.NeedCallback())
246*4a64e381SAndroid Build Coastguard Worker {
247*4a64e381SAndroid Build Coastguard Worker mState = ConnectionState::kCallbackWait;
248*4a64e381SAndroid Build Coastguard Worker mTimeStamp = steady_clock::now();
249*4a64e381SAndroid Build Coastguard Worker }
250*4a64e381SAndroid Build Coastguard Worker else
251*4a64e381SAndroid Build Coastguard Worker {
252*4a64e381SAndroid Build Coastguard Worker // Normal Write back process.
253*4a64e381SAndroid Build Coastguard Worker Write();
254*4a64e381SAndroid Build Coastguard Worker }
255*4a64e381SAndroid Build Coastguard Worker
256*4a64e381SAndroid Build Coastguard Worker exit:
257*4a64e381SAndroid Build Coastguard Worker
258*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
259*4a64e381SAndroid Build Coastguard Worker {
260*4a64e381SAndroid Build Coastguard Worker mResource->ErrorHandler(mResponse, HttpStatusCode::kStatusInternalServerError);
261*4a64e381SAndroid Build Coastguard Worker Write();
262*4a64e381SAndroid Build Coastguard Worker }
263*4a64e381SAndroid Build Coastguard Worker }
264*4a64e381SAndroid Build Coastguard Worker
ProcessWaitCallback(void)265*4a64e381SAndroid Build Coastguard Worker void Connection::ProcessWaitCallback(void)
266*4a64e381SAndroid Build Coastguard Worker {
267*4a64e381SAndroid Build Coastguard Worker auto duration = duration_cast<microseconds>(steady_clock::now() - mTimeStamp).count();
268*4a64e381SAndroid Build Coastguard Worker
269*4a64e381SAndroid Build Coastguard Worker mResource->HandleCallback(mRequest, mResponse);
270*4a64e381SAndroid Build Coastguard Worker
271*4a64e381SAndroid Build Coastguard Worker if (mResponse.IsComplete())
272*4a64e381SAndroid Build Coastguard Worker {
273*4a64e381SAndroid Build Coastguard Worker Write();
274*4a64e381SAndroid Build Coastguard Worker }
275*4a64e381SAndroid Build Coastguard Worker else
276*4a64e381SAndroid Build Coastguard Worker {
277*4a64e381SAndroid Build Coastguard Worker if (duration >= kCallbackTimeout)
278*4a64e381SAndroid Build Coastguard Worker {
279*4a64e381SAndroid Build Coastguard Worker mResource->ErrorHandler(mResponse, HttpStatusCode::kStatusInternalServerError);
280*4a64e381SAndroid Build Coastguard Worker Write();
281*4a64e381SAndroid Build Coastguard Worker }
282*4a64e381SAndroid Build Coastguard Worker }
283*4a64e381SAndroid Build Coastguard Worker }
284*4a64e381SAndroid Build Coastguard Worker
ProcessWaitWrite(const fd_set & aWriteFdSet)285*4a64e381SAndroid Build Coastguard Worker void Connection::ProcessWaitWrite(const fd_set &aWriteFdSet)
286*4a64e381SAndroid Build Coastguard Worker {
287*4a64e381SAndroid Build Coastguard Worker auto duration = duration_cast<microseconds>(steady_clock::now() - mTimeStamp).count();
288*4a64e381SAndroid Build Coastguard Worker
289*4a64e381SAndroid Build Coastguard Worker if (duration <= kWriteTimeout)
290*4a64e381SAndroid Build Coastguard Worker {
291*4a64e381SAndroid Build Coastguard Worker if (FD_ISSET(mFd, &aWriteFdSet))
292*4a64e381SAndroid Build Coastguard Worker {
293*4a64e381SAndroid Build Coastguard Worker Write();
294*4a64e381SAndroid Build Coastguard Worker }
295*4a64e381SAndroid Build Coastguard Worker }
296*4a64e381SAndroid Build Coastguard Worker else
297*4a64e381SAndroid Build Coastguard Worker {
298*4a64e381SAndroid Build Coastguard Worker Disconnect();
299*4a64e381SAndroid Build Coastguard Worker }
300*4a64e381SAndroid Build Coastguard Worker }
301*4a64e381SAndroid Build Coastguard Worker
Write(void)302*4a64e381SAndroid Build Coastguard Worker void Connection::Write(void)
303*4a64e381SAndroid Build Coastguard Worker {
304*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
305*4a64e381SAndroid Build Coastguard Worker std::string errorCode;
306*4a64e381SAndroid Build Coastguard Worker int32_t sendLength;
307*4a64e381SAndroid Build Coastguard Worker int32_t err;
308*4a64e381SAndroid Build Coastguard Worker
309*4a64e381SAndroid Build Coastguard Worker if (mState != ConnectionState::kWriteWait)
310*4a64e381SAndroid Build Coastguard Worker {
311*4a64e381SAndroid Build Coastguard Worker // Change its state when try write for the first time.
312*4a64e381SAndroid Build Coastguard Worker mState = ConnectionState::kWriteWait;
313*4a64e381SAndroid Build Coastguard Worker mTimeStamp = steady_clock::now();
314*4a64e381SAndroid Build Coastguard Worker mWriteContent = mResponse.Serialize();
315*4a64e381SAndroid Build Coastguard Worker }
316*4a64e381SAndroid Build Coastguard Worker
317*4a64e381SAndroid Build Coastguard Worker // Check we do have something to write.
318*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mWriteContent.size() > 0, error = OTBR_ERROR_REST);
319*4a64e381SAndroid Build Coastguard Worker
320*4a64e381SAndroid Build Coastguard Worker sendLength = write(mFd, mWriteContent.c_str(), mWriteContent.size());
321*4a64e381SAndroid Build Coastguard Worker err = errno;
322*4a64e381SAndroid Build Coastguard Worker
323*4a64e381SAndroid Build Coastguard Worker // Write successfully
324*4a64e381SAndroid Build Coastguard Worker if (sendLength == static_cast<int32_t>(mWriteContent.size()))
325*4a64e381SAndroid Build Coastguard Worker {
326*4a64e381SAndroid Build Coastguard Worker // Normal Exit
327*4a64e381SAndroid Build Coastguard Worker Disconnect();
328*4a64e381SAndroid Build Coastguard Worker }
329*4a64e381SAndroid Build Coastguard Worker else if (sendLength > 0)
330*4a64e381SAndroid Build Coastguard Worker {
331*4a64e381SAndroid Build Coastguard Worker // Partly write
332*4a64e381SAndroid Build Coastguard Worker mWriteContent = mWriteContent.substr(sendLength);
333*4a64e381SAndroid Build Coastguard Worker }
334*4a64e381SAndroid Build Coastguard Worker else
335*4a64e381SAndroid Build Coastguard Worker {
336*4a64e381SAndroid Build Coastguard Worker if (errno == EINTR)
337*4a64e381SAndroid Build Coastguard Worker {
338*4a64e381SAndroid Build Coastguard Worker // Try again
339*4a64e381SAndroid Build Coastguard Worker Write();
340*4a64e381SAndroid Build Coastguard Worker }
341*4a64e381SAndroid Build Coastguard Worker else
342*4a64e381SAndroid Build Coastguard Worker {
343*4a64e381SAndroid Build Coastguard Worker // There is an error when we write, if this, we directly disconnect this connection.
344*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(err == EAGAIN || err == EWOULDBLOCK, error = OTBR_ERROR_REST);
345*4a64e381SAndroid Build Coastguard Worker }
346*4a64e381SAndroid Build Coastguard Worker }
347*4a64e381SAndroid Build Coastguard Worker
348*4a64e381SAndroid Build Coastguard Worker exit:
349*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
350*4a64e381SAndroid Build Coastguard Worker {
351*4a64e381SAndroid Build Coastguard Worker Disconnect();
352*4a64e381SAndroid Build Coastguard Worker }
353*4a64e381SAndroid Build Coastguard Worker }
354*4a64e381SAndroid Build Coastguard Worker
IsComplete() const355*4a64e381SAndroid Build Coastguard Worker bool Connection::IsComplete() const
356*4a64e381SAndroid Build Coastguard Worker {
357*4a64e381SAndroid Build Coastguard Worker return mState == ConnectionState::kComplete;
358*4a64e381SAndroid Build Coastguard Worker }
359*4a64e381SAndroid Build Coastguard Worker
360*4a64e381SAndroid Build Coastguard Worker } // namespace rest
361*4a64e381SAndroid Build Coastguard Worker } // namespace otbr
362