1 /******************************************************************************* 2 3 Base class for a connection handler for use with SelectListener, using 4 tasks. 5 6 Copyright: 7 Copyright (c) 2017 dunnhumby Germany GmbH. 8 All rights reserved. 9 10 License: 11 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 12 Alternatively, this file may be distributed under the terms of the Tango 13 3-Clause BSD License (see LICENSE_BSD.txt for details). 14 15 *******************************************************************************/ 16 17 module ocean.net.server.connection.TaskConnectionHandler; 18 19 import ocean.net.server.connection.IConnectionHandler; 20 import ocean.util.container.pool.model.IResettable; 21 22 /// ditto 23 24 abstract class TaskConnectionHandler : IConnectionHandler, Resettable 25 { 26 import ocean.sys.socket.model.ISocket; 27 import ocean.io.select.protocol.task.TaskSelectTransceiver; 28 import ocean.io.select.protocol.generic.ErrnoIOException: IOWarning; 29 import ocean.task.Task: Task; 30 import ocean.task.IScheduler: theScheduler; 31 32 import ocean.meta.types.Qualifiers; 33 34 /*************************************************************************** 35 36 Reads data from and writes data to the connection socket. 37 38 ***************************************************************************/ 39 40 protected TaskSelectTransceiver transceiver; 41 42 /*************************************************************************** 43 44 IOWarning exception instance used by the reader/writer and subclass. 45 46 ***************************************************************************/ 47 48 protected IOWarning io_warning; 49 50 /*************************************************************************** 51 52 Connection handler task, runs the abstract `handle` method and calls the 53 finalizer callback on termination. 54 55 ***************************************************************************/ 56 57 private class ConnectionHandlerTask: Task 58 { 59 /// Constructor. 60 private this ( ) 61 { 62 this.terminationHook = &this.outer.finalize; 63 } 64 65 /// Task method, runs `TaskConnectionHandler.handle.` 66 override protected void run ( ) 67 { 68 this.outer.handle(); 69 } 70 } 71 72 /// ditto 73 private Task task; 74 75 /*************************************************************************** 76 77 Constructor 78 79 Params: 80 socket = the socket 81 error_dg_ = optional user-specified error handler, called when a 82 connection error occurs 83 84 ***************************************************************************/ 85 86 protected this ( ISocket socket, scope ErrorDg error_dg_ = null ) 87 { 88 this(socket, null, error_dg_); 89 } 90 91 /*************************************************************************** 92 93 Constructor 94 95 Params: 96 socket = the socket 97 finalize_dg_ = finalizer callback of the select listener, called 98 when the connection is shut down 99 error_dg_ = optional user-specified error handler, called when a 100 connection error occurs 101 102 ***************************************************************************/ 103 104 protected this ( ISocket socket, scope FinalizeDg finalize_dg_, 105 scope ErrorDg error_dg_ = null ) 106 { 107 super(socket, finalize_dg_, error_dg_); 108 this.io_warning = new IOWarning(this.socket); 109 this.transceiver = new TaskSelectTransceiver( 110 this.socket, this.io_warning, this.socket_error 111 ); 112 this.task = this.new ConnectionHandlerTask; 113 } 114 115 /************************************************************************** 116 117 Called by `finalize` to unregister the connection socket from epoll 118 before closing it. This is done because closing a socket does not always 119 mean that it is unregistered from epoll -- in situations where the 120 process has forked, the fork's reference to the underlying kernel file 121 description will prevent it from being unregistered until the fork 122 exits. Therefore, to be certain that the socket will not fire again in 123 epoll, we need to explicitly unregister it. 124 125 ***************************************************************************/ 126 127 protected override void unregisterSocket () 128 { 129 this.transceiver.reset(); 130 } 131 132 /*************************************************************************** 133 134 Called by the select listener right after the client connection has been 135 assigned. 136 If this method throws an exception, error() and finalize() will be 137 called by the select listener. 138 139 ***************************************************************************/ 140 141 override public void handleConnection ( ) 142 { 143 theScheduler.schedule(this.task); 144 } 145 146 /*************************************************************************** 147 148 Connection handler method, called from a running task. 149 150 ***************************************************************************/ 151 152 abstract protected void handle ( ); 153 154 /************************************************************************** 155 156 Called by IConnectionHandler.finalize(), in order to determine if an I/O 157 error was reported for the connection conduit which made the connection 158 automatically being closed. 159 (See comment for IConnectionHandler.finalize() method.) 160 161 Returns: 162 true if an I/O error was reported to the reader or the writer for 163 the connection conduit which made the connection automatically being 164 closed or false otherwise. 165 166 **************************************************************************/ 167 168 override public bool io_error ( ) 169 { 170 return !!this.socket.error; 171 } 172 }