#!/bin/bash

## Copyright (C) 2012 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

check_tor_bootstrap() {
   if test -f /run/qubes/this-is-templatevm ; then
      return 0
   fi

   if [ "$systemcheck_external_network_found" = "false" ]; then
      local MSG="<p>Tor Connection Result: Skipped. (Because no external network interface detected.)</p>"
      $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"
      $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
      local MSG="<p>Time Synchronization Result: Skipped. (Because no external network interface detected.)</p>"
      $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"
      $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
      return 0
   fi

   while true; do
      check_tor_bootstrap_init

      check_tor_bootstrap_grace || continue || return 0
      check_tor_bootstrap_known_failure_cases || break || return 0
      check_tor_bootstrap_unknown_failure_cases || break || return 0
      check_tor_bootstrap_stop_when_bootstrap_done || break || return 0

      check_tor_bootstrap_show_wait_notification_maybe

      check_tor_bootstrap_wait_longer_maybe || continue || return 0
      check_tor_bootstrap_give_up_on_connection_issue_maybe || break || return 0
      check_tor_bootstrap_give_up_on_timesync_issue_maybe || break || return 0

      check_tor_bootstrap_script_error || break || return 0

      break
   done
}

check_tor_bootstrap_sleep() {
   sleep "$systemcheck_tor_bootstrap_between_attempts" &
   lastpid="$!"
   wait "$lastpid" || true
   systemcheck_tor_bootstrap_waited_seconds="$(( "$systemcheck_tor_bootstrap_waited_seconds" + "$systemcheck_tor_bootstrap_between_attempts" ))"
}

check_tor_bootstrap_init() {
   [ -n "$systemcheck_tor_bootstrap_waited_seconds" ] || systemcheck_tor_bootstrap_waited_seconds="0"
   [ -n "$systemcheck_tor_bootstrap_between_attempts" ] || systemcheck_tor_bootstrap_between_attempts="2"
   [ -n "$systemcheck_tor_bootstrap_wait_max" ] || systemcheck_tor_bootstrap_wait_max="300"
   [ -n "$systemcheck_tor_bootstrap_error_counter" ] || systemcheck_tor_bootstrap_error_counter="0"
   [ -n "$systemcheck_tor_bootstrap_error_max" ] || systemcheck_tor_bootstrap_error_max="5"

   ## sets: check_bootstrap_script
   ## sets: lastpid
   ## sets: tor_bootstrap_percent
   ## sets: tor_bootstrap_status
   ## sets: tor_bootstrap_timeout_type
   ## sets: tor_circuit_established
   ## sets: tor_circuit_established_check_exit_code
   ## sets: tor_circuit_established_word
   source /usr/libexec/helper-scripts/tor_bootstrap_check.bsh

   if [ "$vm_lower_case_short" = "gateway" ] || [ "$vm_lower_case_short" = "machine" ]; then
      check_tor_bootstrap_status
   fi

   check_tor_circuit_established

   true "tor_bootstrap_percent: $tor_bootstrap_percent"
   true "tor_bootstrap_status: $tor_bootstrap_status"
   true "tor_circuit_established: $tor_circuit_established"
   true "tor_circuit_established_check_exit_code: $tor_circuit_established_check_exit_code"
   true "tor_circuit_established_word: $tor_circuit_established_word"

   ## Debugging.
   ## Simulating cases where tor_bootstrap_percent is 100 while
   ## tor_circuit_established is 0.
   #if [ "$systemcheck_tor_bootstrap_waited_seconds" -gt "10" ]; then
      #true
   #else
      #tor_circuit_established="0"
   #fi

   ## `timeout` returns:
   ## - 124 if sigterm was sufficient
   ## - 137 if needed to use kill.

   ## check_socks_port_open_test gets set by check_tor_socks_port_reachability,
   ## which runs earlier.

   if [ "$VM" = "Whonix-Workstation" ]; then
      if [ "$tor_circuit_established" = "1" ]; then
         ## On the workstation we do not have access to tor_bootstrap_percent,
         ## so assume it is 100 for code simplification purposes.
         tor_bootstrap_percent="100"
      else
         tor_bootstrap_percent="0"
      fi
   fi

   if [ -e /run/sdwdate/success ]; then
      time_synchronization_status_word="success"
      time_synchronization_status_notification="done"
   elif [ -e /run/sdwdate/first_success ]; then
      time_synchronization_status_word="first_success"
      time_synchronization_status_notification="done"
   elif [ -e /run/sdwdate/fail ]; then
      time_synchronization_status_word="fail"
      time_synchronization_status_notification="failed"
   else
      time_synchronization_status_word="pending"
      time_synchronization_status_notification="not done"
   fi

   if [ -e /run/sdwdate/msg ]; then
      time_synchronization_msg="$(cat /run/sdwdate/msg)" || true
   fi

   if [ "$time_synchronization_msg" = "" ]; then
      time_synchronization_msg="nothing yet."
   fi

   if [ -e /run/whonix_firewall/consecutive_run.status ]; then
      whonix_firewall_status_word="consecutive_run"
      whonix_firewall_status_notification="consecutive run after boot"
   elif [ -e /run/whonix_firewall/first_run_current_boot.status ]; then
      whonix_firewall_status_word="first_run_current_boot"
      whonix_firewall_status_notification="first run after boot"
   else
      whonix_firewall_status_word="pending"
   fi

   onion_time_pre_script_output=$(timeout --kill-after="5" "5" leaprun onion-time-pre-script 2>&1) || true
   if [ "$onion_time_pre_script_output" = "" ]; then
      onion_time_pre_script_output="onion-time-pre-script did not return any output."
   fi
   onion_time_pre_script_output="$(br_add "$onion_time_pre_script_output")"

   return 0
}

check_tor_bootstrap_grace() {
   if [ "$tor_circuit_established_check_exit_code" = "255" ] || [ "$tor_circuit_established_check_exit_code" = "124" ] || [ "$tor_circuit_established_check_exit_code" = "137" ]; then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   systemcheck_tor_bootstrap_error_counter="$(( $systemcheck_tor_bootstrap_error_counter + 1 ))"
   if [ "$systemcheck_tor_bootstrap_error_counter" -ge "$systemcheck_tor_bootstrap_error_max" ]; then
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   else
      local MSG="<p>Tor Connection Result:
Tor's Control Port could not be reached. Attempt $systemcheck_tor_bootstrap_error_counter of $systemcheck_tor_bootstrap_error_max. Could be temporary due to a Tor restart. Trying again...
</p>"
      $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG" --done

      check_tor_bootstrap_sleep

      ## `continue` check_tor_bootstrap loop. Restart loop from the beginning.
      return 1
   fi
}

check_tor_bootstrap_known_failure_cases() {
   ## 255 Tor Control Port could not be reached.
   ## 277 Variable check_bootstrap_helper_script_output is empty.
   ## 124 if sigterm was sufficient.
   ## 137 if needed to use kill.
   if \
   [ "$tor_circuit_established_check_exit_code" = "255" ] || \
   [ "$tor_circuit_established_check_exit_code" = "277" ] || \
   [ "$tor_circuit_established_check_exit_code" = "124" ] || \
   [ "$tor_circuit_established_check_exit_code" = "137" ]
   then
      true "tor_circuit_established_check_exit_code: $tor_circuit_established_check_exit_code"
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   if [ "$VM" = "Whonix-Gateway" ]; then
      local MSG="<p>Tor Connection Result:
<br></br>Tor's Control Port could not be reached!
<br></br>
<br></br>Please report this $PROJECT_NAME bug!
<br></br>
<br></br>(Technical information:)
<br></br>(tor_circuit_established_check_exit_code: $tor_circuit_established_check_exit_code)
<br></br>(tor_bootstrap_timeout_type: $tor_bootstrap_timeout_type)
<br></br>(tor_bootstrap_status: $tor_bootstrap_status)
<br></br>(check_socks_port_open_test: $check_socks_port_open_test)
<br></br>(Tor Circuit: $tor_circuit_established_word)</p>"
   elif [ "$VM" = "Whonix-Workstation" ]; then
      if [ "$qubes_detected" = "false" ]; then
         local multiple_whonix_ws_msg="<br></br>- If you're running multiple Whonix-Workstations simultaneously, confirm that separate IP addresses are configured (see <a href=${PROJECT_HOMEPAGE}/wiki/Multiple_Whonix-Workstations>${PROJECT_HOMEPAGE}/wiki/Multiple_Whonix-Workstations</a>)."
      fi
      local MSG="<p>Tor Connection Result:
<br></br>Tor's Control Port could not be reached!
<br></br>
<br></br>Troubleshooting:
<br></br>- Confirm that Whonix-Gateway is running.
<br></br>- Run <code>systemcheck</code> on Whonix-Gateway and confirm success.
$multiple_whonix_ws_msg
<br></br>- Rerun <code>systemcheck</code> here in this Whonix-Workstation.
<br></br>
<br></br>(Technical information:)
<br></br>(tor_circuit_established_check_exit_code: $tor_circuit_established_check_exit_code)
<br></br>(tor_bootstrap_timeout_type: $tor_bootstrap_timeout_type)
<br></br>(tor_bootstrap_status: $tor_bootstrap_status)
<br></br>(check_socks_port_open_test: $check_socks_port_open_test)
<br></br>(Tor Circuit: $tor_circuit_established_word)</p>"
   else
      local MSG="<p>Tor Connection Result:
<br></br>Tor's Control Port could not be reached!
<br></br>
<br></br>Troubleshooting:
<br></br>- Confirm that Tor is running.
<br></br>- Rerun <code>systemcheck</code>
<br></br>
<br></br>(Technical information:)
<br></br>(tor_circuit_established_check_exit_code: $tor_circuit_established_check_exit_code)
<br></br>(tor_bootstrap_timeout_type: $tor_bootstrap_timeout_type)
<br></br>(tor_bootstrap_status: $tor_bootstrap_status)
<br></br>(check_socks_port_open_test: $check_socks_port_open_test)
<br></br>(Tor Circuit: $tor_circuit_established_word)</p>"
   fi
   if [ "$started_tor_bootstrap_progress_bar" = "1" ]; then
      $output_x ${output_opts[@]} --progressbaridx "$progressbaridx" --progressx "100"
   fi
   $output_x ${output_opts[@]} --messagex --typex "error" --message "$MSG"
   $output_cli ${output_opts[@]} --messagecli --typecli "error" --message "$MSG"
   EXIT_CODE="1"
   cleanup "1"
   ## `break` check_tor_bootstrap loop.
   return 1
}

check_tor_bootstrap_unknown_failure_cases() {
   if \
   [ "$tor_circuit_established_check_exit_code" = "" ] || \
   [ "$tor_circuit_established_check_exit_code" -gt "100" ] || \
   [ "$tor_circuit_established_check_exit_code" -lt "0" ]
   then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   local MSG="<p>Tor Connection Result:
<br></br>$check_bootstrap_script ERROR:
<br></br>tor_circuit_established_check_exit_code: $tor_circuit_established_check_exit_code
<br></br>(tor_bootstrap_status: $tor_bootstrap_status)
<br></br>(check_socks_port_open_test: $check_socks_port_open_test)
<br></br>(Tor Circuit: $tor_circuit_established_word)
<br></br>Please report this $PROJECT_NAME usability bug! (Not a security bug.)</p>"
   if [ "$started_tor_bootstrap_progress_bar" = "1" ]; then
      $output_x ${output_opts[@]} --progressbaridx "$progressbaridx" --progressx "100"
   fi
   $output_x ${output_opts[@]} --messagex --typex "error" --message "$MSG"
   $output_cli ${output_opts[@]} --messagecli --typecli "error" --message "$MSG"
   EXIT_CODE="1"
   cleanup "1"
   ## `break` check_tor_bootstrap loop.
   return 1
}

check_tor_bootstrap_stop_when_bootstrap_done() {
   ## For testing.
   #if [ "$systemcheck_tor_bootstrap_waited_seconds" -lt "10" ]; then
      #tor_bootstrap_percent="$(( 5 + ${#RANDOM} ))"
   #fi

   if [ "$tor_bootstrap_percent" = "100" ] && [ "$tor_circuit_established" = "1" ]; then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   if [ "$time_synchronization_status_word" = "first_success" ] || [ "$time_synchronization_status_word" = "success" ]; then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   local MSG="<p>Tor Connection Result: Ok.
<br></br>tor_bootstrap_status: <code>$tor_bootstrap_status</code>
<br></br>Tor Circuit: <code>$tor_circuit_established_word</code></p>"
   if [ "$verbose" -ge "1" ]; then
      $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"
      $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
   fi

   local MSG="<p>Time Synchronization Result: Ok.
<br></br>Time synchronization status: <code>$time_synchronization_status_word</code>
<br></br>sdwdate reports: <code>$time_synchronization_msg</code>
<br></br>whonix_firewall status: <code>$whonix_firewall_status_notification</code>
<br></br>onion-time-pre-script reports: <code>$onion_time_pre_script_output</code></p>"
   if [ "$verbose" -ge "1" ]; then
      $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"
      $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
   fi

   local MSG="<p>Connected to Tor.</p>"

   if [ "$started_tor_bootstrap_progress_bar" = "1" ]; then
      $output_x ${output_opts[@]} --progressbaridx "$progressbaridx" --progressx "100"
   fi
   $output_x ${output_opts[@]} --passivepopupqueuex --passivepopupqueuextitle "$passive_popup_title" --typex "info" --message "$MSG" --done
   $output_cli ${output_opts[@]} --waitmessagecli --typecli "info" --message "$MSG" --done
   ## `break` check_tor_bootstrap loop.
   return 1
}

check_tor_bootstrap_show_wait_notification_maybe() {
   if [ "$systemcheck_tor_bootstrap_waited_seconds" -lt "1" ]; then
      return 0
   fi

   if [ "$started_tor_bootstrap_progress_bar" = "1" ]; then
      return 0
   fi

   if [ "$tor_bootstrap_in_progress_passive_popup_shown" = "true" ]; then
      return 0
   fi

   started_tor_bootstrap_progress_bar="1"
   ## Waited for more than 5 seconds.
   progressbaridx="$(cat "/proc/sys/kernel/random/uuid")"
   local MSG="<p>Tor Bootstrap Test: Waiting for Tor Connection... (Will take up to $systemcheck_tor_bootstrap_wait_max seconds.)</p>"
   $output_x ${output_opts[@]} --progressbaridx "$progressbaridx" --progressbarx --parentpid "$$" --progressbartitlex "$TITLE_X" --message "$MSG" --done
   return 0
}

check_tor_bootstrap_wait_longer_maybe() {
   if [ "$systemcheck_tor_bootstrap_waited_seconds" -lt "$systemcheck_tor_bootstrap_wait_max" ]; then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi
   if \
      [ "$tor_bootstrap_percent" -lt "100" ] || \
      [ "$tor_circuit_established" = "0" ] || \
      [ "$time_synchronization_status_word" = "timeout" ] || \
      [ "$time_synchronization_status_word" = "pending" ]; then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   if [ "$PROGRESS" = "" ]; then
      PROGRESS="5"
   fi
   PROGRESS="$(( $PROGRESS + 1 ))"
   if [ "$PROGRESS" -ge "100" ]; then
      PROGRESS="6"
   fi

   if [ "$TOR_BOOTSTRAP_PERCENT_OLD" = "" ]; then
      TOR_BOOTSTRAP_PERCENT_OLD="$tor_bootstrap_percent"
   fi

   local progress_made_text
   if [ "$TOR_BOOTSTRAP_PERCENT_OLD" = "$tor_bootstrap_percent" ]; then
      ## no progress has been made
      progress_made_text=""
   else
      progress_made_text="| Progress has been made."
   fi

   if [ "$VM" = "Whonix-Gateway" ]; then
      local MSG="<p>Tor Connection Result:
- Connecting for $systemcheck_tor_bootstrap_waited_seconds seconds. | $tor_bootstrap_percent % done. $progress_made_text
- Tor Circuit: $tor_circuit_established_word.
- Tor reports: $tor_bootstrap_status
- Timesync status: $time_synchronization_status_notification.
- sdwdate reports: $time_synchronization_msg
- onion-time-pre-script reports: <code>$onion_time_pre_script_output</code></p>"
   else
      local MSG="<p>Tor Connection Result:
- Connecting for $systemcheck_tor_bootstrap_waited_seconds seconds.
- Tor Circuit: $tor_circuit_established_word.
- Timesync status: $time_synchronization_status_notification.
- sdwdate reports: $time_synchronization_msg
- onion-time-pre-script reports: <code>$onion_time_pre_script_output</code></p>"
   fi

   TOR_BOOTSTRAP_PERCENT_OLD="$tor_bootstrap_percent"

   $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG" --done

   if [ "$started_tor_bootstrap_progress_bar" = "1" ]; then
      $output_x ${output_opts[@]} --progressbaridx "$progressbaridx" --progressx "$PROGRESS"
   fi

   check_tor_bootstrap_sleep

   ## `continue` check_tor_bootstrap loop. Restart loop from the beginning.
   return 1
}

check_tor_bootstrap_give_up_on_connection_issue_maybe() {
   if [ "$systemcheck_tor_bootstrap_waited_seconds" -ge "$systemcheck_tor_bootstrap_wait_max" ]; then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   if [ "$tor_circuit_established" = "0" ]; then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   if [ "$tor_circuit_established" = "0" ]; then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   if [ "$VM" = "Whonix-Gateway" ]; then
      check_anondate_do
      ## sets: anondate_issue
      ## sets: anondate_recommendation
      ## sets: anondate_debugging_information
   fi

   if [ "$VM" = "Whonix-Gateway" ]; then
      local MSG="<p>Tor Connection Result:
<br></br><b>systemcheck gave up waiting.</b>
<br></br>Tor Circuit: $tor_circuit_established_word
<br></br>Connection $tor_bootstrap_percent % done. Tor reports: <code>$tor_bootstrap_status</code></p>

<p>Possible issues:
<br></br>- Is the host's internet connection working?
<br></br>- Whonix-Gateway will need a few moments for bootstrapping the Tor network.
<br></br>- Do you live in a censored area?
<br></br>- <a href=${PROJECT_HOMEPAGE}/wiki/Network_Obstacle>${PROJECT_HOMEPAGE}/wiki/Network_Obstacle</a>
$anondate_issue</p>

<p>Recommendations:</p>

$anondate_recommendation

<p>1)
<br></br>Shut down Whonix and try to get the Tor Browser Bundle from <a href=https://www.torproject.org>https://www.torproject.org</a>
working on your host. If you cannot get the Tor Browser Bundle to work, you will most certainly not get Whonix to work either.</p>

<p>The Tor Browser Bundle is great for testing if you live in a censored area. If you need bridges for the Tor Browser Bundle,
you will need them for Whonix as well.</p>

<p>2)
<br></br>Try again: $start_menu_instructions_system_first_part systemcheck
<br></br>or in Terminal: <code>systemcheck</code>
<br></br>or more verbose in Terminal: <code>systemcheck --verbose --gui --cli</code></p>

<p>3)
<br></br>Use Nyx, connection page two, to see if Tor is connected:
<blockquote>$start_menu_instructions_system_first_part Nyx</blockquote>
or in Terminal: <code>nyx</code></p>
$anondate_debugging_information"
   elif [ "$VM" = "Whonix-Workstation" ]; then
      local MSG="<p>Tor Connection Result:
<br></br>systemcheck gave up waiting.
<br></br>Tor Circuit: <code>$tor_circuit_established_word</code></p>

<p>Possible issues:
<br></br>- Is the host's internet connection working?
<br></br>- Whonix-Gateway will need a few moments for connecting to the Tor network.
<br></br>- Did you start Whonix-Gateway beforehand?
<br></br>- <a href=${PROJECT_HOMEPAGE}/wiki/Network_Obstacle>${PROJECT_HOMEPAGE}/wiki/Network_Obstacle</a></p>

<p>Recommendations:</p>

<p>1)
<br></br>Try again: $start_menu_instructions_system_first_part systemcheck
<br></br>           or in Terminal: <code>systemcheck</code>
<br></br>           or more verbose in Terminal: <code>systemcheck --verbose --gui --cli</code></p>

<p>2)
<br></br>Run systemcheck on Whonix-Gateway as well.</p>"

   elif [ "$VM" = "machine" ]; then
      local MSG="<p>Tor Connection Result:
<br></br><b>systemcheck gave up waiting.</b>
<br></br>Tor Circuit: $tor_circuit_established_word
<br></br>Connection $tor_bootstrap_percent % done. Tor reports: <code>$tor_bootstrap_status</code></p>

<p>Possible issues:
<br></br>- Is the host's internet connection working?
<br></br>- $VM will need a few moments for bootstrapping the Tor network.
<br></br>- Do you live in a censored area?
<br></br>- <a href=${PROJECT_HOMEPAGE}/wiki/Network_Obstacle>${PROJECT_HOMEPAGE}/wiki/Network_Obstacle</a>
$anondate_issue</p>

<p>Recommendations:</p>

$anondate_recommendation

<p>1)
<br></br>Try to get the Tor Browser Bundle from <a href=https://www.torproject.org>https://www.torproject.org</a>
working on your host. If you cannot get the Tor Browser Bundle to work, you will most certainly not get system Tor to work either.</p>

<p>The Tor Browser Bundle is great for testing if you live in a censored area. If you need bridges for the Tor Browser Bundle,
you will need them for system Tor as well.</p>

<p>2)
<br></br>Try again: $start_menu_instructions_system_first_part systemcheck
<br></br>or in Terminal: <code>systemcheck</code>
<br></br>or more verbose in Terminal: <code>systemcheck --verbose --gui --cli</code></p>

<p>3)
<br></br>Use Nyx, connection page two, to see if Tor is connected:
<blockquote>$start_menu_instructions_system_first_part Nyx</blockquote>
or in Terminal: <code>nyx</code></p>
$anondate_debugging_information"
   else
      local MSG="$FUNCNAME: Machine detection failed. Please report this $PROJECT_NAME bug!"
   fi

   if [ "$started_tor_bootstrap_progress_bar" = "1" ]; then
      $output_x ${output_opts[@]} --progressbaridx "$progressbaridx" --progressx "100"
   fi
   $output_x ${output_opts[@]} --messagex --typex "error" --message "$MSG"
   $output_cli ${output_opts[@]} --messagecli --typecli "error" --message "$MSG"
   EXIT_CODE="1"
   cleanup "1"
   ## `break` check_tor_bootstrap loop.
   return 1
}

check_tor_bootstrap_give_up_on_timesync_issue_maybe() {
   local sdwdate_wait

   if [ ! "$tor_circuit_established" = "1" ]; then
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   if [ "$time_synchronization_status_word" = "fail" ]; then
      true
      sdwdate_wait=""
      ## No need to wait if time_synchronization_status_word is already set to 'fail'.
   else
      ## Wait maybe.
      if [ "$systemcheck_tor_bootstrap_waited_seconds" -ge "$systemcheck_tor_bootstrap_wait_max" ]; then
         ## Waited long enough. Go on with this function.
         true
         sdwdate_wait="- sdwdate will need a few more moments for fetching the time."
      else
         ## Did not wait long enough yet.
         ## Keep check_tor_bootstrap loop running. Go to next function in loop.
         return 0
      fi
   fi

   if [ "$time_synchronization_status_word" = "pending" ] || [ "$time_synchronization_status_word" = "fail" ]; then
      true
   else
      ## Keep check_tor_bootstrap loop running. Go to next function in loop.
      return 0
   fi

   local if_you_know_what_you_are_doing_msg
   if_you_know_what_you_are_doing_msg="$(if_you_know_what_you_are_doing_funct "$FUNCNAME")"

   if [ "$whonix_firewall_status_word" = "consecutive_run" ]; then
      local MSG="<p>Time Synchronization Result:
<br></br><b>systemcheck gave up waiting.</b>
<br></br>
<br></br>Time synchronization status: <code>$time_synchronization_status_word</code>
<br></br>sdwdate reports: <code>$time_synchronization_msg</code>
<br></br>whonix_firewall status: <code>$whonix_firewall_status_notification</code>
<br></br>onion-time-pre-script reports: <code>$onion_time_pre_script_output</code>
<br></br>
<br></br>Possible issues:
<br></br>$sdwdate_wait
<br></br>- sdwdate time sources might be dysfunctional.
<br></br>
<br></br>Apparently you have already reload Whonix-Firewall.
</p>"
   else
      local MSG="<p>Time Synchronization Result:
<br></br><b>systemcheck gave up waiting.</b>
<br></br>
<br></br>Time synchronization status: <code>$time_synchronization_status_word</code>
<br></br>sdwdate reports: <code>$time_synchronization_msg</code>
<br></br>whonix_firewall status: <code>$whonix_firewall_status_notification</code>
<br></br>onion-time-pre-script reports: <code>$onion_time_pre_script_output</code>
<br></br>
<br></br>Possible issues:
<br></br>$sdwdate_wait
<br></br>- sdwdate time sources might be dysfunctional.
<br></br>
<br></br>Recommendations:
<br></br>
<br></br><b>A)</b> <u>Rerun systemcheck</u>:
<blockquote>$start_menu_instructions_system_first_part systemcheck</blockquote>
or in Terminal: <code>systemcheck</code>
<br></br>or more verbose in Terminal: <code>systemcheck --verbose --gui --cli</code>
<br></br>
<br></br><b>B)</b> <u>Restart sdwdate.</u>
<blockquote>$start_menu_instructions_system_first_part sdwdate-gui -> right click on sdwdate-gui systray -> Restart sdwdate</blockquote>
or in Terminal: <code>sudo service sdwdate restart</code>
<br></br>
<br></br><b>C)</b> <u>Manually set the time.</u>
<br></br>
<br></br>As last resort...
<br></br>
<br></br>1. Open a terminal. ($start_menu_instructions_system_first_part Terminal)
<br></br>2. Use the manual clock setting tool. <blockquote><code>sudo --set-home clock-random-manual-gui</code></blockquote>
3. Simulate sdwdate success. <blockquote><code>sudo -u sdwdate touch /run/sdwdate/first_success</code></blockquote>
4. Rerun systemcheck.</p>"
   fi

   if [ "$started_tor_bootstrap_progress_bar" = "1" ]; then
      $output_x ${output_opts[@]} --progressbaridx "$progressbaridx" --progressx "100"
   fi
   $output_x ${output_opts[@]} --messagex --typex "error" --message "$MSG"
   $output_cli ${output_opts[@]} --messagecli --typecli "error" --message "$MSG"

   if [ "$whonix_firewall_status_word" = "consecutive_run" ]; then
      ## `break` check_tor_bootstrap loop.
      return 1
   else
      EXIT_CODE="1"
      cleanup "1"
      ## `break` check_tor_bootstrap loop.
      return 1
   fi
}

check_tor_bootstrap_script_error() {
   error_handler "<p>(Tor Connection Result:)
<br></br>(Technical information:)
<br></br>(tor_bootstrap_percent: <code>$tor_bootstrap_percent</code>)
<br></br>(tor_circuit_established: <code>$tor_circuit_established</code>)
<br></br>(tor_circuit_established_word: <code>$tor_circuit_established_word</code>)
<br></br>(tor_bootstrap_timeout_type: <code>$tor_bootstrap_timeout_type</code>)
<br></br>(tor_bootstrap_status: <code>$tor_bootstrap_status</code>)
<br></br>(check_socks_port_open_test: <code>$check_socks_port_open_test</code>)
<br></br>(systemcheck_tor_bootstrap_waited_seconds: <code>$systemcheck_tor_bootstrap_waited_seconds</code>)
<br></br>(systemcheck_tor_bootstrap_wait_max: <code>$systemcheck_tor_bootstrap_wait_max</code>)
<br></br>
<br></br>(whonix_firewall_status_word: $whonix_firewall_status_word)
<br></br>(whonix_firewall_status_notification: $whonix_firewall_status_notification)
<br></br>
<br></br>(time_synchronization_status_word: <code>$time_synchronization_status_word</code>)
<br></br>(time_synchronization_msg: <code>$time_synchronization_msg</code>)
<br></br>
<br></br>(anondate_issue: $anondate_issue)
<br></br>(anondate_recommendation: $anondate_recommendation)
<br></br>
<br></br>(anondate_debugging_information: $anondate_debugging_information)
</p>"

   ## `break` check_tor_bootstrap loop.
   return 1
}
