diff --git a/static/build/.tmp_update/script/netplay/easy-netplay_client.sh b/static/build/.tmp_update/script/netplay/easy-netplay_client.sh index 7c2286d6eb..82ce245275 100644 --- a/static/build/.tmp_update/script/netplay/easy-netplay_client.sh +++ b/static/build/.tmp_update/script/netplay/easy-netplay_client.sh @@ -8,384 +8,22 @@ # Used within GLO as an addon script. # Env setup -sysdir=/mnt/SDCARD/.tmp_update -miyoodir=/mnt/SDCARD/miyoo -export LD_LIBRARY_PATH="/lib:/config/lib:$miyoodir/lib:$sysdir/lib:$sysdir/lib/parasyte" -export hostip="192.168.100.100" # This should be the default unless the user has changed it.. +# easy-netplay_env.sh: sysdir, miyoodir, LD_LIBRARY_PATH, hostip, peer_ip +. /mnt/SDCARD/.tmp_update/script/netplay/easy-netplay_env.sh logfile=easy_netplay -. $sysdir/script/log.sh + +# Source scripts +# easy-netplay_common.sh: build_infoPanel_and_log, checksize_func, checksum_func, enable_flag, disable_flag, flag_enabled, is_running, restore_ftp, +# udhcpc_control, url_encode, strip_game_name, format_game_name, wifi_disabled, read_cookie, check_wifi, start_ftp, sync_file +. $sysdir/script/netplay/easy-netplay_common.sh + program=$(basename "$0" .sh) ########## ##Setup.## ########## -# Read the cookie and store the paths and checksums into a var. -read_cookie() { - sync - while IFS= read -r line; do - case $line in - "[core]: "*) - core="${line##"[core]: "}" - ;; - "[rom]: "*) - rom="${line##"[rom]: "}" - ;; - "[coresize]: "*) - corechecksum="${line##"[coresize]: "}" - ;; - "[corechksum]: "*) - corechecksum="${line##"[corechksum]: "}" - ;; - "[romsize]: "*) - romchecksum="${line##"[romsize]: "}" - ;; - "[romchksum]: "*) - romchecksum="${line##"[romchksum]: "}" - ;; - "[cpuspeed]: "*) - cpuspeed="${line##"[cpuspeed]: "}" - ;; - esac - log "$core $rom $coresize $corechksum $romsize $romchksum" - done <"/mnt/SDCARD/RetroArch/retroarch.cookie.client" - - #url encode or curl complains - export core_url=$(url_encode "$core") - export rom_url=$(url_encode "$rom") - - romdirname=$(echo "$rom" | grep -o '/Roms/[^/]*' | cut -d'/' -f3) - romName=$(basename "$rom") - romNameNoExtension=${romName%.*} - Img_path="/mnt/SDCARD/Roms/$romdirname/Imgs/$romNameNoExtension.png" - - log "Cookie file read" -} - -sync_file() { - - MAX_FILE_CHKSUM_SIZE=26214400 - MAX_FILE_DL_SIZE=104857600 - - file_type="$1" # Used in displayed message and some custom actions - file_path="$2" # Local file path - file_check_size="$3" # 0 or 1 to indicate if we have to check the file size - remote_file_checksum="$4" # 0 to skip , real checksum value to check - sync_type="$5" # -o overwrite if different (require file_size or/and checksum != 0) , (if file_size & checksum = 0 then the file is never overwritted, only copied if not present) - # -f overwrite all the time (whatever the value of file_size and checksum) (if file_size & checksum = 0 then the file is overwritted, even if already present ) - # -b if different, backup local file before copying remote file - # -c check only, allows to check the presence of a file, to check its CRC or size and to quit or not the script - file_mandatory="$6" # -m , exit the script on failed sync_success - - #examples : - # sync_file archive /mnt/SDCARD/test.zip 1 5AFC442 -b -m # backup and replace if different file - # sync_file archive /mnt/SDCARD/test.zip 0 0 -f -m # the local file will be systematically replaced - # sync_file archive /mnt/SDCARD/test.zip 0 0 -o -m # the local file will be copied if not exist - # sync_file archive /mnt/SDCARD/test.zip 0 5AFC442 -c -m # exit if the file doesn't have the right checksum - # sync_file archive /mnt/SDCARD/test.zip 1 5AFC442 -o -m # the local file will be replaced if the size or the checksum is different - - # some useful vars - dir_path=$(dirname "$file_path") - file_url="ftp://${hostip}/$(url_encode "${file_path#*/}")" - - echo "############################ DEBUGGING #######################################" - echo file_type $file_type - echo file_path $file_path - echo file_check_size $file_check_size - echo remote_file_checksum $remote_file_checksum - echo sync_type $sync_type - echo file_mandatory $file_mandatory - echo - echo dir_path $dir_path - echo romdirname $romdirname - echo romName $romName - echo romNameNoExtension $romNameNoExtension - echo Img_path $Img_path - echo file_url $file_url - echo "##############################################################################" - - # state vars - same_size= - same_chksum= - sync_success= - run_sync= # tell if the sync task must be done or not - - RequestResult=$(curl -I "$file_url" 2>&1) - - if [[ $RequestResult == *"The file does not exist"* ]]; then - log "The remote file does not exist." - msg="The remote file does not exist." - build_infoPanel_and_log "Syncing" "The remote file does not exist." - run_sync=0 - sync_success=0 - same_size=0 - else - remote_file_size=$(echo "$RequestResult" | grep -i "Content-Length" | awk '{print $2}') - if ! echo "$remote_file_size" | grep -q "^[0-9][0-9]*$"; then # check if the remote file size is a numeric value - log "Impossible to get remote file size." - same_size=0 - run_sync=0 - else - log "remote_file_size: $remote_file_size" - fi - - fi - - if [ -e "$file_path" ]; then - - ########################## File checksum check : same_chksum = 0 different, 1 identical , 2 unknown - checksum_func "$file_path" "$remote_file_checksum" - - ########################## File size check same_size = 0 different, 1 identical , 2 unknown - if [ "$file_check_size" -eq 1 ]; then # file_checksum=0 means skip the difference check = always replace - checksize_func "$file_path" "$remote_file_size" - else - log "Skipping file size check." - same_size=1 # fake same size for skipping - fi - - else - log "The local file does not exist." - same_size=0 - same_chksum=0 - fi - - ########################## exception : max file size check on the remote - if [ "$remote_file_size" -le "$MAX_FILE_DL_SIZE" ]; then - log "Remote file size ok: $remote_file_size bytes (<= $MAX_FILE_DL_SIZE bytes)" - else - log "Remote file size too big: $remote_file_size bytes (> $MAX_FILE_DL_SIZE bytes)" - run_sync=0 - fi - - ########################## We have all the required information, depending the choosen option we run the copy or not - - if [ "$sync_type" == "-o" ]; then # we overwrite the file if different - log "option -o selected : we overwrite the file if different." - if [ "$same_size" -ne 1 ] || [ "$same_chksum" -ne 1 ]; then - [ -z "$run_sync" ] && run_sync=1 - fi - fi - - if [ "$sync_type" == "-b" ]; then # backup - log "option -b selected : we backup before overwrite." - if { [ "$remote_file_checksum" != "0" ] && [ "$same_chksum" -ne 1 ]; } || [ "$remote_file_checksum" == "0" ]; then # if (we don't skip CRC and CRC is not identical) or (if we skip CRC) then we sync -> in other words we only skip the copy when we have an identical CRC - [ -z "$run_sync" ] && run_sync=1 - fi - fi - - if [ "$sync_type" == "-f" ]; then # we overwrite the file if different - log "option -f selected : forced file syncing." - if { [ "$remote_file_checksum" != "0" ] && [ "$same_chksum" -ne 1 ]; } || [ "$remote_file_checksum" == "0" ]; then # if (we don't skip CRC and CRC is not identical) or (if we skip CRC) then we sync -> in other words we only skip the copy when we have an identical CRC - [ -z "$run_sync" ] && run_sync=1 - fi - - fi - - if [ "$sync_type" == "-c" ]; then # we overwrite the file if different - log "option -c selected : no file copy, only check." - run_sync=0 - - if [ "$same_size" -ne 1 ]; then - msg="Files doesn't have the same size." - sync_success=0 - [ "$file_mandatory" = "-m" ] && cleanup - - fi - if [ "$same_chksum" -ne 1 ]; then - msg="$msg\nFiles doesn't have the same checksum." - sync_success=0 - [ "$file_mandatory" = "-m" ] && cleanup - - fi - if [ "$same_size" -eq 1 ] && [ "$same_chksum" -eq 1 ]; then - msg="Remote and local files are identical." - sync_success=1 - fi - build_infoPanel_and_log "File check" "$msg" - - fi - - log "############################ DEBUGGING #######################################" - echo sync_type $sync_type - echo remote_file_checksum $remote_file_checksum - echo same_chksum $same_chksum - echo run_sync $run_sync - echo file_type $file_type - echo - echo - echo "##############################################################################" - - ########################## COPY Operation ########################## - - if [ "$run_sync" -eq 1 ]; then - - if [ $file_type == "Cookie" ]; then # exception for cookies : we don't download with the same target name - file_path="${file_path}.client" - fi - # let's make a backup first whatever the case - if [ -e "$file_path" ]; then - if [ $file_type == "Rom" ]; then - # if rom already here and different file then we create a rom_neplay to avoid to override user games - - # oldpath="$file_path" - # file_path_without_extension="${file_path%.*}" - # file_path="${file_path_without_extension}_netplay.${file_path##*.}" - # if [ -e "$Img_path" ]; then - # cp "$Img_path" "/mnt/SDCARD/Roms/$romdirname/Imgs/${romNameNoExtension}_netplay.png" - # Img_path="/mnt/SDCARD/Roms/$romdirname/Imgs/${romNameNoExtension}_netplay.png" - # fi - - Netplay_Rom_Folder="$(dirname "$file_path")/.netplay" - mkdir -p "$Netplay_Rom_Folder" - file_path="$Netplay_Rom_Folder/$(basename "$file_path")" - rom=$file_path - - elif [ $file_type == "Core" ]; then - # oldpath="$file_path" - # file_path_without_extension="${file_path%.*}" - # file_path="${file_path_without_extension}_netplay.${file_path##*.}" - - Netplay_Core_Folder="$(dirname "$file_path")/.netplay" - mkdir -p "$Netplay_Core_Folder" - file_path="$Netplay_Core_Folder/$(basename "$file_path")" - core=$file_path - else - mv "$file_path" "${file_path}_old" - log "Existing $file_type file moved to ${file_path}_old" - fi - fi - - if [ ! -d "$dir_path" ]; then - mkdir -p "$dir_path" - fi - - log "Starting to download $file_type from $file_url" - curl -o "$file_path" "$file_url" >/dev/null 2>&1 - - if [ $? -eq 0 ]; then - log "$file_type download completed" - else - log "$file_type download failed" - fi - - fi - - ###################### FINAL CHECK RESULT ######################### - - if [ ! -e "$file_path" ]; then - build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - - # copy has failed : restoring the original file - if [ $file_type != "Rom" ] && [ $file_type != "Core" ]; then - mv "${file_path}_old" "$file_path" - log "backup restored" - fi - sleep 2 - [ "$file_mandatory" = "-m" ] && cleanup - - else - - checksum_func "$file_path" "$remote_file_checksum" - - if [ "$file_check_size" -eq 1 ]; then # file_checksum=0 means skip the difference check = always replace - checksize_func "$file_path" "$remote_file_size" - else - log "Skipping file size check." - same_size=1 # fake same size for skipping - fi - - if [ "$same_size" -eq 1 ] && [ "$same_chksum" -eq 1 ]; then - build_infoPanel_and_log "Syncing" "$file_type synced." - if [ $file_type == "Rom" ]; then - log "Refreshing roms list ${rom%/*}/${romdirname}_cache6.db" - rm "${rom%/*}/${romdirname}_cache6.db" - fi - - else - build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - - # copy has failed : restoring the original file - if [ $file_type != "Rom" ] && [ $file_type != "Core" ]; then - mv "${file_path}_old" "$file_path" - log "backup restored" - fi - sleep 2 - [ "$file_mandatory" = "-m" ] && cleanup - fi - #####" - - fi - ###################### FINAL RESULT DISPLAY######################### - - # if [ "$sync_success" -ne 1 ]; then - # build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - # sleep 2 - # cleanup - # else - # build_infoPanel_and_log "Syncing" "$file_type synced." - # fi - - # build_infoPanel_and_log "Syncing" "$file_type checksums don't match, syncing" - # build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - # build_infoPanel_and_log "Syncing" "$file_type synced." - # build_infoPanel_and_log "Syncing" "$file_type doesn't exist locally; syncing with host." - # build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - # build_infoPanel_and_log "Syncing" "$file_type synced." - - ################### END ########################## - -} - -checksum_func() { - local_file_size=$(stat -c%s "$file_path") - local func_file_path="$1" - local CRC="$2" - - ########################## File checksum check : same_chksum = 0 different, 1 identical , 2 unknown - - if [ "$CRC" != "0" ]; then # file_checksum=0 means skip the difference check = always replace - local_file_checksum=$(xcrc "$func_file_path") - - if [ "$local_file_size" -gt "$MAX_FILE_CHKSUM_SIZE" ]; then - log "File size too big for checksum: it would be too long" - same_chksum=2 - else - if [ "$CRC" == "$local_file_checksum" ]; then - same_chksum=1 - else - same_chksum=0 - fi - fi - else - log "Skipping checksum check." - same_chksum=1 # fake same size for skipping - fi -} - -checksize_func() { - - local func_file_path="$1" - local filesize_tocheck="$2" - local_file_size=$(stat -c%s "$func_file_path") - - ########################## File size check same_size = 0 different, 1 identical , 2 unknown - - if echo "$filesize_tocheck" | grep -q "^[0-9][0-9]*$"; then # check if the remote file size is a numeric value - if [ "$filesize_tocheck" -eq "$local_file_size" ]; then - log "Same size as remote" - same_size=1 - else - log "Files size are different" - same_size=0 - fi - else - log "Impossible to get file size : wrong parameter." - same_size=2 - fi -} - # Start retroarch with -C in client mode if everything's gone to plan start_retroarch() { build_infoPanel_and_log "Starting RA" "Starting RetroArch" @@ -420,55 +58,7 @@ start_retroarch() { #Utilities# ########### -# URL encode helper -url_encode() { - encoded_str=$(echo "$*" | awk ' - BEGIN { - split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ") - hextab [0] = 0 - for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0 - } - { - encoded = "" - for ( i=1; i<=length ($0); ++i ) { - c = substr ($0, i, 1) - if ( c ~ /[a-zA-Z0-9.-]/ ) { - encoded = encoded c # safe character - } else if ( c == " " ) { - encoded = encoded "%20" # special handling - } else { - # unsafe character, encode it as a two-digit hex-number - lo = ord [c] % 16 - hi = int (ord [c] / 16); - encoded = encoded "%" hextab [hi] hextab [lo] - } - } - print encoded - } -') - echo "$encoded_str" -} - -wifi_disabled() { - [ $(/customer/app/jsonval wifi) -eq 0 ] -} - -build_infoPanel_and_log() { - local title="$1" - local message="$2" - - log "Info Panel: \n\tStage: $title\n\tMessage: $message" - if is_running infoPanel; then - killall -9 infoPanel - fi - infoPanel --title "$title" --message "$message" --persistent & - sync - touch /tmp/dismiss_info_panel - sync - sleep 0.3 - sync -} - +# confirm_join_panel: show join confirmation UI with ROM image confirm_join_panel() { local title="$1" local message="$2" @@ -490,35 +80,16 @@ confirm_join_panel() { fi } -stripped_game_name() { - game_name=$(awk -F'/' '/\[rom\]:/ {print $NF}' /mnt/SDCARD/RetroArch/retroarch.cookie.client | sed 's/\(.*\)\..*/\1/') -} - -is_running() { - process_name="$1" - pgrep "$process_name" >/dev/null -} - +# cleanup: restore wifi/ftp and remove session temp files cleanup() { - build_infoPanel_and_log "Cleanup" "Cleaning up after netplay session..." - - pkill -9 pressMenu2Kill - - if is_running infoPanel; then - killall -9 infoPanel - fi - rm /tmp/dismiss_info_panel - - sync - - # restore_wifi_state - . "$sysdir/script/network/hotspot_cleanup.sh" - - rm "/mnt/SDCARD/RetroArch/retroarch.cookie.client" - - log "Cleanup done" - sync - exit + # message: cleanup infoPanel text + # args: hotspot_cleanup restore_ftp kill_infopanel disable_hotspot_flag + # remove files + netplay_cleanup \ + "Cleaning up after netplay session..." \ + 1 0 1 0 \ + "/tmp/dismiss_info_panel" \ + "$COOKIE_CLIENT_PATH" } ######### @@ -526,18 +97,37 @@ cleanup() { ######### lets_go() { - + # Allow user to abort via menu while setup runs pressMenu2Kill $(basename $0) & + + # Join host hotspot . "$sysdir/script/network/hotspot_join.sh" - sync_file "Cookie" "/mnt/SDCARD/RetroArch/retroarch.cookie" 0 0 -f -m + build_infoPanel_and_log "Connected" "Client IP: ${IP:-unknown}\nHost IP: $hostip" + + # Fetch cookie from host + sync_file "Cookie" "$COOKIE_FILE" 0 0 -f -m + + # Read host cookie and parse paths/checksums read_cookie + + # Sync required core, rom, and image sync_file "Core" "$core" 1 "$corechecksum" -b -m sync_file "Rom" "$rom" 1 "$romchecksum" -b -m sync_file "Img" "$Img_path" 0 0 -o - stripped_game_name + + # Build display name for confirmation prompt + game_name=$(format_game_name "$(basename "${rom%.*}")") + + # Stop menu watcher before launch pkill -9 pressMenu2Kill + + # Confirm join with host info confirm_join_panel "Join now?" "$game_name" + + # Launch RetroArch client session start_retroarch + + # Cleanup and restore state cleanup } diff --git a/static/build/.tmp_update/script/netplay/easy-netplay_client_pokemon.sh b/static/build/.tmp_update/script/netplay/easy-netplay_client_pokemon.sh index 995e92d92d..292ebf2e37 100644 --- a/static/build/.tmp_update/script/netplay/easy-netplay_client_pokemon.sh +++ b/static/build/.tmp_update/script/netplay/easy-netplay_client_pokemon.sh @@ -2,12 +2,10 @@ # Used within GLO as an addon script. # Env setup -sysdir=/mnt/SDCARD/.tmp_update -miyoodir=/mnt/SDCARD/miyoo -# save_dir="/mnt/SDCARD/Saves/CurrentProfile/saves/TGB Dual/" -LD_LIBRARY_PATH="/lib:/config/lib:$miyoodir/lib:$sysdir/lib:$sysdir/lib/parasyte" +. /mnt/SDCARD/.tmp_update/script/netplay/easy-netplay_env.sh WPACLI=/customer/app/wpa_cli -hostip="192.168.100.100" # This should be the default unless the user has changed it.. + +# Runtime vars rm /tmp/stop_now client_rom="$cookie_rom_path" client_rom_filename=$(basename "$client_rom") @@ -15,9 +13,15 @@ client_rom_filename_NoExt="${client_rom_filename%.*}" SaveFromGambatte=0 -## Source global utils logfile=pokemon_link -. $sysdir/script/log.sh + +# Source scripts +# easy-netplay_common.sh: build_infoPanel_and_log, checksize_func, checksum_func, enable_flag, disable_flag, flag_enabled, is_running, +# restore_ftp, udhcpc_control, url_encode, strip_game_name, format_game_name, read_cookie, check_wifi, start_ftp, sync_file +. $sysdir/script/netplay/easy-netplay_common.sh +# easy-netplay_signalling.sh: check_stop, notify_peer, notify_stop, wait_for_host +. $sysdir/script/netplay/easy-netplay_signalling.sh + program=$(basename "$0" .sh) export CurDate=$(date +%Y%m%d_%H%M%S) @@ -27,55 +31,10 @@ log "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Easy Netplay Pokemon Client -*-*-* ##Setup.## ########## -# Read the cookie and store the paths and checksums into a var. -read_cookie() { - sync - while IFS= read -r line; do - case $line in - "[core]: "*) - core="${line##"[core]: "}" - ;; - "[rom]: "*) - rom="${line##"[rom]: "}" - ;; - "[coresize]: "*) - corechecksum="${line##"[coresize]: "}" - ;; - "[corechksum]: "*) - corechecksum="${line##"[corechksum]: "}" - ;; - "[romsize]: "*) - romchecksum="${line##"[romsize]: "}" - ;; - "[romchksum]: "*) - romchecksum="${line##"[romchksum]: "}" - ;; - "[cpuspeed]: "*) - cpuspeed="${line##"[cpuspeed]: "}" - ;; - esac - log "$core $rom $coresize $corechksum $romsize $romchksum" - done <"/mnt/SDCARD/RetroArch/retroarch.cookie.client" - - #url encode or curl complains - export core_url=$(url_encode "$core") - export rom_url=$(url_encode "$rom") - - romdirname=$(echo "$rom" | grep -o '/Roms/[^/]*' | cut -d'/' -f3) - romName=$(basename "$rom") - romNameNoExtension=${romName%.*} - Img_path="/mnt/SDCARD/Roms/$romdirname/Imgs/$romNameNoExtension.png" - log "Cookie file read :" - log "romdirname $romdirname" - log "romName $romName" - log "romNameNoExtension $romNameNoExtension" - log "Img_path $Img_path" - -} - -# Push our save over to the host - The save will be found based on the rom we've started GLO on and it will look in the $save_dir path for it (see line13) - Backs up first +# Push our save over to the host - The save will be found based on the rom we've started GLO on and it will look in the $save_dir path for it - Backs up first backup_and_send_save() { - check_stop + # check_stop: host reported a setup issue + check_stop "The host has had a problem setting up the session" missing="" build_infoPanel_and_log "Syncing saves" "Syncing our save files with the host" @@ -85,9 +44,9 @@ backup_and_send_save() { if [ -f "$save_gambatte" ]; then SaveFromGambatte=1 - log "Gambatte save file detected." - log "Backing up Gambatte save file to: $client_rom_filename_NoExt.srm_$Curdate" + log "Gambatte save file detected. Backing up Gambatte save file to: $client_rom_filename_NoExt.srm_$Curdate" cp -f "$save_gambatte" "${save_gambatte}_$CurDate" + log_file_state "Gambatte save (backed up)" "$save_gambatte" if [ -f "$save_tgbdual" ]; then confirm_join_panel "Continue ?" "There is a local save for\n$client_rom_filename_NoExt\nfor TGB Dual and for Gambatte.\n Gambatte save will be used by default." log "Existing TGB Dual save file detected. Continue with Gambatte save." @@ -97,55 +56,34 @@ backup_and_send_save() { cp -f "$save_gambatte" "$save_tgbdual" save_file_matched="$save_gambatte" elif [ -f "$save_tgbdual" ]; then - log "No Gambatte save file detected, using TGB Dual save file instead." + log "No Gambatte save file detected, using TGB Dual" log "Backing up current TGB Dual save file to: $client_rom_filename_NoExt.srm_$Curdate" cp -f "$save_tgbdual" "${save_tgbdual}_$CurDate" + log_file_state "TGB Dual save (backed up)" "$save_tgbdual" save_file_matched="$save_tgbdual" else - touch "/tmp/MISSING.srm" - save_file_matched="/tmp/MISSING.srm" + missing=1 + touch "/tmp/missing_save.srm" + save_file_matched="/tmp/missing_save.srm" fi save_file_stripped="${save_file_matched##*/}" encoded_save_file=$(url_encode "$save_file_stripped") log "encoded_save_file: $encoded_save_file" + log_file_state "Save selected for upload" "$save_file_matched" curl -T "$save_file_matched" "ftp://$hostip/tmp/$encoded_save_file" + log "curl exit status (upload save)=$?" if [ "$missing" = "1" ]; then + # hitting this block means we cannot send a save to the host + # in some games, such as pokemon this means the host would start a blank save build_infoPanel_and_log "Save not found" "You don't have a save for this game, \n or we failed to find it. Cannot continue \n Notified host." notify_stop fi } -# Wait for the host to tell us it's ready, this happens just before it starts its RA session and we look in /tmp for a file indicator (file removed in host script cleanup) -wait_for_host() { - - local counter=0 - - build_infoPanel_and_log "Ready" "Waiting for host to ready up" - while true; do - sync - check_stop - for file in /tmp/host_ready; do - if [ -f "$file" ]; then - build_infoPanel_and_log "Message from host" "Setup complete" - rm /tmp/host_ready # be ready for the second use of host_ready flag - break 2 - fi - done - - sleep 1 - counter=$((counter + 1)) - - if [ $counter -ge 25 ]; then - build_infoPanel_and_log "Error" "The host didn't ready up, cannot continue..." - notify_stop - fi - done -} - # Start retroarch with -C in client mode if everything's gone to plan start_retroarch() { build_infoPanel_and_log "Starting RA" "Starting RetroArch" @@ -157,6 +95,7 @@ start_retroarch() { log "core_config_folder: $core_config_folder" log "cpuspeed: $cpuspeed" log "hostip: $hostip" + log_file_state "Client save (pre-RA)" "$save_file_matched" log "###############################################################################" if [ -n "$cpuspeed" ]; then @@ -165,7 +104,6 @@ start_retroarch() { echo -n $cpuspeed >"/mnt/SDCARD/Saves/CurrentProfile/config/${core_config_folder}/cpuclock.txt" fi - wait_for_host # we wait a second flag triggered from the host once RA is running cd /mnt/SDCARD/RetroArch log "Starting RetroArch loaded with $rom and $client_rom" HOME=/mnt/SDCARD/RetroArch ./retroarch --appendconfig=./.retroarch/easynetplay_override.cfg -C $hostip -L "$core" --subsystem "gb_link_2p" "$rom" "$client_rom" @@ -181,7 +119,8 @@ start_retroarch() { # Go into a waiting state for the host to return the save (If you don't call this you don't retransfer the saves - Users cannot under any circumstances miss this function) wait_for_save_return() { build_infoPanel_and_log "Syncing" "Waiting for host to be ready for save sync" - notify_peer "ready_to_receive" + # notify_peer: signal ready to receive save + notify_peer "$hostip" "ready_to_receive" sync @@ -198,6 +137,7 @@ wait_for_save_return() { counter=$((counter + 1)) if [ $counter -ge 30 ]; then + # if we've hit this block the save won't be re-transferred, if this happens progress during this session is lost. build_infoPanel_and_log "Error" "The Host didn't ready up, cannot continue..." log "We ran out of time waiting for the host to ready up, possibly due to host->client connecitivity" sleep 1 @@ -210,11 +150,14 @@ wait_for_save_return() { received_save="/tmp/$(basename "$save_file_matched")_rcvd" + log_file_state "Received save (raw)" "$received_save" + log_file_state "Local save before merge" "$save_file_matched" log "cp -f \"$received_save\" \"$save_file_matched\"" cp -f "${received_save}" "$save_file_matched" cp_exit_status=$? if [ $cp_exit_status -eq 0 ]; then + log_file_state "Local save after merge" "$save_file_matched" if [ $SaveFromGambatte -eq 1 ]; then mv -f "/mnt/SDCARD/Saves/CurrentProfile/states/Gambatte/$client_rom_filename_NoExt.state.auto" "/mnt/SDCARD/Saves/CurrentProfile/states/Gambatte/$client_rom_filename_NoExt.state.auto_$CurDate" else @@ -228,458 +171,32 @@ wait_for_save_return() { fi } +# cleanup: restore wifi/ftp and remove session temp files cleanup() { - build_infoPanel_and_log "Cleanup" "Cleaning up after Pokemon session\n Do not power off!" - - pkill -9 pressMenu2Kill - - if is_running infoPanel; then - killall -9 infoPanel - fi - - # restore_wifi_state - . "$sysdir/script/network/hotspot_cleanup.sh" - restore_ftp - - # Remove some files we prepared and received log "Removing stale files" - rm "/tmp/host_ready" - rm "/tmp/ready_to_send" - rm "/tmp/ready_to_receive" - rm "${save_file_matched}_rcvd" - rm "/tmp/MISSING.srm" - rm "/tmp/stop_now" - rm "/tmp/wpa_supplicant.conf_bk" - rm "/mnt/SDCARD/RetroArch/retroarch.cookie.client" - rm "/mnt/SDCARD/RetroArch/retroarch.cookie" - rm "/tmp/dismiss_info_panel" - sync - - log "Cleanup done" - exit + # message: cleanup infoPanel text + # args: hotspot_cleanup restore_ftp kill_infopanel disable_hotspot_flag + # remove files + netplay_cleanup \ + "Cleaning up after Pokemon session\n Do not power off!" \ + 1 1 1 0 \ + "/tmp/host_ready" \ + "/tmp/ready_to_send" \ + "/tmp/ready_to_receive" \ + "${save_file_matched}_rcvd" \ + "/tmp/missing_save.srm" \ + "/tmp/stop_now" \ + "/tmp/wpa_supplicant.conf_bk" \ + "$COOKIE_CLIENT_PATH" \ + "$COOKIE_FILE" \ + "/tmp/dismiss_info_panel" } ########### #Utilities# ########### -# URL encode helper -url_encode() { - encoded_str=$(echo "$*" | awk ' - BEGIN { - split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ") - hextab [0] = 0 - for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0 - } - { - encoded = "" - for ( i=1; i<=length ($0); ++i ) { - c = substr ($0, i, 1) - if ( c ~ /[a-zA-Z0-9.-]/ ) { - encoded = encoded c # safe character - } else if ( c == " " ) { - encoded = encoded "%20" # special handling - } else { - # unsafe character, encode it as a two-digit hex-number - lo = ord [c] % 16 - hi = int (ord [c] / 16); - encoded = encoded "%" hextab [hi] hextab [lo] - } - } - print encoded - } -') - echo "$encoded_str" -} - -# Use the safe word -notify_stop() { - notify_peer "stop_now" - sleep 2 - cleanup -} - -# Check stop, if the client tells us to stop we will. -check_stop() { - sync - if [ -e "/tmp/stop_now" ]; then - build_infoPanel_and_log "Message from client" "The host has had a problem setting up the session" - sleep 2 - cleanup - fi -} - -# Notify other MMP -notify_peer() { - local notify_file="/tmp/$1" - touch "$notify_file" - sync - curl -T "$notify_file" "ftp://${hostip}/${notify_file}" >/dev/null 2>&1 # the first / after the IP must be not encoded - - if [ $? -eq 0 ]; then - log "Successfully transferred $notify_file to ftp://${hostip}/${notify_file}" - else - log "Failed to transfer $notify_file to ftp://${hostip}/${notify_file}" - fi -} - -# Function to sync files - -sync_file() { - - MAX_FILE_CHKSUM_SIZE=26214400 - MAX_FILE_DL_SIZE=104857600 - - file_type="$1" # Used in displayed message and some custom actions - file_path="$2" # Local file path - file_check_size="$3" # 0 or 1 to indicate if we have to check the file size - remote_file_checksum="$4" # 0 to skip , real checksum value to check - sync_type="$5" # -o overwrite if different (require file_size or/and checksum != 0) , (if file_size & checksum = 0 then the file is never overwritted, only copied if not present) - # -f overwrite all the time (whatever the value of file_size and checksum) (if file_size & checksum = 0 then the file is overwritted, even if already present ) - # -b if different, backup local file before copying remote file - # -c check only, allows to check the presence of a file, to check its CRC or size and to quit or not the script - file_mandatory="$6" # -m , exit the script on failed sync_success - - #examples : - # sync_file archive /mnt/SDCARD/test.zip 1 5AFC442 -b -m # backup and replace if different file - # sync_file archive /mnt/SDCARD/test.zip 0 0 -f -m # the local file will be systematically replaced - # sync_file archive /mnt/SDCARD/test.zip 0 0 -o -m # the local file will be copied if not exist - # sync_file archive /mnt/SDCARD/test.zip 0 5AFC442 -c -m # exit if the file doesn't have the right checksum - # sync_file archive /mnt/SDCARD/test.zip 1 5AFC442 -o -m # the local file will be replaced if the size or the checksum is different - - # some useful vars - dir_path=$(dirname "$file_path") - file_url="ftp://${hostip}/$(url_encode "${file_path#*/}")" - - log -e "\n############################ SYNC_FILE DEBUGGING ############################" - log file_type $file_type - log file_path $file_path - log file_check_size $file_check_size - log remote_file_checksum $remote_file_checksum - log sync_type $sync_type - log file_mandatory $file_mandatory - log file_url $file_url - log dir_path $dir_path - log "#############################################################################" - - # state vars - same_size= - same_chksum= - sync_success= - run_sync= # tell if the sync task must be done or not - - RequestResult=$(curl -I "$file_url" 2>&1) - - if [[ $RequestResult == *"The file does not exist"* ]]; then - log "The remote file does not exist." - msg="The remote file does not exist." - build_infoPanel_and_log "Syncing" "The remote file does not exist." - run_sync=0 - sync_success=0 - same_size=0 - else - remote_file_size=$(echo "$RequestResult" | grep -i "Content-Length" | awk '{print $2}') - if ! echo "$remote_file_size" | grep -q "^[0-9][0-9]*$"; then # check if the remote file size is a numeric value - log "Impossible to get remote file size." - same_size=0 - run_sync=0 - else - log "remote_file_size: $remote_file_size" - fi - - fi - - if [ -e "$file_path" ]; then - - ########################## File checksum check : same_chksum = 0 different, 1 identical , 2 unknown - checksum_func "$file_path" "$remote_file_checksum" - - ########################## File size check same_size = 0 different, 1 identical , 2 unknown - if [ "$file_check_size" -eq 1 ]; then # file_checksum=0 means skip the difference check = always replace - checksize_func "$file_path" "$remote_file_size" - else - log "Skipping file size check." - same_size=1 # fake same size for skipping - fi - - else - log "The local file does not exist." - same_size=0 - same_chksum=0 - fi - - ########################## exception : max file size check on the remote - if [ "$remote_file_size" -le "$MAX_FILE_DL_SIZE" ]; then - log "Remote file size ok: $remote_file_size bytes (<= $MAX_FILE_DL_SIZE bytes)" - else - log "Remote file size too big: $remote_file_size bytes (> $MAX_FILE_DL_SIZE bytes)" - run_sync=0 - fi - - ########################## We have all the required information, depending the choosen option we run the copy or not - - if [ "$sync_type" == "-o" ]; then # we overwrite the file if different - log "option -o selected : we overwrite the file if different." - if [ "$same_size" -ne 1 ] || [ "$same_chksum" -ne 1 ]; then - [ -z "$run_sync" ] && run_sync=1 - fi - fi - - if [ "$sync_type" == "-b" ]; then # backup - log "option -b selected : we backup before overwrite." - if { [ "$remote_file_checksum" != "0" ] && [ "$same_chksum" -ne 1 ]; } || [ "$remote_file_checksum" == "0" ]; then # if (we don't skip CRC and CRC is not identical) or (if we skip CRC) then we sync -> in other words we only skip the copy when we have an identical CRC - [ -z "$run_sync" ] && run_sync=1 - fi - fi - - if [ "$sync_type" == "-f" ]; then # we overwrite the file if different - log "option -f selected : forced file syncing." - if { [ "$remote_file_checksum" != "0" ] && [ "$same_chksum" -ne 1 ]; } || [ "$remote_file_checksum" == "0" ]; then # if (we don't skip CRC and CRC is not identical) or (if we skip CRC) then we sync -> in other words we only skip the copy when we have an identical CRC - [ -z "$run_sync" ] && run_sync=1 - fi - - fi - - if [ "$sync_type" == "-c" ]; then # we overwrite the file if different - log "option -c selected : no file copy, only check." - run_sync=0 - - if [ "$same_size" -ne 1 ]; then - msg="Files doesn't have the same size." - sync_success=0 - [ "$file_mandatory" = "-m" ] && cleanup - - fi - if [ "$same_chksum" -ne 1 ]; then - msg="$msg\nFiles doesn't have the same checksum." - sync_success=0 - [ "$file_mandatory" = "-m" ] && cleanup - - fi - if [ "$same_size" -eq 1 ] && [ "$same_chksum" -eq 1 ]; then - msg="Remote and local files are identical." - sync_success=1 - fi - build_infoPanel_and_log "File check" "$msg" - - fi - - # log "############################ DEBUGGING #######################################" - # log sync_type $sync_type - # log remote_file_checksum $remote_file_checksum - # log same_chksum $same_chksum - # log run_sync $run_sync - # log file_type $file_type - # log -e "\n\n" - # log "##############################################################################" - - ########################## COPY Operation ########################## - - if [ "$run_sync" -eq 1 ]; then - - if [ $file_type == "Cookie" ]; then # exception for cookies : we don't download with the same target name - file_path="${file_path}.client" - fi - # let's make a backup first whatever the case - if [ -e "$file_path" ]; then - if [ $file_type == "Rom" ]; then - # if rom already here and different file then we create a rom_neplay to avoid to override user games - - # oldpath="$file_path" - # file_path_without_extension="${file_path%.*}" - # file_path="${file_path_without_extension}_netplay.${file_path##*.}" - # if [ -e "$Img_path" ]; then - # cp "$Img_path" "/mnt/SDCARD/Roms/$romdirname/Imgs/${romNameNoExtension}_netplay.png" - # Img_path="/mnt/SDCARD/Roms/$romdirname/Imgs/${romNameNoExtension}_netplay.png" - # fi - - Netplay_Rom_Folder="$(dirname "$file_path")/.netplay" - mkdir -p "$Netplay_Rom_Folder" - file_path="$Netplay_Rom_Folder/$(basename "$file_path")" - rom=$file_path - - elif [ $file_type == "Core" ]; then - # oldpath="$file_path" - # file_path_without_extension="${file_path%.*}" - # file_path="${file_path_without_extension}_netplay.${file_path##*.}" - - Netplay_Core_Folder="$(dirname "$file_path")/.netplay" - mkdir -p "$Netplay_Core_Folder" - file_path="$Netplay_Core_Folder/$(basename "$file_path")" - core=$file_path - else - mv "$file_path" "${file_path}_old" - log "Existing $file_type file moved to ${file_path}_old" - fi - fi - - if [ ! -d "$dir_path" ]; then - mkdir -p "$dir_path" - fi - - log "Starting to download $file_type from $file_url" - curl -o "$file_path" "$file_url" >/dev/null 2>&1 - - if [ $? -eq 0 ]; then - log "$file_type download completed" - else - log "$file_type download failed" - fi - - fi - - ###################### FINAL CHECK RESULT ######################### - - if [ ! -e "$file_path" ]; then - build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - - # copy has failed : restoring the original file - if [ $file_type != "Rom" ] && [ $file_type != "Core" ]; then - mv "${file_path}_old" "$file_path" - log "backup restored" - fi - sleep 2 - [ "$file_mandatory" = "-m" ] && cleanup - - else - - checksum_func "$file_path" "$remote_file_checksum" - - if [ "$file_check_size" -eq 1 ]; then # file_checksum=0 means skip the difference check = always replace - checksize_func "$file_path" "$remote_file_size" - else - log "Skipping file size check." - same_size=1 # fake same size for skipping - fi - - if [ "$same_size" -eq 1 ] && [ "$same_chksum" -eq 1 ]; then - build_infoPanel_and_log "Syncing" "$file_type synced." - if [ $file_type == "Rom" ]; then - log "Refreshing roms list ${rom%/*}/${romdirname}_cache6.db" - rm "${rom%/*}/${romdirname}_cache6.db" - fi - - else - build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - - # copy has failed : restoring the original file - if [ $file_type != "Rom" ] && [ $file_type != "Core" ]; then - mv "${file_path}_old" "$file_path" - log "backup restored" - fi - sleep 2 - if [ "$file_mandatory" = "-m" ]; then - notify_peer "stop_now" - cleanup - fi - fi - #####" - - fi - ###################### FINAL RESULT DISPLAY######################### - - # if [ "$sync_success" -ne 1 ]; then - # build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - # sleep 2 - # cleanup - # else - # build_infoPanel_and_log "Syncing" "$file_type synced." - # fi - - # build_infoPanel_and_log "Syncing" "$file_type checksums don't match, syncing" - # build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - # build_infoPanel_and_log "Syncing" "$file_type synced." - # build_infoPanel_and_log "Syncing" "$file_type doesn't exist locally; syncing with host." - # build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - # build_infoPanel_and_log "Syncing" "$file_type synced." - - ################### END ########################## - -} - -# We'll need FTP to transfer files -start_ftp() { - if is_running bftpd; then - log "FTP already running, killing to rebind" - bftpd_p=$(ps | grep bftpd | grep -v grep | awk '{for(i=4;i<=NF;++i) printf $i" "}') - killall -9 bftpd - killall -9 tcpsvd - tcpsvd -E 0.0.0.0 21 ftpd -w / & - else - tcpsvd -E 0.0.0.0 21 ftpd -w / & - log "Starting FTP server" - fi -} - -# Create a cookie with all the required info for the client. (client will use this cookie) -create_cookie_info() { - COOKIE_FILE="/mnt/SDCARD/RetroArch/retroarch.cookie" - MAX_FILE_SIZE_BYTES=26214400 - - echo "[core]: $netplaycore" >"$COOKIE_FILE" - echo "[rom]: $cookie_rom_path" >>"$COOKIE_FILE" - - if [ -s "$netplaycore" ]; then - log "Writing core size" - core_size=$(stat -c%s "$netplaycore") - if [ "$core_size" -gt "$MAX_FILE_SIZE_BYTES" ]; then - echo "[corechksum]: 0" >>"$COOKIE_FILE" - else - echo "[corechksum]: $(xcrc "$netplaycore")" >>"$COOKIE_FILE" - fi - fi - - if [ -s "$cookie_rom_path" ]; then - log "Writing rom size" - rom_size=$(stat -c%s "$cookie_rom_path") - if [ "$rom_size" -gt "$MAX_FILE_SIZE_BYTES" ]; then - echo "[romchksum]: 0" >>"$COOKIE_FILE" - else - echo "[romchksum]: $(xcrc "$cookie_rom_path")" >>"$COOKIE_FILE" - fi - fi - - if [ -s "$cpuspeed" ]; then - echo "[cpuspeed]: $cpuspeed" >>"$COOKIE_FILE" - log "Writing cpuspeed: $cpuspeed" - fi - -} - -# This will restore the users original ftp state -restore_ftp() { - log "Restoring original FTP server" - killall -9 tcpsvd - if flag_enabled ftpState; then - if flag_enabled authftpState; then - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpdauth.conf & - else - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpd.conf & - fi - fi -} - -flag_enabled() { - flag="$1" - [ -f "$sysdir/config/.$flag" ] -} - -build_infoPanel_and_log() { - local title="$1" - local message="$2" - - log "Info Panel: \n\tStage: $title\n\tMessage: $message" - if is_running infoPanel; then - killall -9 infoPanel - fi - infoPanel --title "$title" --message "$message" --persistent & - sync - touch /tmp/dismiss_info_panel - sync - sleep 0.3 - sync -} - +# confirm_join_panel: show join confirmation UI with host/client images confirm_join_panel() { local title="$1" local message="$2" @@ -698,7 +215,6 @@ confirm_join_panel() { fi fi - # TO DO : allow to confirm only once the host has started infoPanel -t "$title" -m "$message" retcode=$? @@ -709,91 +225,58 @@ confirm_join_panel() { fi } -stripped_game_names() { - game_name="Host: \n$(basename "${rom%.*}")" - game_name="$(echo "$game_name" | sed -e 's/ ([^()]*)//g' -e 's/ [[A-z0-9!+]*]//g' -e 's/([^()]*)//g' -e 's/[[A-z0-9!+]*]//g')" - - client_rom_trimmed="$(echo "$client_rom_filename_NoExt" | sed -e 's/ ([^()]*)//g' -e 's/ [[A-z0-9!+]*]//g' -e 's/([^()]*)//g' -e 's/[[A-z0-9!+]*]//g')" - game_name_client="\n Client (me): \n$client_rom_trimmed" -} - -checksum_func() { - local_file_size=$(stat -c%s "$file_path") - local func_file_path="$1" - local CRC="$2" - - ########################## File checksum check : same_chksum = 0 different, 1 identical , 2 unknown - - if [ "$CRC" != "0" ]; then # file_checksum=0 means skip the difference check = always replace - local_file_checksum=$(xcrc "$func_file_path") - - if [ "$local_file_size" -gt "$MAX_FILE_CHKSUM_SIZE" ]; then - log "File size too big for checksum: it would be too long" - same_chksum=2 - else - if [ "$CRC" == "$local_file_checksum" ]; then - same_chksum=1 - else - same_chksum=0 - fi - fi - else - log "Skipping checksum check." - same_chksum=1 # fake same size for skipping - fi -} - -checksize_func() { - - local func_file_path="$1" - local filesize_tocheck="$2" - local_file_size=$(stat -c%s "$func_file_path") - - ########################## File size check same_size = 0 different, 1 identical , 2 unknown - - if echo "$filesize_tocheck" | grep -q "^[0-9][0-9]*$"; then # check if the remote file size is a numeric value - if [ "$filesize_tocheck" -eq "$local_file_size" ]; then - log "Same size as remote" - same_size=1 - else - log "Files size are different" - same_size=0 - fi - else - log "Impossible to get file size : wrong parameter." - same_size=2 - fi -} - -is_running() { - process_name="$1" - pgrep "$process_name" >/dev/null -} - ######### ##Main.## ######### lets_go() { + # Allow user to abort via menu while setup runs pressMenu2Kill $(basename $0) & + + # Write cookie for host (core/rom metadata) create_cookie_info + + # Join host hotspot . "$sysdir/script/network/hotspot_join.sh" - start_ftp - sync_file "Cookie" "/mnt/SDCARD/RetroArch/retroarch.cookie" 0 0 -f -m - read_cookie + build_infoPanel_and_log "Connected" "Client IP: ${IP:-unknown}\nHost IP: $hostip" + + # start_ftp: start FTP without preflight + start_ftp + + # Send cookie to host + sync_file "Cookie" "$COOKIE_FILE" 0 0 -f -m + + # Read host cookie and parse paths/checksums (verbose logging) + read_cookie 1 + + # Send local save to host backup_and_send_save - # backup_save - # sync_file Rom "$client_rom" # Doesn't sync anything, just uses the sync function to confirm it exists locally + + # Sync required core, rom, and image sync_file "Core" "$core" 1 "$corechecksum" -b -m sync_file "Rom" "$rom" 1 "$romchecksum" -b -m sync_file "Img" "$Img_path" 0 0 -o - stripped_game_names + + # Build display names for confirmation prompt + game_name=$(format_game_name "$(basename "${rom%.*}")" "Host") + game_name_client=$(format_game_name "$client_rom_filename_NoExt" "Client (me)" "\n ") + + # Wait for host ready signal wait_for_host - confirm_join_panel "Join now?" "Start the game on the host first! \n $game_name \n $game_name_client" + + # Confirm join with host/client info + confirm_join_panel "Join now?" "$game_name \n $game_name_client" + + # Stop menu watcher before launch pkill -9 pressMenu2Kill + + # Launch RetroArch client session start_retroarch + + # Wait for save return from host wait_for_save_return - # TO DO : export save to Gambatte (with question) + + # Cleanup and restore state cleanup } diff --git a/static/build/.tmp_update/script/netplay/easy-netplay_client_pokemon_GBA.sh b/static/build/.tmp_update/script/netplay/easy-netplay_client_pokemon_GBA.sh index afb9ff5c43..921fd35108 100644 --- a/static/build/.tmp_update/script/netplay/easy-netplay_client_pokemon_GBA.sh +++ b/static/build/.tmp_update/script/netplay/easy-netplay_client_pokemon_GBA.sh @@ -2,20 +2,22 @@ # Used within GLO as an addon script. # Env setup -sysdir=/mnt/SDCARD/.tmp_update -miyoodir=/mnt/SDCARD/miyoo -LD_LIBRARY_PATH="/lib:/config/lib:$miyoodir/lib:$sysdir/lib:$sysdir/lib/parasyte" -hostip="192.168.100.100" # This should be the default unless the user has changed it.. -rm /tmp/stop_now +. /mnt/SDCARD/.tmp_update/script/netplay/easy-netplay_env.sh + +# Runtime vars client_rom="$1" romdirname=$(echo "$client_rom" | grep -o '/Roms/[^/]*' | cut -d'/' -f3) client_rom_filename=$(basename "$client_rom") client_rom_filename_NoExt="${client_rom_filename%.*}" netplaycore="/mnt/SDCARD/RetroArch/.retroarch/cores/gpsp_libretro.so" -## Source global utils logfile=pokemon_link -. $sysdir/script/log.sh + +# Source scripts +# easy-netplay_common.sh: build_infoPanel_and_log, checksize_func, checksum_func, enable_flag, disable_flag, flag_enabled, is_running, restore_ftp, udhcpc_control, url_encode, strip_game_name, format_game_name, check_wifi, start_ftp +. $sysdir/script/netplay/easy-netplay_common.sh +# easy-netplay_signalling.sh: wait_for_host, check_stop, notify_stop +. $sysdir/script/netplay/easy-netplay_signalling.sh log "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Easy Netplay Pokemon Client GBA -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*" @@ -23,34 +25,7 @@ log "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Easy Netplay Pokemon Client GBA -* ##Setup.## ########## -# Wait for the host to tell us it's ready, this happens just before it starts its RA session and we look in /tmp for a file indicator (file removed in host script cleanup) -wait_for_host() { - - local counter=0 - - build_infoPanel_and_log "Ready" "Waiting for host to ready up" - while true; do - sync - check_stop - for file in /tmp/host_ready; do - if [ -f "$file" ]; then - build_infoPanel_and_log "Message from host" "Setup complete" - rm /tmp/host_ready # be ready for the second use of host_ready flag - break 2 - fi - done - - sleep 1 - counter=$((counter + 1)) - - if [ $counter -ge 25 ]; then - build_infoPanel_and_log "Error" "The host didn't ready up, cannot continue..." - notify_stop - fi - done -} - -# Start retroarch with -C in client mode if everything's gone to plan +# start_retroarch: launch RetroArch in client mode with local ROM start_retroarch() { build_infoPanel_and_log "Starting RA" "Starting RetroArch" @@ -68,7 +43,6 @@ start_retroarch() { echo -n $cpuspeed >"/mnt/SDCARD/Saves/CurrentProfile/config/${core_config_folder}/cpuclock.txt" fi - wait_for_host # we wait a second flag triggered from the host once RA is running cd /mnt/SDCARD/RetroArch log "Starting RetroArch loaded with $client_rom" HOME=/mnt/SDCARD/RetroArch ./retroarch --appendconfig=./.retroarch/easynetplay_override.cfg -C $hostip -L "$netplaycore" "$client_rom" @@ -81,115 +55,21 @@ start_retroarch() { fi } +# cleanup: restore network/ftp and clean temp files cleanup() { - build_infoPanel_and_log "Cleanup" "Cleaning up after Pokemon session\n Do not power off!" - - pkill -9 pressMenu2Kill - - if is_running infoPanel; then - killall -9 infoPanel - fi - - # restore_wifi_state - . "$sysdir/script/network/hotspot_cleanup.sh" - restore_ftp - - # Remove some files we prepared and received log "Removing stale files" - rm "/tmp/host_ready" - rm "/tmp/stop_now" - rm "/tmp/wpa_supplicant.conf_bk" - rm "/tmp/dismiss_info_panel" - sync - - log "Cleanup done" - - exit -} - -########### -#Utilities# -########### - -# Use the safe word -notify_stop() { - notify_peer "stop_now" - sleep 2 - cleanup -} - -# Check stop, if the client tells us to stop we will. -check_stop() { - sync - if [ -e "/tmp/stop_now" ]; then - build_infoPanel_and_log "Message from client" "The host has had a problem setting up the session" - sleep 2 - cleanup - fi -} - -# Notify other MMP -notify_peer() { - local notify_file="/tmp/$1" - touch "$notify_file" - sync - curl -T "$notify_file" "ftp://${hostip}/${notify_file}" >/dev/null 2>&1 # the first / after the IP must be not encoded - - if [ $? -eq 0 ]; then - log "Successfully transferred $notify_file to ftp://${hostip}/${notify_file}" - else - log "Failed to transfer $notify_file to ftp://${hostip}/${notify_file}" - fi -} - -# We'll need FTP to transfer files -start_ftp() { - if is_running bftpd; then - log "FTP already running, killing to rebind" - bftpd_p=$(ps | grep bftpd | grep -v grep | awk '{for(i=4;i<=NF;++i) printf $i" "}') - killall -9 bftpd - killall -9 tcpsvd - tcpsvd -E 0.0.0.0 21 ftpd -w / & - else - tcpsvd -E 0.0.0.0 21 ftpd -w / & - log "Starting FTP server" - fi -} - -# This will restore the users original ftp state -restore_ftp() { - log "Restoring original FTP server" - killall -9 tcpsvd - if flag_enabled ftpState; then - if flag_enabled authftpState; then - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpdauth.conf & - else - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpd.conf & - fi - fi -} - -flag_enabled() { - flag="$1" - [ -f "$sysdir/config/.$flag" ] -} - -build_infoPanel_and_log() { - local title="$1" - local message="$2" - - log "Info Panel: \n\tStage: $title\n\tMessage: $message" - if is_running infoPanel; then - killall -9 infoPanel - fi - infoPanel --title "$title" --message "$message" --persistent & - sync - touch /tmp/dismiss_info_panel - sync - sleep 0.3 - sync + # message: cleanup infoPanel text + # args: hotspot_cleanup restore_ftp kill_infopanel disable_hotspot_flag + # remove files + netplay_cleanup \ + "Cleaning up after Pokemon session\n Do not power off!" \ + 1 1 1 0 \ + "/tmp/host_ready" \ + "/tmp/wpa_supplicant.conf_bk" \ + "/tmp/dismiss_info_panel" } +# confirm_join_panel: show join confirmation UI with local ROM image confirm_join_panel() { local title="$1" local message="$2" @@ -202,7 +82,6 @@ confirm_join_panel() { fi fi - # TO DO : allow to confirm only once the host has started infoPanel -t "$title" -m "$message" retcode=$? @@ -213,33 +92,44 @@ confirm_join_panel() { fi } -stripped_game_names() { - client_rom_trimmed="$(echo "$client_rom_filename_NoExt" | sed -e 's/ ([^()]*)//g' -e 's/ [[A-z0-9!+]*]//g' -e 's/([^()]*)//g' -e 's/[[A-z0-9!+]*]//g')" - game_name_client="Client (me): \n$client_rom_trimmed" -} - -is_running() { - process_name="$1" - pgrep "$process_name" >/dev/null -} - ######### ##Main.## ######### +# lets_go: main flow for joining GBA session lets_go() { + # Allow user to abort via menu while setup runs pressMenu2Kill $(basename $0) & + + # Ensure ROM path is provided if [ -z "$client_rom" ]; then build_infoPanel_and_log "Error" "No ROM path provided." exit 1 fi - . "$sysdir/script/network/hotspot_join.sh" - start_ftp - stripped_game_names + + # Join host hotspot + . "$sysdir/script/network/hotspot_join.sh" + build_infoPanel_and_log "Connected" "Client IP: ${IP:-unknown}\nHost IP: $hostip" + + # Start FTP for lightweight signaling + start_ftp + + # Build display names for confirmation prompt + game_name_client=$(format_game_name "$client_rom_filename_NoExt" "Client (me)") + + # Wait for host ready signal wait_for_host - confirm_join_panel "Join now?" "Start the game on the host first! \n $game_name_client" + + # Confirm join with local ROM display + confirm_join_panel "Join now?" "$game_name_client" + + # Stop menu watcher before launch pkill -9 pressMenu2Kill + + # Launch RetroArch client session start_retroarch + + # Cleanup and restore state cleanup } diff --git a/static/build/.tmp_update/script/netplay/easy-netplay_common.sh b/static/build/.tmp_update/script/netplay/easy-netplay_common.sh new file mode 100644 index 0000000000..9bd047d521 --- /dev/null +++ b/static/build/.tmp_update/script/netplay/easy-netplay_common.sh @@ -0,0 +1,729 @@ +# Shared netplay helpers + +# logging (needed by helpers in this file) +. $sysdir/script/log.sh + +# Tunables +# seconds unless stated otherwise; bytes unless stated otherwise +NETPLAY_FTP_CHECK_RETRIES=3 # ftp head retry count for preflight checks +NETPLAY_FTP_CHECK_DELAY=1 # delay between ftp head retries +NETPLAY_FTP_READY_DELAY=3 # wait before first ftp head to allow peer ftp start +NETPLAY_FTP_DOWNLOAD_RETRIES=5 # download retry count per file +NETPLAY_FTP_DOWNLOAD_DELAY=1 # delay between download retries +NETPLAY_FTP_HEAD_TIMEOUT=2 # curl connect timeout for ftp head +NETPLAY_UDHCPC_RESTART_DELAY=1 # delay before restarting udhcpc +NETPLAY_FTP_START_DELAY=0.5 # wait after starting ftp before checks +NETPLAY_WIFI_POWER_ON_DELAY=2 # delay after wifi power-on +NETPLAY_WIFI_UP_DELAY=1 # delay after bringing wlan0 up +NETPLAY_WIFI_POST_START_DELAY=2 # delay after wifi start sequence +NETPLAY_WIFI_SOFT_FAIL_DELAY=1 # delay after wifi soft-fail +NETPLAY_SYNC_MAX_FILE_CHKSUM_SIZE=26214400 # max file size to allow checksum +NETPLAY_SYNC_MAX_FILE_DL_SIZE=104857600 # max file size to allow download +NETPLAY_COOKIE_MAX_FILE_SIZE=26214400 # max file size for cookie checksum entries +NETPLAY_SYNC_FAIL_DELAY=2 # delay after sync failures before cleanup +NETPLAY_INFOPANEL_SLEEP=0.5 # infoPanel delay +NETPLAY_FTP_HEAD_READY=0 # flag to avoid repeated FTP warmup delays +COOKIE_CLIENT_PATH="/mnt/SDCARD/RetroArch/retroarch.cookie.client" +COOKIE_FILE="/mnt/SDCARD/RetroArch/retroarch.cookie" + +# checksize_func +# - sets: same_size (0 different, 1 identical, 2 unknown) +checksize_func() { + local func_file_path="${1:-$file_path}" + local filesize_tocheck="${2:-$remote_file_size}" + + if [ -e "$func_file_path" ]; then + local_file_size=$(stat -c%s "$func_file_path") + log "checksize_func: local_file_size=$local_file_size for $func_file_path" + log "checksize_func: remote_file_size='$filesize_tocheck'" + if echo "$filesize_tocheck" | grep -q "^[0-9][0-9]*$"; then + if [ "$filesize_tocheck" -eq "$local_file_size" ]; then + same_size=1 + else + same_size=0 + fi + log "checksize_func: same_size=$same_size (numeric compare)" + else + log "Non-numeric remote file size for checksize_func: '$filesize_tocheck' (skipping size check)" + same_size=1 + fi + else + same_size=0 + fi +} + +# checksum_func +# - uses: NETPLAY_SYNC_MAX_FILE_CHKSUM_SIZE +# - sets: same_chksum +checksum_func() { + local_file_size=$(stat -c%s "$file_path") + local func_file_path="$1" + local CRC="$2" + + ########################## File checksum check : same_chksum = 0 different, 1 identical , 2 unknown + + if [ "$CRC" != "0" ]; then # file_checksum=0 means skip the difference check = always replace + local_file_checksum=$(xcrc "$func_file_path") + + if [ "$local_file_size" -gt "$NETPLAY_SYNC_MAX_FILE_CHKSUM_SIZE" ]; then + log "File size too big for checksum: it would be too long" + same_chksum=2 + else + if [ "$CRC" == "$local_file_checksum" ]; then + same_chksum=1 + else + same_chksum=0 + fi + fi + else + log "Skipping checksum check." + same_chksum=1 + fi +} + +# enable_flag +# - creates $sysdir/config/. +enable_flag() { + flag="$1" + touch "$sysdir/config/.$flag" +} + +# disable_flag +# - removes $sysdir/config/. +disable_flag() { + flag="$1" + mv "$sysdir/config/.$flag" "$sysdir/config/.$flag_" +} + +# flag_enabled +# - returns 0 if flag file exists +flag_enabled() { + flag="$1" + [ -f "$sysdir/config/.$flag" ] +} + +# is_running +# - returns 0 if process is running +is_running() { + process_name="$1" + pgrep "$process_name" >/dev/null +} + +# build_infoPanel_and_log <message> +# - uses: NETPLAY_INFOPANEL_SLEEP +# - shows persistent infoPanel and logs message +build_infoPanel_and_log() { + local title="$1" + local message="$2" + local delay="$NETPLAY_INFOPANEL_SLEEP" + + log "Info Panel: \n\tStage: $title\n\tMessage: $message" + if is_running infoPanel; then + killall -9 infoPanel + fi + infoPanel --title "$title" --message "$message" --persistent & + sync + touch /tmp/dismiss_info_panel + sync + sleep "$delay" + sync +} + +# restore_ftp +# - restores original FTP state based on flags +restore_ftp() { + log "Restoring original FTP server" + killall -9 tcpsvd + if flag_enabled ftpState; then + if flag_enabled authftpState; then + bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpdauth.conf & + else + bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpd.conf & + fi + fi +} + +# udhcpc_control +# - restarts udhcpc on wlan0 +udhcpc_control() { + if pgrep udhcpc >/dev/null; then + killall -9 udhcpc + fi + sleep "$NETPLAY_UDHCPC_RESTART_DELAY" + udhcpc -i wlan0 -s /etc/init.d/udhcpc.script >/dev/null 2>&1 & +} + +# url_encode <path> +# - encodes each path segment but keeps '/' +url_encode() { + local path="$1" + local encoded="" + local IFS='/' + local part + + for part in $path; do + if [ -n "$encoded" ]; then + encoded="${encoded}/" + fi + encoded="${encoded}$(echo "$part" | awk ' + BEGIN { + split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ") + hextab [0] = 0 + for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0 + } + { + encoded = "" + for ( i=1; i<=length ($0); ++i ) { + c = substr ($0, i, 1) + if ( c ~ /[a-zA-Z0-9._-]/ ) { + encoded = encoded c # safe character + } else if ( c == " " ) { + encoded = encoded "%20" # special handling + } else { + # unsafe character, encode it as a two-digit hex-number + lo = ord [c] % 16 + hi = int (ord [c] / 16); + encoded = encoded "%" hextab [hi] hextab [lo] + } + } + print encoded + }')" + done + + printf '%s\n' "$encoded" +} + +# strip_game_name <name> +# - strips region/version tags and returns cleaned name +strip_game_name() { + echo "$1" | sed -e 's/ ([^()]*)//g' -e 's/ [[A-z0-9!+]*]//g' -e 's/([^()]*)//g' -e 's/[[A-z0-9!+]*]//g' +} + +# format_game_name <name> [label] [prefix] +# - label adds "<label>: \n" before the name +# - prefix allows leading newline/spacing (e.g. "\n ") +format_game_name() { + local name="$1" + local label="$2" + local prefix="$3" + local trimmed + + trimmed=$(strip_game_name "$name") + if [ -n "$label" ]; then + printf '%s%s: \n%s' "$prefix" "$label" "$trimmed" + else + printf '%s%s' "$prefix" "$trimmed" + fi +} + +# remove_files +# - removes files if they exist +remove_files() { + local f + for f in "$@"; do + if [ -n "$f" ] && [ -e "$f" ]; then + echo "Removing: $f" + rm -f "$f" + fi + done +} + +# netplay_cleanup <message> <hotspot_cleanup> <restore_ftp> <kill_infopanel> <disable_hotspot_flag> [files...] +# - runs common cleanup steps and exits +netplay_cleanup() { + local message="$1" + local do_hotspot_cleanup="$2" + local do_restore_ftp="$3" + local do_kill_infopanel="$4" + local do_disable_hotspot="$5" + shift 5 + + build_infoPanel_and_log "Cleanup" "$message" + + pkill -9 pressMenu2Kill + + if [ "$do_kill_infopanel" -eq 1 ] && is_running infoPanel; then + killall -9 infoPanel + fi + + if [ "$do_hotspot_cleanup" -eq 1 ]; then + . "$sysdir/script/network/hotspot_cleanup.sh" + fi + + if [ "$do_restore_ftp" -eq 1 ]; then + restore_ftp + fi + + remove_files "$@" + + if [ "$do_disable_hotspot" -eq 1 ]; then + disable_flag hotspotState + fi + + # reset power save on the wifi ints + iw wlan0 set power_save on + iw wlan1 set power_save on + + sync + log "Cleanup done" + exit +} + +# wifi_disabled +# - returns 0 if wifi is disabled +wifi_disabled() { + [ $(/customer/app/jsonval wifi) -eq 0 ] +} + +# read_cookie [verbose] +# - parses "$COOKIE_CLIENT_PATH" into core/rom/checksum vars +# - sets: core_url, rom_url, romdirname, romName, romNameNoExtension, Img_path +read_cookie() { + local verbose="$1" + sync + while IFS= read -r line; do + case $line in + "[core]: "*) + core="${line##"[core]: "}" + ;; + "[rom]: "*) + rom="${line##"[rom]: "}" + ;; + "[coresize]: "*) + corechecksum="${line##"[coresize]: "}" + ;; + "[corechksum]: "*) + corechecksum="${line##"[corechksum]: "}" + ;; + "[romsize]: "*) + romchecksum="${line##"[romsize]: "}" + ;; + "[romchksum]: "*) + romchecksum="${line##"[romchksum]: "}" + ;; + "[cpuspeed]: "*) + cpuspeed="${line##"[cpuspeed]: "}" + ;; + esac + log "$core $rom $coresize $corechksum $romsize $romchksum" + done <"$COOKIE_CLIENT_PATH" + + # url encode or curl complains + export core_url=$(url_encode "$core") + export rom_url=$(url_encode "$rom") + + romdirname=$(echo "$rom" | grep -o '/Roms/[^/]*' | cut -d'/' -f3) + romName=$(basename "$rom") + romNameNoExtension=${romName%.*} + Img_path="/mnt/SDCARD/Roms/$romdirname/Imgs/$romNameNoExtension.png" + + if [ "$verbose" = "1" ]; then + log "Cookie file read :" + log "romdirname $romdirname" + log "romName $romName" + log "romNameNoExtension $romNameNoExtension" + log "Img_path $Img_path" + else + log "Cookie file read" + fi +} + +# sync_file <type> <path> <check_size> <checksum> <sync_type> <mandatory> +# - uses: peer_ip or hostip, ensure_ftp_head, checksize_func, checksum_func +# - sync_type: -o overwrite if different, -f force, -b backup, -c check only +# - mandatory: -m to cleanup on failure +sync_file() { + + file_type="$1" # Used in displayed message and some custom actions + file_path="$2" # Local file path + file_check_size="$3" # 0 or 1 to indicate if we have to check the file size + remote_file_checksum="$4" # 0 to skip , real checksum value to check + sync_type="$5" # -o overwrite if different, -f forced, -b backup, -c check only + file_mandatory="$6" # -m , exit the script on failed sync_success + + # some useful vars + dir_path=$(dirname "$file_path") + remote_ip="${peer_ip:-$hostip}" + file_url="ftp://${remote_ip}/$(url_encode "${file_path#*/}")" + + log "\n############################ SYNC_FILE DEBUGGING ############################" + log file_type $file_type + log file_path $file_path + log file_check_size $file_check_size + log remote_file_checksum $remote_file_checksum + log sync_type $sync_type + log file_mandatory $file_mandatory + log file_url $file_url + log dir_path $dir_path + log "#############################################################################" + + # state vars + same_size= + same_chksum= + sync_success= + run_sync= # tell if the sync task must be done or not + + if ! ensure_ftp_head "$file_url" "$remote_ip" "$file_mandatory"; then + same_size=0 + run_sync=0 + sync_success=0 + fi + RequestResult="$ftp_head_result" + + if [[ $RequestResult == *"The file does not exist"* ]]; then + log "The remote file does not exist." + msg="The remote file does not exist." + build_infoPanel_and_log "Syncing" "The remote file does not exist." + run_sync=0 + sync_success=0 + same_size=0 + else + remote_file_size=$(echo "$RequestResult" | grep -i "Content-Length" | awk '{print $2}') + if ! echo "$remote_file_size" | grep -q "^[0-9][0-9]*$"; then # check if the remote file size is a numeric value + log "Non-numeric remote file size: '$remote_file_size'" + log "HEAD response: $RequestResult" + same_size=0 + else + log "remote_file_size: $remote_file_size" + fi + + fi + + if [ -e "$file_path" ]; then + + ########################## File checksum check : same_chksum = 0 different, 1 identical , 2 unknown + checksum_func "$file_path" "$remote_file_checksum" + + ########################## File size check same_size = 0 different, 1 identical , 2 unknown + if [ "$file_check_size" -eq 1 ]; then # file_checksum=0 means skip the difference check = always replace + checksize_func "$file_path" "$remote_file_size" + else + log "Skipping file size check." + same_size=1 # fake same size for skipping + fi + + else + log "The local file does not exist." + same_size=0 + same_chksum=0 + fi + + ########################## exception : max file size check on the remote + if echo "$remote_file_size" | grep -q "^[0-9][0-9]*$"; then + if [ "$remote_file_size" -le "$NETPLAY_SYNC_MAX_FILE_DL_SIZE" ]; then + log "Remote file size ok: $remote_file_size bytes (<= $NETPLAY_SYNC_MAX_FILE_DL_SIZE bytes)" + else + log "Remote file size too big: $remote_file_size bytes (> $NETPLAY_SYNC_MAX_FILE_DL_SIZE bytes)" + run_sync=0 + fi + else + log "Skipping max file size check due to non-numeric remote size: '$remote_file_size'" + fi + + ########################## We have all the required information, depending the chosen option we run the copy or not + + if [ "$sync_type" == "-o" ]; then # we overwrite the file if different + log "option -o selected : we overwrite the file if different." + if [ "$same_size" -ne 1 ] || [ "$same_chksum" -ne 1 ]; then + [ -z "$run_sync" ] && run_sync=1 + fi + fi + + if [ "$sync_type" == "-b" ]; then # backup + log "option -b selected : we backup before overwrite." + if { [ "$remote_file_checksum" != "0" ] && [ "$same_chksum" -ne 1 ]; } || [ "$remote_file_checksum" == "0" ]; then + [ -z "$run_sync" ] && run_sync=1 + fi + fi + + if [ "$sync_type" == "-f" ]; then # we overwrite the file if different + log "option -f selected : forced file syncing." + if { [ "$remote_file_checksum" != "0" ] && [ "$same_chksum" -ne 1 ]; } || [ "$remote_file_checksum" == "0" ]; then + [ -z "$run_sync" ] && run_sync=1 + fi + + fi + + if [ "$sync_type" == "-c" ]; then # we overwrite the file if different + log "option -c selected : no file copy, only check." + run_sync=0 + + if [ "$same_size" -ne 1 ]; then + msg="Files doesn't have the same size." + sync_success=0 + [ "$file_mandatory" = "-m" ] && cleanup + + fi + if [ "$same_chksum" -ne 1 ]; then + msg="$msg\nFiles doesn't have the same checksum." + sync_success=0 + [ "$file_mandatory" = "-m" ] && cleanup + + fi + if [ "$same_size" -eq 1 ] && [ "$same_chksum" -eq 1 ]; then + msg="Remote and local files are identical." + sync_success=1 + fi + build_infoPanel_and_log "File check" "$msg" + + fi + + ########################## COPY Operation ########################## + + if [ "$run_sync" -eq 1 ]; then + + if [ $file_type == "Cookie" ]; then # exception for cookies : we don't download with the same target name + file_path="${file_path}.client" + fi + # let's make a backup first whatever the case + if [ -e "$file_path" ]; then + if [ $file_type == "Rom" ]; then + Netplay_Rom_Folder="$(dirname "$file_path")/.netplay" + mkdir -p "$Netplay_Rom_Folder" + file_path="$Netplay_Rom_Folder/$(basename "$file_path")" + rom=$file_path + + elif [ $file_type == "Core" ]; then + Netplay_Core_Folder="$(dirname "$file_path")/.netplay" + mkdir -p "$Netplay_Core_Folder" + file_path="$Netplay_Core_Folder/$(basename "$file_path")" + core=$file_path + else + mv "$file_path" "${file_path}_old" + log "Existing $file_type file moved to ${file_path}_old" + fi + fi + + if [ ! -d "$dir_path" ]; then + mkdir -p "$dir_path" + fi + + log "Starting to download $file_type from $file_url" + download_attempt=1 + while [ $download_attempt -le $NETPLAY_FTP_DOWNLOAD_RETRIES ]; do + curl_output=$(curl -S -o "$file_path" "$file_url" 2>&1) + curl_exit=$? + + if [ $curl_exit -eq 0 ]; then + log "$file_type download completed" + break + fi + + log "$file_type download failed (curl exit=$curl_exit, attempt $download_attempt/$NETPLAY_FTP_DOWNLOAD_RETRIES)" + log "curl error: $curl_output" + if [ $curl_exit -eq 9 ] || [ $curl_exit -eq 78 ]; then + log "FTP path denied for $file_url" + break + fi + + download_attempt=$((download_attempt + 1)) + sleep "$NETPLAY_FTP_DOWNLOAD_DELAY" + done + + fi + + ###################### FINAL CHECK RESULT ######################### + + if [ ! -e "$file_path" ]; then + if [ "$file_type" = "Img" ]; then + log "Image not found on peer; continuing without image." + else + build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." + fi + + # copy has failed : restoring the original file + if [ $file_type != "Rom" ] && [ $file_type != "Core" ]; then + mv "${file_path}_old" "$file_path" + log "backup restored" + fi + sleep "$NETPLAY_SYNC_FAIL_DELAY" + if [ "$file_mandatory" = "-m" ]; then + if [ "$file_type" != "Img" ]; then + if type notify_peer >/dev/null 2>&1; then + notify_peer "$remote_ip" "stop_now" + fi + cleanup + fi + fi + + else + + checksum_func "$file_path" "$remote_file_checksum" + + if [ "$file_check_size" -eq 1 ]; then # file_checksum=0 means skip the difference check = always replace + checksize_func "$file_path" "$remote_file_size" + else + log "Skipping file size check." + same_size=1 # fake same size for skipping + fi + + if [ "$same_size" -eq 1 ] && [ "$same_chksum" -eq 1 ]; then + build_infoPanel_and_log "Syncing" "$file_type synced." + if [ $file_type == "Rom" ]; then + log "Refreshing roms list ${rom%/*}/${romdirname}_cache6.db" + rm "${rom%/*}/${romdirname}_cache6.db" + fi + + else + build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." + + # copy has failed : restoring the original file + if [ $file_type != "Rom" ] && [ $file_type != "Core" ]; then + mv "${file_path}_old" "$file_path" + log "backup restored" + fi + sleep "$NETPLAY_SYNC_FAIL_DELAY" + if [ "$file_mandatory" = "-m" ]; then + if type notify_peer >/dev/null 2>&1; then + notify_peer "$remote_ip" "stop_now" + fi + cleanup + fi + fi + #####" + + fi + + ################### END ########################## +} + +# create_cookie_info +# - writes core/rom/checksum/cpuspeed into retroarch.cookie +create_cookie_info() { + echo "[core]: $netplaycore" >"$COOKIE_FILE" + echo "[rom]: $cookie_rom_path" >>"$COOKIE_FILE" + + if [ -s "$netplaycore" ]; then + log "Writing core size" + core_size=$(stat -c%s "$netplaycore") + if [ "$core_size" -gt "$NETPLAY_COOKIE_MAX_FILE_SIZE" ]; then + echo "[corechksum]: 0" >>"$COOKIE_FILE" + else + echo "[corechksum]: $(xcrc "$netplaycore")" >>"$COOKIE_FILE" + fi + fi + + if [ -s "$cookie_rom_path" ]; then + rom_size=$(stat -c%s "$cookie_rom_path") + log "Cookie local rom size : $rom_size" + if [ "$rom_size" -gt "$NETPLAY_COOKIE_MAX_FILE_SIZE" ]; then + echo "[romchksum]: 0" >>"$COOKIE_FILE" + else + echo "[romchksum]: $(xcrc "$cookie_rom_path")" >>"$COOKIE_FILE" + fi + fi + + if [ -s "$cpuspeed" ]; then + echo "[cpuspeed]: $cpuspeed" >>"$COOKIE_FILE" + log "Writing custom cpuspeed: $cpuspeed" + fi +} + +# start_ftp [check_stop_message] +# - starts built-in FTP server for signaling +# - if a message is provided, check_stop is invoked with it first +start_ftp() { + if [ -n "$1" ]; then + check_stop "$1" + fi + if is_running bftpd; then + log "FTP already running, killing to rebind" + bftpd_p=$(ps | grep bftpd | grep -v grep | awk '{for(i=4;i<=NF;++i) printf $i\" \"}') + killall -9 bftpd + killall -9 tcpsvd + tcpsvd -E 0.0.0.0 21 ftpd -w / & + else + tcpsvd -E 0.0.0.0 21 ftpd -w / & + log "Starting FTP server" + fi + check_ftp_local + sleep "$NETPLAY_FTP_START_DELAY" +} + +# check_ftp_local [port] +# - logs whether tcpsvd is running and its args/port +check_ftp_local() { + local port="${1:-21}" + if pgrep tcpsvd >/dev/null; then + local tcpsvd_ps + tcpsvd_ps=$(ps | grep tcpsvd | grep -v grep) + log "FTP tcpsvd running (expected port $port): $tcpsvd_ps" + else + log "FTP tcpsvd not running (expected port $port)" + build_infoPanel_and_log "FTP Error" "FTP server failed to start." + fi +} + +# ensure_ftp_head <url> <remote_ip> <mandatory> +# - give peer time to start FTP before first transfer, then do a quick HEAD +# - sets: ftp_head_result, ftp_head_exit +ensure_ftp_head() { + # wait for peer tcpsvd only on the first HEAD; subsequent calls skip delay once ready + if [ "${NETPLAY_FTP_HEAD_READY:-0}" -eq 0 ]; then + sleep "$NETPLAY_FTP_READY_DELAY" + fi + ftp_head_result=$(curl -sS -I --connect-timeout "$NETPLAY_FTP_HEAD_TIMEOUT" "$1" 2>&1) + ftp_head_exit=$? + if [ $ftp_head_exit -eq 0 ]; then + NETPLAY_FTP_HEAD_READY=1 + fi + return 0 +} + +# check_wifi <use_udhcpc> <hard_fail> <down_wlan1> +# - use_udhcpc: 1 to call udhcpc_control after wpa_supplicant +# - hard_fail: 1 to notify_stop on failure, 0 to just pause +# - down_wlan1: 1 to bring wlan1 down before checks +check_wifi() { + local use_udhcpc="$1" + local hard_fail="$2" + local down_wlan1="$3" + + if [ "$down_wlan1" -eq 1 ]; then + ifconfig wlan1 down + fi + + if ifconfig wlan0 &>/dev/null; then + log "Wifi up" + else + build_infoPanel_and_log "WIFI" "Wifi disabled, starting..." + + /customer/app/axp_test wifion + sleep "$NETPLAY_WIFI_POWER_ON_DELAY" + ifconfig wlan0 up + sleep "$NETPLAY_WIFI_UP_DELAY" + $miyoodir/app/wpa_supplicant -B -D nl80211 -iwlan0 -c /appconfigs/wpa_supplicant.conf + + if [ "$use_udhcpc" -eq 1 ]; then + udhcpc_control + fi + + if is_running wpa_supplicant && ifconfig wlan0 >/dev/null 2>&1; then + build_infoPanel_and_log "WIFI" "Wifi started." + else + build_infoPanel_and_log "WIFI" "Unable to start WiFi\n unable to continue." + if [ "$hard_fail" -eq 1 ]; then + notify_stop + else + sleep "$NETPLAY_WIFI_SOFT_FAIL_DELAY" + fi + fi + + sleep "$NETPLAY_WIFI_POST_START_DELAY" + fi +} + +# capture quick state of a file for debugging save/rom transfer issues. +log_file_state() { + local label="$1" + local path="$2" + if [ -f "$path" ]; then + local size + size=$(stat -c%s "$path" 2>/dev/null || wc -c <"$path") + local md5 + md5=$(md5sum "$path" 2>/dev/null | awk '{print $1}') + log "$label: exists size=${size} md5=${md5:-N/A} path=$path" + else + log "$label: missing path=$path" + fi +} diff --git a/static/build/.tmp_update/script/netplay/easy-netplay_env.sh b/static/build/.tmp_update/script/netplay/easy-netplay_env.sh new file mode 100644 index 0000000000..158b8ab5c2 --- /dev/null +++ b/static/build/.tmp_update/script/netplay/easy-netplay_env.sh @@ -0,0 +1,15 @@ +# Shared netplay environment setup + +sysdir=/mnt/SDCARD/.tmp_update +miyoodir=/mnt/SDCARD/miyoo + +LD_LIBRARY_PATH="/lib:/config/lib:$miyoodir/lib:$sysdir/lib:$sysdir/lib/parasyte" +export LD_LIBRARY_PATH + +hostip="${hostip:-192.168.100.100}" # default unless overridden by caller +peer_ip="${peer_ip:-$hostip}" +export hostip peer_ip + +# turn off power save on the wifi - this is turned back on in the netplay_cleanup function +iw wlan0 set power_save off +iw wlan1 set power_save off \ No newline at end of file diff --git a/static/build/.tmp_update/script/netplay/easy-netplay_server.sh b/static/build/.tmp_update/script/netplay/easy-netplay_server.sh index 1ec4255326..4288fa1767 100644 --- a/static/build/.tmp_update/script/netplay/easy-netplay_server.sh +++ b/static/build/.tmp_update/script/netplay/easy-netplay_server.sh @@ -7,43 +7,33 @@ # Used within GLO as an addon script. # Env setup -sysdir=/mnt/SDCARD/.tmp_update -miyoodir=/mnt/SDCARD/miyoo -export LD_LIBRARY_PATH="/lib:/config/lib:$miyoodir/lib:$sysdir/lib:$sysdir/lib/parasyte" +# easy-netplay_env.sh: sysdir, miyoodir, LD_LIBRARY_PATH, hostip, peer_ip +. /mnt/SDCARD/.tmp_update/script/netplay/easy-netplay_env.sh logfile=easy_netplay -. $sysdir/script/log.sh + +# Source scripts +# easy-netplay_common.sh: build_infoPanel_and_log, checksize_func, checksum_func, enable_flag, disable_flag, flag_enabled, is_running, restore_ftp, udhcpc_control, url_encode, check_wifi, start_ftp +. $sysdir/script/netplay/easy-netplay_common.sh + program=$(basename "$0" .sh) ########## ##Setup.## ########## -# We'll need FTP to host the cookie to the client - use the built in FTP, it allows us to curl (errors on bftpd re: path) -start_ftp() { - if is_running bftpd; then - log "FTP already running, killing to rebind" - bftpd_p=$(ps | grep bftpd | grep -v grep | awk '{for(i=4;i<=NF;++i) printf $i" "}') - killall -9 bftpd - killall -9 tcpsvd - tcpsvd -E 0.0.0.0 21 ftpd -w / & - else - tcpsvd -E 0.0.0.0 21 ftpd -w / & - log "Starting FTP server" - fi -} - # Find the recommended core for the current system. -Get_NetplayCore() { - +get_netplay_core() { platform=$(echo "$cookie_rom_path" | grep -o '/Roms/[^/]*' | cut -d'/' -f3) netplaycore_info=$(grep "^${platform};" "$sysdir/config/netplay_cores.conf") + if [ -n "$netplaycore_info" ]; then netplaycore=$(echo "$netplaycore_info" | cut -d ';' -f 2) netplaycore="/mnt/SDCARD/RetroArch/.retroarch/cores/$netplaycore" core_config_folder=$(echo "$netplaycore_info" | cut -d ';' -f 3) cpuspeed=$(echo "$netplaycore_info" | cut -d ';' -f 4) fi + if [ -n "$netplaycore" ]; then if [ "$netplaycore" = "none" ]; then build_infoPanel_and_log "Netplay impossible" "$platform not compatible with Netplay" @@ -53,46 +43,11 @@ Get_NetplayCore() { else netplaycore="$cookie_core_path" fi + return 0 - } -# Create a cookie with all the required info for the client. (client will use this cookie) -create_cookie_info() { - COOKIE_FILE="/mnt/SDCARD/RetroArch/retroarch.cookie" - MAX_FILE_SIZE_BYTES=26214400 - - echo "[core]: $netplaycore" >"$COOKIE_FILE" - echo "[rom]: $cookie_rom_path" >>"$COOKIE_FILE" - - if [ -s "$netplaycore" ]; then - log "Writing core size" - core_size=$(stat -c%s "$netplaycore") - if [ "$core_size" -gt "$MAX_FILE_SIZE_BYTES" ]; then - echo "[corechksum]: 0" >>"$COOKIE_FILE" - else - echo "[corechksum]: $(xcrc "$netplaycore")" >>"$COOKIE_FILE" - fi - fi - - if [ -s "$cookie_rom_path" ]; then - log "Writing rom size" - rom_size=$(stat -c%s "$cookie_rom_path") - if [ "$rom_size" -gt "$MAX_FILE_SIZE_BYTES" ]; then - echo "[romchksum]: 0" >>"$COOKIE_FILE" - else - echo "[romchksum]: $(xcrc "$cookie_rom_path")" >>"$COOKIE_FILE" - fi - fi - - if [ -s "$cpuspeed" ]; then - echo "[cpuspeed]: $cpuspeed" >>"$COOKIE_FILE" - log "Writing cpuspeed: $cpuspeed" - fi - -} - -# We'll start Retroarch in host mode with -H with the core and rom paths loaded in. +# start_retroarch: launch RetroArch host with selected core and ROM start_retroarch() { log "RetroArch" "Starting RetroArch..." echo "*****************************************" @@ -123,73 +78,17 @@ start_retroarch() { fi } +# cleanup: restore wifi/ftp and remove session temp files cleanup() { - build_infoPanel_and_log "Cleanup" "Cleaning up after netplay session..." - - pkill -9 pressMenu2Kill - - . "$sysdir/script/network/hotspot_cleanup.sh" - - restore_ftp - - # Remove some files we prepared and received log "Removing stale files" - rm "/mnt/SDCARD/RetroArch/retroarch.cookie" - rm "/tmp/dismiss_info_panel" - sync - log "Cleanup done" - exit - -} - -########### -#Utilities# -########### - -build_infoPanel_and_log() { - local title="$1" - local message="$2" - - log "Info Panel: \n\tStage: $title\n\tMessage: $message" - if is_running infoPanel; then - killall -9 infoPanel - fi - infoPanel --title "$title" --message "$message" --persistent & - sync - touch /tmp/dismiss_info_panel - sync - sleep 0.3 - sync -} - -restore_ftp() { - log "Restoring original FTP server" - killall -9 tcpsvd - if flag_enabled ftpState; then - if flag_enabled authftpState; then - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpdauth.conf & - else - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpd.conf & - fi - fi -} - -flag_enabled() { - flag="$1" - [ -f "$sysdir/config/.$flag" ] -} - -udhcpc_control() { - if pgrep udhcpc >/dev/null; then - killall -9 udhcpc - fi - sleep 1 - udhcpc -i wlan0 -s /etc/init.d/udhcpc.script >/dev/null 2>&1 & -} - -is_running() { - process_name="$1" - pgrep "$process_name" >/dev/null + # message: cleanup infoPanel text + # args: hotspot_cleanup restore_ftp kill_infopanel disable_hotspot_flag + # remove files + netplay_cleanup \ + "Cleaning up after netplay session..." \ + 1 1 0 0 \ + "$COOKIE_FILE" \ + "/tmp/dismiss_info_panel" } ######### @@ -197,13 +96,28 @@ is_running() { ######### lets_go() { + # Allow user to abort via menu while setup runs pressMenu2Kill $(basename $0) & + + # Create hotspot for client . "$sysdir/script/network/hotspot_create.sh" + + # start_ftp: start FTP without preflight start_ftp - Get_NetplayCore + + # Determine netplay core based on ROM/core config + get_netplay_core + + # Write cookie with core/rom metadata create_cookie_info + + # Stop menu watcher before launch pkill -9 pressMenu2Kill + + # Launch RetroArch host session start_retroarch + + # Cleanup and restore state cleanup } diff --git a/static/build/.tmp_update/script/netplay/easy-netplay_server_pokemon.sh b/static/build/.tmp_update/script/netplay/easy-netplay_server_pokemon.sh index b7f4f8a538..791cce7349 100644 --- a/static/build/.tmp_update/script/netplay/easy-netplay_server_pokemon.sh +++ b/static/build/.tmp_update/script/netplay/easy-netplay_server_pokemon.sh @@ -2,15 +2,22 @@ # Used within GLO as an addon script. # Env setup -sysdir=/mnt/SDCARD/.tmp_update -miyoodir=/mnt/SDCARD/miyoo -LD_LIBRARY_PATH="/lib:/config/lib:$miyoodir/lib:$sysdir/lib:$sysdir/lib/parasyte" +. /mnt/SDCARD/.tmp_update/script/netplay/easy-netplay_env.sh logfile=pokemon_link -. $sysdir/script/log.sh + +# Source scripts +# easy-netplay_common.sh: build_infoPanel_and_log, checksize_func, checksum_func, enable_flag, disable_flag, flag_enabled, is_running, restore_ftp, udhcpc_control, url_encode, strip_game_name, format_game_name, check_wifi, start_ftp, sync_file +. $sysdir/script/netplay/easy-netplay_common.sh +# easy-netplay_signalling.sh: wait_for_client, ready_up, notify_peer, check_stop, notify_stop +. $sysdir/script/netplay/easy-netplay_signalling.sh + program=$(basename "$0" .sh) +# Remove existing stop_now rm /tmp/stop_now + +# Runtime vars host_rom="$cookie_rom_path" host_rom_filename=$(basename "$host_rom") host_rom_filename_NoExt="${host_rom_filename%.*}" @@ -19,34 +26,25 @@ netplaycore="/mnt/SDCARD/RetroArch/.retroarch/cores/tgbdual_libretro.so" SaveFromGambatte=0 export CurDate=$(date +%Y%m%d_%H%M%S) log "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Easy Netplay Pokemon Host -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ndate : $CurDate" -########## -##Setup.## -########## -# We'll need wifi up for this. Lets try and start it.. -check_wifi() { - if ifconfig wlan0 &>/dev/null; then - build_infoPanel_and_log "WIFI" "Wifi up" +# Helper: capture quick state of a file for debugging save/rom transfer issues. +log_file_state() { + local label="$1" + local path="$2" + if [ -f "$path" ]; then + # Prefer stat, fall back to wc -c for size + local size + size=$(stat -c%s "$path" 2>/dev/null || wc -c <"$path") + local md5 + md5=$(md5sum "$path" 2>/dev/null | awk '{print $1}') + log "$label: exists size=${size} md5=${md5:-N/A} path=$path" else - build_infoPanel_and_log "WIFI" "Wifi disabled, starting..." - - /customer/app/axp_test wifion - sleep 2 - ifconfig wlan0 up - sleep 1 - $miyoodir/app/wpa_supplicant -B -D nl80211 -iwlan0 -c /appconfigs/wpa_supplicant.conf - udhcpc_control - - if is_running wpa_supplicant && ifconfig wlan0 >/dev/null 2>&1; then - build_infoPanel_and_log "WIFI" "Wifi started." - else - build_infoPanel_and_log "WIFI" "Unable to start WiFi\n unable to continue." - notify_stop - fi - - sleep 2 + log "$label: missing path=$path" fi } +########## +##Setup.## +########## # We'll need hotspot to host the local connection start_hotspot() { @@ -62,113 +60,12 @@ start_hotspot() { $sysdir/script/network/update_networking.sh hotspot toggle } -# We'll need FTP to host the cookie to the client - use the built in FTP, it allows us to curl (errors on bftpd re: path) -start_ftp() { - check_stop - if is_running bftpd; then - log "FTP already running, killing to rebind" - bftpd_p=$(ps | grep bftpd | grep -v grep | awk '{for(i=4;i<=NF;++i) printf $i" "}') - killall -9 bftpd - killall -9 tcpsvd - tcpsvd -E 0.0.0.0 21 ftpd -w / & - else - tcpsvd -E 0.0.0.0 21 ftpd -w / & - log "Starting FTP server" - fi -} - # Create a cookie with all the required info for the client. (client will use this cookie) -create_cookie_info() { - COOKIE_FILE="/mnt/SDCARD/RetroArch/retroarch.cookie" - MAX_FILE_SIZE_BYTES=26214400 - - echo "[core]: $netplaycore" >"$COOKIE_FILE" - echo "[rom]: $cookie_rom_path" >>"$COOKIE_FILE" - - if [ -s "$netplaycore" ]; then - log "Writing core size" - core_size=$(stat -c%s "$netplaycore") - if [ "$core_size" -gt "$MAX_FILE_SIZE_BYTES" ]; then - echo "[corechksum]: 0" >>"$COOKIE_FILE" - else - echo "[corechksum]: $(xcrc "$netplaycore")" >>"$COOKIE_FILE" - fi - fi - - if [ -s "$cookie_rom_path" ]; then - rom_size=$(stat -c%s "$cookie_rom_path") - log "Cookie local rom size : $rom_size" - if [ "$rom_size" -gt "$MAX_FILE_SIZE_BYTES" ]; then - echo "[romchksum]: 0" >>"$COOKIE_FILE" - else - echo "[romchksum]: $(xcrc "$cookie_rom_path")" >>"$COOKIE_FILE" - fi - fi - - if [ -s "$cpuspeed" ]; then - echo "[cpuspeed]: $cpuspeed" >>"$COOKIE_FILE" - log "Writing custom cpuspeed: $cpuspeed" - fi - -} - -# Wait for a hit on the sta list for someone joining the hotspot -wait_for_client() { - check_stop - build_infoPanel_and_log "Hotspot" "Waiting for a client to connect..." - - client_ip="" - client_mac="" - counter=0 - - killall -9 wpa_supplicant - killall -9 udhcpc - - sleep 1 - - while true; do - sta_list=$($sysdir/bin/hostapd_cli all_sta 2>/dev/null) - $sysdir/bin/hostapd_cli all_sta flush - - if [ $? -ne 0 ]; then - build_infoPanel_and_log "Hotspot" "Hostapd hook failing, retrying." - counter=$((counter + 1)) - fi - - if [ ! -z "$sta_list" ]; then - client_mac=$(echo "$sta_list" | awk 'NR==2{print $1; exit}') - client_ip=$(arp -an | awk '/'"$client_mac"'/ {gsub(/[\(\)]/,""); print $2}') - - if [ ! -z "$client_ip" ]; then - case "$client_ip" in - 192.168.100.*) - log "$sta_list" - log "A client has connected. IP: $client_ip" - build_infoPanel_and_log "Hotspot" "A client has connected! \n IP: $client_ip" - break - ;; - esac - fi - fi - - sleep 1 - counter=$((counter + 1)) - - if [ $counter -ge 30 ]; then - log "No client has connected" - build_infoPanel_and_log "Hotspot error" "No client has connected. Exiting..." - cleanup - fi - done - - sleep 1 - log "$client_ip has joined the hotspot" -} - # Backup the save we're going to use before we do anythign else host_save_backup() { - check_stop + # check_stop: client reported a setup/join issue + check_stop "The client has had a problem joining the session." mkdir -p "/mnt/SDCARD/Saves/CurrentProfile/saves/TGB Dual" save_gambatte="/mnt/SDCARD/Saves/CurrentProfile/saves/Gambatte/$host_rom_filename_NoExt.srm" save_tgbdual="/mnt/SDCARD/Saves/CurrentProfile/saves/TGB Dual/$host_rom_filename_NoExt.srm" @@ -177,11 +74,13 @@ host_save_backup() { log "Gambatte save file detected." log "Backing up Gambatte save file to: $host_rom_filename_NoExt.srm_$Curdate" cp -f "$save_gambatte" "${save_gambatte}_$CurDate" + log_file_state "Gambatte save (backed up)" "$save_gambatte" SaveFromGambatte=1 if [ -f "$save_tgbdual" ]; then confirm_join_panel "Continue ?" "There is a local save for\n$host_rom_filename_NoExt\nfor TGB Dual and for Gambatte.\n Gambatte save will be used by default." log "Backing up the existing TGB Dual save file to: $host_rom_filename_NoExt.srm_$Curdate" cp -f "$save_tgbdual" "${save_tgbdual}_$CurDate" + log_file_state "Existing TGB Dual save (backed up)" "$save_tgbdual" fi # copy save from Gambatte to TGB Dual cp -f "$save_gambatte" "$save_tgbdual" @@ -189,6 +88,7 @@ host_save_backup() { log "No Gambatte save file detected, using TGB Dual save file instead." log "Backing up current TGB Dual save file to: $host_rom_filename_NoExt.srm_$Curdate" cp -f "$save_tgbdual" "${save_tgbdual}_$CurDate" + log_file_state "TGB Dual save (backed up)" "$save_tgbdual" fi sync @@ -196,7 +96,8 @@ host_save_backup() { # The client will send us a save file, we'll pull the name from this, find it on the host and call duplicate_rename_rom - send to tmp client_save_get() { - check_stop + # check_stop: client reported a setup/join issue + check_stop "The client has had a problem joining the session." build_infoPanel_and_log "Setting up" "Setting up session \n Waiting for save files." client_save_file="" @@ -206,7 +107,8 @@ client_save_get() { sync for file in /tmp/*.srm; do if [ -f "$file" ]; then - if [ "$(basename "$file")" = "MISSING.srm" ]; then + log_file_state "Incoming client save candidate" "$file" + if [ "$(basename "$file")" = "missing_save.srm" ]; then build_infoPanel_and_log "Sync error" "Client advises they don't have a save file. \n Cannot continue." notify_stop else @@ -229,13 +131,15 @@ client_save_get() { # Prep the clients save file client_save_rename() { - check_stop + # check_stop: client reported a setup/join issue + check_stop "The client has had a problem joining the session." if [ ! -z "$client_save_file" ]; then save_base_name=$(basename "$client_save_file" .srm) save_new_name="${save_base_name}_client.srm" save_new_path="/mnt/SDCARD/Saves/CurrentProfile/saves/TGB Dual/$save_new_name" mv "$client_save_file" "$save_new_path" log "Save file found and processed - old save path:$client_save_file, new save path:$save_new_path " + log_file_state "Client save after move" "$save_new_path" sync else build_infoPanel_and_log "Syncing" "Save file not found, cannot continue" @@ -271,7 +175,7 @@ client_read_cookie() { ;; esac log "$core $rom $coresize $corechksum $romsize $romchksum" - done <"/mnt/SDCARD/RetroArch/retroarch.cookie.client" + done <"$COOKIE_CLIENT_PATH" #url encode or curl complains export core_url=$(url_encode "$core") @@ -290,7 +194,8 @@ client_read_cookie() { # Duplicate the rom to spoof the save loaded in on the host client_rom_rename() { - check_stop + # check_stop: client reported a setup/join issue + check_stop "The client has had a problem joining the session." rom_extension="${client_rom##*.}" client_rom_clone="${client_rom%.*}_client.$rom_extension" @@ -302,26 +207,15 @@ client_rom_rename() { fi } -# Tell the client we're ready to accept connections -ready_up() { - check_stop - ping -c 5 $client_ip >/dev/null 2>&1 - if [ $? -eq 0 ]; then - notify_peer "host_ready" - else - build_infoPanel_and_log "Error" "No connectivity to $client_ip, \n is the client still connected?" - notify_stop - fi -} - # We'll start Retroarch in host mode with -H with the core and rom paths loaded in. start_retroarch() { - log "\n############################ RETROARCH DEBUGGING ############################" log "host_rom: $host_rom" log "client_rom_clone: ${client_rom_clone}" log "netplaycore: $netplaycore" log "cpuspeed: $cpuspeed" + log_file_state "Host save (pre-RA)" "$save_tgbdual" + log_file_state "Client save (pre-RA)" "$save_new_path" log "###############################################################################" if [ -n "$cpuspeed" ]; then @@ -332,7 +226,8 @@ start_retroarch() { cd /mnt/SDCARD/RetroArch log "Starting RetroArch loaded with $host_rom and $client_rom_clone" - (sleep 2 && notify_peer "host_ready" &) & + # notify_peer: signal host ready to client + (sleep 2 && notify_peer "$client_ip" "host_ready" &) & HOME=/mnt/SDCARD/RetroArch ./retroarch --appendconfig=./.retroarch/easynetplay_override.cfg -H -v -L .retroarch/cores/tgbdual_libretro.so --subsystem "gb_link_2p" "$host_rom" "$client_rom_clone" if [ -n "$PreviousCPUspeed" ]; then @@ -358,11 +253,13 @@ host_save_overwrite() { # Go into a waiting state for the client to be ready to accept the save client_wait_for_save_return() { - check_stop + # check_stop: client reported a setup/join issue + check_stop "The client has had a problem joining the session." local counter=0 build_infoPanel_and_log "Syncing" "Waiting for client to be ready for save sync" - notify_peer "ready_to_send" + # notify_peer: signal ready to send save + notify_peer "$client_ip" "ready_to_send" sync while true; do @@ -387,7 +284,8 @@ client_wait_for_save_return() { # Push the clients save file back client_save_send() { - check_stop + # check_stop: client reported a setup/join issue + check_stop "The client has had a problem joining the session." build_infoPanel_and_log "Syncing" "Returning client save..." received_save="tmp/$(basename "${save_new_path/_client/}")" encoded_path=$(url_encode "${received_save}") @@ -398,99 +296,35 @@ client_save_send() { if [ $curl_exit_status -eq 0 ]; then build_infoPanel_and_log "Syncing" "Client save returned!" + log_file_state "Save returned to client (local copy)" "$save_new_path" else build_infoPanel_and_log "Syncing" "Failed to return the client save \n Progress has likely been lost \n Curl exit code: $curl_exit_status" + log "curl exit status while returning client save: $curl_exit_status" fi } # Cleanup. If you don't call this you don't retransfer the saves - Users cannot under any circumstances miss this function. cleanup() { - build_infoPanel_and_log "Cleanup" "Cleaning up after Pokemon session\n Do not power off!" - - pkill -9 pressMenu2Kill - - . "$sysdir/script/network/hotspot_cleanup.sh" - - restore_ftp - - # Remove some files we prepared and received - rm "/tmp/host_ready" - rm "$save_new_path" - rm "$client_rom_clone" - rm "/tmp/ready_to_send" - rm "/tmp/ready_to_receive" - rm "/tmp/MISSING.srm" - rm "/tmp/stop_now" - disable_flag hotspotState - rm "/tmp/dismiss_info_panel" - sync - log "Cleanup done" - exit + # message: cleanup infoPanel text + # args: hotspot_cleanup restore_ftp kill_infopanel disable_hotspot_flag + # remove files + netplay_cleanup \ + "Cleaning up after Pokemon session\n Do not power off!" \ + 1 1 0 1 \ + "/tmp/host_ready" \ + "$save_new_path" \ + "$client_rom_clone" \ + "/tmp/ready_to_send" \ + "/tmp/ready_to_receive" \ + "/tmp/missing_save.srm" \ + "/tmp/stop_now" \ + "/tmp/dismiss_info_panel" } ########### #Utilities# ########### -# URL encode helper -url_encode() { - encoded_str=$(echo "$*" | awk ' - BEGIN { - split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ") - hextab [0] = 0 - for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0 - } - { - encoded = "" - for ( i=1; i<=length ($0); ++i ) { - c = substr ($0, i, 1) - if ( c ~ /[a-zA-Z0-9.-]/ ) { - encoded = encoded c # safe character - } else if ( c == " " ) { - encoded = encoded "%20" # special handling - } else { - # unsafe character, encode it as a two-digit hex-number - lo = ord [c] % 16 - hi = int (ord [c] / 16); - encoded = encoded "%" hextab [hi] hextab [lo] - } - } - print encoded - } -') - echo "$encoded_str" -} - -# Use the safe word -notify_stop() { - notify_peer "stop_now" - sleep 2 - cleanup -} - -# Check stop, if the client tells us to stop we will. -check_stop() { - sync - if [ -e "/tmp/stop_now" ]; then - build_infoPanel_and_log "Message from client" "The client has had a problem joining the session." - sleep 2 - cleanup - fi -} - -notify_peer() { - local notify_file="/tmp/$1" - touch "$notify_file" - sync - curl -T "$notify_file" "ftp://${client_ip}/${notify_file}" >/dev/null 2>&1 # the first / after the IP must be not encoded - - if [ $? -eq 0 ]; then - log "Successfully transferred $notify_file to ftp://${client_ip}/${notify_file}" - else - log "Failed to transfer $notify_file to ftp://${client_ip}/${notify_file}" - fi -} - # Rename the new save back to the original one ready to be re-transferred remove_client_save_suffix() { if [ ! -z "$save_new_path" ]; then @@ -501,6 +335,7 @@ remove_client_save_suffix() { fi } +# confirm_join_panel: show host confirmation UI with host/client images confirm_join_panel() { local title="$1" local message="$2" @@ -537,338 +372,7 @@ confirm_join_panel() { fi } -stripped_game_names() { - host_game_name="$(basename "${host_rom%.*}")" - host_game_name="$(echo "$host_game_name" | sed -e 's/ ([^()]*)//g' -e 's/ [[A-z0-9!+]*]//g' -e 's/([^()]*)//g' -e 's/[[A-z0-9!+]*]//g')" - host_game_name="Host (me): \n$host_game_name" - - client_rom_trimmed="$(basename "${client_rom%.*}" | sed -e 's/ ([^()]*)//g' -e 's/ [[A-z0-9!+]*]//g' -e 's/([^()]*)//g' -e 's/[[A-z0-9!+]*]//g')" - client_game_name="\n Client: \n$client_rom_trimmed" -} - -# Function to sync files - -sync_file() { - - MAX_FILE_CHKSUM_SIZE=26214400 - MAX_FILE_DL_SIZE=104857600 - - file_type="$1" # Used in displayed message and some custom actions - file_path="$2" # Local file path - file_check_size="$3" # 0 or 1 to indicate if we have to check the file size - remote_file_checksum="$4" # 0 to skip , real checksum value to check - sync_type="$5" # -o overwrite if different (require file_size or/and checksum != 0) , (if file_size & checksum = 0 then the file is never overwritted, only copied if not present) - # -f overwrite all the time (whatever the value of file_size and checksum) (if file_size & checksum = 0 then the file is overwritted, even if already present ) - # -b if different, backup local file before copying remote file - # -c check only, allows to check the presence of a file, to check its CRC or size and to quit or not the script - file_mandatory="$6" # -m , exit the script on failed sync_success - - #examples : - # sync_file archive /mnt/SDCARD/test.zip 1 5AFC442 -b -m # backup and replace if different file - # sync_file archive /mnt/SDCARD/test.zip 0 0 -f -m # the local file will be systematically replaced - # sync_file archive /mnt/SDCARD/test.zip 0 0 -o -m # the local file will be copied if not exist - # sync_file archive /mnt/SDCARD/test.zip 0 5AFC442 -c -m # exit if the file doesn't have the right checksum - # sync_file archive /mnt/SDCARD/test.zip 1 5AFC442 -o -m # the local file will be replaced if the size or the checksum is different - - # some useful vars - dir_path=$(dirname "$file_path") - file_url="ftp://${client_ip}/$(url_encode "${file_path#*/}")" - - log "\n############################ SYNC_FILE DEBUGGING ############################" - log file_type $file_type - log file_path $file_path - log file_check_size $file_check_size - log remote_file_checksum $remote_file_checksum - log sync_type $sync_type - log file_mandatory $file_mandatory - log file_url $file_url - log dir_path $dir_path - log "#############################################################################" - - # state vars - same_size= - same_chksum= - sync_success= - run_sync= # tell if the sync task must be done or not - - RequestResult=$(curl -I "$file_url" 2>&1) - - if [[ $RequestResult == *"The file does not exist"* ]]; then - log "The remote file does not exist." - msg="The remote file does not exist." - build_infoPanel_and_log "Syncing" "The remote file does not exist." - run_sync=0 - sync_success=0 - same_size=0 - else - remote_file_size=$(echo "$RequestResult" | grep -i "Content-Length" | awk '{print $2}') - if ! echo "$remote_file_size" | grep -q "^[0-9][0-9]*$"; then # check if the remote file size is a numeric value - log "Impossible to get remote file size." - same_size=0 - run_sync=0 - else - log "remote_file_size: $remote_file_size" - fi - - fi - - if [ -e "$file_path" ]; then - - ########################## File checksum check : same_chksum = 0 different, 1 identical , 2 unknown - checksum_func "$file_path" "$remote_file_checksum" - - ########################## File size check same_size = 0 different, 1 identical , 2 unknown - if [ "$file_check_size" -eq 1 ]; then # file_checksum=0 means skip the difference check = always replace - checksize_func "$file_path" "$remote_file_size" - else - log "Skipping file size check." - same_size=1 # fake same size for skipping - fi - - else - log "The local file does not exist." - same_size=0 - same_chksum=0 - fi - - ########################## exception : max file size check on the remote - if [ "$remote_file_size" -le "$MAX_FILE_DL_SIZE" ]; then - log "Remote file size ok: $remote_file_size bytes (<= $MAX_FILE_DL_SIZE bytes)" - else - log "Remote file size too big: $remote_file_size bytes (> $MAX_FILE_DL_SIZE bytes)" - run_sync=0 - fi - - ########################## We have all the required information, depending the choosen option we run the copy or not - - if [ "$sync_type" == "-o" ]; then # we overwrite the file if different - log "option -o selected : we overwrite the file if different." - if [ "$same_size" -ne 1 ] || [ "$same_chksum" -ne 1 ]; then - [ -z "$run_sync" ] && run_sync=1 - fi - fi - - if [ "$sync_type" == "-b" ]; then # backup - log "option -b selected : we backup before overwrite." - if { [ "$remote_file_checksum" != "0" ] && [ "$same_chksum" -ne 1 ]; } || [ "$remote_file_checksum" == "0" ]; then # if (we don't skip CRC and CRC is not identical) or (if we skip CRC) then we sync -> in other words we only skip the copy when we have an identical CRC - [ -z "$run_sync" ] && run_sync=1 - fi - fi - - if [ "$sync_type" == "-f" ]; then # we overwrite the file if different - log "option -f selected : forced file syncing." - if { [ "$remote_file_checksum" != "0" ] && [ "$same_chksum" -ne 1 ]; } || [ "$remote_file_checksum" == "0" ]; then # if (we don't skip CRC and CRC is not identical) or (if we skip CRC) then we sync -> in other words we only skip the copy when we have an identical CRC - [ -z "$run_sync" ] && run_sync=1 - fi - - fi - - if [ "$sync_type" == "-c" ]; then # we overwrite the file if different - log "option -c selected : no file copy, only check." - run_sync=0 - - if [ "$same_size" -ne 1 ]; then - msg="Files doesn't have the same size." - sync_success=0 - [ "$file_mandatory" = "-m" ] && cleanup - - fi - if [ "$same_chksum" -ne 1 ]; then - msg="$msg\nFiles doesn't have the same checksum." - sync_success=0 - [ "$file_mandatory" = "-m" ] && cleanup - - fi - if [ "$same_size" -eq 1 ] && [ "$same_chksum" -eq 1 ]; then - msg="Remote and local files are identical." - sync_success=1 - fi - build_infoPanel_and_log "File check" "$msg" - - fi - - log "############################ DEBUGGING #######################################" - log sync_type $sync_type - log remote_file_checksum $remote_file_checksum - log same_chksum $same_chksum - log run_sync $run_sync - log file_type $file_type - log - log - log "##############################################################################" - - ########################## COPY Operation ########################## - - if [ "$run_sync" -eq 1 ]; then - - # let's make a backup first whatever the case - if [ -e "$file_path" ]; then - if [ $file_type == "Rom" ]; then - # if rom already here and different file then we create a rom_neplay to avoid to override user games - - # oldpath="$file_path" - # file_path_without_extension="${file_path%.*}" - # file_path="${file_path_without_extension}_netplay.${file_path##*.}" - # if [ -e "$client_Img_path" ]; then - # cp "$client_Img_path" "/mnt/SDCARD/Roms/$romdirname/Imgs/${romNameNoExtension}_netplay.png" - # client_Img_path="/mnt/SDCARD/Roms/$romdirname/Imgs/${romNameNoExtension}_netplay.png" - # fi - - Netplay_Rom_Folder="$(dirname "$file_path")/.netplay" - mkdir -p "$Netplay_Rom_Folder" - file_path="$Netplay_Rom_Folder/$(basename "$file_path")" - rom=$file_path - - elif [ $file_type == "Core" ]; then - # oldpath="$file_path" - # file_path_without_extension="${file_path%.*}" - # file_path="${file_path_without_extension}_netplay.${file_path##*.}" - - Netplay_Core_Folder="$(dirname "$file_path")/.netplay" - mkdir -p "$Netplay_Core_Folder" - file_path="$Netplay_Core_Folder/$(basename "$file_path")" - core=$file_path - else - mv "$file_path" "${file_path}_old" - log "Existing $file_type file moved to ${file_path}_old" - fi - fi - if [ $file_type == "Cookie" ]; then # exception for cookies : we don't download with the same target name - file_path="${file_path}.client" - fi - - if [ ! -d "$dir_path" ]; then - mkdir -p "$dir_path" - fi - - log "Starting to download $file_type from $file_url" - curl -o "$file_path" "$file_url" >/dev/null 2>&1 - - if [ $? -eq 0 ]; then - log "$file_type download completed" - else - log "$file_type download failed" - fi - - fi - - ###################### FINAL CHECK RESULT ######################### - - if [ ! -e "$file_path" ]; then - build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - - # copy has failed : restoring the original file - if [ $file_type != "Rom" ] && [ $file_type != "Core" ]; then - mv "${file_path}_old" "$file_path" - log "backup restored" - fi - sleep 2 - [ "$file_mandatory" = "-m" ] && cleanup - - else - - checksum_func "$file_path" "$remote_file_checksum" - - if [ "$file_check_size" -eq 1 ]; then # file_checksum=0 means skip the difference check = always replace - checksize_func "$file_path" "$remote_file_size" - else - log "Skipping file size check." - same_size=1 # fake same size for skipping - fi - - if [ "$same_size" -eq 1 ] && [ "$same_chksum" -eq 1 ]; then - build_infoPanel_and_log "Syncing" "$file_type synced." - if [ $file_type == "Rom" ]; then - log "Refreshing roms list ${rom%/*}/${romdirname}_cache6.db" - rm "${rom%/*}/${romdirname}_cache6.db" - fi - - else - build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - - # copy has failed : restoring the original file - if [ $file_type != "Rom" ] && [ $file_type != "Core" ]; then - mv "${file_path}_old" "$file_path" - log "backup restored" - fi - sleep 2 - if [ "$file_mandatory" = "-m" ]; then - notify_peer "stop_now" - cleanup - fi - fi - #####" - - fi - ###################### FINAL RESULT DISPLAY######################### - - # if [ "$sync_success" -ne 1 ]; then - # build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - # sleep 2 - # cleanup - # else - # build_infoPanel_and_log "Syncing" "$file_type synced." - # fi - - # build_infoPanel_and_log "Syncing" "$file_type checksums don't match, syncing" - # build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - # build_infoPanel_and_log "Syncing" "$file_type synced." - # build_infoPanel_and_log "Syncing" "$file_type doesn't exist locally; syncing with host." - # build_infoPanel_and_log "Sync Failed" "Failed to download the $file_type file." - # build_infoPanel_and_log "Syncing" "$file_type synced." - - ################### END ########################## - -} - -checksum_func() { - local_file_size=$(stat -c%s "$file_path") - local func_file_path="$1" - local CRC="$2" - - ########################## File checksum check : same_chksum = 0 different, 1 identical , 2 unknown - - if [ "$CRC" != "0" ]; then # file_checksum=0 means skip the difference check = always replace - local_file_checksum=$(xcrc "$func_file_path") - - if [ "$local_file_size" -gt "$MAX_FILE_CHKSUM_SIZE" ]; then - log "File size too big for checksum: it would be too long" - same_chksum=2 - else - if [ "$CRC" == "$local_file_checksum" ]; then - same_chksum=1 - else - same_chksum=0 - fi - fi - else - log "Skipping checksum check." - same_chksum=1 # fake same size for skipping - fi -} - -checksize_func() { - - local func_file_path="$1" - local filesize_tocheck="$2" - local_file_size=$(stat -c%s "$func_file_path") - - ########################## File size check same_size = 0 different, 1 identical , 2 unknown - - if echo "$filesize_tocheck" | grep -q "^[0-9][0-9]*$"; then # check if the remote file size is a numeric value - if [ "$filesize_tocheck" -eq "$local_file_size" ]; then - log "Same size as remote" - same_size=1 - else - log "Files size are different" - same_size=0 - fi - else - log "Impossible to get file size : wrong parameter." - same_size=2 - fi -} - +# unpack_rom: extract archive into its folder unpack_rom() { file="$1" folder=$(dirname "$file") @@ -881,83 +385,68 @@ unpack_rom() { fi } -build_infoPanel_and_log() { - local title="$1" - local message="$2" - - log "Info Panel: \n\tStage: $title\n\tMessage: $message" - if is_running infoPanel; then - killall -9 infoPanel - fi - infoPanel --title "$title" --message "$message" --persistent & - sync - touch /tmp/dismiss_info_panel - sync - sleep 0.5 - sync -} - -restore_ftp() { - log "Restoring original FTP server" - killall -9 tcpsvd - if flag_enabled ftpState; then - if flag_enabled authftpState; then - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpdauth.conf & - else - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpd.conf & - fi - fi -} - -flag_enabled() { - flag="$1" - [ -f "$sysdir/config/.$flag" ] -} - -udhcpc_control() { - if pgrep udhcpc >/dev/null; then - killall -9 udhcpc - fi - sleep 1 - udhcpc -i wlan0 -s /etc/init.d/udhcpc.script >/dev/null 2>&1 & -} - -is_running() { - process_name="$1" - pgrep "$process_name" >/dev/null -} - -enable_flag() { - flag="$1" - touch "$sysdir/config/.$flag" -} - ######### ##Main.## ######### lets_go() { + # Allow user to abort via menu while setup runs pressMenu2Kill $(basename $0) & + + # Ensure WiFi is up (udhcpc, hard fail, keep wlan1) + # check_wifi: use udhcpc, hard fail, keep wlan1 + check_wifi 1 1 0 + + # Write cookie with host metadata create_cookie_info + + # Create hotspot for client . "$sysdir/script/network/hotspot_create.sh" - start_ftp + + # start_ftp: preflight check_stop for client join issues + start_ftp "The client has had a problem joining the session." + + # Wait for client connection wait_for_client - sync_file "Cookie" "/mnt/SDCARD/RetroArch/retroarch.cookie" 0 0 -f -m # will be downloaded as retroarch.cookie.client ! + wait_for_client_network + + # Send cookie to client (downloaded as retroarch.cookie.client) + sync_file "Cookie" "$COOKIE_FILE" 0 0 -f -m + + # Read client cookie for display and params client_read_cookie + + # Backup host save and fetch client save host_save_backup client_save_get client_save_rename + + # Sync client ROM and prepare local clone sync_file "Rom" "$client_rom" 1 "$romchecksum" -b -m client_rom_rename - ready_up + + # Sync client image for confirmation display sync_file "Img" "$client_Img_path" 0 0 -o - stripped_game_names + + # Build display names for confirmation prompt + host_game_name=$(format_game_name "$(basename "${host_rom%.*}")" "Host (me)") + client_game_name=$(format_game_name "$(basename "${client_rom%.*}")" "Client" "\n ") + + # Confirm host start with host/client info confirm_join_panel "Host now?" "$host_game_name \n $client_game_name" + + # Stop menu watcher before launch pkill -9 pressMenu2Kill + + # Launch RetroArch host session start_retroarch + + # Restore saves and send back to client host_save_overwrite client_wait_for_save_return client_save_send + + # Cleanup and restore state cleanup } diff --git a/static/build/.tmp_update/script/netplay/easy-netplay_server_pokemon_GBA.sh b/static/build/.tmp_update/script/netplay/easy-netplay_server_pokemon_GBA.sh index 5150a2227e..ce3f950f83 100644 --- a/static/build/.tmp_update/script/netplay/easy-netplay_server_pokemon_GBA.sh +++ b/static/build/.tmp_update/script/netplay/easy-netplay_server_pokemon_GBA.sh @@ -2,13 +2,17 @@ # Used within GLO as an addon script. # Env setup -sysdir=/mnt/SDCARD/.tmp_update -miyoodir=/mnt/SDCARD/miyoo -LD_LIBRARY_PATH="/lib:/config/lib:$miyoodir/lib:$sysdir/lib:$sysdir/lib/parasyte" +. /mnt/SDCARD/.tmp_update/script/netplay/easy-netplay_env.sh logfile=pokemon_link -. $sysdir/script/log.sh +# Source scripts +# easy-netplay_common.sh: build_infoPanel_and_log, checksize_func, checksum_func, enable_flag, disable_flag, flag_enabled, is_running, restore_ftp, udhcpc_control, url_encode, strip_game_name, format_game_name, check_wifi, start_ftp +. $sysdir/script/netplay/easy-netplay_common.sh +# easy-netplay_signalling.sh: wait_for_client, ready_up, notify_peer, check_stop, notify_stop +. $sysdir/script/netplay/easy-netplay_signalling.sh + +# Runtime vars rm /tmp/stop_now host_rom="$1" romdirname=$(echo "$host_rom" | grep -o '/Roms/[^/]*' | cut -d'/' -f3) @@ -22,87 +26,7 @@ log "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Easy Netplay Pokemon Host GBA -*-* ##Setup.## ########## -# We'll need FTP for lightweight signaling - use the built in FTP, it allows us to curl (errors on bftpd re: path) -start_ftp() { - check_stop - if is_running bftpd; then - log "FTP already running, killing to rebind" - bftpd_p=$(ps | grep bftpd | grep -v grep | awk '{for(i=4;i<=NF;++i) printf $i" "}') - killall -9 bftpd - killall -9 tcpsvd - tcpsvd -E 0.0.0.0 21 ftpd -w / & - else - tcpsvd -E 0.0.0.0 21 ftpd -w / & - log "Starting FTP server" - fi -} - -# Wait for a hit on the sta list for someone joining the hotspot -wait_for_client() { - check_stop - build_infoPanel_and_log "Hotspot" "Waiting for a client to connect..." - - client_ip="" - client_mac="" - counter=0 - - killall -9 wpa_supplicant - killall -9 udhcpc - - sleep 1 - - while true; do - sta_list=$($sysdir/bin/hostapd_cli all_sta 2>/dev/null) - $sysdir/bin/hostapd_cli all_sta flush - - if [ $? -ne 0 ]; then - build_infoPanel_and_log "Hotspot" "Hostapd hook failing, retrying." - counter=$((counter + 1)) - fi - - if [ ! -z "$sta_list" ]; then - client_mac=$(echo "$sta_list" | awk 'NR==2{print $1; exit}') - client_ip=$(arp -an | awk '/'"$client_mac"'/ {gsub(/[\(\)]/,""); print $2}') - - if [ ! -z "$client_ip" ]; then - case "$client_ip" in - 192.168.100.*) - log "$sta_list" - log "A client has connected. IP: $client_ip" - build_infoPanel_and_log "Hotspot" "A client has connected! \n IP: $client_ip" - break - ;; - esac - fi - fi - - sleep 1 - counter=$((counter + 1)) - - if [ $counter -ge 30 ]; then - log "No client has connected" - build_infoPanel_and_log "Hotspot error" "No client has connected. Exiting..." - cleanup - fi - done - - sleep 1 - log "$client_ip has joined the hotspot" -} - -# Tell the client we're ready to accept connections -ready_up() { - check_stop - ping -c 5 $client_ip >/dev/null 2>&1 - if [ $? -eq 0 ]; then - notify_peer "host_ready" - else - build_infoPanel_and_log "Error" "No connectivity to $client_ip, \n is the client still connected?" - notify_stop - fi -} - -# We'll start Retroarch in host mode with -H with the core and rom paths loaded in. +# start_retroarch: launch RetroArch in host mode with the local ROM start_retroarch() { log "\n############################ RETROARCH DEBUGGING ############################" @@ -119,7 +43,8 @@ start_retroarch() { cd /mnt/SDCARD/RetroArch log "Starting RetroArch loaded with $host_rom" - (sleep 2 && notify_peer "host_ready" &) & + # notify_peer: signal host ready to client + (sleep 2 && notify_peer "$client_ip" "host_ready" &) & HOME=/mnt/SDCARD/RetroArch ./retroarch --appendconfig=./.retroarch/easynetplay_override.cfg -H -v -L .retroarch/cores/gpsp_libretro.so "$host_rom" if [ -n "$PreviousCPUspeed" ]; then @@ -130,64 +55,23 @@ start_retroarch() { fi } -# Cleanup. If you don't call this you don't retransfer the saves - Users cannot under any circumstances miss this function. +# cleanup: restore network/ftp and clean temp files cleanup() { - build_infoPanel_and_log "Cleanup" "Cleaning up after Pokemon session\n Do not power off!" - - pkill -9 pressMenu2Kill - - . "$sysdir/script/network/hotspot_cleanup.sh" - - restore_ftp - - # Remove some files we prepared and received - rm "/tmp/host_ready" - rm "/tmp/stop_now" - disable_flag hotspotState - rm "/tmp/dismiss_info_panel" - sync - log "Cleanup done" - - #Rename savestate_auto_load so savestate doesn't overwrite next loadsave + # Rename savestate_auto_load so savestate doesn't overwrite next loadsave mv -f "/mnt/SDCARD/Saves/CurrentProfile/states/gpSP/$host_rom_filename_NoExt.state.auto" "/mnt/SDCARD/Saves/CurrentProfile/states/gpSP/$host_rom_filename_NoExt.state.auto_$CurDate" - - exit -} - -########### -#Utilities# -########### - -# Use the safe word -notify_stop() { - notify_peer "stop_now" - sleep 2 - cleanup -} -# Check stop, if the client tells us to stop we will. -check_stop() { - sync - if [ -e "/tmp/stop_now" ]; then - build_infoPanel_and_log "Message from client" "The client has had a problem joining the session." - sleep 2 - cleanup - fi -} - -notify_peer() { - local notify_file="/tmp/$1" - touch "$notify_file" - sync - curl -T "$notify_file" "ftp://${client_ip}/${notify_file}" >/dev/null 2>&1 # the first / after the IP must be not encoded - - if [ $? -eq 0 ]; then - log "Successfully transferred $notify_file to ftp://${client_ip}/${notify_file}" - else - log "Failed to transfer $notify_file to ftp://${client_ip}/${notify_file}" - fi + # message: cleanup infoPanel text + # args: hotspot_cleanup restore_ftp kill_infopanel disable_hotspot_flag + # remove files + netplay_cleanup \ + "Cleaning up after Pokemon session\n Do not power off!" \ + 1 1 0 1 \ + "/tmp/host_ready" \ + "/tmp/stop_now" \ + "/tmp/dismiss_info_panel" } +# confirm_join_panel: show host confirmation UI with local ROM image confirm_join_panel() { local title="$1" local message="$2" @@ -218,81 +102,43 @@ confirm_join_panel() { fi } -stripped_game_names() { - host_game_name="$(basename "${host_rom%.*}")" - host_game_name="$(echo "$host_game_name" | sed -e 's/ ([^()]*)//g' -e 's/ [[A-z0-9!+]*]//g' -e 's/([^()]*)//g' -e 's/[[A-z0-9!+]*]//g')" - host_game_name="Host (me): \n$host_game_name" -} - -build_infoPanel_and_log() { - local title="$1" - local message="$2" - - log "Info Panel: \n\tStage: $title\n\tMessage: $message" - if is_running infoPanel; then - killall -9 infoPanel - fi - infoPanel --title "$title" --message "$message" --persistent & - sync - touch /tmp/dismiss_info_panel - sync - sleep 0.5 - sync -} - -restore_ftp() { - log "Restoring original FTP server" - killall -9 tcpsvd - if flag_enabled ftpState; then - if flag_enabled authftpState; then - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpdauth.conf & - else - bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpd.conf & - fi - fi -} - -flag_enabled() { - flag="$1" - [ -f "$sysdir/config/.$flag" ] -} - -udhcpc_control() { - if pgrep udhcpc >/dev/null; then - killall -9 udhcpc - fi - sleep 1 - udhcpc -i wlan0 -s /etc/init.d/udhcpc.script >/dev/null 2>&1 & -} - -is_running() { - process_name="$1" - pgrep "$process_name" >/dev/null -} - -enable_flag() { - flag="$1" - touch "$sysdir/config/.$flag" -} - ######### ##Main.## ######### +# lets_go: main flow for hosting GBA session lets_go() { + # Allow user to abort via menu while setup runs pressMenu2Kill $(basename $0) & + + # Ensure ROM path is provided if [ -z "$host_rom" ]; then build_infoPanel_and_log "Error" "No ROM path provided." exit 1 fi + + # Create hotspot for client . "$sysdir/script/network/hotspot_create.sh" - start_ftp + + # Start FTP with preflight stop check + start_ftp "The client has had a problem joining the session." + + # Wait for client connection wait_for_client - ready_up - stripped_game_names + + # Build display names for confirmation prompt + host_game_name=$(format_game_name "$(basename "${host_rom%.*}")" "Host (me)") + + # Confirm host start with local ROM display confirm_join_panel "Host now?" "$host_game_name" + + # Stop menu watcher before launch pkill -9 pressMenu2Kill + + # Launch RetroArch host session start_retroarch + + # Cleanup and restore state cleanup } diff --git a/static/build/.tmp_update/script/netplay/easy-netplay_signalling.sh b/static/build/.tmp_update/script/netplay/easy-netplay_signalling.sh new file mode 100644 index 0000000000..eb6df9ea9b --- /dev/null +++ b/static/build/.tmp_update/script/netplay/easy-netplay_signalling.sh @@ -0,0 +1,182 @@ +# Netplay signalling helpers + +# notify_peer [target_ip] <flag> +# - uses: peer_ip if target_ip is omitted +# - sends /tmp/<flag> via FTP to peer +notify_peer() { + local target_ip="" + local notify_flag="" + + if [ $# -eq 1 ]; then + target_ip="$peer_ip" + notify_flag="$1" + else + target_ip="$1" + notify_flag="$2" + fi + + if [ -z "$target_ip" ]; then + log "No peer IP set for notify_peer ($notify_flag)." + return 1 + fi + + local notify_file="/tmp/$notify_flag" + touch "$notify_file" + sync + curl -T "$notify_file" "ftp://${target_ip}/${notify_file}" >/dev/null 2>&1 # the first / after the IP must be not encoded + + if [ $? -eq 0 ]; then + log "Successfully transferred $notify_file to ftp://${target_ip}/${notify_file}" + else + log "Failed to transfer $notify_file to ftp://${target_ip}/${notify_file}" + fi +} + +# check_stop [message] +# - uses: /tmp/stop_now sentinel to abort +check_stop() { + local message="$1" + sync + if [ -e "/tmp/stop_now" ]; then + build_infoPanel_and_log "Message from client" "${message:-The client has had a problem joining the session.}" + sleep 2 + cleanup + fi +} + +# notify_stop +# - best-effort notify peer and cleanup +notify_stop() { + # notify_peer: best-effort stop signal to peer + notify_peer "stop_now" >/dev/null 2>&1 + sleep 2 + cleanup +} + +# ready_up +# - pings client_ip then signals host_ready +ready_up() { + # check_stop: client reported a setup/join issue + check_stop "The client has had a problem joining the session." + ping -c 5 $client_ip >/dev/null 2>&1 + if [ $? -eq 0 ]; then + # notify_peer: signal host ready to client + notify_peer "$client_ip" "host_ready" + else + build_infoPanel_and_log "Error" "No connectivity to $client_ip, \n is the client still connected?" + notify_stop + fi +} + +# wait_for_client +# - waits for client connection on hotspot +# - sets: client_ip, peer_ip +wait_for_client() { + # check_stop: client reported a setup/join issue + check_stop "The client has had a problem joining the session." + build_infoPanel_and_log "Hotspot" "Waiting for a client to connect..." + log "wait_for_client: start (sysdir=$sysdir)" + + client_ip="" + client_mac="" + counter=0 + lease_file=$(grep -E '^dhcp-leasefile=' "$sysdir/config/dnsmasq.conf" 2>/dev/null | head -n 1 | cut -d'=' -f2) + + killall -9 wpa_supplicant + killall -9 udhcpc + + sleep 1 + + while true; do + sta_list=$($sysdir/bin/hostapd_cli all_sta 2>/dev/null) + $sysdir/bin/hostapd_cli all_sta flush + + log "wait_for_client: sta_list='${sta_list}'" + + if [ $? -ne 0 ]; then + build_infoPanel_and_log "Hotspot" "Hostapd hook failing, retrying." + counter=$((counter + 1)) + fi + + if [ ! -z "$sta_list" ]; then + client_mac=$(printf '%s\n' "$sta_list" | awk 'NR==2{print $1; exit}') + client_mac=$(printf '%s' "$client_mac" | tr -cd '0-9a-fA-F:' | tr 'A-F' 'a-f') + log "wait_for_client: client_mac='${client_mac}'" + if [ -n "$client_mac" ] && [ -n "$lease_file" ] && [ -f "$lease_file" ]; then + sync + lease_dump=$(cat "$lease_file" 2>/dev/null) + client_ip=$(printf '%s\n' "$lease_dump" | awk -v mac="$client_mac" 'tolower($2)==tolower(mac){print $3; exit}') + fi + if [ -z "$client_ip" ]; then + arp_dump=$(arp -an 2>/dev/null) + if [ -n "$client_mac" ]; then + client_ip=$(printf '%s\n' "$arp_dump" | awk -v mac="$client_mac" 'tolower($0) ~ tolower(mac) {gsub(/[()]/,"",$2); print $2; exit}') + fi + fi + log "wait_for_client: client_ip='${client_ip}'" + + if [ ! -z "$client_ip" ]; then + case "$client_ip" in + 192.168.100.*) + log "$sta_list" + log "A client has connected. IP: $client_ip" + build_infoPanel_and_log "Hotspot" "A client has connected! \n IP: $client_ip" + peer_ip="$client_ip" + sync + break + ;; + esac + fi + fi + + sleep 0.5 + counter=$((counter + 1)) + + # wait for 15 seconds, then bail + if [ $counter -ge 30 ]; then + log "No client has connected" + build_infoPanel_and_log "Hotspot error" "No client has connected. Exiting..." + cleanup + fi + done + + sleep 1 + log "$client_ip has joined the hotspot" +} + +# wait_for_client_network: ensure client responds to ping before transfers +wait_for_client_network() { + local counter=0 + build_infoPanel_and_log "Hotspot" "Client connected.\nWaiting for client network..." + while true; do + if ping -c 1 -W 1 "$client_ip" >/dev/null 2>&1; then + log "Client network reachable at $client_ip" + break + fi + sleep 1 + counter=$((counter + 1)) + if [ $((counter % 10)) -eq 0 ]; then + build_infoPanel_and_log "Hotspot" "Still waiting for client network...\nIP: $client_ip" + fi + done +} + +# wait_for_host +# - waits for /tmp/host_ready signal +wait_for_host() { + build_infoPanel_and_log "Ready" "Waiting for host to start game" + while true; do + sync + # check_stop: host reported a setup issue + check_stop "The host has had a problem setting up the session" + for file in /tmp/host_ready; do + if [ -f "$file" ]; then + build_infoPanel_and_log "Message from host" "Setup complete" + rm /tmp/host_ready # be ready for the second use of host_ready flag + break 2 + fi + done + + sleep 1 + done +} diff --git a/static/build/.tmp_update/script/netplay/standard-netplay.sh b/static/build/.tmp_update/script/netplay/standard-netplay.sh index a62272527f..07ee3ea204 100644 --- a/static/build/.tmp_update/script/netplay/standard-netplay.sh +++ b/static/build/.tmp_update/script/netplay/standard-netplay.sh @@ -5,9 +5,9 @@ # Used within GLO as an addon script. # Env setup -sysdir=/mnt/SDCARD/.tmp_update -miyoodir=/mnt/SDCARD/miyoo -export LD_LIBRARY_PATH="/lib:/config/lib:$miyoodir/lib:$sysdir/lib:$sysdir/lib/parasyte" +. /mnt/SDCARD/.tmp_update/script/netplay/easy-netplay_env.sh + +# Runtime vars romfullpath="$1" romname=$(basename "$1") echo "cookie_core_path $cookie_core_path" @@ -15,7 +15,11 @@ CurrentSystem=$(echo "$1" | grep -o '/Roms/[^/]*' | cut -d'/' -f3) NetplayAction="$3" # host or join logfile=netplay -. $sysdir/script/log.sh + +# Source scripts +# easy-netplay_common.sh: build_infoPanel_and_log, checksize_func, checksum_func, enable_flag, disable_flag, flag_enabled, is_running, restore_ftp, udhcpc_control, url_encode, check_wifi, start_ftp +. $sysdir/script/netplay/easy-netplay_common.sh + program=$(basename "$0" .sh) ########## @@ -23,32 +27,9 @@ program=$(basename "$0" .sh) ########## # We'll need wifi up for this. Lets try and start it.. -check_wifi() { - ifconfig wlan1 down - if ifconfig wlan0 &>/dev/null; then - log "Wifi up" - else - build_infoPanel_and_log "WIFI" "Wifi disabled, starting..." - - /customer/app/axp_test wifion - sleep 2 - ifconfig wlan0 up - sleep 1 - $miyoodir/app/wpa_supplicant -B -D nl80211 -iwlan0 -c /appconfigs/wpa_supplicant.conf - - if is_running wpa_supplicant && ifconfig wlan0 >/dev/null 2>&1; then - build_infoPanel_and_log "WIFI" "Wifi started." - else - build_infoPanel_and_log "WIFI" "Unable to start WiFi\n unable to continue." - sleep 1 - fi - - sleep 2 - fi -} # Find the recommended core for the current system. -Get_NetplayCore() { +get_netplay_core() { platform="$1" netplaycore_info=$(grep "^${platform};" "$sysdir/config/netplay_cores.conf") @@ -127,34 +108,17 @@ Check_PlayerName() { #Utilities# ########### -build_infoPanel_and_log() { - local title="$1" - local message="$2" - - log "Info Panel: \n\tStage: $title\n\tMessage: $message" - if is_running infoPanel; then - killall -9 infoPanel - fi - infoPanel --title "$title" --message "$message" --persistent & - sync - touch /tmp/dismiss_info_panel - sync - sleep 0.5 - sync -} - -is_running() { - process_name="$1" - pgrep "$process_name" >/dev/null -} - ######### ##Main.## ######### lets_go() { - check_wifi - Get_NetplayCore "$CurrentSystem" + # Ensure WiFi is ready (no udhcpc, soft fail, down wlan1) + # check_wifi: no udhcpc, soft fail, down wlan1 + check_wifi 0 0 1 + + # Determine netplay core based on platform + get_netplay_core "$CurrentSystem" if [ $? -eq 0 ]; then echo "*****************************************" echo "romfullpath: $romfullpath" @@ -166,7 +130,11 @@ lets_go() { else exit fi + + # Validate player name before launch Check_PlayerName + + # Launch RetroArch netplay session start_retroarch } diff --git a/static/build/.tmp_update/script/network/hotspot_create.sh b/static/build/.tmp_update/script/network/hotspot_create.sh index 592defc821..f2dfb90abd 100644 --- a/static/build/.tmp_update/script/network/hotspot_create.sh +++ b/static/build/.tmp_update/script/network/hotspot_create.sh @@ -78,6 +78,7 @@ start_hotspot() { $sysdir/bin/hostapd -P /var/run/hostapd.pid -B -i wlan1 $sysdir/config/hostapd.conf & $sysdir/bin/dnsmasq --conf-file=$sysdir/config/dnsmasq.conf -u root & ip route add default via $gateway0addr + iw wlan1 set power_save off if pgrep "hostapd" >/dev/null; then $log_func "Started with IP of: $hotspot0addr, subnet of: $subnetmask" diff --git a/static/build/.tmp_update/script/network/hotspot_join.sh b/static/build/.tmp_update/script/network/hotspot_join.sh index 3814f256b6..80f8fd9271 100644 --- a/static/build/.tmp_update/script/network/hotspot_join.sh +++ b/static/build/.tmp_update/script/network/hotspot_join.sh @@ -103,18 +103,20 @@ wait_for_ip() { ip addr flush dev wlan0 while [ -z "$IP" ]; do - IP=$(ip route get 1 2>/dev/null | awk '{print $NF;exit}') + # prefer direct interface address (works even if route not set yet) + IP=$(ip -4 addr show wlan0 2>/dev/null | awk '/inet /{sub(/\\/.*$/,"",$2);print $2;exit}') + [ -z "$IP" ] && IP=$(ip route get 1 2>/dev/null | awk '{print $NF;exit}') sleep 0.5 counter=$((counter + 1)) - if [ $counter -eq 20 ]; then + if [ $counter -eq 40 ]; then $display_func "Fallback" "Using static IP..." killall -9 udhcpc ip addr flush dev wlan0 RAND_IP=$((101 + RANDOM % 150)) ip addr add 192.168.100.$RAND_IP/24 dev wlan0 ip route add default via 192.168.100.100 - elif [ $counter -ge 40 ]; then + elif [ $counter -ge 80 ]; then $display_func "Failed to connect!" "Could not get an IP in 20 seconds.\n Try again" sleep 1 $cleanup_func