#!/bin/sh -eu

__package haproxy
require="__package/haproxy" __start_on_boot haproxy

tmpdir="$__object/files"
mkdir "$tmpdir"
configtmp="$__object/files/haproxy.cfg"

os=$(cat "$__global/explorer/os")
case $os in
	freebsd)
		CONFIG_FILE="/usr/local/etc/haproxy.conf"
		cat <<EOF > "$configtmp"
global
	maxconn	4000
	user	nobody
	group	nogroup
	daemon

EOF

		;;
	*)
		CONFIG_FILE="/etc/haproxy/haproxy.cfg"
		cat <<EOF > "$configtmp"
global
	log	[::1] local2
	chroot	/var/lib/haproxy
	pidfile	/var/run/haproxy.pid
	maxconn	4000
	user	haproxy
	group	haproxy
	daemon

	# turn on stats unix socket
	stats socket	/var/lib/haproxy/stats

EOF
		;;
esac

cat <<EOF >> "$configtmp"
defaults
	retries	3
	log	global
	timeout http-request	10s
	timeout queue		1m
	timeout connect		10s
	timeout client		1m
	timeout server		1m
	timeout http-keep-alive	10s
	timeout check		10s
EOF

dig_cmd="$(command -v dig || true)"
get_ip() {
	# Usage: get_ip (ipv4|ipv6) NAME
	# uses "dig" if available, else fallback to "host"
	case $1 in
		ipv4)
			if [ -n "${dig_cmd}" ]; then
				${dig_cmd} +short A "$2"
			else
				host -t A "$2" | cut -d ' ' -f 4 | grep -v 'found:'
			fi
			;;
		ipv6)
			if [ -n "${dig_cmd}" ]; then
				${dig_cmd} +short AAAA "$2"
			else
				host -t AAAA "$2" | cut -d ' ' -f 5 | grep -v 'NXDOMAIN'
			fi
			;;
	esac
}

PROTOCOLS="$(cat "$__object/parameter/protocol")"

for proxy in v4proxy v6proxy; do
	param=$__object/parameter/$proxy
	# no backend? skip generating code
	if [ ! -f "$param" ]; then
		continue
	fi

	# turn backend name into bind parameter: v4backend -> ipv4@
	bind=$(echo $proxy | sed -e 's/^/ip/' -e 's/proxy//')

	case $bind in
		ipv4)
			backendproto=ipv6
			;;
		ipv6)
			backendproto=ipv4
			;;
	esac

	for proto in ${PROTOCOLS}; do
		# Add protocol "header"
		printf "\n# %s %s \n" "${bind}" "${proto}" >> "$configtmp"

		sed -e "s/BIND/$bind/" \
			-e "s/\(frontend[[:space:]].*\)/\1$bind/" \
			-e "s/\(backend[[:space:]].*\)/\\1$bind/" \
			"$__type/files/$proto" >> "$configtmp"

		while read -r hostdefinition; do
			if echo "$hostdefinition" | grep -qE '^proxy:'; then
				# Proxy protocol was requested
				host="$(echo "$hostdefinition" | sed -E 's/^proxy:([^:]+).*$/\1/')"
				send_proxy=" send-proxy"
			else
				# Just use tcp proxy mode
				host="$hostdefinition"
				send_proxy=""
			fi
			if echo "$hostdefinition" | grep -qE ":${proto}="; then
				# Use custom port definition if requested
				port="$(echo "$hostdefinition" | sed -E "s/^(.*:)?${proto}=([0-9]+).*$/:\2/")"
			else
				# Else use the default
				port=""
			fi
			servername=$host

			res=$(get_ip "$bind" "$servername")

			if [ -z "$res" ]; then
				echo "$servername does not resolve - aborting config" >&2
				exit 1
			fi

			# Treat protocols without TLS+SNI specially
			if [ "$proto" = http ]; then
				echo "	use-server $servername if { hdr(host) -i $host }" >> "$configtmp"
			else
				echo "	use-server $servername if { req_ssl_sni -i $host }" >> "$configtmp"
			fi

			# Create the "server" itself.
			# Note that port and send_proxy will be empty unless
			# they were requested by the type user
			echo "	server $servername ${backendproto}@${host}${port}${send_proxy}" >> "$configtmp"

		done < "$param"
	done
done

# Create config file
require="__package/haproxy" __file ${CONFIG_FILE} --source "$configtmp" --mode 0644

require="__file${CONFIG_FILE}" __check_messages "haproxy_reload" \
	--pattern "^__file${CONFIG_FILE}" \
	--execute "service haproxy reload || service haproxy restart"
