1 /******************************************************************************* 2 3 Utility for handling requests via a unix socket. 4 5 Commands can be registered to the registry 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 Copyright: 10 Copyright (c) 2009-2018 dunnhumby Germany GmbH. 11 All rights reserved. 12 13 License: 14 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 15 Alternatively, this file may be distributed under the terms of the Tango 16 3-Clause BSD License (see LICENSE_BSD.txt for details). 17 18 *******************************************************************************/ 19 20 module ocean.net.server.unix.CommandRegistry; 21 22 import ocean.meta.types.Qualifiers; 23 24 /// ditto 25 public class CommandsRegistry 26 { 27 import ocean.core.array.Mutation: filterInPlace; 28 import ocean.core.array.Transformation: split; 29 import ocean.core.Buffer; 30 import ocean.core.Enforce; 31 import ocean.core.Verify; 32 import ocean.text.convert.Integer; 33 import ocean.io.device.IODevice; 34 35 /// Alias for our interactive handler delegate. 36 public alias void delegate ( cstring[], 37 void delegate (cstring), 38 void delegate (ref mstring) ) InteractiveHandler; 39 40 /// Alias for our non-interactive handler delegate. 41 public alias void delegate ( cstring[], 42 void delegate (cstring) ) Handler; 43 44 /// Alias for the type of handler delegate which accepts 45 /// the socket instance for direct control over it 46 public alias void delegate ( cstring[], void delegate (cstring), 47 void delegate (ref mstring), IODevice socket ) RawSocketHandler; 48 49 /// Our registered map of interactive handlers by command. 50 private InteractiveHandler[istring] interactive_handlers; 51 52 /// Our registered map of handlers by command. 53 private Handler[istring] handlers; 54 55 /// Registered map of handlers that accept socket by command. 56 private RawSocketHandler[istring] handlers_ex; 57 58 /// Stores the command arguments split by " "; 59 private cstring[] args_buf; 60 61 /*************************************************************************** 62 63 Receives all commands from the socket and splits the command by " ". 64 If a matching command is registered then the command will be called with 65 the remaining arguments. This method will be called by the 66 UnixSocketListener whenever a command is received. 67 68 Params: 69 command = The command received by the unix socket. 70 args = The arguments provided with the command. 71 send_response = Delegate to call with response string. 72 wait_reply = Delegate to call to obtain the reply from the user 73 socket = connected socket stream 74 75 ***************************************************************************/ 76 77 public void handle ( cstring command, cstring args, 78 scope void delegate (cstring) send_response, 79 scope void delegate (ref mstring buf) wait_reply, 80 IODevice socket ) 81 { 82 scope predicate = (cstring v) { return !v.length; }; 83 84 // escape the command, remove empty elements. 85 scope arguments_split = () { 86 split(args, " ", this.args_buf); 87 return this.args_buf[0..filterInPlace(this.args_buf[], predicate)]; 88 }; 89 90 if (auto handler = command in this.interactive_handlers) 91 { 92 auto arguments = arguments_split(); 93 (*handler)(arguments, send_response, wait_reply); 94 } 95 else if (auto handler = command in this.handlers) 96 { 97 auto arguments = arguments_split(); 98 (*handler)(arguments, send_response); 99 } 100 else if (auto handler = command in handlers_ex) 101 { 102 auto arguments = arguments_split(); 103 (*handler)(arguments, send_response, wait_reply, socket); 104 } 105 else 106 { 107 send_response("Command not found\n"); 108 } 109 } 110 111 /*************************************************************************** 112 113 Register a command and interactive handler to the unix listener. 114 115 Params: 116 command = The command to listen for in the socket listener. 117 handler = The interactive handler to call when command is received. 118 119 ***************************************************************************/ 120 121 public void addHandler ( istring command, 122 scope InteractiveHandler handler ) 123 { 124 this.interactive_handlers[command] = handler; 125 } 126 127 /*************************************************************************** 128 129 Register a command and a handler the registry. 130 131 Params: 132 command = The command name 133 handler = The handler to call when command is received. 134 135 ***************************************************************************/ 136 137 public void addHandler ( istring command, scope Handler handler ) 138 { 139 this.handlers[command] = handler; 140 } 141 142 /*************************************************************************** 143 144 Registers a command and the raw socket handler with the registry 145 146 Params: 147 command = The command name 148 handler = The handler to call when command is received. 149 150 ***************************************************************************/ 151 152 public void addHandler ( istring command, scope RawSocketHandler handler ) 153 { 154 this.handlers_ex[command] = handler; 155 } 156 157 /*************************************************************************** 158 159 Register a command and handler to the unix listener. 160 161 Params: 162 command = The command name of the command to remove from the registry 163 164 ***************************************************************************/ 165 166 public void removeHandler ( istring command ) 167 { 168 this.handlers.remove(command); 169 this.interactive_handlers.remove(command); 170 this.handlers_ex.remove(command); 171 } 172 }