4
4
namespace NHttp {
5
5
6
6
template <typename TSocketImpl>
7
- class TOutgoingConnectionActor : public NActors ::TActor <TOutgoingConnectionActor<TSocketImpl>>, public TSocketImpl, virtual public THttpConfig {
7
+ class TOutgoingConnectionActor : public NActors ::TActorBootstrapped <TOutgoingConnectionActor<TSocketImpl>>, public TSocketImpl, virtual public THttpConfig {
8
8
public:
9
- using TBase = NActors::TActor <TOutgoingConnectionActor<TSocketImpl>>;
9
+ using TBase = NActors::TActorBootstrapped <TOutgoingConnectionActor<TSocketImpl>>;
10
10
using TSelf = TOutgoingConnectionActor<TSocketImpl>;
11
+ using TBase::Become;
11
12
using TBase::Send;
12
13
using TBase::Schedule;
13
14
using TBase::SelfId;
@@ -23,14 +24,18 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
23
24
bool AllowConnectionReuse = false ;
24
25
NActors::TPollerToken::TPtr PollerToken;
25
26
26
- TOutgoingConnectionActor (const TActorId& owner)
27
- : TBase(&TSelf::StateWaiting)
28
- , Owner(owner)
27
+ TOutgoingConnectionActor (const TActorId& owner, TEvHttpProxy::TEvHttpOutgoingRequest::TPtr& event)
28
+ : Owner(owner)
29
29
{
30
+ InitiateRequest (event);
30
31
}
31
32
32
33
static constexpr char ActorName[] = " OUT_CONNECTION_ACTOR" ;
33
34
35
+ void Bootstrap () {
36
+ PerformRequest ();
37
+ }
38
+
34
39
void PassAway () override {
35
40
Send (Owner, new TEvHttpProxy::TEvHttpOutgoingConnectionClosed (SelfId (), Destination));
36
41
TSocketImpl::Shutdown (); // to avoid errors when connection already closed
@@ -60,19 +65,28 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
60
65
PassAway ();
61
66
} else {
62
67
ALOG_DEBUG (HttpLog, GetSocketName () << " connection available for reuse" );
68
+ CheckClose ();
63
69
Send (Owner, new TEvHttpProxy::TEvHttpOutgoingConnectionAvailable (SelfId (), Destination));
64
70
}
65
71
}
66
72
67
73
void ReplyErrorAndPassAway (const TString& error) {
68
- ALOG_ERROR (HttpLog, GetSocketName () << " connection closed with error: " << error);
74
+ if (error) {
75
+ ALOG_ERROR (HttpLog, GetSocketName () << " connection closed with error: " << error);
76
+ } else {
77
+ ALOG_DEBUG (HttpLog, GetSocketName () << " connection closed" );
78
+ }
69
79
if (RequestOwner) {
70
- Send (RequestOwner, new TEvHttpProxy::TEvHttpIncomingResponse (Request, Response, error));
80
+ if (!error && Response && !Response->IsReady ()) {
81
+ Send (RequestOwner, new TEvHttpProxy::TEvHttpIncomingResponse (Request, Response, " ConnectionClosed" )); // connection closed prematurely
82
+ } else {
83
+ Send (RequestOwner, new TEvHttpProxy::TEvHttpIncomingResponse (Request, Response, error));
84
+ }
71
85
RequestOwner = TActorId ();
72
86
THolder<TEvHttpProxy::TEvReportSensors> sensors (BuildOutgoingRequestSensors (Request, Response));
73
87
Send (Owner, sensors.Release ());
74
- PassAway ();
75
88
}
89
+ PassAway ();
76
90
}
77
91
78
92
protected:
@@ -84,7 +98,7 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
84
98
}
85
99
86
100
void Connect () {
87
- ALOG_DEBUG (HttpLog, GetSocketName () << " connecting" );
101
+ ALOG_DEBUG (HttpLog, GetSocketName () << " connecting to " << Address-> ToString () );
88
102
TSocketImpl::Create (Address->SockAddr ()->sa_family );
89
103
TSocketImpl::SetNonBlock ();
90
104
TSocketImpl::SetTimeout (ConnectionTimeout);
@@ -101,6 +115,26 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
101
115
}
102
116
}
103
117
118
+ void InitiateRequest (TEvHttpProxy::TEvHttpOutgoingRequest::TPtr& event) {
119
+ Request = std::move (event->Get ()->Request );
120
+ Destination = Request->GetDestination ();
121
+ TSocketImpl::SetHost (TString (Request->Host ));
122
+ RequestOwner = event->Sender ;
123
+ if (event->Get ()->Timeout ) {
124
+ ConnectionTimeout = event->Get ()->Timeout ;
125
+ }
126
+ AllowConnectionReuse = event->Get ()->AllowConnectionReuse ;
127
+ }
128
+
129
+ void PerformRequest () {
130
+ Request->Timer .Reset ();
131
+ ALOG_DEBUG (HttpLog, GetSocketName () << " resolving " << TSocketImpl::Host);
132
+ Send (Owner, new TEvHttpProxy::TEvResolveHostRequest (TSocketImpl::Host));
133
+ Schedule (ConnectionTimeout, new NActors::TEvents::TEvWakeup ());
134
+ LastActivity = NActors::TActivationContext::Now ();
135
+ TBase::Become (&TOutgoingConnectionActor::StateResolving);
136
+ }
137
+
104
138
void FlushOutput () {
105
139
if (Request != nullptr ) {
106
140
Request->Finish ();
@@ -123,13 +157,38 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
123
157
}
124
158
break ;
125
159
} else {
126
- ReplyErrorAndPassAway (res == 0 ? " ConnectionClosed " : strerror (-res));
160
+ ReplyErrorAndPassAway (res == 0 ? " " : strerror (-res));
127
161
break ;
128
162
}
129
163
}
130
164
}
131
165
}
132
166
167
+ void CheckClose () {
168
+ char buf[8 ];
169
+ for (;;) {
170
+ bool read = false , write = false ;
171
+ ssize_t res = TSocketImpl::Recv (&buf, 0 , read , write );
172
+ if (res > 0 ) {
173
+ return ReplyErrorAndPassAway (" Unexpected data received" );
174
+ } else if (-res == EINTR) {
175
+ continue ;
176
+ } else if (-res == EAGAIN || -res == EWOULDBLOCK) {
177
+ if (PollerToken) {
178
+ if (!read && !write ) {
179
+ read = true ;
180
+ }
181
+ if (PollerToken->RequestNotificationAfterWouldBlock (read , write )) {
182
+ continue ;
183
+ }
184
+ }
185
+ return ;
186
+ } else {
187
+ return ReplyErrorAndPassAway (res == 0 ? " " : strerror (-res));
188
+ }
189
+ }
190
+ }
191
+
133
192
void PullInput () {
134
193
for (;;) {
135
194
if (Response == nullptr ) {
@@ -165,7 +224,7 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
165
224
if (Response->IsDone () && Response->IsReady ()) {
166
225
return ReplyAndPassAway ();
167
226
}
168
- return ReplyErrorAndPassAway (res == 0 ? " ConnectionClosed " : strerror (-res));
227
+ return ReplyErrorAndPassAway (res == 0 ? " " : strerror (-res));
169
228
}
170
229
}
171
230
}
@@ -247,20 +306,8 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
247
306
}
248
307
249
308
void HandleWaiting (TEvHttpProxy::TEvHttpOutgoingRequest::TPtr& event) {
250
- Request = std::move (event->Get ()->Request );
251
- Destination = Request->GetDestination ();
252
- TSocketImpl::SetHost (TString (Request->Host ));
253
- ALOG_DEBUG (HttpLog, GetSocketName () << " resolving " << TSocketImpl::Host);
254
- Request->Timer .Reset ();
255
- RequestOwner = event->Sender ;
256
- Send (Owner, new TEvHttpProxy::TEvResolveHostRequest (TSocketImpl::Host));
257
- if (event->Get ()->Timeout ) {
258
- ConnectionTimeout = event->Get ()->Timeout ;
259
- }
260
- AllowConnectionReuse = event->Get ()->AllowConnectionReuse ;
261
- Schedule (ConnectionTimeout, new NActors::TEvents::TEvWakeup ());
262
- LastActivity = NActors::TActivationContext::Now ();
263
- TBase::Become (&TOutgoingConnectionActor::StateResolving);
309
+ InitiateRequest (event);
310
+ PerformRequest ();
264
311
}
265
312
266
313
void HandleConnected (TEvHttpProxy::TEvHttpOutgoingRequest::TPtr& event) {
@@ -284,8 +331,12 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
284
331
if (event->Get ()->Write && RequestOwner) {
285
332
FlushOutput ();
286
333
}
287
- if (event->Get ()->Read && RequestOwner) {
288
- PullInput ();
334
+ if (event->Get ()->Read ) {
335
+ if (RequestOwner) {
336
+ PullInput ();
337
+ } else {
338
+ CheckClose ();
339
+ }
289
340
}
290
341
}
291
342
@@ -311,13 +362,6 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
311
362
}
312
363
}
313
364
314
- STATEFN (StateWaiting) {
315
- switch (ev->GetTypeRewrite ()) {
316
- hFunc (TEvHttpProxy::TEvHttpOutgoingRequest, HandleWaiting);
317
- cFunc (NActors::TEvents::TEvWakeup::EventType, HandleTimeout);
318
- }
319
- }
320
-
321
365
STATEFN (StateResolving) {
322
366
switch (ev->GetTypeRewrite ()) {
323
367
hFunc (TEvHttpProxy::TEvResolveHostResponse, HandleResolving);
@@ -349,11 +393,11 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
349
393
}
350
394
};
351
395
352
- NActors::IActor* CreateOutgoingConnectionActor (const TActorId& owner, bool secure ) {
353
- if (secure ) {
354
- return new TOutgoingConnectionActor<TSecureSocketImpl>(owner);
396
+ NActors::IActor* CreateOutgoingConnectionActor (const TActorId& owner, TEvHttpProxy::TEvHttpOutgoingRequest::TPtr& event ) {
397
+ if (event-> Get ()-> Request -> Secure ) {
398
+ return new TOutgoingConnectionActor<TSecureSocketImpl>(owner, event );
355
399
} else {
356
- return new TOutgoingConnectionActor<TPlainSocketImpl>(owner);
400
+ return new TOutgoingConnectionActor<TPlainSocketImpl>(owner, event );
357
401
}
358
402
}
359
403
0 commit comments