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