mirror of
				https://github.com/therootcompany/telebit.git
				synced 2025-11-04 07:12:52 +00:00 
			
		
		
		
	cleanup
This commit is contained in:
		
							parent
							
								
									eef6ca679f
								
							
						
					
					
						commit
						c234077fdc
					
				
							
								
								
									
										18
									
								
								.jshintrc
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								.jshintrc
									
									
									
									
									
								
							@ -1,18 +0,0 @@
 | 
			
		||||
{ "node": true
 | 
			
		||||
, "browser": true
 | 
			
		||||
, "jquery": true
 | 
			
		||||
, "globals": { "angular": true, "Promise": true }
 | 
			
		||||
 | 
			
		||||
, "indent": 2
 | 
			
		||||
, "onevar": true
 | 
			
		||||
, "laxcomma": true
 | 
			
		||||
, "laxbreak": true
 | 
			
		||||
, "curly": true
 | 
			
		||||
, "nonbsp": true
 | 
			
		||||
 | 
			
		||||
, "eqeqeq": true
 | 
			
		||||
, "immed": true
 | 
			
		||||
, "undef": true
 | 
			
		||||
, "unused": true
 | 
			
		||||
, "latedef": true
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
// +build !dev
 | 
			
		||||
//go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.rootprojects.org/root/telebit/admin".AdminFS
 | 
			
		||||
//go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.rootprojects.org/root/telebit/assets/admin".AdminFS
 | 
			
		||||
 | 
			
		||||
package admin
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
// +build !dev
 | 
			
		||||
//go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.rootprojects.org/root/telebit/files".Assets
 | 
			
		||||
//go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.rootprojects.org/root/telebit/assets/files".Assets
 | 
			
		||||
 | 
			
		||||
package files
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
go generate ./...
 | 
			
		||||
 | 
			
		||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod vendor -o mgmt-server-linux ./cmd/mgmt/*.go
 | 
			
		||||
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -mod vendor -o mgmt-server-macos ./cmd/mgmt/*.go
 | 
			
		||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -o mgmt-server-windows-debug.exe ./cmd/mgmt/*.go
 | 
			
		||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -ldflags "-H windowsgui" -o mgmt-server-windows.exe ./cmd/mgmt/*.go
 | 
			
		||||
@ -1,11 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
set -u
 | 
			
		||||
 | 
			
		||||
go generate ./...
 | 
			
		||||
 | 
			
		||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod vendor -o telebit-relay-linux ./cmd/telebit/*.go
 | 
			
		||||
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -mod vendor -o telebit-relay-macos ./cmd/telebit/*.go
 | 
			
		||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -o telebit-relay-windows-debug.exe ./cmd/telebit/*.go
 | 
			
		||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -ldflags "-H windowsgui" -o telebit-relay-windows.exe ./cmd/telebit/*.go
 | 
			
		||||
@ -5,7 +5,7 @@ import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/iplist"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/iplist"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func help() {
 | 
			
		||||
 | 
			
		||||
@ -11,9 +11,9 @@ import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/telebit"
 | 
			
		||||
 | 
			
		||||
	"github.com/denisbrodbeck/machineid"
 | 
			
		||||
	_ "github.com/joho/godotenv/autoload"
 | 
			
		||||
 | 
			
		||||
@ -19,17 +19,15 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dns01"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/http01"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/iplist"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/mgmt"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/service"
 | 
			
		||||
	telebitX "git.rootprojects.org/root/telebit/internal/telebit"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/iplist"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/table"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/tunnel"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/telebit"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/tunnel"
 | 
			
		||||
 | 
			
		||||
	"github.com/coolaj86/certmagic"
 | 
			
		||||
	"github.com/denisbrodbeck/machineid"
 | 
			
		||||
@ -590,7 +588,7 @@ func muxAll(
 | 
			
		||||
	if "" != *apiHostname {
 | 
			
		||||
		// this is a generic net listener
 | 
			
		||||
		r := chi.NewRouter()
 | 
			
		||||
		telebitX.RouteAdmin(*authURL, r)
 | 
			
		||||
		telebit.RouteAdmin(*authURL, r)
 | 
			
		||||
		apiListener := tunnel.NewListener()
 | 
			
		||||
		go func() {
 | 
			
		||||
			httpsrv := &http.Server{Handler: r}
 | 
			
		||||
@ -716,7 +714,7 @@ func routeSubscribersAndClients(client net.Conn) error {
 | 
			
		||||
 | 
			
		||||
// tryToServeName picks the server tunnel with the least connections, if any
 | 
			
		||||
func tryToServeName(servername string, wconn *telebit.ConnWrap) bool {
 | 
			
		||||
	srv, ok := table.GetServer(servername)
 | 
			
		||||
	srv, ok := telebit.GetServer(servername)
 | 
			
		||||
	if !ok || nil == srv {
 | 
			
		||||
		if ok {
 | 
			
		||||
			// TODO BUG: Sometimes srv=nil & ok=true, which should not be possible
 | 
			
		||||
 | 
			
		||||
@ -11,9 +11,9 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/mgmt"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/telebit"
 | 
			
		||||
 | 
			
		||||
	"github.com/denisbrodbeck/machineid"
 | 
			
		||||
	"github.com/gorilla/websocket"
 | 
			
		||||
 | 
			
		||||
@ -13,9 +13,8 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	telebit "git.rootprojects.org/root/telebit"
 | 
			
		||||
	tbDns01 "git.rootprojects.org/root/telebit/internal/dns01"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/table"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/telebit"
 | 
			
		||||
 | 
			
		||||
	"github.com/coolaj86/certmagic"
 | 
			
		||||
	"github.com/dgrijalva/jwt-go"
 | 
			
		||||
@ -219,7 +218,7 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wsTun := telebit.NewWebsocketTunnel(conn)
 | 
			
		||||
	server := &table.SubscriberConn{
 | 
			
		||||
	server := &telebit.SubscriberConn{
 | 
			
		||||
		RemoteAddr:   r.RemoteAddr,
 | 
			
		||||
		WSConn:       conn,
 | 
			
		||||
		WSTun:        wsTun,
 | 
			
		||||
@ -243,7 +242,7 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		fmt.Printf("a subscriber stream is done: %q\n", err)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	table.Add(server)
 | 
			
		||||
	telebit.Add(server)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getACMEProvider(acmeRelay, token *string) (challenge.Provider, error) {
 | 
			
		||||
 | 
			
		||||
@ -1,57 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta charset="utf-8" />
 | 
			
		||||
        <title>Page Not Found</title>
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1" />
 | 
			
		||||
        <style>
 | 
			
		||||
            * {
 | 
			
		||||
                line-height: 1.2;
 | 
			
		||||
                margin: 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            html {
 | 
			
		||||
                color: #888;
 | 
			
		||||
                display: table;
 | 
			
		||||
                font-family: sans-serif;
 | 
			
		||||
                height: 100%;
 | 
			
		||||
                text-align: center;
 | 
			
		||||
                width: 100%;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            body {
 | 
			
		||||
                display: table-cell;
 | 
			
		||||
                vertical-align: middle;
 | 
			
		||||
                margin: 2em auto;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            h1 {
 | 
			
		||||
                color: #555;
 | 
			
		||||
                font-size: 2em;
 | 
			
		||||
                font-weight: 400;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            p {
 | 
			
		||||
                margin: 0 auto;
 | 
			
		||||
                width: 280px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @media only screen and (max-width: 280px) {
 | 
			
		||||
                body,
 | 
			
		||||
                p {
 | 
			
		||||
                    width: 95%;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                h1 {
 | 
			
		||||
                    font-size: 1.5em;
 | 
			
		||||
                    margin: 0 0 0.3em;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        </style>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <h1>Page Not Found</h1>
 | 
			
		||||
        <p>Sorry, but the page you were trying to view does not exist.</p>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
<!-- IE needs 512+ bytes: http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx -->
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 3.9 KiB  | 
@ -1,12 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!-- Please read: https://msdn.microsoft.com/en-us/library/ie/dn455106.aspx -->
 | 
			
		||||
<browserconfig>
 | 
			
		||||
    <msapplication>
 | 
			
		||||
        <tile>
 | 
			
		||||
            <square70x70logo src="tile.png"/>
 | 
			
		||||
            <square150x150logo src="tile.png"/>
 | 
			
		||||
            <wide310x150logo src="tile-wide.png"/>
 | 
			
		||||
            <square310x310logo src="tile.png"/>
 | 
			
		||||
        </tile>
 | 
			
		||||
    </msapplication>
 | 
			
		||||
</browserconfig>
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
 | 
			
		||||
<cross-domain-policy>
 | 
			
		||||
    <!-- Read this: https://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->
 | 
			
		||||
 | 
			
		||||
    <!-- Most restrictive policy: -->
 | 
			
		||||
    <site-control permitted-cross-domain-policies="none"/>
 | 
			
		||||
 | 
			
		||||
    <!-- Least restrictive policy: -->
 | 
			
		||||
    <!--
 | 
			
		||||
    <site-control permitted-cross-domain-policies="all"/>
 | 
			
		||||
    <allow-access-from domain="*" to-ports="*" secure="false"/>
 | 
			
		||||
    <allow-http-request-headers-from domain="*" headers="*" secure="false"/>
 | 
			
		||||
    -->
 | 
			
		||||
</cross-domain-policy>
 | 
			
		||||
@ -1,263 +0,0 @@
 | 
			
		||||
/*! HTML5 Boilerplate v5.3.0 | MIT License | https://html5boilerplate.com/ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * What follows is the result of much research on cross-browser styling.
 | 
			
		||||
 * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
 | 
			
		||||
 * Kroc Camen, and the H5BP dev community and team.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* ==========================================================================
 | 
			
		||||
   Base styles: opinionated defaults
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
html {
 | 
			
		||||
    color: #222;
 | 
			
		||||
    font-size: 1em;
 | 
			
		||||
    line-height: 1.4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Remove text-shadow in selection highlight:
 | 
			
		||||
 * https://twitter.com/miketaylr/status/12228805301
 | 
			
		||||
 *
 | 
			
		||||
 * These selection rule sets have to be separate.
 | 
			
		||||
 * Customize the background color to match your design.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
::-moz-selection {
 | 
			
		||||
    background: #b3d4fc;
 | 
			
		||||
    text-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::selection {
 | 
			
		||||
    background: #b3d4fc;
 | 
			
		||||
    text-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A better looking default horizontal rule
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
hr {
 | 
			
		||||
    display: block;
 | 
			
		||||
    height: 1px;
 | 
			
		||||
    border: 0;
 | 
			
		||||
    border-top: 1px solid #ccc;
 | 
			
		||||
    margin: 1em 0;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Remove the gap between audio, canvas, iframes,
 | 
			
		||||
 * images, videos and the bottom of their containers:
 | 
			
		||||
 * https://github.com/h5bp/html5-boilerplate/issues/440
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
audio,
 | 
			
		||||
canvas,
 | 
			
		||||
iframe,
 | 
			
		||||
img,
 | 
			
		||||
svg,
 | 
			
		||||
video {
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Remove default fieldset styles.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
fieldset {
 | 
			
		||||
    border: 0;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Allow only vertical resizing of textareas.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
textarea {
 | 
			
		||||
    resize: vertical;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ==========================================================================
 | 
			
		||||
   Browser Upgrade Prompt
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
.browserupgrade {
 | 
			
		||||
    margin: 0.2em 0;
 | 
			
		||||
    background: #ccc;
 | 
			
		||||
    color: #000;
 | 
			
		||||
    padding: 0.2em 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ==========================================================================
 | 
			
		||||
   Author's custom styles
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
/* ==========================================================================
 | 
			
		||||
   Helper classes
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Hide visually and from screen readers
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.hidden {
 | 
			
		||||
    display: none !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Hide only visually, but have it available for screen readers:
 | 
			
		||||
 * http://snook.ca/archives/html_and_css/hiding-content-for-accessibility
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.visuallyhidden {
 | 
			
		||||
    border: 0;
 | 
			
		||||
    clip: rect(0 0 0 0);
 | 
			
		||||
    height: 1px;
 | 
			
		||||
    margin: -1px;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    width: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Extends the .visuallyhidden class to allow the element
 | 
			
		||||
 * to be focusable when navigated to via the keyboard:
 | 
			
		||||
 * https://www.drupal.org/node/897638
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.visuallyhidden.focusable:active,
 | 
			
		||||
.visuallyhidden.focusable:focus {
 | 
			
		||||
    clip: auto;
 | 
			
		||||
    height: auto;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    overflow: visible;
 | 
			
		||||
    position: static;
 | 
			
		||||
    width: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Hide visually and from screen readers, but maintain layout
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.invisible {
 | 
			
		||||
    visibility: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Clearfix: contain floats
 | 
			
		||||
 *
 | 
			
		||||
 * For modern browsers
 | 
			
		||||
 * 1. The space content is one way to avoid an Opera bug when the
 | 
			
		||||
 *    `contenteditable` attribute is included anywhere else in the document.
 | 
			
		||||
 *    Otherwise it causes space to appear at the top and bottom of elements
 | 
			
		||||
 *    that receive the `clearfix` class.
 | 
			
		||||
 * 2. The use of `table` rather than `block` is only necessary if using
 | 
			
		||||
 *    `:before` to contain the top-margins of child elements.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.clearfix:before,
 | 
			
		||||
.clearfix:after {
 | 
			
		||||
    content: " "; /* 1 */
 | 
			
		||||
    display: table; /* 2 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.clearfix:after {
 | 
			
		||||
    clear: both;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ==========================================================================
 | 
			
		||||
   EXAMPLE Media Queries for Responsive Design.
 | 
			
		||||
   These examples override the primary ('mobile first') styles.
 | 
			
		||||
   Modify as content requires.
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
@media only screen and (min-width: 35em) {
 | 
			
		||||
    /* Style adjustments for viewports that meet the condition */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media print, (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 1.25dppx), (min-resolution: 120dpi) {
 | 
			
		||||
    /* Style adjustments for high resolution devices */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ==========================================================================
 | 
			
		||||
   Print styles.
 | 
			
		||||
   Inlined to avoid the additional HTTP request:
 | 
			
		||||
   http://www.phpied.com/delay-loading-your-print-css/
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
@media print {
 | 
			
		||||
    *,
 | 
			
		||||
    *:before,
 | 
			
		||||
    *:after,
 | 
			
		||||
    *:first-letter,
 | 
			
		||||
    *:first-line {
 | 
			
		||||
        background: transparent !important;
 | 
			
		||||
        color: #000 !important; /* Black prints faster:
 | 
			
		||||
                                   http://www.sanbeiji.com/archives/953 */
 | 
			
		||||
        box-shadow: none !important;
 | 
			
		||||
        text-shadow: none !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    a,
 | 
			
		||||
    a:visited {
 | 
			
		||||
        text-decoration: underline;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    a[href]:after {
 | 
			
		||||
        content: " (" attr(href) ")";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    abbr[title]:after {
 | 
			
		||||
        content: " (" attr(title) ")";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Don't show links that are fragment identifiers,
 | 
			
		||||
     * or use the `javascript:` pseudo protocol
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    a[href^="#"]:after,
 | 
			
		||||
    a[href^="javascript:"]:after {
 | 
			
		||||
        content: "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pre,
 | 
			
		||||
    blockquote {
 | 
			
		||||
        border: 1px solid #999;
 | 
			
		||||
        page-break-inside: avoid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Printing Tables:
 | 
			
		||||
     * http://css-discuss.incutio.com/wiki/Printing_Tables
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    thead {
 | 
			
		||||
        display: table-header-group;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tr,
 | 
			
		||||
    img {
 | 
			
		||||
        page-break-inside: avoid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    img {
 | 
			
		||||
        max-width: 100% !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    p,
 | 
			
		||||
    h2,
 | 
			
		||||
    h3 {
 | 
			
		||||
        orphans: 3;
 | 
			
		||||
        widows: 3;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    h2,
 | 
			
		||||
    h3 {
 | 
			
		||||
        page-break-after: avoid;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										424
									
								
								html/admin/css/normalize.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										424
									
								
								html/admin/css/normalize.css
									
									
									
									
										vendored
									
									
								
							@ -1,424 +0,0 @@
 | 
			
		||||
/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 1. Set default font family to sans-serif.
 | 
			
		||||
 * 2. Prevent iOS and IE text size adjust after device orientation change,
 | 
			
		||||
 *    without disabling user zoom.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
html {
 | 
			
		||||
    font-family: sans-serif; /* 1 */
 | 
			
		||||
    -ms-text-size-adjust: 100%; /* 2 */
 | 
			
		||||
    -webkit-text-size-adjust: 100%; /* 2 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove default margin.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* HTML5 display definitions
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Correct `block` display not defined for any HTML5 element in IE 8/9.
 | 
			
		||||
 * Correct `block` display not defined for `details` or `summary` in IE 10/11
 | 
			
		||||
 * and Firefox.
 | 
			
		||||
 * Correct `block` display not defined for `main` in IE 11.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
article,
 | 
			
		||||
aside,
 | 
			
		||||
details,
 | 
			
		||||
figcaption,
 | 
			
		||||
figure,
 | 
			
		||||
footer,
 | 
			
		||||
header,
 | 
			
		||||
hgroup,
 | 
			
		||||
main,
 | 
			
		||||
menu,
 | 
			
		||||
nav,
 | 
			
		||||
section,
 | 
			
		||||
summary {
 | 
			
		||||
    display: block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 1. Correct `inline-block` display not defined in IE 8/9.
 | 
			
		||||
 * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
audio,
 | 
			
		||||
canvas,
 | 
			
		||||
progress,
 | 
			
		||||
video {
 | 
			
		||||
    display: inline-block; /* 1 */
 | 
			
		||||
    vertical-align: baseline; /* 2 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prevent modern browsers from displaying `audio` without controls.
 | 
			
		||||
 * Remove excess height in iOS 5 devices.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
audio:not([controls]) {
 | 
			
		||||
    display: none;
 | 
			
		||||
    height: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address `[hidden]` styling not present in IE 8/9/10.
 | 
			
		||||
 * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
[hidden],
 | 
			
		||||
template {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Links
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove the gray background color from active links in IE 10.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Improve readability of focused elements when they are also in an
 | 
			
		||||
 * active/hover state.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
a:active,
 | 
			
		||||
a:hover {
 | 
			
		||||
    outline: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Text-level semantics
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
abbr[title] {
 | 
			
		||||
    border-bottom: 1px dotted;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
b,
 | 
			
		||||
strong {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address styling not present in Safari and Chrome.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
dfn {
 | 
			
		||||
    font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address variable `h1` font-size and margin within `section` and `article`
 | 
			
		||||
 * contexts in Firefox 4+, Safari, and Chrome.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
    font-size: 2em;
 | 
			
		||||
    margin: 0.67em 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address styling not present in IE 8/9.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
mark {
 | 
			
		||||
    background: #ff0;
 | 
			
		||||
    color: #000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address inconsistent and variable font size in all browsers.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
small {
 | 
			
		||||
    font-size: 80%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prevent `sub` and `sup` affecting `line-height` in all browsers.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
sub,
 | 
			
		||||
sup {
 | 
			
		||||
    font-size: 75%;
 | 
			
		||||
    line-height: 0;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    vertical-align: baseline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sup {
 | 
			
		||||
    top: -0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub {
 | 
			
		||||
    bottom: -0.25em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Embedded content
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove border when inside `a` element in IE 8/9/10.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
img {
 | 
			
		||||
    border: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Correct overflow not hidden in IE 9/10/11.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
svg:not(:root) {
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Grouping content
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address margin not present in IE 8/9 and Safari.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
figure {
 | 
			
		||||
    margin: 1em 40px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address differences between Firefox and other browsers.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
hr {
 | 
			
		||||
    box-sizing: content-box;
 | 
			
		||||
    height: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Contain overflow in all browsers.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
pre {
 | 
			
		||||
    overflow: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address odd `em`-unit font size rendering in all browsers.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
code,
 | 
			
		||||
kbd,
 | 
			
		||||
pre,
 | 
			
		||||
samp {
 | 
			
		||||
    font-family: monospace, monospace;
 | 
			
		||||
    font-size: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Forms
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Known limitation: by default, Chrome and Safari on OS X allow very limited
 | 
			
		||||
 * styling of `select`, unless a `border` property is set.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 1. Correct color not being inherited.
 | 
			
		||||
 *    Known issue: affects color of disabled elements.
 | 
			
		||||
 * 2. Correct font properties not being inherited.
 | 
			
		||||
 * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
button,
 | 
			
		||||
input,
 | 
			
		||||
optgroup,
 | 
			
		||||
select,
 | 
			
		||||
textarea {
 | 
			
		||||
    color: inherit; /* 1 */
 | 
			
		||||
    font: inherit; /* 2 */
 | 
			
		||||
    margin: 0; /* 3 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address `overflow` set to `hidden` in IE 8/9/10/11.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
button {
 | 
			
		||||
    overflow: visible;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address inconsistent `text-transform` inheritance for `button` and `select`.
 | 
			
		||||
 * All other form control elements do not inherit `text-transform` values.
 | 
			
		||||
 * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
 | 
			
		||||
 * Correct `select` style inheritance in Firefox.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
button,
 | 
			
		||||
select {
 | 
			
		||||
    text-transform: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
 | 
			
		||||
 *    and `video` controls.
 | 
			
		||||
 * 2. Correct inability to style clickable `input` types in iOS.
 | 
			
		||||
 * 3. Improve usability and consistency of cursor style between image-type
 | 
			
		||||
 *    `input` and others.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
button,
 | 
			
		||||
html input[type="button"], /* 1 */
 | 
			
		||||
input[type="reset"],
 | 
			
		||||
input[type="submit"] {
 | 
			
		||||
    -webkit-appearance: button; /* 2 */
 | 
			
		||||
    cursor: pointer; /* 3 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Re-set default cursor for disabled elements.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
button[disabled],
 | 
			
		||||
html input[disabled] {
 | 
			
		||||
    cursor: default;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove inner padding and border in Firefox 4+.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
button::-moz-focus-inner,
 | 
			
		||||
input::-moz-focus-inner {
 | 
			
		||||
    border: 0;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Address Firefox 4+ setting `line-height` on `input` using `!important` in
 | 
			
		||||
 * the UA stylesheet.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
input {
 | 
			
		||||
    line-height: normal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * It's recommended that you don't attempt to style these elements.
 | 
			
		||||
 * Firefox's implementation doesn't respect box-sizing, padding, or width.
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Address box sizing set to `content-box` in IE 8/9/10.
 | 
			
		||||
 * 2. Remove excess padding in IE 8/9/10.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
input[type="checkbox"],
 | 
			
		||||
input[type="radio"] {
 | 
			
		||||
    box-sizing: border-box; /* 1 */
 | 
			
		||||
    padding: 0; /* 2 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Fix the cursor style for Chrome's increment/decrement buttons. For certain
 | 
			
		||||
 * `font-size` values of the `input`, it causes the cursor style of the
 | 
			
		||||
 * decrement button to change from `default` to `text`.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
input[type="number"]::-webkit-inner-spin-button,
 | 
			
		||||
input[type="number"]::-webkit-outer-spin-button {
 | 
			
		||||
    height: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
 | 
			
		||||
 * 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
input[type="search"] {
 | 
			
		||||
    -webkit-appearance: textfield; /* 1 */
 | 
			
		||||
    box-sizing: content-box; /* 2 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove inner padding and search cancel button in Safari and Chrome on OS X.
 | 
			
		||||
 * Safari (but not Chrome) clips the cancel button when the search input has
 | 
			
		||||
 * padding (and `textfield` appearance).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
input[type="search"]::-webkit-search-cancel-button,
 | 
			
		||||
input[type="search"]::-webkit-search-decoration {
 | 
			
		||||
    -webkit-appearance: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Define consistent border, margin, and padding.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
fieldset {
 | 
			
		||||
    border: 1px solid #c0c0c0;
 | 
			
		||||
    margin: 0 2px;
 | 
			
		||||
    padding: 0.35em 0.625em 0.75em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 1. Correct `color` not being inherited in IE 8/9/10/11.
 | 
			
		||||
 * 2. Remove padding so people aren't caught out if they zero out fieldsets.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
legend {
 | 
			
		||||
    border: 0; /* 1 */
 | 
			
		||||
    padding: 0; /* 2 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove default vertical scrollbar in IE 8/9/10/11.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
textarea {
 | 
			
		||||
    overflow: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Don't inherit the `font-weight` (applied by a rule above).
 | 
			
		||||
 * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
optgroup {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Tables
 | 
			
		||||
   ========================================================================== */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove most spacing between table cells.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
table {
 | 
			
		||||
    border-collapse: collapse;
 | 
			
		||||
    border-spacing: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
td,
 | 
			
		||||
th {
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 766 B  | 
@ -1,15 +0,0 @@
 | 
			
		||||
# humanstxt.org/
 | 
			
		||||
# The humans responsible & technology colophon
 | 
			
		||||
 | 
			
		||||
# TEAM
 | 
			
		||||
 | 
			
		||||
    <name> -- <role> -- <twitter>
 | 
			
		||||
 | 
			
		||||
# THANKS
 | 
			
		||||
 | 
			
		||||
    <name>
 | 
			
		||||
 | 
			
		||||
# TECHNOLOGY COLOPHON
 | 
			
		||||
 | 
			
		||||
    CSS3, HTML5
 | 
			
		||||
    Apache Server Configs, jQuery, Modernizr, Normalize.css
 | 
			
		||||
							
								
								
									
										0
									
								
								html/admin/img/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								html/admin/img/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,97 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html class="no-js" lang="">
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta charset="utf-8" />
 | 
			
		||||
        <meta http-equiv="x-ua-compatible" content="ie=edge" />
 | 
			
		||||
        <title></title>
 | 
			
		||||
        <meta name="description" content="" />
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1" />
 | 
			
		||||
 | 
			
		||||
        <link rel="apple-touch-icon" href="apple-touch-icon.png" />
 | 
			
		||||
        <!-- Place favicon.ico in the root directory -->
 | 
			
		||||
 | 
			
		||||
        <link rel="stylesheet" href="css/normalize.css" />
 | 
			
		||||
        <link rel="stylesheet" href="css/main.css" />
 | 
			
		||||
        <script src="js/vendor/modernizr-2.8.3.min.js"></script>
 | 
			
		||||
        <base href="/" />
 | 
			
		||||
    </head>
 | 
			
		||||
    <body ng-app="rvpnApp">
 | 
			
		||||
        <!--[if lt IE 8]>
 | 
			
		||||
            <p class="browserupgrade">
 | 
			
		||||
                You are using an <strong>outdated</strong> browser. Please
 | 
			
		||||
                <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.
 | 
			
		||||
            </p>
 | 
			
		||||
        <![endif]-->
 | 
			
		||||
 | 
			
		||||
        <!-- Admin GUI Begins Here -->
 | 
			
		||||
        <header class="bs-docs-nav navbar navbar-static-top" id="top">
 | 
			
		||||
            <div class="container">
 | 
			
		||||
                <div class="navbar-header">
 | 
			
		||||
                    <a href="/admin/index.html" target="_parent" class="navbar-brand">RVPN Admin</a>
 | 
			
		||||
                </div>
 | 
			
		||||
                <nav class="collapse navbar-collapse" id="bs-navbar">
 | 
			
		||||
                    <ul class="nav navbar-nav">
 | 
			
		||||
                        <li><a href="/admin/status">Status</a></li>
 | 
			
		||||
                        <li><a href="/admin/servers">Servers</a></li>
 | 
			
		||||
                        <li><a href="/admin/#domains">Domains</a></li>
 | 
			
		||||
                        <li><a href="/admin/#connections">Connections</a></li>
 | 
			
		||||
                    </ul>
 | 
			
		||||
 | 
			
		||||
                    <ul class="nav navbar-nav navbar-right">
 | 
			
		||||
                        <li><a href="#">Help</a></li>
 | 
			
		||||
                        <li><a href="#">Login</a></li>
 | 
			
		||||
                    </ul>
 | 
			
		||||
                </nav>
 | 
			
		||||
            </div>
 | 
			
		||||
        </header>
 | 
			
		||||
 | 
			
		||||
        <div ng-view></div>
 | 
			
		||||
 | 
			
		||||
        <script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
 | 
			
		||||
        <script>
 | 
			
		||||
            window.jQuery || document.write('<script src="admin/js/vendor/jquery-1.12.0.min.js"><\/script>');
 | 
			
		||||
        </script>
 | 
			
		||||
        <script src="admin/js/plugins.js"></script>
 | 
			
		||||
        <script src="admin/js/main.js"></script>
 | 
			
		||||
 | 
			
		||||
        <!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
 | 
			
		||||
        <script>
 | 
			
		||||
            (function (b, o, i, l, e, r) {
 | 
			
		||||
                b.GoogleAnalyticsObject = l;
 | 
			
		||||
                b[l] ||
 | 
			
		||||
                    (b[l] = function () {
 | 
			
		||||
                        (b[l].q = b[l].q || []).push(arguments);
 | 
			
		||||
                    });
 | 
			
		||||
                b[l].l = +new Date();
 | 
			
		||||
                e = o.createElement(i);
 | 
			
		||||
                r = o.getElementsByTagName(i)[0];
 | 
			
		||||
                e.src = "https://www.google-analytics.com/analytics.js";
 | 
			
		||||
                r.parentNode.insertBefore(e, r);
 | 
			
		||||
            })(window, document, "script", "ga");
 | 
			
		||||
            ga("create", "UA-XXXXX-X", "auto");
 | 
			
		||||
            ga("send", "pageview");
 | 
			
		||||
        </script>
 | 
			
		||||
    </body>
 | 
			
		||||
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
 | 
			
		||||
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
 | 
			
		||||
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-route.js"></script>
 | 
			
		||||
    <link
 | 
			
		||||
        rel="stylesheet"
 | 
			
		||||
        href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
 | 
			
		||||
        integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
 | 
			
		||||
        crossorigin="anonymous"
 | 
			
		||||
    />
 | 
			
		||||
    <link
 | 
			
		||||
        rel="stylesheet"
 | 
			
		||||
        href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
 | 
			
		||||
        integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
 | 
			
		||||
        crossorigin="anonymous"
 | 
			
		||||
    />
 | 
			
		||||
    <script
 | 
			
		||||
        src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
 | 
			
		||||
        integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
 | 
			
		||||
        crossorigin="anonymous"
 | 
			
		||||
    ></script>
 | 
			
		||||
    <script src="/admin/js/vendor/filter.js"></script>
 | 
			
		||||
    <script src="/admin/js/app.js"></script>
 | 
			
		||||
</html>
 | 
			
		||||
@ -1,129 +0,0 @@
 | 
			
		||||
console.log("app.sh startup");
 | 
			
		||||
 | 
			
		||||
var app = angular.module("rvpnApp", ["ngRoute", "angular-duration-format"]);
 | 
			
		||||
 | 
			
		||||
app.config(function ($routeProvider, $locationProvider) {
 | 
			
		||||
    $routeProvider
 | 
			
		||||
 | 
			
		||||
        .when("/admin/status/", {
 | 
			
		||||
            templateUrl: "admin/partials/status.html"
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        .when("/admin/index.html", {
 | 
			
		||||
            templateUrl: "admin/partials/servers.html"
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        .when("/admin/servers/", {
 | 
			
		||||
            templateUrl: "admin/partials/servers.html"
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        .when("/admin/#domains", {
 | 
			
		||||
            templateUrl: "green.htm"
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        .when("/blue", {
 | 
			
		||||
            templateUrl: "blue.htm"
 | 
			
		||||
        });
 | 
			
		||||
    $locationProvider.html5Mode(true);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.filter("bytes", function () {
 | 
			
		||||
    return function (bytes, precision) {
 | 
			
		||||
        if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return "-";
 | 
			
		||||
        if (typeof precision === "undefined") precision = 1;
 | 
			
		||||
        var units = ["bytes", "kB", "MB", "GB", "TB", "PB"],
 | 
			
		||||
            number = Math.floor(Math.log(bytes) / Math.log(1024));
 | 
			
		||||
        return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + " " + units[number];
 | 
			
		||||
    };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.filter("hfcduration", function () {
 | 
			
		||||
    return function (duration, precision) {
 | 
			
		||||
        remain = duration;
 | 
			
		||||
        duration_day = 24 * 60 * 60;
 | 
			
		||||
        duration_hour = 60 * 60;
 | 
			
		||||
        duration_minute = 60;
 | 
			
		||||
        duration_str = "";
 | 
			
		||||
 | 
			
		||||
        days = Math.floor(remain / duration_day);
 | 
			
		||||
        if (days > 0) {
 | 
			
		||||
            remain = remain - days * duration_day;
 | 
			
		||||
            duration_str = duration_str + days + "d";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        hours = Math.floor(remain / duration_hour);
 | 
			
		||||
        if (hours > 0) {
 | 
			
		||||
            remain = remain - hours * duration_hour;
 | 
			
		||||
            duration_str = duration_str + hours + "h";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mins = Math.floor(remain / duration_minute);
 | 
			
		||||
        if (mins > 0) {
 | 
			
		||||
            remain = remain - mins * duration_minute;
 | 
			
		||||
            duration_str = duration_str + mins + "m";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        secs = Math.floor(remain);
 | 
			
		||||
        duration_str = duration_str + secs + "s";
 | 
			
		||||
 | 
			
		||||
        return duration_str;
 | 
			
		||||
    };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.controller("statusController", function ($scope, $http) {
 | 
			
		||||
    console.log("statusController");
 | 
			
		||||
    $scope.status_search = "";
 | 
			
		||||
 | 
			
		||||
    var api = "/api/org.rootprojects.tunnel/status";
 | 
			
		||||
 | 
			
		||||
    $scope.updateView = function () {
 | 
			
		||||
        $http.get(api).then(function (response) {
 | 
			
		||||
            console.log(response);
 | 
			
		||||
            data = response.data;
 | 
			
		||||
            if (data.error == "ok") {
 | 
			
		||||
                $scope.status = data.result;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $scope.updateView();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.controller("serverController", function ($scope, $http) {
 | 
			
		||||
    $scope.servers = [];
 | 
			
		||||
    $scope.servers_search = "";
 | 
			
		||||
    $scope.servers_trigger_details = [];
 | 
			
		||||
    $scope.filtered;
 | 
			
		||||
 | 
			
		||||
    var api = "/api/org.rootprojects.tunnel/servers";
 | 
			
		||||
 | 
			
		||||
    $scope.updateView = function () {
 | 
			
		||||
        $http.get(api).then(function (response) {
 | 
			
		||||
            //console.log(response);
 | 
			
		||||
            data = response.data;
 | 
			
		||||
            if (data.error == "ok") {
 | 
			
		||||
                $scope.servers = data.result.servers;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $scope.triggerDetail = function (id) {
 | 
			
		||||
        //console.log("triggerDetail ", id, $scope.servers_trigger_details[id])
 | 
			
		||||
        if ($scope.servers_trigger_details[id] == true) {
 | 
			
		||||
            $scope.servers_trigger_details[id] = false;
 | 
			
		||||
        } else {
 | 
			
		||||
            $scope.servers_trigger_details[id] = true;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $scope.checkDetail = function (id) {
 | 
			
		||||
        //console.log("checkDetail ", id, $scope.servers_trigger_details[id])
 | 
			
		||||
        if ($scope.servers_trigger_details[id] == true) {
 | 
			
		||||
            return false;
 | 
			
		||||
        } else {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $scope.updateView();
 | 
			
		||||
});
 | 
			
		||||
@ -1,44 +0,0 @@
 | 
			
		||||
// Avoid `console` errors in browsers that lack a console.
 | 
			
		||||
(function () {
 | 
			
		||||
    var method;
 | 
			
		||||
    var noop = function () {};
 | 
			
		||||
    var methods = [
 | 
			
		||||
        "assert",
 | 
			
		||||
        "clear",
 | 
			
		||||
        "count",
 | 
			
		||||
        "debug",
 | 
			
		||||
        "dir",
 | 
			
		||||
        "dirxml",
 | 
			
		||||
        "error",
 | 
			
		||||
        "exception",
 | 
			
		||||
        "group",
 | 
			
		||||
        "groupCollapsed",
 | 
			
		||||
        "groupEnd",
 | 
			
		||||
        "info",
 | 
			
		||||
        "log",
 | 
			
		||||
        "markTimeline",
 | 
			
		||||
        "profile",
 | 
			
		||||
        "profileEnd",
 | 
			
		||||
        "table",
 | 
			
		||||
        "time",
 | 
			
		||||
        "timeEnd",
 | 
			
		||||
        "timeline",
 | 
			
		||||
        "timelineEnd",
 | 
			
		||||
        "timeStamp",
 | 
			
		||||
        "trace",
 | 
			
		||||
        "warn"
 | 
			
		||||
    ];
 | 
			
		||||
    var length = methods.length;
 | 
			
		||||
    var console = (window.console = window.console || {});
 | 
			
		||||
 | 
			
		||||
    while (length--) {
 | 
			
		||||
        method = methods[length];
 | 
			
		||||
 | 
			
		||||
        // Only stub undefined methods.
 | 
			
		||||
        if (!console[method]) {
 | 
			
		||||
            console[method] = noop;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
// Place any jQuery/helper plugins in here.
 | 
			
		||||
							
								
								
									
										165
									
								
								html/admin/js/vendor/filter.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										165
									
								
								html/admin/js/vendor/filter.js
									
									
									
									
										vendored
									
									
								
							@ -1,165 +0,0 @@
 | 
			
		||||
// ### filter.js >>
 | 
			
		||||
 | 
			
		||||
angular.module("angular-duration-format.filter", []).filter("duration", function () {
 | 
			
		||||
    var DURATION_FORMATS_SPLIT = /((?:[^ydhms']+)|(?:'(?:[^']|'')*')|(?:y+|d+|h+|m+|s+))(.*)/;
 | 
			
		||||
    var DURATION_FORMATS = {
 | 
			
		||||
        y: {
 | 
			
		||||
            // years
 | 
			
		||||
            // "longer" years are not supported
 | 
			
		||||
            value: 365 * 24 * 60 * 60 * 1000
 | 
			
		||||
        },
 | 
			
		||||
        yy: {
 | 
			
		||||
            value: "y",
 | 
			
		||||
            pad: 2
 | 
			
		||||
        },
 | 
			
		||||
        d: {
 | 
			
		||||
            // days
 | 
			
		||||
            value: 24 * 60 * 60 * 1000
 | 
			
		||||
        },
 | 
			
		||||
        dd: {
 | 
			
		||||
            value: "d",
 | 
			
		||||
            pad: 2
 | 
			
		||||
        },
 | 
			
		||||
        h: {
 | 
			
		||||
            // hours
 | 
			
		||||
            value: 60 * 60 * 1000
 | 
			
		||||
        },
 | 
			
		||||
        hh: {
 | 
			
		||||
            // padded hours
 | 
			
		||||
            value: "h",
 | 
			
		||||
            pad: 2
 | 
			
		||||
        },
 | 
			
		||||
        m: {
 | 
			
		||||
            // minutes
 | 
			
		||||
            value: 60 * 1000
 | 
			
		||||
        },
 | 
			
		||||
        mm: {
 | 
			
		||||
            // padded minutes
 | 
			
		||||
            value: "m",
 | 
			
		||||
            pad: 2
 | 
			
		||||
        },
 | 
			
		||||
        s: {
 | 
			
		||||
            // seconds
 | 
			
		||||
            value: 1000
 | 
			
		||||
        },
 | 
			
		||||
        ss: {
 | 
			
		||||
            // padded seconds
 | 
			
		||||
            value: "s",
 | 
			
		||||
            pad: 2
 | 
			
		||||
        },
 | 
			
		||||
        sss: {
 | 
			
		||||
            // milliseconds
 | 
			
		||||
            value: 1
 | 
			
		||||
        },
 | 
			
		||||
        ssss: {
 | 
			
		||||
            // padded milliseconds
 | 
			
		||||
            value: "sss",
 | 
			
		||||
            pad: 4
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function _parseFormat(string) {
 | 
			
		||||
        // @inspiration AngularJS date filter
 | 
			
		||||
        var parts = [];
 | 
			
		||||
        var format = string ? string.toString() : "";
 | 
			
		||||
 | 
			
		||||
        while (format) {
 | 
			
		||||
            var match = DURATION_FORMATS_SPLIT.exec(format);
 | 
			
		||||
 | 
			
		||||
            if (match) {
 | 
			
		||||
                parts = parts.concat(match.slice(1));
 | 
			
		||||
 | 
			
		||||
                format = parts.pop();
 | 
			
		||||
            } else {
 | 
			
		||||
                parts.push(format);
 | 
			
		||||
 | 
			
		||||
                format = null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return parts;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _formatDuration(timestamp, format) {
 | 
			
		||||
        var text = "";
 | 
			
		||||
        var values = {};
 | 
			
		||||
 | 
			
		||||
        format
 | 
			
		||||
            .filter(function (format) {
 | 
			
		||||
                // filter only value parts of format
 | 
			
		||||
                return DURATION_FORMATS.hasOwnProperty(format);
 | 
			
		||||
            })
 | 
			
		||||
            .map(function (format) {
 | 
			
		||||
                // get formats with values only
 | 
			
		||||
                var config = DURATION_FORMATS[format];
 | 
			
		||||
 | 
			
		||||
                if (config.hasOwnProperty("pad")) {
 | 
			
		||||
                    return config.value;
 | 
			
		||||
                } else {
 | 
			
		||||
                    return format;
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            .filter(function (format, index, arr) {
 | 
			
		||||
                // remove duplicates
 | 
			
		||||
                return arr.indexOf(format) === index;
 | 
			
		||||
            })
 | 
			
		||||
            .map(function (format) {
 | 
			
		||||
                // get format configurations with values
 | 
			
		||||
                return angular.extend(
 | 
			
		||||
                    {
 | 
			
		||||
                        name: format
 | 
			
		||||
                    },
 | 
			
		||||
                    DURATION_FORMATS[format]
 | 
			
		||||
                );
 | 
			
		||||
            })
 | 
			
		||||
            .sort(function (a, b) {
 | 
			
		||||
                // sort formats descending by value
 | 
			
		||||
                return b.value - a.value;
 | 
			
		||||
            })
 | 
			
		||||
            .forEach(function (format) {
 | 
			
		||||
                // create values for format parts
 | 
			
		||||
                var value = (values[format.name] = Math.floor(timestamp / format.value));
 | 
			
		||||
 | 
			
		||||
                timestamp = timestamp - value * format.value;
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        format.forEach(function (part) {
 | 
			
		||||
            var format = DURATION_FORMATS[part];
 | 
			
		||||
 | 
			
		||||
            if (format) {
 | 
			
		||||
                var value = values[format.value];
 | 
			
		||||
 | 
			
		||||
                text += format.hasOwnProperty("pad")
 | 
			
		||||
                    ? _padNumber(value, Math.max(format.pad, value.toString().length))
 | 
			
		||||
                    : values[part];
 | 
			
		||||
            } else {
 | 
			
		||||
                text += part.replace(/(^'|'$)/g, "").replace(/''/g, "'");
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return text;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _padNumber(number, len) {
 | 
			
		||||
        return (new Array(len + 1).join("0") + number).slice(-len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return function (value, format) {
 | 
			
		||||
        var parsedValue = parseFloat(value, 10);
 | 
			
		||||
        var parsedFormat = _parseFormat(format);
 | 
			
		||||
 | 
			
		||||
        if (isNaN(parsedValue) || parsedFormat.length === 0) {
 | 
			
		||||
            return value;
 | 
			
		||||
        } else {
 | 
			
		||||
            return _formatDuration(parsedValue, parsedFormat);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// ### << filter.js
 | 
			
		||||
 | 
			
		||||
// ### main.js >>
 | 
			
		||||
 | 
			
		||||
angular.module("angular-duration-format", ["angular-duration-format.filter"]);
 | 
			
		||||
 | 
			
		||||
// ### << main.js
 | 
			
		||||
							
								
								
									
										5
									
								
								html/admin/js/vendor/jquery-1.12.0.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								html/admin/js/vendor/jquery-1.12.0.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										4
									
								
								html/admin/js/vendor/modernizr-2.8.3.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								html/admin/js/vendor/modernizr-2.8.3.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -1,98 +0,0 @@
 | 
			
		||||
<div class="panel panel-default" data-ng-controller="serverController">
 | 
			
		||||
    <div class="panel-heading">
 | 
			
		||||
        <div class="panel-title">
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                <div class="col-md-6">
 | 
			
		||||
                    Servers
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="col-md-6">
 | 
			
		||||
                    <form class="form-inline pull-right">
 | 
			
		||||
                        <div class="form-group">
 | 
			
		||||
                            <label for="search">Search:</label>
 | 
			
		||||
                            <input type="text" class="form-control" id="search" data-ng-model="servers_search" />
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <button type="button" title="Refresh" class="btn btn-default" aria-label="Refresh">
 | 
			
		||||
                            <span
 | 
			
		||||
                                class="glyphicon glyphicon-refresh"
 | 
			
		||||
                                title="Refresh"
 | 
			
		||||
                                aria-hidden="false"
 | 
			
		||||
                                ng-click="updateView()"
 | 
			
		||||
                            ></span>
 | 
			
		||||
                        </button>
 | 
			
		||||
                    </form>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="panel-body">
 | 
			
		||||
        <table class="table table-striped table-bordered">
 | 
			
		||||
            <th width="3%">ID</th>
 | 
			
		||||
            <th width="10%">Name</th>
 | 
			
		||||
            <th width="10%">Address</th>
 | 
			
		||||
            <th width="10%">Xfer (in/out)</th>
 | 
			
		||||
            <th width="10%">Req/Resp</th>
 | 
			
		||||
            <th width="5%">Duration</th>
 | 
			
		||||
            <th width="5%">State</th>
 | 
			
		||||
            <th width="5%">Idle</th>
 | 
			
		||||
            <th width="1%">
 | 
			
		||||
                <center><span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span></center>
 | 
			
		||||
            </th>
 | 
			
		||||
 | 
			
		||||
            <tr ng-repeat="s in servers | filter:servers_search | orderBy:'server_id'">
 | 
			
		||||
                <td>{{ s.server_id }}</td>
 | 
			
		||||
                <td>{{ s.server_name }}</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    {{ s.source_address }}
 | 
			
		||||
                    <div ng-hide="checkDetail(s.server_id)">
 | 
			
		||||
                        domains({{ s.domains.length}})
 | 
			
		||||
                        <div ng-repeat="d in s.domains | orderBy:'domain_name'">
 | 
			
		||||
                               {{ d.domain_name }}
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    {{ s.bytes_in | bytes }}/{{ s.bytes_out | bytes }}
 | 
			
		||||
                    <div ng-hide="checkDetail(s.server_id)">
 | 
			
		||||
                         
 | 
			
		||||
                        <div ng-repeat="d in s.domains | orderBy:'domain_name'">
 | 
			
		||||
                               {{ d.bytes_in | bytes }}/{{ d.bytes_out | bytes }}
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    {{ s.requests }}/{{ s.responses }}
 | 
			
		||||
                    <div ng-hide="checkDetail(s.server_id)">
 | 
			
		||||
                         
 | 
			
		||||
                        <div ng-repeat="d in s.domains | orderBy:'domain_name'">
 | 
			
		||||
                               {{ d.requests }}/{{ d.responses }}
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </td>
 | 
			
		||||
 | 
			
		||||
                <td>{{ s.duration | hfcduration }}</td>
 | 
			
		||||
                <td>{{ s.server_state }}</td>
 | 
			
		||||
                <td>{{ s.idle | hfcduration }}</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <span
 | 
			
		||||
                        class="glyphicon glyphicon-zoom-in"
 | 
			
		||||
                        title="Detail"
 | 
			
		||||
                        aria-hidden="false"
 | 
			
		||||
                        ng-click="triggerDetail(s.server_id)"
 | 
			
		||||
                    ></span>
 | 
			
		||||
                    <div ng-hide="checkDetail(s.server_id)">
 | 
			
		||||
                         
 | 
			
		||||
                        <div ng-repeat="d in s.domains | orderBy:'domain_name'">
 | 
			
		||||
                            <span
 | 
			
		||||
                                class="glyphicon glyphicon-zoom-in"
 | 
			
		||||
                                title="Detail"
 | 
			
		||||
                                aria-hidden="false"
 | 
			
		||||
                                ng-click="triggerDetail(s.server_id+d.domain_name)"
 | 
			
		||||
                            ></span>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </table>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
@ -1,52 +0,0 @@
 | 
			
		||||
<div class="panel panel-default" data-ng-controller="statusController">
 | 
			
		||||
    <div class="panel-heading">
 | 
			
		||||
        <div class="panel-title">
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                <div class="col-md-6">
 | 
			
		||||
                    Status
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="col-md-6">
 | 
			
		||||
                    <form class="form-inline pull-right">
 | 
			
		||||
                        <div class="form-group">
 | 
			
		||||
                            <label for="search">Search:</label>
 | 
			
		||||
                            <input type="text" class="form-control" id="search" data-ng-model="servers_search" />
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <button type="button" title="Refresh" class="btn btn-default" aria-label="Refresh">
 | 
			
		||||
                            <span
 | 
			
		||||
                                class="glyphicon glyphicon-refresh"
 | 
			
		||||
                                title="Refresh"
 | 
			
		||||
                                aria-hidden="false"
 | 
			
		||||
                                ng-click="updateView()"
 | 
			
		||||
                            ></span>
 | 
			
		||||
                        </button>
 | 
			
		||||
                    </form>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="panel-body">
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-md-4"></div>
 | 
			
		||||
            <div class="col-md-8">Server Name: {{ status.name }} (Uptime: {{ status.uptime | hfcduration }}</div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-md-4"></div>
 | 
			
		||||
            <div class="col-md-8">Administrative Domain: {{ status.admin_domain }}</div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-md-4"></div>
 | 
			
		||||
            <div class="col-md-8">Server Domain: {{ status.wss_domain }}</div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-md-4"></div>
 | 
			
		||||
            <div class="col-md-8">Default LB Method: {{ status.loadbalance_default_method }}</div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-md-4"></div>
 | 
			
		||||
            <div class="col-md-8">
 | 
			
		||||
                Deadtime: dwell:{{ status.dead_time.dwell}} idle:{{ status.dead_time.idle}} cancel:{{
 | 
			
		||||
                status.dead_time.cancel_check}}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
# www.robotstxt.org/
 | 
			
		||||
 | 
			
		||||
# Allow crawling of all content
 | 
			
		||||
User-agent: *
 | 
			
		||||
Disallow:
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 1.8 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 3.4 KiB  | 
@ -7,9 +7,9 @@ import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	telebit "git.rootprojects.org/root/telebit"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/telebit"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type SuccessResponse struct {
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,8 @@ import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
 | 
			
		||||
	jwt "github.com/dgrijalva/jwt-go"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/files"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/assets/files"
 | 
			
		||||
 | 
			
		||||
	"github.com/jmoiron/sqlx"
 | 
			
		||||
	// pq injects itself into sql as 'postgres'
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/mgmt/authstore"
 | 
			
		||||
 | 
			
		||||
	"github.com/dgrijalva/jwt-go"
 | 
			
		||||
 | 
			
		||||
@ -13,17 +13,15 @@ import (
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/admin"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/table"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/assets/admin"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
 | 
			
		||||
	"github.com/go-chi/chi"
 | 
			
		||||
	"github.com/go-chi/chi/middleware"
 | 
			
		||||
	"github.com/gorilla/websocket"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var authorizer telebit.Authorizer
 | 
			
		||||
var authorizer Authorizer
 | 
			
		||||
 | 
			
		||||
// RouteAdmin sets up the API, including the Mgmt proxy and ACME relay
 | 
			
		||||
func RouteAdmin(authURL string, r chi.Router) {
 | 
			
		||||
@ -134,7 +132,7 @@ type SubscriberStatus struct {
 | 
			
		||||
 | 
			
		||||
func getAllSubscribers(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	statuses := []*SubscriberStatus{}
 | 
			
		||||
	table.Servers.Range(func(key, value interface{}) bool {
 | 
			
		||||
	Servers.Range(func(key, value interface{}) bool {
 | 
			
		||||
		srvMap := value.(*sync.Map)
 | 
			
		||||
		status := getSubscribersHelper(srvMap)
 | 
			
		||||
		statuses = append(statuses, status)
 | 
			
		||||
@ -160,7 +158,7 @@ func getSubscribers(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var srvMap *sync.Map
 | 
			
		||||
	srvMapX, ok := table.Servers.Load(subject)
 | 
			
		||||
	srvMapX, ok := Servers.Load(subject)
 | 
			
		||||
	if ok {
 | 
			
		||||
		srvMap = srvMapX.(*sync.Map)
 | 
			
		||||
		statuses.Subscribers = append(statuses.Subscribers, getSubscribersHelper(srvMap))
 | 
			
		||||
@ -179,7 +177,7 @@ func getSubscribersHelper(srvMap *sync.Map) *SubscriberStatus {
 | 
			
		||||
 | 
			
		||||
	srvMap.Range(func(k, v interface{}) bool {
 | 
			
		||||
		status.Sockets = append(status.Sockets, k.(string))
 | 
			
		||||
		srv := v.(*table.SubscriberConn)
 | 
			
		||||
		srv := v.(*SubscriberConn)
 | 
			
		||||
		if nil == status.Since || srv.Since.Sub(*status.Since) < 0 {
 | 
			
		||||
			copied := srv.Since.Truncate(time.Second)
 | 
			
		||||
			status.Since = &copied
 | 
			
		||||
@ -199,7 +197,7 @@ func getSubscribersHelper(srvMap *sync.Map) *SubscriberStatus {
 | 
			
		||||
func delSubscribers(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	subject := chi.URLParam(r, "subject")
 | 
			
		||||
 | 
			
		||||
	ok := table.Remove(subject)
 | 
			
		||||
	ok := Remove(subject)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		// TODO should this be an error?
 | 
			
		||||
		_ = json.NewEncoder(w).Encode(&struct {
 | 
			
		||||
@ -243,7 +241,7 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wsTun := telebit.NewWebsocketTunnel(conn)
 | 
			
		||||
	wsTun := NewWebsocketTunnel(conn)
 | 
			
		||||
	fmt.Printf("New Authenticated WebSocket Remote Server\n")
 | 
			
		||||
	fmt.Printf("\thttp.req.RemoteAddr: %+v\n", r.RemoteAddr)
 | 
			
		||||
	fmt.Printf("\tconn.RemoteAddr(): %+v\n", conn.RemoteAddr())
 | 
			
		||||
@ -255,15 +253,15 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	// Rather the client's local address (the specific relay server) would be more useful.
 | 
			
		||||
	ctxEncoder, cancelEncoder := context.WithCancel(context.Background())
 | 
			
		||||
	now := time.Now()
 | 
			
		||||
	server := &table.SubscriberConn{
 | 
			
		||||
	server := &SubscriberConn{
 | 
			
		||||
		Since:        &now,
 | 
			
		||||
		RemoteAddr:   r.RemoteAddr,
 | 
			
		||||
		WSConn:       conn,
 | 
			
		||||
		WSTun:        wsTun,
 | 
			
		||||
		Grants:       grants,
 | 
			
		||||
		Clients:      &sync.Map{},
 | 
			
		||||
		MultiEncoder: telebit.NewEncoder(ctxEncoder, wsTun),
 | 
			
		||||
		MultiDecoder: telebit.NewDecoder(wsTun),
 | 
			
		||||
		MultiEncoder: NewEncoder(ctxEncoder, wsTun),
 | 
			
		||||
		MultiDecoder: NewDecoder(wsTun),
 | 
			
		||||
	}
 | 
			
		||||
	// TODO should this happen at NewEncoder()?
 | 
			
		||||
	// (or is it even necessary anymore?)
 | 
			
		||||
@ -283,8 +281,8 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		fmt.Printf("a subscriber stream is done: %q\n", err)
 | 
			
		||||
		// TODO check what happens when we leave a junk connection
 | 
			
		||||
		//fmt.Println("[debug] [warn] removing server turned off")
 | 
			
		||||
		table.RemoveServer(server)
 | 
			
		||||
		RemoveServer(server)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	table.Add(server)
 | 
			
		||||
	Add(server)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,12 +4,10 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewAuthorizer(authURL string) telebit.Authorizer {
 | 
			
		||||
	return func(r *http.Request) (*telebit.Grants, error) {
 | 
			
		||||
func NewAuthorizer(authURL string) Authorizer {
 | 
			
		||||
	return func(r *http.Request) (*Grants, error) {
 | 
			
		||||
		// do we have a valid wss_client?
 | 
			
		||||
 | 
			
		||||
		fmt.Printf("[authz] Authorization = %s\n", r.Header.Get("Authorization"))
 | 
			
		||||
@ -28,7 +26,7 @@ func NewAuthorizer(authURL string) telebit.Authorizer {
 | 
			
		||||
 | 
			
		||||
		fmt.Printf("[authz] authURL = %s\n", authURL)
 | 
			
		||||
		fmt.Printf("[authz] token = %s\n", tokenString)
 | 
			
		||||
		grants, err := telebit.Inspect(authURL, tokenString)
 | 
			
		||||
		grants, err := Inspect(authURL, tokenString)
 | 
			
		||||
 | 
			
		||||
		if nil != err {
 | 
			
		||||
			fmt.Printf("[authorizer] error inspecting %q: %s\ntoken: %s\n", authURL, err, tokenString)
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,8 @@ import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/sni"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/sni"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ConnWrap is just a cheap way to DRY up some switch conn.(type) statements to handle special features of Conn
 | 
			
		||||
@ -5,7 +5,7 @@ import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Decoder handles a Reader stream containing mplexy-encoded clients
 | 
			
		||||
@ -9,7 +9,7 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TODO: try to be more like encoding/csv, or more like encoding/pem and encoding/json?
 | 
			
		||||
@ -9,7 +9,7 @@ import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A Listener transforms a multiplexed websocket connection into individual net.Conn-like connections.
 | 
			
		||||
@ -5,7 +5,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Parser struct {
 | 
			
		||||
@ -9,7 +9,7 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A RouteMux is a net.Conn multiplexer.
 | 
			
		||||
@ -1,18 +1,17 @@
 | 
			
		||||
package table
 | 
			
		||||
package telebit
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"io"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
 | 
			
		||||
	telebit "git.rootprojects.org/root/telebit"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"github.com/gorilla/websocket"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -108,18 +107,18 @@ type SubscriberConn struct {
 | 
			
		||||
	Since      *time.Time
 | 
			
		||||
	RemoteAddr string
 | 
			
		||||
	WSConn     *websocket.Conn
 | 
			
		||||
	WSTun      net.Conn // *telebit.WebsocketTunnel
 | 
			
		||||
	Grants     *telebit.Grants
 | 
			
		||||
	WSTun      net.Conn // *WebsocketTunnel
 | 
			
		||||
	Grants     *Grants
 | 
			
		||||
	Clients    *sync.Map
 | 
			
		||||
 | 
			
		||||
	// TODO is this the right codec type?
 | 
			
		||||
	MultiEncoder *telebit.Encoder
 | 
			
		||||
	MultiDecoder *telebit.Decoder
 | 
			
		||||
	MultiEncoder *Encoder
 | 
			
		||||
	MultiDecoder *Decoder
 | 
			
		||||
 | 
			
		||||
	// to fulfill Router interface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SubscriberConn) RouteBytes(src, dst telebit.Addr, payload []byte) {
 | 
			
		||||
func (s *SubscriberConn) RouteBytes(src, dst Addr, payload []byte) {
 | 
			
		||||
	id := fmt.Sprintf("%s:%d", src.Hostname(), src.Port())
 | 
			
		||||
	if dbg.Debug {
 | 
			
		||||
		fmt.Fprintf(
 | 
			
		||||
@ -163,9 +162,9 @@ func (s *SubscriberConn) RouteBytes(src, dst telebit.Addr, payload []byte) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SubscriberConn) Serve(client net.Conn) error {
 | 
			
		||||
	var wconn *telebit.ConnWrap
 | 
			
		||||
	var wconn *ConnWrap
 | 
			
		||||
	switch conn := client.(type) {
 | 
			
		||||
	case *telebit.ConnWrap:
 | 
			
		||||
	case *ConnWrap:
 | 
			
		||||
		wconn = conn
 | 
			
		||||
	default:
 | 
			
		||||
		// this probably isn't strictly necessary
 | 
			
		||||
@ -201,27 +200,27 @@ func (s *SubscriberConn) Serve(client net.Conn) error {
 | 
			
		||||
 | 
			
		||||
	servername := wconn.Servername()
 | 
			
		||||
 | 
			
		||||
	termination := telebit.Unknown
 | 
			
		||||
	scheme := telebit.None
 | 
			
		||||
	termination := Unknown
 | 
			
		||||
	scheme := None
 | 
			
		||||
	if "" != servername {
 | 
			
		||||
		dstAddr = servername
 | 
			
		||||
		//scheme = telebit.TLS
 | 
			
		||||
		scheme = telebit.HTTPS
 | 
			
		||||
		//scheme = TLS
 | 
			
		||||
		scheme = HTTPS
 | 
			
		||||
	}
 | 
			
		||||
	if 80 == dstPort {
 | 
			
		||||
		scheme = telebit.HTTPS
 | 
			
		||||
		scheme = HTTPS
 | 
			
		||||
	} else if 443 == dstPort {
 | 
			
		||||
		// TODO dstAddr = wconn.Servername()
 | 
			
		||||
		scheme = telebit.HTTP
 | 
			
		||||
		scheme = HTTP
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	src := telebit.NewAddr(
 | 
			
		||||
	src := NewAddr(
 | 
			
		||||
		scheme,
 | 
			
		||||
		termination,
 | 
			
		||||
		srcAddr,
 | 
			
		||||
		srcPort,
 | 
			
		||||
	)
 | 
			
		||||
	dst := telebit.NewAddr(
 | 
			
		||||
	dst := NewAddr(
 | 
			
		||||
		scheme,
 | 
			
		||||
		termination,
 | 
			
		||||
		dstAddr,
 | 
			
		||||
@ -16,8 +16,8 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	httpshim "git.rootprojects.org/root/telebit/tunnel"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
	httpshim "git.rootprojects.org/root/telebit/internal/tunnel"
 | 
			
		||||
 | 
			
		||||
	"github.com/coolaj86/certmagic"
 | 
			
		||||
	"github.com/mholt/acmez"
 | 
			
		||||
@ -7,7 +7,7 @@ import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@ -10,7 +10,7 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.rootprojects.org/root/telebit/dbg"
 | 
			
		||||
	"git.rootprojects.org/root/telebit/internal/dbg"
 | 
			
		||||
 | 
			
		||||
	"github.com/gorilla/websocket"
 | 
			
		||||
)
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
TOKEN=$(go run cmd/signjwt/*.go)
 | 
			
		||||
echo "TOKEN: $TOKEN"
 | 
			
		||||
 | 
			
		||||
echo "Active:"
 | 
			
		||||
curl -L http://localhost:3000/api/devices -H "Authorization: Bearer ${TOKEN}"
 | 
			
		||||
 | 
			
		||||
echo "Inactive:"
 | 
			
		||||
curl -L http://localhost:3000/api/devices?inactive=true -H "Authorization: Bearer ${TOKEN}"
 | 
			
		||||
							
								
								
									
										43
									
								
								mgmt.sh
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								mgmt.sh
									
									
									
									
									
								
							@ -1,43 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
set -u
 | 
			
		||||
 | 
			
		||||
# 1. (srv) create a new shared key for a given slug
 | 
			
		||||
# 2. (dev) try to update via ping
 | 
			
		||||
# 3. (dev) use key to exchange machine id
 | 
			
		||||
# 4. (dev) use key to connect to remote
 | 
			
		||||
# 5. (dev) ping occasionally
 | 
			
		||||
 | 
			
		||||
TOKEN=$(go run cmd/signjwt/*.go)
 | 
			
		||||
echo "TOKEN: $TOKEN"
 | 
			
		||||
 | 
			
		||||
my_shared="ZR2rxYmcKJcmtKgmH9D5Qw"
 | 
			
		||||
my_domain="example.com"
 | 
			
		||||
my_client="1-client-slug"
 | 
			
		||||
TOK=$(curl -X POST http://localhost:3000/api/devices -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -d '{ "slug": "'$my_client'", "shared_key": "'$my_shared'" }')
 | 
			
		||||
echo Response: $TOK
 | 
			
		||||
 | 
			
		||||
SHARED=$(echo "$TOK" | sed 's/.*shared_key":"//g' | sed 's/".*//')
 | 
			
		||||
echo Shared Key: $SHARED
 | 
			
		||||
my_parts=$(go run cmd/signjwt/*.go $SHARED machineid)
 | 
			
		||||
my_ppid=$(echo $my_parts | cut -d' ' -f1)
 | 
			
		||||
my_keyid=$(echo $my_parts | cut -d' ' -f2)
 | 
			
		||||
echo "PPID: $my_ppid KeyID: $my_keyid"
 | 
			
		||||
 | 
			
		||||
TOKEN=$(go run cmd/signjwt/*.go $my_ppid)
 | 
			
		||||
echo "PING 1 (should fail)"
 | 
			
		||||
curl -X POST http://localhost:3000/api/ping  -H "Authorization: Bearer ${TOKEN}"
 | 
			
		||||
echo ""
 | 
			
		||||
 | 
			
		||||
curl -X POST http://localhost:3000/api/register-device/$SHARED -H "Content-Type: application/json" -d '{ "machine_ppid": "'$my_ppid'", "public_key": "'$my_keyid'" }'
 | 
			
		||||
echo ''
 | 
			
		||||
 | 
			
		||||
echo "PING 2 (should work)"
 | 
			
		||||
curl -X POST http://localhost:3000/api/ping  -H "Authorization: Bearer ${TOKEN}"
 | 
			
		||||
echo ""
 | 
			
		||||
 | 
			
		||||
curl -X POST http://localhost:3000/api/dns/"${my_client}.${my_domain}" \
 | 
			
		||||
    -H "Authorization: Bearer ${TOKEN}" \
 | 
			
		||||
    -H "Content-Type: application/json" \
 | 
			
		||||
    -d '{ "token": "xxxx", "key_authorization": "yyyy" }'
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user