#!/usr/bin/env bash
#
# Description: A Nat Script by sean bugfan
#
# Copyright (C) 2022 - Now  bugfan <bugfan53@gmail.com>
# URL: i996.me
# https://github.com/bugfan
#
access_token=$1
pipe_dir="/tmp/clotho/"
if [ -d ${pipe_dir} ]; then
    rm -rf ${pipe_dir}
fi
if [ ! -d ${pipe_dir} ]; then
    mkdir ${pipe_dir}
fi
pipe_websocket=$(echo ${pipe_dir}"websocket")
if [ ! -p ${pipe_websocket} ]; then
    mkfifo ${pipe_websocket}
fi
pipe_internal=$(echo ${pipe_dir}"internal")
if [ ! -p ${pipe_internal} ]; then
    mkfifo ${pipe_internal}
fi

message_request="ClothoHTTPRequest"
message_broadcast="ClothoBroadcast"
message_break="ClothoBreakClient"
message_key="ClothoMsg"


sys_protocol="https://"
sys_host="api.i996.me"
public_api_protocol="https://"
public_host="xxxx.i996.me"
private_host="127.0.0.1:8080"
wxtoken="xxxx"

include(){
    tmp=$(echo $1 | grep "${2}")
    if [[ "$tmp" != "" ]]
    then
        return 1
    else
        return 0
    fi
}

check_token(){
    if [ -z "${1}" ]; then
        return 1
    fi
    msg=$(curl -s --http1.1 -X POST ''$sys_protocol$sys_host'/sys-auth' -H 'Authorization: '${1}'')
    if [ $? != 0 ]; then
        return 2 
    fi

    include $msg $message_broadcast
    stat=$?
    if [ ${#msg} == '0' ]; then
        return 1
    fi
    if [ $stat == 0 ]; then
        return 1
    fi
    wxtoken=${1}
    info=${msg#*$message_broadcast}
    private_host=${info#*|}
    public_host=${info%%|*}
    echo 'forward a:'$private_host
    echo 'forward b:'$public_host
    echo 'forward c:'$wxtoken
    return 0
}

init(){
    while :
    do
        # # read token
        # echo "请输入Token: \c"
        # token=''
        # while : ;
        # do
        #     read -n 1 -s -p "" pw
        #     if [ $pw ]; then
        #         token=${token}$pw
        #         echo "*\c"
        #     else
        #         echo
        #         break
        #     fi
        # done

        # # read token
        # # read -p "请输入Token:" token
        # check_token $token
        # state=$?
        # if [ $state == 0 ]; then
        #     break
        # fi
        # if [ $state == 2 ]; then
        #     echo '抱歉,服务器可能暂时出了点问题!请稍后再尝试～'
        # else
        #     echo 'Token验证失败!请关注"敲代码斯基"公众号获取Token!(免费)'
        # fi

        # check token
        token=${access_token}
        if [ ${#token} == '0' ];then
            echo '请指定Token参数!(curl -s i996.me | bash -s Token)'
            exit 0
        fi
        check_token $token
        state=$?
        if [ $state == 0 ]; then
            break
        fi
        if [ $state == 2 ]; then
            echo '抱歉,服务器可能暂时出了点问题!请稍后再尝试～'
        else
            echo 'Token验证失败!请关注"敲代码斯基"公众号获取Token!(免费)'
        fi
        exit 0
    done

}

init

new_fifo_name(){
    echo $1$2
}

string_index(){ 
  x="${1%%$2*}"
  [[ $x = $1 ]] && echo -1 || echo ${#x}
}
do_request(){
    # get message id
    tmp="${1#*${message_key}:}"
    message_id=${tmp%%\'*}
    if [ ${#message_id} -lt 5 ]; then
        printf "error message:%s\n" $message_id
        return
    fi
    echo "==== request ====>:"$message_id

    internal_fifo=$(new_fifo_name ${pipe_dir} ${message_id})
    mkfifo ${internal_fifo}
    response ${message_id} ${internal_fifo} &
    (eval "$1") > ${internal_fifo}
    echo "===tunnel-client curl exit state===>:"$?
    rm ${internal_fifo}
}

response(){
    # printf 'normal msg id is:%s,%s\n' $1 $2
    curl -X POST --http1.1 -v ''$sys_protocol$sys_host'/sys-callback' -H 'Authorization: '${wxtoken}'' -H 'ClothoMsg: '${1}'' --data-binary '@'${2}'' 2>/dev/null
    echo "<==== response ====:"${1}
}

handle(){
    msg=${1}
    # printf "===message===>:%s\n" ${msg}
    include $msg $message_request
    req=$?
    if [ $req > 0 ]; then
        payload=${msg#*$message_request}
        printf "%s\n" $payload
        cmd=$(echo $payload|base64 -d)
        # cmd="curl -X 'GET' -d '' -H 'Accept: */*' -H 'ClothoMsg: '${wxtoken}'' -H 'User-Agent: curl/7.77.0' 'http://127.0.0.1:9090'"
        do_request "$cmd" &
    fi

    # if [ $msg == *$message_break* ]; then
    #     echo '远端更新了，请输入Token重新启动！！'
    #     exit 0
    # fi

}
ssh_response(){
    while :
    do
        read msg < ${pipe_internal}
        printf 'normal msg is:%s\n' $msg
        curl -X POST --http1.1 -v ''$sys_protocol$sys_host'/sys-callback' -H 'Authorization: '${wxtoken}'' -H 'ClothoMsg: '${msg}'' --data-binary '@'${pipe_internal}''
        echo "----send response ok ----\n"

    done
    echo "finish ssh_response\n"
}

read_io(){
    # tail -f ${pipe_websocket} | while read -r line ; do
    echo "It works!!! "
    while IFS= read -r line ; do
        handle "${line}"
    done < "${pipe_websocket}"
    echo "Connect exception...\n"
}


sys_connect(){
    # listen conn
    read_io & 2>/dev/null
    read_io_pid=$!
    printf "worker pid:%s\n" ${read_io_pid}

    # ssh_response &
    # ssh_response_pid=$!
    # printf "read response pid:%s\n" ${ssh_response_pid}

    # do connect
    curl -s --no-buffer --http1.1 -H 'Authorization: '${wxtoken}'' -H 'Connection: keep-alive, Upgrade' -H 'Upgrade: websocket' -v -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: websocket' ''$sys_protocol$sys_host'/sys-ws' ws -o ${pipe_websocket} 2>/dev/null
    echo "System connection has broken! Retry...."
    kill ${read_io_pid} 2>/dev/null
}

# finish func
finish () {
    kill ${read_io_pid}
    rm -rf ${pipe_dir}
    rm 0
    exit 0
}

# catch "Exit"
# catch "Ctrl + c"
trap finish EXIT SIGTERM SIGINT SIGQUIT

run(){
    while :
    do
        sys_connect
        sleep 5
    done
}

run


# # Inifinite sleep
# sleep infinity
# wait $!
