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