# 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_dependency_requires '*' rm
bishbosh_connection_packetIdentifier_initialise()
{
	if core_variable_isUnset bishbosh_connect_cleanSession; then
		bishbosh_connect_cleanSession=1
	fi
	
	# bishbosh_connection_sessionPath: Can be overridden, but not listed in help or README.md
	if [ $bishbosh_connect_cleanSession -eq 0 ]; then
		_bishbosh_connection_defaultFolderPath bishbosh_connection_sessionPath "$bishbosh_sessionPath"/servers/"$bishbosh_server"/ports/"$bishbosh_port"/client-ids "_${bishbosh_clientId}"
	else
		_bishbosh_connection_defaultFolderPath bishbosh_connection_sessionPath "$bishbosh_temporaryFolderPath" session
		
		# Destroy any former clean session = 0 session data, so can't be accidentially re-used if clean session changed from 1 back to 0 in the future
		local formerCleanSession0Path="$bishbosh_sessionPath"/servers/"$bishbosh_server"/ports/"$bishbosh_port"/client-ids/"_${bishbosh_clientId}"
		if [ -d "$formerCleanSession0Path" ]; then
			bishbosh_connection_cleanContentsOfFolderPath "$formerCleanSession0Path"
		fi
	fi
	
	# our-packet-identifiers: Can be overridden, but not listed in help or README.md
	_bishbosh_connection_defaultFolderPath bishbosh_connection_sessionOurPacketIdentifiersPath "$bishbosh_connection_sessionPath" our-packet-identifiers
	
	# their-packet-identifiers: Can be overridden, but not listed in help or README.md
	_bishbosh_connection_defaultFolderPath bishbosh_connection_sessionTheirPacketIdentifiersPath "$bishbosh_connection_sessionPath" their-packet-identifiers
		
	# retransmission: Can be overridden, but not listed in help or README.md
	_bishbosh_connection_defaultFolderPath bishbosh_connection_sessionRetransmissionPath "$bishbosh_connection_sessionPath" retransmission
	
	# Make sure retransmission path is clean
	bishbosh_connection_cleanContentsOfFolderPath "$bishbosh_connection_sessionRetransmissionPath"
	
	bishbosh_connection_packetIdentifier_transmissionCounter=0
	bishbosh_connection_packetIdentifier_inFlight=0
	bishbosh_connection_packetIdentifier_forWriting=1
	
	# Create retransmissions, in transmission order NOT packet identifier order
	local packetIdentifier
	local transmissionCounterFile
	local transmissionCounter
	local paddedTransmissionCounter
	local specificRetransmissionPath
	pushd "$bishbosh_connection_sessionOurPacketIdentifiersPath"
		set +f
		for packetIdentifier in *
		do
			set -f
			if [ ! -d "$packetIdentifier" ]; then
				# ie '*'
				if [ ! -e "$packetIdentifier" ]; then
					continue
				fi
				core_exitError $core_commandLine_exitCode_DATAERR "What is '$packetIdentifier' doing in sent stored session state at '$bishbosh_connection_sessionOurPacketIdentifiersPath'?"
			fi
			
			transmissionCounterFile="$packetIdentifier"/transmission-counter
			if [ ! -f "$transmissionCounterFile" ]; then
				core_message WARN "Cleaning up sent packet identifier '$packetIdentifier' that lacks a transmission-counter"
				rm -rf "$packetIdentifier"
				continue
			fi
			
			bishbosh_connection_packetIdentifier_inFlight=$((bishbosh_connection_packetIdentifier_inFlight+1))
			
			transmissionCounter="$(<"$transmissionCounterFile")"
			
			if [ $transmissionCounter -ge $bishbosh_connection_packetIdentifier_transmissionCounter ]; then
				bishbosh_connection_packetIdentifier_transmissionCounter=$((transmissionCounter+1))
			fi
			
			paddedTransmissionCounter="$(printf '%09s' $transmissionCounter)"
			specificRetransmissionPath="$bishbosh_connection_sessionRetransmissionPath"/"$paddedTransmissionCounter"
			ln -s "$bishbosh_connection_sessionOurPacketIdentifiersPath"/"$packetIdentifier" "$specificRetransmissionPath" || core_exitError $core_commandLine_exitCode_DATAERR "Sent retransmission '$transmissionCounter' (padded as '$paddedTransmissionCounter') already exists for '$packetIdentifier' at path '$specificRetransmissionPath'."
		done
		set -f
	popd
	
	# PUBRECs to resend
	pushd "$bishbosh_connection_sessionTheirPacketIdentifiersPath"
		set +f
		for packetIdentifier in *
		do
			set -f 
			if [ ! -d "$packetIdentifier" ]; then
				# ie '*'
				if [ ! -e "$packetIdentifier" ]; then
					continue
				fi
				core_exitError $core_commandLine_exitCode_DATAERR "What is '$packetIdentifier' doing in received stored session state at '$bishbosh_connection_sessionOurPacketIdentifiersPath'?"
			fi
			
			transmissionCounterFile="$packetIdentifier"/transmission-counter
			if [ ! -f "$transmissionCounterFile" ]; then
				core_message WARN "Cleaning up sent packet identifier '$packetIdentifier' that lacks a transmission-counter"
				rm -rf "$packetIdentifier"
				continue
			fi
			
			transmissionCounter="$(<"$transmissionCounterFile")"
			
			if [ $transmissionCounter -ge $bishbosh_connection_packetIdentifier_transmissionCounter ]; then
				bishbosh_connection_packetIdentifier_transmissionCounter=$((transmissionCounter+1))
			fi
			
			paddedTransmissionCounter="$(printf '%09s' $transmissionCounter)"
			specificRetransmissionPath="$bishbosh_connection_sessionRetransmissionPath"/"$paddedTransmissionCounter"
			ln -s "$bishbosh_connection_sessionTheirPacketIdentifiersPath"/"$packetIdentifier" "$specificRetransmissionPath" || core_exitError $core_commandLine_exitCode_DATAERR "Received retransmission '$transmissionCounter' (padded as '$paddedTransmissionCounter') already exists for '$packetIdentifier' at path '$specificRetransmissionPath'."
		done
		
		set -f
	popd
}

bishbosh_connection_packetIdentifier_useOneOfOurs()
{
	# publish, subscribe, unsubcribe
	local kind="$1"
	local callback="$2"
	shift 2
	
	if [ $bishbosh_connection_packetIdentifier_inFlight -eq 65535 ]; then
		core_exitError $core_commandLine_exitCode_DATAERR "All packet identifiers are in flight"
	fi
	bishbosh_connection_packetIdentifier_inFlight=$((bishbosh_connection_packetIdentifier_inFlight+1))
	
	while [ -d "$bishbosh_connection_sessionOurPacketIdentifiersPath"/$bishbosh_connection_packetIdentifier_forWriting ]
	do
		if [ $bishbosh_connection_packetIdentifier_forWriting -eq 65535 ]; then
			bishbosh_connection_packetIdentifier_forWriting=1
		else
			bishbosh_connection_packetIdentifier_forWriting=$((bishbosh_connection_packetIdentifier_forWriting+1))
		fi
	done
	
	ourPacketIdentifierFolderPath="$bishbosh_connection_sessionOurPacketIdentifiersPath"/"$bishbosh_connection_packetIdentifier_forWriting"
	mkdir -m 0700 -p "$ourPacketIdentifierFolderPath"
	
	printf '' >"$ourPacketIdentifierFolderPath"/"$kind"
	
	$callback "$@"
	
	# only once transmission counter is written is this publish, etc, good to be sent
	bishbosh_connection_packetIdentifier_incrementTransmissionCounter "$ourPacketIdentifierFolderPath"
}

bishbosh_connection_packetIdentifier_incrementTransmissionCounter()
{
	local packetIdentifierFolderPath="$1"
	local transmissionCounter=$bishbosh_connection_packetIdentifier_transmissionCounter
	bishbosh_connection_packetIdentifier_transmissionCounter=$((bishbosh_connection_packetIdentifier_transmissionCounter+1))
	printf '%s' "$transmissionCounter" >"$packetIdentifierFolderPath"/transmission-counter
}

# Assumes  packetIdentifier  already set
bishbosh_connection_packetIdentifier_retireOneOfOurs()
{
	bishbosh_connection_packetIdentifier_inFlight=$((bishbosh_connection_packetIdentifier_inFlight-1))
	
	ourPacketIdentifierFolderPath="$bishbosh_connection_sessionOurPacketIdentifiersPath"/"$packetIdentifier"
	rm -rf "$ourPacketIdentifierFolderPath"
}

# Assumes  packetIdentifier  already set
bishbosh_connection_packetIdentifier_ourPacketIdentifierFolderPath()
{
	ourPacketIdentifierFolderPath="$bishbosh_connection_sessionOurPacketIdentifiersPath"/$packetIdentifier
}

bishbosh_connection_packetIdentifier_write()
{
	bishbosh_connection_write_twoByteLength $bishbosh_connection_packetIdentifier_forWriting
}

# Assumes  packetIdentifier  already set
bishbosh_connection_packetIdentifier_theirPacketIdentifierFolderPath()
{
	theirPacketIdentifierFolderPath="$bishbosh_connection_sessionOurPacketIdentifiersPath"/$packetIdentifier
}