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