# This file is part of bish-bosh. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/raphaelcohn/bish-bosh/master/COPYRIGHT. No part of bish-bosh, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
# Copyright © 2014-2015 The developers of bish-bosh. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/raphaelcohn/bish-bosh/master/COPYRIGHT.


core_usesIn core functions
core_functions_register _bishbosh_backend_registration socat

# Homebrew, Debian
bishbosh_backend_socat_check()
{
	case "$bishbosh_tunnel" in
		
		none|tls)
			:
		;;
		
		*)
			return 1
		;;
		
	esac
	
	if core_compatibility_whichNoOutput socat; then
		bishbosh_backend_name=socat
		bishbosh_backend_path="$(core_compatibility_which socat)"
		return 0
	fi
	return 1
}

bishbosh_backend_socat_port()
{
	if [ "$bishbosh_tunnel" = 'none' ]; then
		printf '%s' 1883
	elif [ "$bishbosh_tunnel" = 'tls' ]; then
		printf '%s' 8883
	else
		printf '%s' 'invalid-tunnel'
	fi
}

core_usesIn core variable variable/array
bishbosh_backend_socat_start()
{
	local options
	local options_initialised
	core_variable_array_initialise options

	# Forces error messages to stderr
	core_variable_array_append options -ls
	
	# Makes socat appear to be bish-bosh
	core_variable_array_append options -lp${_program_name}
	
	case $(core_init_verbosity) in
		
		0)
			:
		;;
		
		1)
			core_variable_array_append options -d
		;;
		
		2)
			core_variable_array_append options -d -d
		;;
		
		3)
			core_variable_array_append options -d -d -d
		;;
		
		4)
			core_variable_array_append options -d -d -d -d
		;;
	esac

	# Forces 4 or 6, because we can not always use 'TCP4/6'
	case "$bishbosh_transport" in
		
		inet4)
			core_variable_array_append options '-4'
		;;
		
		inet6)
			core_variable_array_append options '-6'
		;;
	esac
	
	core_variable_array_append options 'STDIO'
	
	case "$bishbosh_transport" in
		
		unix)
			if [ "$bishbosh_tunnel" = 'tls' ]; then
				core_exitError $core_commandLine_exitCode_CONFIG "The backend socat does not support the 'unix' transport when the tunnel is 'tls'"
			fi
			core_variable_array_append options "UNIX-CONNECT:${bishbosh_server}"
			core_variable_array_passToFunctionAsArguments options "$bishbosh_backend_path" <"$bishbosh_connection_toServerFifo" >"$bishbosh_connection_fromServerFifo" &
		;;
		
		serial)
			if [ "$bishbosh_tunnel" = 'tls' ]; then
				core_exitError $core_commandLine_exitCode_CONFIG "The backend socat does not support the 'serial' transport when the tunnel is 'tls'"
			fi
			core_variable_array_append options "${bishbosh_server},raw,echo=0"
			core_variable_array_passToFunctionAsArguments options "$bishbosh_backend_path" <"$bishbosh_connection_toServerFifo" >"$bishbosh_connection_fromServerFifo" &
		;;
		
		inet*)
			local addressKind
			case "$bishbosh_proxyKind" in
				
				SOCKS4|SOCKS4a)

					if [ "$bishbosh_tunnel" = 'tls' ]; then
						core_exitError $core_commandLine_exitCode_CONFIG "The backend socat does not support the '$bishbosh_proxyKind' proxy kind when the tunnel is 'tls'"
					fi
					
					addressKind="${bishbosh_proxyKind}:${bishbosh_proxyAddress}:${bishbosh_server}:${bishbosh_port}"
					if core_variable_isSet bishbosh_proxyPort; then
						addressKind="${addressKind},socksport=${bishbosh_proxyPort}"
					fi
	
					if core_variable_isSet bishbosh_proxyUsername; then
						addressKind="${addressKind},socksuser=${bishbosh_proxyUsername}"
					fi
					
					if core_variable_isSet bishbosh_proxyPassword; then
						core_message WARN "The backend socat does not support specifing the proxy password for 'SOCKS4' bishbosh_proxyKind."
					fi
				;;
				
				SOCKS5)
					core_exitError $core_commandLine_exitCode_CONFIG "The backend socat does not support the 'SOCKS5' bishbosh_proxyKind."
				;;
		
				HTTP)
					if [ "$bishbosh_tunnel" = 'tls' ]; then
						core_exitError $core_commandLine_exitCode_CONFIG "The backend socat does not support the '$bishbosh_proxyKind' proxy kind when the tunnel is 'tls'"
					fi
					
					addressKind="PROXY:${bishbosh_proxyAddress}:${bishbosh_server}:${bishbosh_port}"
					if core_variable_isSet bishbosh_proxyPort; then
						addressKind="${addressKind},socksport=${bishbosh_proxyPort}"
					fi
					if core_variable_isSet bishbosh_proxyUsername; then
						if core_variable_isSet bishbosh_proxyPassword; then
							addressKind="${addressKind},proxyauth=${bishbosh_proxyUsername}:${bishbosh_proxyPassword}"
						else
							core_message WARN $core_commandLine_exitCode_CONFIG "The backend socat requires 'bishbosh_proxyUsername' and 'bishbosh_proxyPassword' for the 'HTTP' bishbosh_proxyKind."
						fi
					elif core_variable_isSet bishbosh_proxyPassword; then
						core_message WARN $core_commandLine_exitCode_CONFIG "The backend socat requires 'bishbosh_proxyUsername' and 'bishbosh_proxyPassword' for the 'HTTP' bishbosh_proxyKind."
					fi
				;;
				
				*)
					if [ "$bishbosh_tunnel" = 'tls' ]; then
						if core_variable_isTrue "$bishbosh_tunnelTlsUseDer"; then
							core_exitError $core_commandLine_exitCode_CONFIG "The backend socat does not support DER certificates and keys."
						fi
						
						# We do not specify method=TLSv1. This is because this DISABLES support for TLSv1.1 and TLSv1.2
						# Instead, if one uses OpenSSL's SSLv23_method(), then there is support for TLSv1.2 (counter-intuitively).
						addressKind="OPENSSL:${bishbosh_server}:${bishbosh_port},compress=none"
						
						if core_variable_isSet bishbosh_tunnelTlsCertificate; then
							addressKind="${addressKind},cert=$bishbosh_tunnelTlsCertificate"
						fi
						
						if core_variable_isSet bishbosh_tunnelTlsKey; then
							addressKind="${addressKind},key=$bishbosh_tunnelTlsKey"
						fi
						
						if core_variable_isSet bishbosh_tunnelTlsCaFile; then
							addressKind="${addressKind},file=$bishbosh_tunnelTlsCaFile"
						fi
						
						if core_variable_isSet bishbosh_tunnelTlsCaBundle; then
							addressKind="${addressKind},capath=$bishbosh_tunnelTlsCaBundle"
						fi

						if core_variable_isTrue "$bishbosh_tunnelTlsVerify"; then
							addressKind="${addressKind},verify=1"
						else
							addressKind="${addressKind},verify=0"
						fi
						
						if core_variable_isSet bishbosh_tunnelTlsCiphers; then
							addressKind="${addressKind},cipher=$bishbosh_tunnelTlsCiphers"
						fi
						
					else
						case "$bishbosh_transport" in
						
							inet)
								addressKind='TCP'
							;;
		
							inet4)
								addressKind='TCP4'
							;;
		
							inet6)
								addressKind='TCP6'
							;;
						esac
					
						addressKind="${addressKind}:${bishbosh_server}:${bishbosh_port}"
					fi
				;;
		
			esac
			
			local binding=''
			if core_variable_isSet bishbosh_sourceAddress; then
				binding=",bind=$bishbosh_sourceAddress"
				if core_variable_isSet bishbosh_sourcePort; then
					binding="${binding}:${bishbosh_sourcePort}"
				fi
			elif core_variable_isSet bishbosh_sourcePort; then
				binding=",sourceport=${bishbosh_sourcePort}"
			fi
			
			local connectTimeout=''
			if [ $bishbosh_connectTimeout -ne 0 ]; then
				connectTimeout=",connect-timeout=${bishbosh_connectTimeout}"
			fi
			
			# keepidle, keepintvl, keepcnt, linger2, mss, mss-late, syncnt
			core_variable_array_append options "${addressKind}${binding}${connectTimeout},keepalive,linger=1,nodelay"
		;;
		
		*)
			core_exitError $core_commandLine_exitCode_SOFTWARE "Please validate the values for bishbosh_transport ('$bishbosh_transport')"
		;;
		
	esac
	
	bishbosh_backend_debugOptions
	
	core_variable_array_passToFunctionAsArguments options "$bishbosh_backend_path" <"$bishbosh_connection_toServerFifo" >"$bishbosh_connection_fromServerFifo" &
}
