1 /** @file
2
3 ProxyTransaction - Base class for protocol client transactions.
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 #include "http/HttpSM.h"
25 #include "Plugin.h"
26
27 #define HttpTxnDebug(fmt, ...) SsnDebug(this, "http_txn", fmt, __VA_ARGS__)
28
29 extern ClassAllocator<HttpSM> httpSMAllocator;
30
ProxyTransaction(ProxySession * session)31 ProxyTransaction::ProxyTransaction(ProxySession *session) : VConnection(nullptr), _proxy_ssn(session) {}
32
~ProxyTransaction()33 ProxyTransaction::~ProxyTransaction()
34 {
35 this->_sm = nullptr;
36 this->mutex.clear();
37 }
38
39 void
new_transaction(bool from_early_data)40 ProxyTransaction::new_transaction(bool from_early_data)
41 {
42 ink_release_assert(_sm == nullptr);
43
44 // Defensive programming, make sure nothing persists across
45 // connection re-use
46
47 ink_release_assert(_proxy_ssn != nullptr);
48 _sm = THREAD_ALLOC(httpSMAllocator, this_thread());
49 _sm->init(from_early_data);
50 HttpTxnDebug("[%" PRId64 "] Starting transaction %d using sm [%" PRId64 "]", _proxy_ssn->connection_id(),
51 _proxy_ssn->get_transact_count(), _sm->sm_id);
52
53 // PI tag valid only for internal requests
54 if (this->get_netvc()->get_is_internal_request()) {
55 PluginIdentity *pi = dynamic_cast<PluginIdentity *>(this->get_netvc());
56 if (pi) {
57 _sm->plugin_tag = pi->getPluginTag();
58 _sm->plugin_id = pi->getPluginId();
59 }
60 }
61
62 this->increment_client_transactions_stat();
63 _sm->attach_client_session(this, _reader);
64 }
65
66 bool
attach_server_session(PoolableSession * ssession,bool transaction_done)67 ProxyTransaction::attach_server_session(PoolableSession *ssession, bool transaction_done)
68 {
69 return _proxy_ssn->attach_server_session(ssession, transaction_done);
70 }
71
72 void
set_rx_error_code(ProxyError e)73 ProxyTransaction::set_rx_error_code(ProxyError e)
74 {
75 if (this->_sm) {
76 this->_sm->t_state.client_info.rx_error_code = e;
77 }
78 }
79
80 void
set_tx_error_code(ProxyError e)81 ProxyTransaction::set_tx_error_code(ProxyError e)
82 {
83 if (this->_sm) {
84 this->_sm->t_state.client_info.tx_error_code = e;
85 }
86 }
87
88 NetVConnection *
get_netvc() const89 ProxyTransaction::get_netvc() const
90 {
91 return (_proxy_ssn) ? _proxy_ssn->get_netvc() : nullptr;
92 }
93
94 bool
is_first_transaction() const95 ProxyTransaction::is_first_transaction() const
96 {
97 return _proxy_ssn->get_transact_count() == 1;
98 }
99
100 void
set_session_active()101 ProxyTransaction::set_session_active()
102 {
103 if (_proxy_ssn) {
104 _proxy_ssn->set_session_active();
105 }
106 }
107
108 void
clear_session_active()109 ProxyTransaction::clear_session_active()
110 {
111 if (_proxy_ssn) {
112 _proxy_ssn->clear_session_active();
113 }
114 }
115
116 const IpAllow::ACL &
get_acl() const117 ProxyTransaction::get_acl() const
118 {
119 return _proxy_ssn ? _proxy_ssn->acl : IpAllow::DENY_ALL_ACL;
120 }
121
122 // outbound values Set via the server port definition. Really only used for Http1 at the moment
123 in_port_t
get_outbound_port() const124 ProxyTransaction::get_outbound_port() const
125 {
126 return upstream_outbound_options.outbound_port;
127 }
128 void
set_outbound_port(in_port_t port)129 ProxyTransaction::set_outbound_port(in_port_t port)
130 {
131 upstream_outbound_options.outbound_port = port;
132 }
133
134 IpAddr
get_outbound_ip4() const135 ProxyTransaction::get_outbound_ip4() const
136 {
137 return upstream_outbound_options.outbound_ip4;
138 }
139
140 IpAddr
get_outbound_ip6() const141 ProxyTransaction::get_outbound_ip6() const
142 {
143 return upstream_outbound_options.outbound_ip6;
144 }
145
146 void
set_outbound_ip(const IpAddr & new_addr)147 ProxyTransaction::set_outbound_ip(const IpAddr &new_addr)
148 {
149 if (new_addr.isIp4()) {
150 upstream_outbound_options.outbound_ip4 = new_addr;
151 } else if (new_addr.isIp6()) {
152 upstream_outbound_options.outbound_ip6 = new_addr;
153 } else {
154 upstream_outbound_options.outbound_ip4.invalidate();
155 upstream_outbound_options.outbound_ip6.invalidate();
156 }
157 }
158 bool
is_outbound_transparent() const159 ProxyTransaction::is_outbound_transparent() const
160 {
161 return upstream_outbound_options.f_outbound_transparent;
162 }
163
164 void
set_outbound_transparent(bool flag)165 ProxyTransaction::set_outbound_transparent(bool flag)
166 {
167 upstream_outbound_options.f_outbound_transparent = flag;
168 }
169
170 int
get_transaction_priority_weight() const171 ProxyTransaction::get_transaction_priority_weight() const
172 {
173 return 0;
174 }
175
176 int
get_transaction_priority_dependence() const177 ProxyTransaction::get_transaction_priority_dependence() const
178 {
179 return 0;
180 }
181
182 void
transaction_done()183 ProxyTransaction::transaction_done()
184 {
185 SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
186 this->decrement_client_transactions_stat();
187 }
188
189 // Implement VConnection interface.
190 VIO *
do_io_read(Continuation * c,int64_t nbytes,MIOBuffer * buf)191 ProxyTransaction::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
192 {
193 return _proxy_ssn->do_io_read(c, nbytes, buf);
194 }
195 VIO *
do_io_write(Continuation * c,int64_t nbytes,IOBufferReader * buf,bool owner)196 ProxyTransaction::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
197 {
198 return _proxy_ssn->do_io_write(c, nbytes, buf, owner);
199 }
200
201 void
do_io_close(int lerrno)202 ProxyTransaction::do_io_close(int lerrno)
203 {
204 _proxy_ssn->do_io_close(lerrno);
205 // this->destroy(); Parent owns this data structure. No need for separate destroy.
206 }
207
208 void
do_io_shutdown(ShutdownHowTo_t howto)209 ProxyTransaction::do_io_shutdown(ShutdownHowTo_t howto)
210 {
211 _proxy_ssn->do_io_shutdown(howto);
212 }
213
214 void
reenable(VIO * vio)215 ProxyTransaction::reenable(VIO *vio)
216 {
217 _proxy_ssn->reenable(vio);
218 }
219
220 bool
has_request_body(int64_t request_content_length,bool is_chunked) const221 ProxyTransaction::has_request_body(int64_t request_content_length, bool is_chunked) const
222 {
223 return request_content_length > 0 || is_chunked;
224 }
225
226 bool
allow_half_open() const227 ProxyTransaction::allow_half_open() const
228 {
229 return false;
230 }
231