1 /** @file
2 
3   Public VConnection declaration and associated declarations
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 #pragma once
26 
27 #include "ts/ink_platform.h"
28 #include "I_EventSystem.h"
29 
30 #if !defined(I_VIO_h)
31 #error "include I_VIO.h"
32 #endif
33 
34 #include <array>
35 
36 static constexpr int TS_VCONN_MAX_USER_ARG = 4;
37 
38 //
39 // Data Types
40 //
41 #define VCONNECTION_CACHE_DATA_BASE 0
42 #define VCONNECTION_NET_DATA_BASE 100
43 #define VCONNECTION_API_DATA_BASE 200
44 
45 //
46 // Event signals
47 //
48 
49 #define VC_EVENT_NONE EVENT_NONE
50 
51 /** When a Continuation is first scheduled on a processor. */
52 #define VC_EVENT_IMMEDIATE EVENT_IMMEDIATE
53 
54 #define VC_EVENT_READ_READY VC_EVENT_EVENTS_START
55 
56 /**
57   Any data in the accociated buffer *will be written* when the
58   Continuation returns.
59 
60 */
61 #define VC_EVENT_WRITE_READY (VC_EVENT_EVENTS_START + 1)
62 
63 #define VC_EVENT_READ_COMPLETE (VC_EVENT_EVENTS_START + 2)
64 #define VC_EVENT_WRITE_COMPLETE (VC_EVENT_EVENTS_START + 3)
65 
66 /**
67   No more data (end of stream). It should be interpreted by a
68   protocol engine as either a COMPLETE or ERROR.
69 
70 */
71 #define VC_EVENT_EOS (VC_EVENT_EVENTS_START + 4)
72 
73 #define VC_EVENT_ERROR EVENT_ERROR
74 
75 /**
76   VC_EVENT_INACTIVITY_TIMEOUT indiates that the operation (read or write) has:
77     -# been enabled for more than the inactivity timeout period
78        (for a read, there has been space in the buffer)
79        (for a write, there has been data in the buffer)
80     -# no progress has been made
81        (for a read, no data has been read from the connection)
82        (for a write, no data has been written to the connection)
83 
84 */
85 #define VC_EVENT_INACTIVITY_TIMEOUT (VC_EVENT_EVENTS_START + 5)
86 
87 /**
88   Total time for some operation has been exeeded, regardless of any
89   intermediate progress.
90 
91 */
92 #define VC_EVENT_ACTIVE_TIMEOUT (VC_EVENT_EVENTS_START + 6)
93 
94 #define VC_EVENT_OOB_COMPLETE (VC_EVENT_EVENTS_START + 7)
95 
96 //
97 // Event names
98 //
99 
100 //
101 // VC_EVENT_READ_READ occurs when data *has been written* into
102 // the associated buffer.
103 //
104 // VC_EVENT_ERROR indicates that some error has occured.  The
105 // "data" will be either 0 if the errno is unavailable or errno.
106 //
107 // VC_EVENT_INTERVAL indidates that an interval timer has expired.
108 //
109 
110 //
111 // Event return codes
112 //
113 #define VC_EVENT_DONE CONTINUATION_DONE
114 #define VC_EVENT_CONT CONTINUATION_CONT
115 
116 //////////////////////////////////////////////////////////////////////////////
117 //
118 //      Support Data Structures
119 //
120 //////////////////////////////////////////////////////////////////////////////
121 
122 /** Used in VConnection::shutdown(). */
123 enum ShutdownHowTo_t {
124   IO_SHUTDOWN_READ = 0,
125   IO_SHUTDOWN_WRITE,
126   IO_SHUTDOWN_READWRITE,
127 };
128 
129 /** Used in VConnection::get_data(). */
130 enum TSApiDataType {
131   TS_API_DATA_READ_VIO = VCONNECTION_API_DATA_BASE,
132   TS_API_DATA_WRITE_VIO,
133   TS_API_DATA_OUTPUT_VC,
134   TS_API_DATA_CLOSED,
135   TS_API_DATA_LAST ///< Used by other classes to extend the enum values.
136 };
137 
138 extern "C" {
139 typedef struct tsapi_vio *TSVIO;
140 }
141 
142 /**
143   Base class for the connection classes that provide IO capabilities.
144 
145   The VConnection class is an abstract representation of a uni or
146   bi-directional data conduit returned by a Processor. In a sense,
147   they serve a similar purpose to file descriptors. A VConnection
148   is a pure base class that defines methods to perform stream IO.
149   It is also a Continuation that is called back from processors.
150 
151 */
152 class VConnection : public Continuation
153 {
154 public:
155   virtual ~VConnection();
156 
157   /**
158     Read data from the VConnection.
159 
160     Called by a state machine to read data from the VConnection.
161     Processors implementing read functionality take out lock, put
162     new bytes on the buffer and call the continuation back before
163     releasing the lock in order to enable the state machine to
164     handle transfer schemes where the end of a given transaction
165     is marked by a special character (ie: NNTP).
166 
167     <b>Possible Event Codes</b>
168 
169     On the callback to the continuation, the VConnection may use
170     on of the following values for the event code:
171 
172     <table border="1">
173       <tr>
174         <td align="center"><b>Event code</b></td>
175         <td align="center"><b>Meaning</b></td>
176       </tr>
177       <tr>
178         <td>VC_EVENT_READ_READY</td>
179         <td>Data has been added to the buffer or the buffer is full</td>
180       </tr>
181       <tr>
182         <td>VC_EVENT_READ_COMPLETE</td>
183         <td>The amount of data indicated by 'nbytes' has been read into the
184             buffer</td>
185       </tr>
186       <tr>
187         <td>VC_EVENT_EOS</td>
188         <td>The stream being read from has been shutdown</td>
189       </tr>
190       <tr>
191         <td>VC_EVENT_ERROR</td>
192         <td>An error occurred during the read</td>
193       </tr>
194     </table>
195 
196     @param c Continuation to be called back with events.
197     @param nbytes Number of bytes to read. If unknown, nbytes must
198       be set to INT64_MAX.
199     @param buf buffer to read into.
200     @return VIO representing the scheduled IO operation.
201 
202   */
203   virtual VIO *do_io_read(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, MIOBuffer *buf = 0) = 0;
204 
205   /**
206     Write data to the VConnection.
207 
208     This method is called by a state machine to write data to the
209     VConnection.
210 
211     <b>Possible Event Codes</b>
212 
213     On the callback to the continuation, the VConnection may use
214     on of the following event codes:
215 
216     <table border="1">
217       <tr>
218         <td align="center"><b>Event code</b></td>
219         <td align="center"><b>Meaning</b></td>
220       </tr>
221       <tr>
222         <td>VC_EVENT_WRITE_READY</td>
223         <td>Data was written from the reader or there are no bytes available
224         for the reader to write.</td>
225       </tr>
226       <tr>
227         <td>VC_EVENT_WRITE_COMPLETE</td>
228         <td>The amount of data indicated by 'nbytes' has been written to the
229             VConnection</td>
230       </tr>
231       <tr>
232         <td>VC_EVENT_INACTIVITY_TIMEOUT</td>
233         <td>No activity was performed for a certain period.</td>
234       </tr>
235       <tr>
236         <td>VC_EVENT_ACTIVE_TIMEOUT</td>
237         <td>Write operation continued beyond a time limit.</td>
238       </tr>
239       <tr>
240         <td>VC_EVENT_ERROR</td>
241         <td>An error occurred during the write</td>
242       </tr>
243     </table>
244 
245     @param c Continuation to be called back with events.
246     @param nbytes Number of bytes to write. If unknown, nbytes must
247       be set to INT64_MAX.
248     @param buf Reader whose data is to be read from.
249     @param owner
250     @return VIO representing the scheduled IO operation.
251 
252   */
253   virtual VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = 0, bool owner = false) = 0;
254 
255   /**
256     Indicate that the VConnection is no longer needed.
257 
258     Once the state machine has finished using this VConnection, it
259     must call this function to indicate that the VConnection can
260     be deallocated.  After a close has been called, the VConnection
261     and underlying processor must not send any more events related
262     to this VConnection to the state machine. Likeswise, the state
263     machine must not access the VConnection or any VIOs obtained
264     from it after calling this method.
265 
266     @param lerrno indicates where a close is a normal close or an
267       abort. The difference between a normal close and an abort
268       depends on the underlying type of the VConnection.
269 
270   */
271   virtual void do_io_close(int lerrno = -1) = 0;
272 
273   /**
274     Terminate one or both directions of the VConnection.
275 
276     Indicates that one or both sides of the VConnection should be
277     terminated. After this call is issued, no further I/O can be
278     done on the specified direction of the connection. The processor
279     must not send any further events (including timeout events) to
280     the state machine, and the state machine must not use any VIOs
281     from a shutdown direction of the connection. Even if both sides
282     of a connection are shutdown, the state machine must still call
283     do_io_close() when it wishes the VConnection to be deallocated.
284 
285     <b>Possible howto values</b>
286 
287     <table border="1">
288       <tr>
289         <td align="center"><b>Value</b></td>
290         <td align="center"><b>Meaning</b></td>
291       </tr>
292       <tr>
293         <td>IO_SHUTDOWN_READ</td>
294         <td>Indicates that this VConnection should not generate any more
295         read events</td>
296       </tr>
297       <tr>
298         <td>IO_SHUTDOWN_WRITE</td>
299         <td>Indicates that this VConnection should not generate any more
300         write events</td>
301       </tr>
302       <tr>
303         <td>IO_SHUTDOWN_READWRITE</td>
304         <td>Indicates that this VConnection should not generate any more
305         read nor write events</td>
306       </tr>
307     </table>
308 
309     @param howto Specifies which direction of the VConnection to
310       shutdown.
311 
312   */
313   virtual void do_io_shutdown(ShutdownHowTo_t howto) = 0;
314 
315   VConnection(ProxyMutex *aMutex);
316   VConnection(Ptr<ProxyMutex> &aMutex);
317 
318   // Private
319   // Set continuation on a given vio. The public interface
320   // is through VIO::set_continuation()
321   virtual void set_continuation(VIO *vio, Continuation *cont);
322 
323   // Reenable a given vio.  The public interface is through VIO::reenable
324   virtual void reenable(VIO *vio);
325   virtual void reenable_re(VIO *vio);
326 
327   /**
328     Convenience function to retrieve information from VConnection.
329 
330     This function is provided as a convenience for state machines
331     to transmit information from/to a VConnection without breaking
332     the VConnection abstraction. Its behavior varies depending on
333     the type of VConnection being used.
334 
335     @param id Identifier associated to interpret the data field
336     @param data Value or pointer with state machine or VConnection data.
337     @return True if the oparation is successful.
338 
339   */
340   virtual bool
341   get_data(int id, void *data)
342   {
343     (void)id;
344     (void)data;
345     return false;
346   }
347 
348   /**
349     Convenience function to set information into the VConnection.
350 
351     This function is provided as a convenience for state machines
352     to transmit information from/to a VConnection without breaking
353     the VConnection abstraction. Its behavior varies depending on
354     the type of VConnection being used.
355 
356     @param id Identifier associated to interpret the data field.
357     @param data Value or pointer with state machine or VConnection data.
358     @return True if the oparation is successful.
359 
360   */
361   virtual bool
362   set_data(int id, void *data)
363   {
364     (void)id;
365     (void)data;
366     return false;
367   }
368 
369 public:
370   /**
371     The error code from the last error.
372 
373     Indicates the last error on the VConnection. They are either
374     system error codes or from the InkErrno.h file.
375 
376   */
377   int lerrno;
378 };
379 
380 /**
381   Subclass of VConnection to provide support for user arguments
382 
383   Inherited by DummyVConnection (down to INKContInternal) and NetVConnection
384 */
385 class AnnotatedVConnection : public VConnection
386 {
387   using self_type  = AnnotatedVConnection;
388   using super_type = VConnection;
389 
390 public:
391   AnnotatedVConnection(ProxyMutex *aMutex) : super_type(aMutex){};
392   AnnotatedVConnection(Ptr<ProxyMutex> &aMutex) : super_type(aMutex){};
393 
394   void *
395   get_user_arg(unsigned ix) const
396   {
397     ink_assert(ix < user_args.size());
398     return this->user_args[ix];
399   };
400   void
401   set_user_arg(unsigned ix, void *arg)
402   {
403     ink_assert(ix < user_args.size());
404     user_args[ix] = arg;
405   };
406 
407 protected:
408   std::array<void *, TS_VCONN_MAX_USER_ARG> user_args;
409 };
410 
411 struct DummyVConnection : public AnnotatedVConnection {
412   virtual VIO *
413   do_io_write(Continuation * /* c ATS_UNUSED */, int64_t /* nbytes ATS_UNUSED */, IOBufferReader * /* buf ATS_UNUSED */,
414               bool /* owner ATS_UNUSED */)
415   {
416     ink_assert(!"VConnection::do_io_write -- "
417                 "cannot use default implementation");
418     return nullptr;
419   }
420 
421   virtual VIO *
422   do_io_read(Continuation * /* c ATS_UNUSED */, int64_t /* nbytes ATS_UNUSED */, MIOBuffer * /* buf ATS_UNUSED */)
423   {
424     ink_assert(!"VConnection::do_io_read -- "
425                 "cannot use default implementation");
426     return nullptr;
427   }
428 
429   virtual void
430   do_io_close(int /* alerrno ATS_UNUSED */)
431   {
432     ink_assert(!"VConnection::do_io_close -- "
433                 "cannot use default implementation");
434   }
435 
436   virtual void do_io_shutdown(ShutdownHowTo_t /* howto ATS_UNUSED */)
437   {
438     ink_assert(!"VConnection::do_io_shutdown -- "
439                 "cannot use default implementation");
440   }
441 
442   DummyVConnection(ProxyMutex *m) : AnnotatedVConnection(m) {}
443 };
444