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,24 @@ 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
80
Send (RequestOwner, new TEvHttpProxy::TEvHttpIncomingResponse (Request, Response, error));
71
81
RequestOwner = TActorId ();
72
82
THolder<TEvHttpProxy::TEvReportSensors> sensors (BuildOutgoingRequestSensors (Request, Response));
73
83
Send (Owner, sensors.Release ());
74
- PassAway ();
75
84
}
85
+ PassAway ();
76
86
}
77
87
78
88
protected:
@@ -84,7 +94,7 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
84
94
}
85
95
86
96
void Connect () {
87
- ALOG_DEBUG (HttpLog, GetSocketName () << " connecting" );
97
+ ALOG_DEBUG (HttpLog, GetSocketName () << " connecting to " << Address-> ToString () );
88
98
TSocketImpl::Create (Address->SockAddr ()->sa_family );
89
99
TSocketImpl::SetNonBlock ();
90
100
TSocketImpl::SetTimeout (ConnectionTimeout);
@@ -101,6 +111,26 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
101
111
}
102
112
}
103
113
114
+ void InitiateRequest (TEvHttpProxy::TEvHttpOutgoingRequest::TPtr& event) {
115
+ Request = std::move (event->Get ()->Request );
116
+ Destination = Request->GetDestination ();
117
+ TSocketImpl::SetHost (TString (Request->Host ));
118
+ RequestOwner = event->Sender ;
119
+ if (event->Get ()->Timeout ) {
120
+ ConnectionTimeout = event->Get ()->Timeout ;
121
+ }
122
+ AllowConnectionReuse = event->Get ()->AllowConnectionReuse ;
123
+ }
124
+
125
+ void PerformRequest () {
126
+ Request->Timer .Reset ();
127
+ ALOG_DEBUG (HttpLog, GetSocketName () << " resolving " << TSocketImpl::Host);
128
+ Send (Owner, new TEvHttpProxy::TEvResolveHostRequest (TSocketImpl::Host));
129
+ Schedule (ConnectionTimeout, new NActors::TEvents::TEvWakeup ());
130
+ LastActivity = NActors::TActivationContext::Now ();
131
+ TBase::Become (&TOutgoingConnectionActor::StateResolving);
132
+ }
133
+
104
134
void FlushOutput () {
105
135
if (Request != nullptr ) {
106
136
Request->Finish ();
@@ -123,13 +153,38 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
123
153
}
124
154
break ;
125
155
} else {
126
- ReplyErrorAndPassAway (res == 0 ? " ConnectionClosed " : strerror (-res));
156
+ ReplyErrorAndPassAway (res == 0 ? " " : strerror (-res));
127
157
break ;
128
158
}
129
159
}
130
160
}
131
161
}
132
162
163
+ void CheckClose () {
164
+ char buf[8 ];
165
+ for (;;) {
166
+ bool read = false , write = false ;
167
+ ssize_t res = TSocketImpl::Recv (&buf, 0 , read , write );
168
+ if (res > 0 ) {
169
+ return ReplyErrorAndPassAway (" Unexpected data received" );
170
+ } else if (-res == EINTR) {
171
+ continue ;
172
+ } else if (-res == EAGAIN || -res == EWOULDBLOCK) {
173
+ if (PollerToken) {
174
+ if (!read && !write ) {
175
+ read = true ;
176
+ }
177
+ if (PollerToken->RequestNotificationAfterWouldBlock (read , write )) {
178
+ continue ;
179
+ }
180
+ }
181
+ return ;
182
+ } else {
183
+ return ReplyErrorAndPassAway (res == 0 ? " " : strerror (-res));
184
+ }
185
+ }
186
+ }
187
+
133
188
void PullInput () {
134
189
for (;;) {
135
190
if (Response == nullptr ) {
@@ -165,7 +220,7 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
165
220
if (Response->IsDone () && Response->IsReady ()) {
166
221
return ReplyAndPassAway ();
167
222
}
168
- return ReplyErrorAndPassAway (res == 0 ? " ConnectionClosed " : strerror (-res));
223
+ return ReplyErrorAndPassAway (res == 0 ? " " : strerror (-res));
169
224
}
170
225
}
171
226
}
@@ -247,20 +302,8 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
247
302
}
248
303
249
304
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);
305
+ InitiateRequest (event);
306
+ PerformRequest ();
264
307
}
265
308
266
309
void HandleConnected (TEvHttpProxy::TEvHttpOutgoingRequest::TPtr& event) {
@@ -284,8 +327,12 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
284
327
if (event->Get ()->Write && RequestOwner) {
285
328
FlushOutput ();
286
329
}
287
- if (event->Get ()->Read && RequestOwner) {
288
- PullInput ();
330
+ if (event->Get ()->Read ) {
331
+ if (RequestOwner) {
332
+ PullInput ();
333
+ } else {
334
+ CheckClose ();
335
+ }
289
336
}
290
337
}
291
338
@@ -311,13 +358,6 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
311
358
}
312
359
}
313
360
314
- STATEFN (StateWaiting) {
315
- switch (ev->GetTypeRewrite ()) {
316
- hFunc (TEvHttpProxy::TEvHttpOutgoingRequest, HandleWaiting);
317
- cFunc (NActors::TEvents::TEvWakeup::EventType, HandleTimeout);
318
- }
319
- }
320
-
321
361
STATEFN (StateResolving) {
322
362
switch (ev->GetTypeRewrite ()) {
323
363
hFunc (TEvHttpProxy::TEvResolveHostResponse, HandleResolving);
@@ -349,11 +389,11 @@ class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor
349
389
}
350
390
};
351
391
352
- NActors::IActor* CreateOutgoingConnectionActor (const TActorId& owner, bool secure ) {
353
- if (secure ) {
354
- return new TOutgoingConnectionActor<TSecureSocketImpl>(owner);
392
+ NActors::IActor* CreateOutgoingConnectionActor (const TActorId& owner, TEvHttpProxy::TEvHttpOutgoingRequest::TPtr& event ) {
393
+ if (event-> Get ()-> Request -> Secure ) {
394
+ return new TOutgoingConnectionActor<TSecureSocketImpl>(owner, event );
355
395
} else {
356
- return new TOutgoingConnectionActor<TPlainSocketImpl>(owner);
396
+ return new TOutgoingConnectionActor<TPlainSocketImpl>(owner, event );
357
397
}
358
398
}
359
399
0 commit comments