1 /******************************************************************************* 2 3 Application extension for handling requests via a unix socket. 4 5 Commands can be registered to the extension and when the command is received 6 the provided delegate will be called. Any provided arguments will be split 7 by the space character and provided as an array. 8 9 The socket will be created under the path defined by the config option 10 `path` under the `[UNIX_SOCKET]` config group. If the config path is not 11 defined then the unix socket will not be created. If there's a need to 12 setup the permissions mode, config option `mode` will be used to read the 13 mode as octal string (usually you want 0600 for this). 14 15 Copyright: 16 Copyright (c) 2009-2017 dunnhumby Germany GmbH. 17 All rights reserved. 18 19 License: 20 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 21 Alternatively, this file may be distributed under the terms of the Tango 22 3-Clause BSD License (see LICENSE_BSD.txt for details). 23 24 *******************************************************************************/ 25 26 module ocean.util.app.ext.UnixSocketExt; 27 28 import ocean.meta.types.Qualifiers; 29 import ocean.core.Verify; 30 31 import ocean.core.Enforce; 32 import ocean.io.select.EpollSelectDispatcher; 33 import ocean.util.app.model.IApplication; 34 import ocean.util.app.model.IApplicationExtension; 35 import ocean.util.app.ext.model.IConfigExtExtension; 36 37 /// ditto 38 public class UnixSocketExt : IApplicationExtension, IConfigExtExtension 39 { 40 import ocean.application.components.UnixSocketCommands; 41 import ocean.text.convert.Integer; 42 import ocean.text.util.StringC; 43 import ocean.util.config.ConfigParser; 44 import ocean.net.server.unix.CommandRegistry; 45 import ocean.net.server.unix.UnixListener; 46 47 /// Handler delegate 48 public alias UnixSocketCommands.Handler Handler; 49 50 /// Interactive handler delegate 51 public alias UnixSocketCommands.InteractiveHandler InteractiveHandler; 52 53 /// RawSocketHandler delegate 54 public alias UnixSocketCommands.RawSocketHandler RawSocketHandler; 55 56 // Unix socket commands wrapper. 57 private UnixSocketCommands unix_socket; 58 59 /************************************************************************* 60 61 Constructor 62 63 **************************************************************************/ 64 65 this ( ) 66 { 67 this.unix_socket = new UnixSocketCommands; 68 } 69 70 /************************************************************************* 71 72 Initializes the socket listener. 73 74 Params: 75 epoll = Epoll instance. 76 77 **************************************************************************/ 78 79 public void initializeSocket ( EpollSelectDispatcher epoll ) 80 { 81 this.unix_socket.startEventHandling(epoll); 82 } 83 84 /*************************************************************************** 85 86 Setup the unix socket listener if the config for the socket path exists. 87 88 Params: 89 app = the application instance 90 config = configuration instance 91 92 ***************************************************************************/ 93 94 public override void processConfig ( IApplication app, ConfigParser config ) 95 { 96 this.unix_socket.parseConfig(config); 97 } 98 99 /*************************************************************************** 100 101 Params: 102 command = The command to listen for in the socket listener. 103 handler = The handler to call when command is received. 104 105 ***************************************************************************/ 106 107 public void addHandler ( istring command, scope Handler handler ) 108 { 109 this.unix_socket.commands.addHandler(command, handler); 110 } 111 112 /*************************************************************************** 113 114 Params: 115 command = The command to listen for in the socket listener. 116 handler = The handler to call when command is received. 117 118 ***************************************************************************/ 119 120 public void addHandler ( istring command, scope InteractiveHandler handler ) 121 { 122 this.unix_socket.commands.addHandler(command, handler); 123 } 124 125 /*************************************************************************** 126 127 Register a command and raw handler to the unix listener. 128 129 Params: 130 command = The command to listen for in the socket listener. 131 handler = The handler to call when command is received. 132 133 ***************************************************************************/ 134 135 public void addHandler ( istring command, scope RawSocketHandler handler ) 136 { 137 this.unix_socket.commands.addHandler(command, handler); 138 } 139 140 /*************************************************************************** 141 142 Unregisters a command and handler to the unix listener. 143 144 Params: 145 command = The command to be removed from the listener. 146 147 ***************************************************************************/ 148 149 public void removeHandler ( istring command ) 150 { 151 this.unix_socket.commands.removeHandler(command); 152 } 153 154 /*************************************************************************** 155 156 Shut down the unix listener upon exit of the application. 157 158 Params: 159 app = Application instance. 160 args = Provided application arguments. 161 status = Return code status. 162 exception = Exception if exists. 163 164 ***************************************************************************/ 165 166 public override void atExit ( IApplication app, istring[] args, int status, 167 ExitException exception ) 168 { 169 this.unix_socket.shutdown(); 170 } 171 172 /*************************************************************************** 173 174 Unused IConfigExtExtension method to satisfy interface. 175 176 Params: 177 app = the application instance 178 config = configuration instance 179 180 ***************************************************************************/ 181 182 public override void preParseConfig ( IApplication app, ConfigParser config ) 183 { 184 // Unused 185 } 186 187 /*************************************************************************** 188 189 Unused IConfigExtExtension method to satisfy interface. 190 191 Params: 192 app = the application instance 193 config = configuration instance 194 files = current list of configuration files to parse 195 196 Returns: 197 new list of configuration files to parse 198 199 ***************************************************************************/ 200 201 public override istring[] filterConfigFiles ( IApplication app, 202 ConfigParser config, 203 istring[] files ) 204 { 205 // Unused 206 return files; 207 } 208 209 /*************************************************************************** 210 211 Return: 212 Use the default ordering. 213 214 ***************************************************************************/ 215 216 public override int order ( ) 217 { 218 return -1; 219 } 220 221 /*************************************************************************** 222 223 Unused IApplicationExtension methods to satisfy interface. 224 225 ***************************************************************************/ 226 227 public override void preRun ( IApplication app, istring[] args ) 228 { 229 } 230 231 /// ditto 232 public override void postRun ( IApplication app, istring[] args, int status ) 233 { 234 } 235 236 /// ditto 237 public override ExitException onExitException ( IApplication app, istring[] args, 238 ExitException exception ) 239 { 240 return exception; 241 } 242 } 243 244 version (unittest) 245 { 246 import ocean.util.app.DaemonApp; 247 } 248 249 /// 250 unittest 251 { 252 class TestApp : DaemonApp 253 { 254 public this ( ) 255 { 256 super("TestApp", "Test UnixSocketExt", null); 257 } 258 259 override public int run ( Arguments args, ConfigParser config ) 260 { 261 this.startEventHandling(new EpollSelectDispatcher); 262 this.unix_socket_ext.addHandler("test", &this.test); 263 264 return 0; 265 } 266 267 private void test ( cstring[] args, 268 scope void delegate ( cstring response ) send_response, 269 scope void delegate ( ref mstring response ) wait_reply ) 270 { 271 send_response("Test request received"); 272 } 273 } 274 275 TestApp app = new TestApp; 276 }