# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
+add_hook() {
+ # local name="$1" # not used
+ local value="$2"
+
+ local tag
+ local handler
+
+ tag="${value%%:*}"
+ handler="${value#*:}"
+
+ hooks["$tag"]="$handler"
+ return 0
+}
+
signal_handler() {
signal_received=1
}
+handle_hook_data() {
+ local endpoint="$1"
+ local hook_data="$2"
+
+ local tag
+ local data
+ local handler
+
+ if ! tag=$(json_object_get "$hook_data" "tag"); then
+ log_warn "Dropping message without tag"
+ return 1
+ fi
+
+ handler="${hooks[$tag]}"
+
+ if [[ -z "$handler" ]]; then
+ log_warn "No handler for tag $tag"
+ return 0
+ fi
+
+ if ! data=$(json_object_get "$hook_data" "data"); then
+ log_warn "Dropping message without data"
+ return 1
+ fi
+
+ if ! "$handler" <<< "$data"; then
+ return 1
+ fi
+
+ return 0
+}
+
+handle_ipc_message() {
+ local endpoint="$1"
+ local data="$2"
+
+ local topic
+
+ if ! topic=$(ipc_msg_get_topic "$data"); then
+ log_warn "Dropping message without topic"
+ return 1
+ fi
+
+ if ! ipc_endpoint_publish "$endpoint" "$topic" "$data"; then
+ log_error "Could not publish message for $topic on $endpoint"
+ return 1
+ fi
+
+ return 0
+}
+
+handle_message() {
+ local endpoint="$1"
+ local message="$2"
+
+ local decoded
+ local type
+ local data
+ local handler
+
+ if ! decoded=$(base64 -d <<< "$message"); then
+ log_warn "Could not decode message"
+ return 1
+ fi
+
+ if ! type=$(json_object_get "$decoded" "type") ||
+ ! data=$(json_object_get "$decoded" "data"); then
+ log_warn "Could not parse message"
+ return 1
+ fi
+
+ handler="${message_handler[$type]}"
+
+ if [[ -n "$handler" ]]; then
+ "$handler" "$endpoint" "$data"
+ fi
+
+ return 0
+}
+
main() {
local endpoint
local message
+ declare -gA hooks
declare -gi signal_received
+ declare -gA message_handler
+
+ message_handler["HookData"]=handle_hook_data
+ message_handler["IPCMessage"]=handle_ipc_message
signal_received=0
+ opt_add_arg "k" "hook" "v" "" \
+ "Command for handling hook data" \
+ '^[^:]+:.*$' \
+ add_hook
+
if ! opt_parse "$@"; then
return 1
fi
trap signal_handler INT TERM ABRT ALRM USR1 USR2
while (( signal_received == 0 )) && read -r message; do
- local topic
-
- if ! topic=$(ipc_msg_get_topic "$message"); then
- log_warn "Dropping message without topic"
- continue
- fi
-
- if ! ipc_endpoint_publish "$endpoint" "$topic" "$message"; then
- log_error "Could not publish message for $topic on $endpoint"
- fi
+ handle_message "$endpoint" "$message"
done
log_info "Closing endpoint $endpoint"
return 0
}
+add_hook() {
+ # local name="$1" # not needed
+ local value="$2"
+
+ local topic
+ local hook
+
+ topic="${value%%:*}"
+ hook="${value#*:}"
+
+ # hooks is inherited from main() via opt_parse()
+ hooks["$topic"]="$hook"
+}
+
signal_handler() {
signal_received=1
}
+output_message() {
+ local type="$1"
+ local data="$2"
+
+ local message
+
+ if ! message=$(json_object "type" "$type" \
+ "data" "$data"); then
+ return 1
+ fi
+
+ if ! base64 -w 0 <<< "$message"; then
+ return 1
+ fi
+
+ printf '\n'
+ return 0
+}
+
+invoke_hooks() {
+ local topic="$1"
+ local message="$2"
+
+ local data
+
+ if data=$("${hooks[$topic]}" <<< "$message") &&
+ [[ -n "$data" ]]; then
+ output_message "HookData" "$data"
+ fi
+
+ return 0
+}
+
tap_topics() {
local topics=("$@")
while (( signal_received == 0 )); do
local message
+ local topic
- if message=$(ipc_endpoint_recv "$endpoint" 5); then
- printf '%s\n' "$message"
+ if ! message=$(ipc_endpoint_recv "$endpoint" 5); then
+ continue
fi
+
+ if ! topic=$(ipc_msg_get_topic "$message"); then
+ log_warn "Dropping message without topic"
+ continue
+ fi
+
+ invoke_hooks "$topic" "$message"
+ output_message "IPCMessage" "$message"
done
fi
main() {
local topics
+ declare -gA hooks
topics=()
- opt_add_arg "t" "topic" "rv" "" "A topic to tap into" "" add_topic
+ opt_add_arg "t" "topic" "rv" "" \
+ "A topic to tap into" \
+ '' \
+ add_topic
+ opt_add_arg "k" "hook" "v" "" \
+ "Hook to execute upon receipt" \
+ '^[^:]+:.+$' \
+ add_hook
if ! opt_parse "$@"; then
return 1
exit 1
fi
- if ! include "log" "opt" "ipc"; then
+ if ! include "log" "opt" "ipc" "json"; then
exit 1
fi