1 /** @file
2
3 A brief file description
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 /****************************************************************************
25
26 PluginVC.h
27
28 Description: Allows bi-directional transfer for data from one
29 continuation to another via a mechanism that impersonates a
30 NetVC. Should implement all external attributes of NetVConnections.
31 [See PluginVC.cc for further comments]
32
33
34 ****************************************************************************/
35
36 #pragma once
37
38 #include "Plugin.h"
39 #include "P_Net.h"
40 #include "tscore/ink_atomic.h"
41
42 class PluginVCCore;
43
44 struct PluginVCState {
45 PluginVCState();
46 VIO vio;
47 bool shutdown = false;
48 };
49
PluginVCState()50 inline PluginVCState::PluginVCState() : vio() {}
51
52 enum PluginVC_t {
53 PLUGIN_VC_UNKNOWN,
54 PLUGIN_VC_ACTIVE,
55 PLUGIN_VC_PASSIVE,
56 };
57
58 // For the id in set_data/get_data
59 enum {
60 PLUGIN_VC_DATA_LOCAL = TS_API_DATA_LAST,
61 PLUGIN_VC_DATA_REMOTE,
62 };
63
64 enum {
65 PLUGIN_VC_MAGIC_ALIVE = 0xaabbccdd,
66 PLUGIN_VC_MAGIC_DEAD = 0xaabbdead,
67 };
68
69 class PluginVC : public NetVConnection, public PluginIdentity
70 {
71 friend class PluginVCCore;
72
73 public:
74 PluginVC(PluginVCCore *core_obj);
75 ~PluginVC() override;
76
77 VIO *do_io_read(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override;
78
79 VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = nullptr,
80 bool owner = false) override;
81
82 void do_io_close(int lerrno = -1) override;
83 void do_io_shutdown(ShutdownHowTo_t howto) override;
84
85 // Reenable a given vio. The public interface is through VIO::reenable
86 void reenable(VIO *vio) override;
87 void reenable_re(VIO *vio) override;
88
89 // Timeouts
90 void set_active_timeout(ink_hrtime timeout_in) override;
91 void set_inactivity_timeout(ink_hrtime timeout_in) override;
92 void set_default_inactivity_timeout(ink_hrtime timeout_in) override;
93 bool is_default_inactivity_timeout() override;
94 void cancel_active_timeout() override;
95 void cancel_inactivity_timeout() override;
96 void add_to_keep_alive_queue() override;
97 void remove_from_keep_alive_queue() override;
98 bool add_to_active_queue() override;
99 ink_hrtime get_active_timeout() override;
100 ink_hrtime get_inactivity_timeout() override;
101
102 // Pure virtual functions we need to compile
103 SOCKET get_socket() override;
104 void set_local_addr() override;
105 void set_remote_addr() override;
106 void set_remote_addr(const sockaddr *) override;
107 void set_mptcp_state() override;
108 int set_tcp_congestion_control(int) override;
109
110 void apply_options() override;
111
112 bool get_data(int id, void *data) override;
113 bool set_data(int id, void *data) override;
114
115 virtual PluginVC *
get_other_side()116 get_other_side()
117 {
118 return other_side;
119 }
120
121 //@{ @name Plugin identity.
122 /// Override for @c PluginIdentity.
123 const char *
getPluginTag()124 getPluginTag() const override
125 {
126 return plugin_tag;
127 }
128 /// Override for @c PluginIdentity.
129 int64_t
getPluginId()130 getPluginId() const override
131 {
132 return plugin_id;
133 }
134
135 /// Setter for plugin tag.
136 virtual void
setPluginTag(const char * tag)137 setPluginTag(const char *tag)
138 {
139 plugin_tag = tag;
140 }
141 /// Setter for plugin id.
142 virtual void
setPluginId(int64_t id)143 setPluginId(int64_t id)
144 {
145 plugin_id = id;
146 }
147 //@}
148
149 int main_handler(int event, void *data);
150
151 private:
152 void process_read_side(bool);
153 void process_write_side(bool);
154 void process_close();
155 void process_timeout(Event **e, int event_to_send);
156
157 // Clear the Event pointer pointed to by e
158 // Cancel the action first if it is a periodic event
159 void clear_event(Event **e);
160
161 void setup_event_cb(ink_hrtime in, Event **e_ptr);
162
163 void update_inactive_time();
164 int64_t transfer_bytes(MIOBuffer *transfer_to, IOBufferReader *transfer_from, int64_t act_on);
165
166 uint32_t magic;
167 PluginVC_t vc_type;
168 PluginVCCore *core_obj;
169
170 PluginVC *other_side;
171
172 PluginVCState read_state;
173 PluginVCState write_state;
174
175 bool need_read_process;
176 bool need_write_process;
177
178 bool closed;
179 Event *sm_lock_retry_event;
180 Event *core_lock_retry_event;
181
182 bool deletable;
183 int reentrancy_count;
184
185 ink_hrtime active_timeout;
186 Event *active_event;
187
188 ink_hrtime inactive_timeout;
189 ink_hrtime inactive_timeout_at;
190 Event *inactive_event;
191
192 const char *plugin_tag;
193 int64_t plugin_id;
194 };
195
196 class PluginVCCore : public Continuation
197 {
198 friend class PluginVC;
199
200 public:
201 PluginVCCore();
202 ~PluginVCCore() override;
203
204 // Allocate a PluginVCCore object, passing the continuation which
205 // will receive NET_EVENT_ACCEPT to accept the new session.
206 static PluginVCCore *alloc(Continuation *acceptor);
207
208 int state_send_accept(int event, void *data);
209 int state_send_accept_failed(int event, void *data);
210
211 void attempt_delete();
212
213 PluginVC *connect();
214 Action *connect_re(Continuation *c);
215 void kill_no_connect();
216
217 /// Set the active address.
218 void set_active_addr(in_addr_t ip, ///< IPv4 address in host order.
219 int port ///< IP Port in host order.
220 );
221 /// Set the active address and port.
222 void set_active_addr(sockaddr const *ip ///< Address and port used.
223 );
224 /// Set the passive address.
225 void set_passive_addr(in_addr_t ip, ///< IPv4 address in host order.
226 int port ///< IP port in host order.
227 );
228 /// Set the passive address.
229 void set_passive_addr(sockaddr const *ip ///< Address and port.
230 );
231
232 void set_active_data(void *data);
233 void set_passive_data(void *data);
234
235 void set_transparent(bool passive_side, bool active_side);
236
237 /// Set the plugin ID for the internal VCs.
238 void set_plugin_id(int64_t id);
239 /// Set the plugin tag for the internal VCs.
240 void set_plugin_tag(const char *tag);
241
242 // The active vc is handed to the initiator of
243 // connection. The passive vc is handled to
244 // receiver of the connection
245 PluginVC active_vc;
246 PluginVC passive_vc;
247
248 private:
249 void init();
250 void destroy();
251
252 Continuation *connect_to = nullptr;
253 bool connected = false;
254
255 MIOBuffer *p_to_a_buffer = nullptr;
256 IOBufferReader *p_to_a_reader = nullptr;
257
258 MIOBuffer *a_to_p_buffer = nullptr;
259 IOBufferReader *a_to_p_reader = nullptr;
260
261 IpEndpoint passive_addr_struct;
262 IpEndpoint active_addr_struct;
263
264 void *passive_data = nullptr;
265 void *active_data = nullptr;
266
267 static int32_t nextid;
268 unsigned id = 0;
269 };
270
PluginVCCore()271 inline PluginVCCore::PluginVCCore() : active_vc(this), passive_vc(this)
272
273 {
274 memset(&active_addr_struct, 0, sizeof active_addr_struct);
275 memset(&passive_addr_struct, 0, sizeof passive_addr_struct);
276
277 id = ink_atomic_increment(&nextid, 1);
278 }
279