github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/cmd/geph-client/stats.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/zip"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"os"
     9  	"runtime"
    10  	"runtime/pprof"
    11  	"strings"
    12  	"sync"
    13  	"sync/atomic"
    14  	"time"
    15  
    16  	"github.com/geph-official/geph2/libs/bdclient"
    17  	log "github.com/sirupsen/logrus"
    18  )
    19  
    20  type stats struct {
    21  	Connected bool
    22  	PublicIP  string
    23  	UpBytes   uint64
    24  	DownBytes uint64
    25  	MinPing   uint64
    26  	PingTime  time.Time
    27  	Username  string
    28  	Tier      string
    29  	PayTxes   []bdclient.PaymentTx
    30  	Expiry    time.Time
    31  	LogLines  []string
    32  	Bridges   map[string]int
    33  	//bridgeThunk func() []niaucchi4.LinkInfo
    34  
    35  	lock sync.Mutex
    36  }
    37  
    38  var statsCollector = &stats{}
    39  
    40  func useStats(f func(sc *stats)) {
    41  	statsCollector.lock.Lock()
    42  	defer statsCollector.lock.Unlock()
    43  	f(statsCollector)
    44  }
    45  
    46  func handleKill(w http.ResponseWriter, r *http.Request) {
    47  	log.Println("dying on command")
    48  	go func() {
    49  		time.Sleep(time.Millisecond * 100)
    50  		os.Exit(0)
    51  	}()
    52  }
    53  
    54  func handleStats(w http.ResponseWriter, r *http.Request) {
    55  	w.Header().Add("Access-Control-Allow-Origin", "*")
    56  	var bts []byte
    57  	useStats(func(sc *stats) {
    58  		sc.Bridges = make(map[string]int)
    59  		// bridges
    60  		if !direct {
    61  			trackerMap.Range(func(key, value interface{}) bool {
    62  				v := int(atomic.LoadInt64(value.(*int64)))
    63  				if v > 0 {
    64  					sc.Bridges[key.(string)] = v
    65  				}
    66  				return true
    67  			})
    68  		}
    69  		ll := sc.LogLines
    70  		sc.LogLines = nil
    71  		var err error
    72  		bts, err = json.Marshal(sc)
    73  		if err != nil {
    74  			panic(err)
    75  		}
    76  		sc.LogLines = ll
    77  	})
    78  	w.Header().Add("content-type", "application/json")
    79  	w.Write(bts)
    80  }
    81  
    82  func handleDebugPack(w http.ResponseWriter, r *http.Request) {
    83  	w.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=\"geph-logs-%v-%v.zip\"", username, time.Now().Format(time.RFC3339)))
    84  	w.Header().Add("content-type", "application/zip")
    85  	zwriter := zip.NewWriter(w)
    86  	defer zwriter.Close()
    87  	logFile, err := zwriter.Create("logs.txt")
    88  	if err != nil {
    89  		return
    90  	}
    91  	useStats(func(sc *stats) {
    92  		for _, line := range sc.LogLines {
    93  			fmt.Fprintln(logFile, line)
    94  		}
    95  	})
    96  	straceFile, err := zwriter.Create("stacktrace.txt")
    97  	if err != nil {
    98  		return
    99  	}
   100  	buf := make([]byte, 8192)
   101  	for {
   102  		n := runtime.Stack(buf, true)
   103  		if n < len(buf) {
   104  			buf = buf[:n]
   105  			break
   106  		}
   107  		buf = append(buf, buf...)
   108  	}
   109  	straceFile.Write(buf)
   110  	heapprofFile, err := zwriter.Create("heap.pprof")
   111  	pprof.WriteHeapProfile(heapprofFile)
   112  }
   113  
   114  func handleLogs(w http.ResponseWriter, r *http.Request) {
   115  	w.Header().Add("Access-Control-Allow-Origin", "*")
   116  	var bts []byte
   117  	useStats(func(sc *stats) {
   118  		for _, line := range sc.LogLines {
   119  			fmt.Fprintln(w, line)
   120  		}
   121  	})
   122  	w.Header().Add("content-type", "text/plain")
   123  	w.Write(bts)
   124  }
   125  
   126  func handleProxyPac(w http.ResponseWriter, r *http.Request) {
   127  	w.Write([]byte(fmt.Sprintf(`function FindProxyForURL(url, host)
   128  	{
   129  		return "PROXY %v";
   130  	}
   131  	`, strings.Replace(httpAddr, strings.Split(httpAddr, ":")[0], "localhost", -1))))
   132  }
   133  
   134  func handleStacktrace(w http.ResponseWriter, r *http.Request) {
   135  	buf := make([]byte, 8192)
   136  	for {
   137  		n := runtime.Stack(buf, true)
   138  		if n < len(buf) {
   139  			buf = buf[:n]
   140  			break
   141  		}
   142  		buf = append(buf, buf...)
   143  	}
   144  	w.Write(buf)
   145  }