add exit status codes
This commit is contained in:
parent
b2aa111263
commit
830c401030
|
@ -37,6 +37,20 @@ import (
|
||||||
_ "github.com/joho/godotenv/autoload"
|
_ "github.com/joho/godotenv/autoload"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// exitOk is for normal exits, such as a graceful disconnect or shutdown
|
||||||
|
exitOk = 0
|
||||||
|
|
||||||
|
// exitBadArguments is for positive failures as a result of arguments
|
||||||
|
exitBadArguments = 1
|
||||||
|
|
||||||
|
// exitBadConfig is for positive failures from an external service
|
||||||
|
exitBadConfig = 2
|
||||||
|
|
||||||
|
// exitRetry is for potentially false negative failures from temporary conditions such as a DNS resolution or network failure for which it would be reasonable to wait 10 seconds and try again
|
||||||
|
exitRetry = 29
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// GitRev refers to the abbreviated commit hash
|
// GitRev refers to the abbreviated commit hash
|
||||||
GitRev = "0000000"
|
GitRev = "0000000"
|
||||||
|
@ -97,14 +111,14 @@ func main() {
|
||||||
if len(os.Args) >= 2 {
|
if len(os.Args) >= 2 {
|
||||||
if "version" == os.Args[1] {
|
if "version" == os.Args[1] {
|
||||||
fmt.Printf("telebit %s %s %s\n", GitVersion, GitRev[:7], GitTimestamp)
|
fmt.Printf("telebit %s %s %s\n", GitVersion, GitRev[:7], GitTimestamp)
|
||||||
os.Exit(0)
|
os.Exit(exitOk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*acmeDirectory) > 0 {
|
if len(*acmeDirectory) > 0 {
|
||||||
if *acmeStaging {
|
if *acmeStaging {
|
||||||
fmt.Fprintf(os.Stderr, "pick either acme-directory or acme-staging\n")
|
fmt.Fprintf(os.Stderr, "pick either acme-directory or acme-staging\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadArguments)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,7 +195,7 @@ func main() {
|
||||||
portForwards, err := parsePortForwards(portToPorts)
|
portForwards, err := parsePortForwards(portToPorts)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "%s", err)
|
fmt.Fprintf(os.Stderr, "%s", err)
|
||||||
os.Exit(1)
|
os.Exit(exitBadArguments)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +205,7 @@ func main() {
|
||||||
bindAddrs, err := parseBindAddrs(*bindAddrsStr)
|
bindAddrs, err := parseBindAddrs(*bindAddrsStr)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "invalid bind address(es) given to --listen\n")
|
fmt.Fprintf(os.Stderr, "invalid bind address(es) given to --listen\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadArguments)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +215,7 @@ func main() {
|
||||||
} else if 0 != len(*vendorID) {
|
} else if 0 != len(*vendorID) {
|
||||||
if VendorID != *vendorID {
|
if VendorID != *vendorID {
|
||||||
fmt.Fprintf(os.Stderr, "invalid --vendor-id\n")
|
fmt.Fprintf(os.Stderr, "invalid --vendor-id\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadArguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if 0 == len(VendorID) {
|
if 0 == len(VendorID) {
|
||||||
|
@ -209,7 +223,7 @@ func main() {
|
||||||
} else if 0 != len(os.Getenv("VENDOR_ID")) {
|
} else if 0 != len(os.Getenv("VENDOR_ID")) {
|
||||||
if VendorID != os.Getenv("VENDOR_ID") {
|
if VendorID != os.Getenv("VENDOR_ID") {
|
||||||
fmt.Fprintf(os.Stderr, "invalid VENDOR_ID\n")
|
fmt.Fprintf(os.Stderr, "invalid VENDOR_ID\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadArguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if 0 == len(ClientSecret) {
|
if 0 == len(ClientSecret) {
|
||||||
|
@ -217,7 +231,7 @@ func main() {
|
||||||
} else if 0 != len(*secret) {
|
} else if 0 != len(*secret) {
|
||||||
if ClientSecret != *secret {
|
if ClientSecret != *secret {
|
||||||
fmt.Fprintf(os.Stderr, "invalid --secret\n")
|
fmt.Fprintf(os.Stderr, "invalid --secret\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadArguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if 0 == len(ClientSecret) {
|
if 0 == len(ClientSecret) {
|
||||||
|
@ -225,13 +239,13 @@ func main() {
|
||||||
} else if 0 != len(os.Getenv("SECRET")) {
|
} else if 0 != len(os.Getenv("SECRET")) {
|
||||||
if ClientSecret != os.Getenv("SECRET") {
|
if ClientSecret != os.Getenv("SECRET") {
|
||||||
fmt.Fprintf(os.Stderr, "invalid SECRET\n")
|
fmt.Fprintf(os.Stderr, "invalid SECRET\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadArguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ppid, err := machineid.ProtectedID(fmt.Sprintf("%s|%s", VendorID, ClientSecret))
|
ppid, err := machineid.ProtectedID(fmt.Sprintf("%s|%s", VendorID, ClientSecret))
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "unauthorized device\n")
|
fmt.Fprintf(os.Stderr, "unauthorized device\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadConfig)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ppidBytes, err := hex.DecodeString(ppid)
|
ppidBytes, err := hex.DecodeString(ppid)
|
||||||
|
@ -251,7 +265,7 @@ func main() {
|
||||||
}
|
}
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "neither secret nor token provided\n")
|
fmt.Fprintf(os.Stderr, "neither secret nor token provided\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadArguments)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,7 +277,7 @@ func main() {
|
||||||
fmt.Fprintf(os.Stderr, "Acting as Relay\n")
|
fmt.Fprintf(os.Stderr, "Acting as Relay\n")
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(os.Stderr, "error: must provide Relay, or act as Relay\n")
|
fmt.Fprintf(os.Stderr, "error: must provide Relay, or act as Relay\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadArguments)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,12 +290,13 @@ func main() {
|
||||||
directory, err := tunnel.Discover(*relay)
|
directory, err := tunnel.Discover(*relay)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "Error: invalid Tunnel Relay URL %q: %s\n", *relay, err)
|
fmt.Fprintf(os.Stderr, "Error: invalid Tunnel Relay URL %q: %s\n", *relay, err)
|
||||||
os.Exit(1)
|
os.Exit(exitRetry)
|
||||||
}
|
}
|
||||||
fmt.Printf("[Directory] %s\n", *relay)
|
fmt.Printf("[Directory] %s\n", *relay)
|
||||||
jsonb, _ := json.Marshal(directory)
|
jsonb, _ := json.Marshal(directory)
|
||||||
fmt.Printf("\t%s\n", string(jsonb))
|
fmt.Printf("\t%s\n", string(jsonb))
|
||||||
|
|
||||||
|
// TODO trimming this should no longer be necessary, but I need to double check
|
||||||
authBase := strings.TrimSuffix(directory.Authenticate.URL, "/inspect")
|
authBase := strings.TrimSuffix(directory.Authenticate.URL, "/inspect")
|
||||||
if "" == *authURL {
|
if "" == *authURL {
|
||||||
*authURL = authBase
|
*authURL = authBase
|
||||||
|
@ -292,7 +307,7 @@ func main() {
|
||||||
if "" == *authURL {
|
if "" == *authURL {
|
||||||
fmt.Fprintf(os.Stderr, "Discovered Directory Endpoints: %+v\n", directory)
|
fmt.Fprintf(os.Stderr, "Discovered Directory Endpoints: %+v\n", directory)
|
||||||
fmt.Fprintf(os.Stderr, "No Auth URL detected, nor supplied\n")
|
fmt.Fprintf(os.Stderr, "No Auth URL detected, nor supplied\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadConfig)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("Auth URL", *authURL)
|
fmt.Println("Auth URL", *authURL)
|
||||||
|
@ -305,10 +320,10 @@ func main() {
|
||||||
fmt.Println("Suggested ACME DNS 01 Proxy URL:", dns01Base)
|
fmt.Println("Suggested ACME DNS 01 Proxy URL:", dns01Base)
|
||||||
fmt.Println("--acme-relay-url ACME DNS 01 Proxy URL:", *acmeRelay)
|
fmt.Println("--acme-relay-url ACME DNS 01 Proxy URL:", *acmeRelay)
|
||||||
}
|
}
|
||||||
if "" == *authURL {
|
if "" == *acmeRelay {
|
||||||
fmt.Fprintf(os.Stderr, "Discovered Directory Endpoints: %+v\n", directory)
|
fmt.Fprintf(os.Stderr, "Discovered Directory Endpoints: %+v\n", directory)
|
||||||
fmt.Fprintf(os.Stderr, "No ACME DNS 01 Proxy URL detected, nor supplied\n")
|
fmt.Fprintf(os.Stderr, "No ACME DNS 01 Proxy URL detected, nor supplied\n")
|
||||||
os.Exit(1)
|
os.Exit(exitBadConfig)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("DNS 01 URL", *acmeRelay)
|
fmt.Println("DNS 01 URL", *acmeRelay)
|
||||||
|
@ -322,17 +337,21 @@ func main() {
|
||||||
if nil != err {
|
if nil != err {
|
||||||
if !strings.Contains(err.Error(), `"E_NOT_FOUND"`) {
|
if !strings.Contains(err.Error(), `"E_NOT_FOUND"`) {
|
||||||
fmt.Fprintf(os.Stderr, "invalid client credentials: %s\n", err)
|
fmt.Fprintf(os.Stderr, "invalid client credentials: %s\n", err)
|
||||||
os.Exit(2)
|
// the server confirmed that the client is bad
|
||||||
|
os.Exit(exitBadConfig)
|
||||||
} else {
|
} else {
|
||||||
|
// there may have been a network error
|
||||||
fmt.Fprintf(os.Stderr, "failed to register client: %s\n", err)
|
fmt.Fprintf(os.Stderr, "failed to register client: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(exitRetry)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
grants, err = telebit.Inspect(*authURL, *token)
|
grants, err = telebit.Inspect(*authURL, *token)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "failed to authenticate after registering client: %s\n", err)
|
fmt.Fprintf(os.Stderr, "failed to authenticate after registering client: %s\n", err)
|
||||||
os.Exit(1)
|
// there was no error registering the client, yet there was one authenticating
|
||||||
|
// therefore this may be an error that will be resolved
|
||||||
|
os.Exit(exitRetry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Printf("[Grants]\n\t%#v\n", grants)
|
fmt.Printf("[Grants]\n\t%#v\n", grants)
|
||||||
|
@ -343,7 +362,9 @@ func main() {
|
||||||
provider, err := getACMEProvider(acmeRelay, token)
|
provider, err := getACMEProvider(acmeRelay, token)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||||
os.Exit(1)
|
// it's possible for some providers this could be a failed network request,
|
||||||
|
// but I think in the case of what we specifically support it's bad arguments
|
||||||
|
os.Exit(exitBadArguments)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Printf("Email: %q\n", *email)
|
fmt.Printf("Email: %q\n", *email)
|
||||||
|
@ -404,14 +425,14 @@ func main() {
|
||||||
msg = " (may be auth related)"
|
msg = " (may be auth related)"
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "Error connecting to %s: %s%s\n", *relay, err, msg)
|
fmt.Fprintf(os.Stderr, "Error connecting to %s: %s%s\n", *relay, err, msg)
|
||||||
os.Exit(1)
|
os.Exit(exitRetry)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mgmt.Ping(*authURL, *token)
|
err = mgmt.Ping(*authURL, *token)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "failed to ping mgmt server: %s\n", err)
|
fmt.Fprintf(os.Stderr, "failed to ping mgmt server: %s\n", err)
|
||||||
//os.Exit(1)
|
//os.Exit(exitRetry)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -424,7 +445,7 @@ func main() {
|
||||||
err = mgmt.Ping(*authURL, *token)
|
err = mgmt.Ping(*authURL, *token)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "failed to ping mgmt server: %s\n", err)
|
fmt.Fprintf(os.Stderr, "failed to ping mgmt server: %s\n", err)
|
||||||
//os.Exit(1)
|
//os.Exit(exitRetry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -437,7 +458,7 @@ func main() {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := <-done; nil != err {
|
if err := <-done; nil != err {
|
||||||
os.Exit(1)
|
os.Exit(exitRetry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -343,6 +343,7 @@ func TerminateTLS(client net.Conn, acme *ACME) net.Conn {
|
||||||
var err error
|
var err error
|
||||||
magic, err = NewCertMagic(acme)
|
magic, err = NewCertMagic(acme)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
// TODO find a way to channel this to an initialization error
|
||||||
fmt.Fprintf(
|
fmt.Fprintf(
|
||||||
os.Stderr,
|
os.Stderr,
|
||||||
"failed to initialize certificate management (discovery url? local folder perms?): %s\n",
|
"failed to initialize certificate management (discovery url? local folder perms?): %s\n",
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,8 +45,7 @@ func Discover(relay string) (*Endpoints, error) {
|
||||||
directives := &Endpoints{}
|
directives := &Endpoints{}
|
||||||
relayURL, err := url.Parse(relay)
|
relayURL, err := url.Parse(relay)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "Error: invalid Tunnel Relay URL %q: %s\n", relay, err)
|
return nil, err
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
if "ws" != relayURL.Scheme[:2] {
|
if "ws" != relayURL.Scheme[:2] {
|
||||||
|
|
||||||
|
@ -56,8 +54,7 @@ func Discover(relay string) (*Endpoints, error) {
|
||||||
}
|
}
|
||||||
resp, err := http.Get(relayURL.String() + ".well-known/telebit.app/index.json")
|
resp, err := http.Get(relayURL.String() + ".well-known/telebit.app/index.json")
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "Error: invalid Tunnel Relay URL %q: %s\n", relay, err)
|
return nil, err
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
b, err := ioutil.ReadAll(resp.Body)
|
b, err := ioutil.ReadAll(resp.Body)
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
|
|
Loading…
Reference in New Issue