Skip to content

Commit e0d52c1

Browse files
committed
[filter] Added connection state callback to the connectHTTPTunnel() filter
1 parent 7d98726 commit e0d52c1

File tree

4 files changed

+58
-5
lines changed

4 files changed

+58
-5
lines changed

src/api/pipeline-api.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ void PipelineDesigner::connect(const pjs::Value &target, pjs::Object *options) {
174174
}
175175
}
176176

177-
void PipelineDesigner::connect_http_tunnel(pjs::Object *handshake) {
178-
require_sub_pipeline(append_filter(new http::TunnelClient(handshake)));
177+
void PipelineDesigner::connect_http_tunnel(pjs::Object *handshake, pjs::Object *options) {
178+
require_sub_pipeline(append_filter(new http::TunnelClient(handshake, options)));
179179
}
180180

181181
void PipelineDesigner::connect_proxy_protocol(const pjs::Value &address) {
@@ -750,8 +750,9 @@ template<> void ClassDef<PipelineDesigner>::init() {
750750
// PipelineDesigner.connectHTTPTunnel
751751
filter("connectHTTPTunnel", [](Context &ctx, PipelineDesigner *obj) {
752752
Object *handshake;
753-
if (!ctx.arguments(1, &handshake)) return;
754-
obj->connect_http_tunnel(handshake);
753+
Object *options = nullptr;
754+
if (!ctx.arguments(1, &handshake, &options)) return;
755+
obj->connect_http_tunnel(handshake, options);
755756
});
756757

757758
// PipelineDesigner.connectProxyProtocol

src/api/pipeline-api.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class PipelineDesigner : public pjs::ObjectTemplate<PipelineDesigner> {
6363
void compress(const pjs::Value &algorithm);
6464
void compress_http(const pjs::Value &algorithm);
6565
void connect(const pjs::Value &target, pjs::Object *options);
66-
void connect_http_tunnel(pjs::Object *handshake);
66+
void connect_http_tunnel(pjs::Object *handshake, pjs::Object *options);
6767
void connect_proxy_protocol(const pjs::Value &address);
6868
void connect_socks(const pjs::Value &address);
6969
void connect_tls(pjs::Object *options);

src/filters/http.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -1909,14 +1909,27 @@ void TunnelServer::start_tunnel(Message *response) {
19091909
// TunnelClient
19101910
//
19111911

1912+
TunnelClient::Options::Options(pjs::Object *options) {
1913+
Value(options, "onState")
1914+
.get(on_state_f)
1915+
.check_nullable();
1916+
}
1917+
19121918
TunnelClient::TunnelClient(pjs::Object *handshake)
19131919
: m_handshake(handshake)
19141920
{
19151921
}
19161922

1923+
TunnelClient::TunnelClient(pjs::Object *handshake, const Options &options)
1924+
: m_handshake(handshake)
1925+
, m_options(options)
1926+
{
1927+
}
1928+
19171929
TunnelClient::TunnelClient(const TunnelClient &r)
19181930
: Filter(r)
19191931
, m_handshake(r.m_handshake)
1932+
, m_options(r.m_options)
19201933
{
19211934
}
19221935

@@ -1941,11 +1954,18 @@ void TunnelClient::reset() {
19411954
m_request_head = nullptr;
19421955
m_response_head = nullptr;
19431956
m_eos = nullptr;
1957+
m_on_state_change = nullptr;
19441958
m_is_tunnel_started = false;
19451959
}
19461960

19471961
void TunnelClient::process(Event *evt) {
19481962
if (!m_pipeline) {
1963+
if (m_options.on_state_f) {
1964+
m_on_state_change = [=](State state) {
1965+
pjs::Value arg(pjs::EnumDef<State>::name(state)), ret;
1966+
Filter::callback(m_options.on_state_f, 1, &arg, ret);
1967+
};
1968+
}
19491969
pjs::Ref<pjs::Object> handshake;
19501970
if (m_handshake) {
19511971
if (m_handshake->is_instance_of<Message>()) {
@@ -1964,6 +1984,9 @@ void TunnelClient::process(Event *evt) {
19641984
m_request_head = pjs::coerce<RequestHead>(msg->head());
19651985
m_pipeline = sub_pipeline(0, true, EventSource::reply())->start();
19661986
Filter::output(msg->as<Message>(), m_pipeline->input());
1987+
if (m_on_state_change) {
1988+
m_on_state_change(State::connecting);
1989+
}
19671990
}
19681991

19691992
if (m_is_tunnel_started) {
@@ -1992,12 +2015,18 @@ void TunnelClient::on_reply(Event *evt) {
19922015
auto tt = m_request_head->tunnel_type();
19932016
if (m_response_head->is_tunnel_ok(tt)) {
19942017
m_is_tunnel_started = true;
2018+
if (m_on_state_change) {
2019+
m_on_state_change(State::connected);
2020+
}
19952021
if (m_eos) {
19962022
EventFunction::input()->input_async(m_eos);
19972023
} else {
19982024
EventFunction::input()->flush_async();
19992025
}
20002026
} else {
2027+
if (m_on_state_change) {
2028+
m_on_state_change(State::closed);
2029+
}
20012030
Filter::output(StreamEnd::make());
20022031
}
20032032
m_request_head = nullptr;
@@ -2024,4 +2053,11 @@ template<> void ClassDef<Server::Handler>::init() {
20242053
super<Promise::Callback>();
20252054
}
20262055

2056+
template<> void EnumDef<TunnelClient::State>::init() {
2057+
define(TunnelClient::State::idle, "idle");
2058+
define(TunnelClient::State::connecting, "connecting");
2059+
define(TunnelClient::State::connected, "connected");
2060+
define(TunnelClient::State::closed, "closed");
2061+
}
2062+
20272063
} // namespace pjs

src/filters/http.hpp

+16
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,21 @@ class TunnelServer : public Filter {
529529

530530
class TunnelClient : public Filter, public EventSource {
531531
public:
532+
enum class State {
533+
idle,
534+
connecting,
535+
connected,
536+
closed,
537+
};
538+
539+
struct Options : public pipy::Options {
540+
pjs::Ref<pjs::Function> on_state_f;
541+
Options() {}
542+
Options(pjs::Object *options);
543+
};
544+
532545
TunnelClient(pjs::Object *handshake);
546+
TunnelClient(pjs::Object *handshake, const Options &options);
533547

534548
private:
535549
TunnelClient(const TunnelClient &r);
@@ -547,6 +561,8 @@ class TunnelClient : public Filter, public EventSource {
547561
pjs::Ref<ResponseHead> m_response_head;
548562
pjs::Ref<StreamEnd> m_eos;
549563
Data m_buffer;
564+
Options m_options;
565+
std::function<void(State state)> m_on_state_change;
550566
bool m_is_tunnel_started = false;
551567
};
552568

0 commit comments

Comments
 (0)