#!/usr/bin/env bash
#
# Special test for plain(non-tls) upgrade of http/1 to http/2
# Only native
# Three cases controlled by compile-time #ifdef:s
# http/1-only
# http/2-only
# http/1 + http/2

# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi

# Only works with native
if [ "${WITH_RESTCONF}" != "native" ]; then
    rm -rf $dir
    if [ "$s" = $0 ]; then exit 0; else return 0; fi # skip
fi

# Cant make it work in sum.sh...
if ! ${HAVE_HTTP1}; then
    echo "...skipped: must run with http/1"
    rm -rf $dir
    if [ "$s" = $0 ]; then exit 0; else return 0; fi
fi

APPNAME=example

cfg=$dir/conf.xml

RCPROTO=http
RESTCONFIG=$(restconf_config none false)
if [ $? -ne 0 ]; then
    err1 "Error when generating certs"
fi

# Clixon config
cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
  <CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
  <CLICON_FEATURE>clixon-restconf:allow-auth-none</CLICON_FEATURE> <!-- Use auth-type=none -->
  <CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
  <CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
  <CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
  <CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
  <CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
  <CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
  <CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
  <CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
  <CLICON_SOCK>/usr/local/var/run/$APPNAME.sock</CLICON_SOCK>
  <CLICON_BACKEND_PIDFILE>/usr/local/var/run/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
  <CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
  <CLICON_RESTCONF_HTTP2_PLAIN>true</CLICON_RESTCONF_HTTP2_PLAIN>
  $RESTCONFIG <!-- only fcgi -->
</clixon-config>
EOF


# Restconf test routine with arguments:
# 1. Enable http for http/2 (CLICON_RESTCONF_HTTP2_PLAIN)
# 2. Expected http return value
function testrun()
{
    h2enable=$1

    new "test params: -f $cfg -- -s"
    if [ $BE -ne 0 ]; then
        new "kill old backend"
        sudo clixon_backend -zf $cfg
        if [ $? -ne 0 ]; then
            err
        fi
        sudo pkill -f clixon_backend # to be sure

        new "start backend -s init -f $cfg"
        start_backend -s init -f $cfg
    fi

    new "wait backend"
    wait_backend

    if [ $RC -ne 0 ]; then
        new "kill old restconf daemon"
        stop_restconf_pre

        new "start restconf daemon -o CLICON_RESTCONF_HTTP2_PLAIN=${h2enable}"
        start_restconf -f $cfg -o CLICON_RESTCONF_HTTP2_PLAIN=${h2enable}
    fi



    if [ ${HAVE_LIBNGHTTP2} = false -a ${HAVE_HTTP1} = true ]; then    # http/1 only

        new "wait restconf"
        wait_restconf

        # http/1-only always stays on http/1 in http/1 + http/2 mode
        new "restconf http1.1 no upgrade (h2:$h2enable)"
        echo "curl -Ssik --http1.1 -X GET http://localhost/.well-known/host-meta"
        expectpart "$(curl -Ssik --http1.1 -X GET http://localhost/.well-known/host-meta)" 0 "HTTP/1.1 200" "<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>" "<Link rel='restconf' href='/restconf'/>" "</XRD>" --not-- "HTTP/2"
        
        # http/1->http/2 switched if h2enable, otherwise it stays in http/1
        new "restconf upgrade http1->http2 (h2:$h2enable)"
        echo "curl -Ssik --http2 -X GET http://localhost/.well-known/host-meta"
        # stay on http/1
        expectpart "$(curl -Ssik --http2 -X GET http://localhost/.well-known/host-meta)" 0 "HTTP/1.1 200" "<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>" "<Link rel='restconf' href='/restconf'/>" "</XRD>"  --not-- "HTTP/2"

        # http/2-only is always an error in http/1 + http/2 mode
        new "restconf http2 prior-knowledge (h2:$h2enable)"
        echo "curl -Ssik --http2-prior-knowledge -X GET http://localhost/.well-known/host-meta"
        expectpart "$(curl -Ssik --http2-prior-knowledge -X GET http://localhost/.well-known/host-meta 2>&1)" "16 52 55 56"

    elif [ ${HAVE_LIBNGHTTP2} = true -a ${HAVE_HTTP1} = false ]; then  # http/2 only

        sleep 2 # Cannot do wait restconf
        
        # http/1-only always stays on http/1 in http/1 + http/2 mode
        new "restconf http1.1 no upgrade (h2:$h2enable)"
        echo "curl -Ssik --http1.1 -X GET http://localhost/.well-known/host-meta"
        # XXX cannot use expectpart due to null in pipe
        curl -Ssik --http1.1 -X GET http://localhost/.well-known/host-meta
        if [ $? == 0 ]; then
            err "NULL" "sucess"
        fi

        # http/1->http/2 switched if h2enable, otherwise it stays in http/1
        new "restconf upgrade http1->http2 (h2:$h2enable)"
        echo "curl -Ssik --http2 -X GET http://localhost/.well-known/host-meta"
        # stay on http/1
        curl -Ssik --http2 -X GET http://localhost/.well-known/host-meta
        if [ $? == 0 ]; then
            err "NULL" "sucess"
        fi

        # http/2-only is always an error in http/1 + http/2 mode
        new "restconf http2 prior-knowledge (h2:$h2enable)"
        echo "curl -Ssik --http2-prior-knowledge -X GET http://localhost/.well-known/host-meta"
        if $h2enable; then
            new "wait restconf"
            wait_restconf

            expectpart "$(curl -Ssik --http2-prior-knowledge -X GET http://localhost/.well-known/host-meta 2>&1)" 0 "HTTP/2 200" "<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>" "<Link rel='restconf' href='/restconf'/>" "</XRD>" --not-- "HTTP/1.1"

        else
            expectpart "$(curl -Ssik --http2-prior-knowledge -X GET http://localhost/.well-known/host-meta 2>&1)" 0 "HTTP/2 405"
        fi

    elif [ ${HAVE_LIBNGHTTP2} = true -a ${HAVE_HTTP1} = true ]; then  # http/1 + http/2

        new "wait restconf"
        wait_restconf
        
        # http/1-only always stays on http/1 in http/1 + http/2 mode
        new "restconf http1.1 no upgrade (h2:$h2enable)"
        echo "curl -Ssik --http1.1 -X GET http://localhost/.well-known/host-meta"
        expectpart "$(curl -Ssik --http1.1 -X GET http://localhost/.well-known/host-meta)" 0 "HTTP/1.1 200" "<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>" "<Link rel='restconf' href='/restconf'/>" "</XRD>" --not-- "HTTP/2"
        
        # http/1->http/2 switched if h2enable, otherwise it stays in http/1
        new "restconf upgrade http1->http2 (h2:$h2enable)"
        echo "curl -Ssik --http2 -X GET http://localhost/.well-known/host-meta"
        if $h2enable; then
            # switch to http/2
            expectpart "$(curl -Ssik --http2 -X GET http://localhost/.well-known/host-meta)" 0 "HTTP/2 200" "<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>" "<Link rel='restconf' href='/restconf'/>" "</XRD>"  "HTTP/1.1 101 Switching" "HTTP/2 200" --not-- "HTTP/1.1 200"
        else
            # stay on http/1
            expectpart "$(curl -Ssik --http2 -X GET http://localhost/.well-known/host-meta)" 0 "HTTP/1.1 200" "<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>" "<Link rel='restconf' href='/restconf'/>" "</XRD>"  --not-- "HTTP/2"
        fi

        # http/2-only is always an error in http/1 + http/2 mode
        new "restconf http2 prior-knowledge (h2:$h2enable)"
        echo "curl -Ssik --http2-prior-knowledge -X GET http://localhost/.well-known/host-meta"
        expectpart "$(curl -Ssik --http2-prior-knowledge -X GET http://localhost/.well-known/host-meta 2>&1)" "16 52 55 56"

    fi

    if [ $RC -ne 0 ]; then
        new "Kill restconf daemon"
        stop_restconf
    fi

    if [ $BE -ne 0 ]; then
        new "Kill backend"
        # Check if premature kill
        pid=$(pgrep -u root -f clixon_backend)
        if [ -z "$pid" ]; then
            err "backend already dead"
        fi
        # kill backend
        stop_backend -f $cfg
    fi
}

new "disable plain http/2"
testrun false

new "enable plain http/2"
testrun true

rm -rf $dir

new "endtest"
endtest
