| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 | 
							- package dashboard
 
- import (
 
- 	"math/rand"
 
- 	"net/http"
 
- 	"time"
 
- 	log "github.com/Sirupsen/logrus"
 
- 	_ "github.com/flashmob/go-guerrilla/dashboard/statik"
 
- 	"github.com/gorilla/mux"
 
- 	"github.com/gorilla/websocket"
 
- 	"github.com/rakyll/statik/fs"
 
- )
 
- var (
 
- 	config   *Config
 
- 	sessions map[string]*session
 
- )
 
- var upgrader = websocket.Upgrader{
 
- 	ReadBufferSize:  1024,
 
- 	WriteBufferSize: 1024,
 
- 	// TODO below for testing w/ webpack only, change before merging
 
- 	CheckOrigin: func(r *http.Request) bool { return true },
 
- }
 
- type Config struct {
 
- 	Enabled         bool   `json:"is_enabled"`
 
- 	ListenInterface string `json:"listen_interface"`
 
- 	// Interval at which we send measure and send dataframe to frontend
 
- 	TickInterval string `json:"tick_interval"`
 
- 	// Maximum interval for which we store data
 
- 	MaxWindow string `json:"max_window"`
 
- 	// Granularity for which rankings are aggregated
 
- 	RankingUpdateInterval string `json:"ranking_aggregation_interval"`
 
- 	// Determines at which ratio of unique HELOs to unique connections we
 
- 	// will stop collecting data to prevent memory exhaustion attack.
 
- 	// Number between 0-1, set to >1 if you never want to stop collecting data.
 
- 	// Default is 0.8
 
- 	UniqueHeloRatioMax float64 `json:"unique_helo_ratio"`
 
- }
 
- // Begin collecting data and listening for dashboard clients
 
- func Run(c *Config) {
 
- 	statikFS, _ := fs.New()
 
- 	applyConfig(c)
 
- 	sessions = map[string]*session{}
 
- 	r := mux.NewRouter()
 
- 	r.HandleFunc("/ws", webSocketHandler)
 
- 	r.PathPrefix("/").Handler(http.FileServer(statikFS))
 
- 	rand.Seed(time.Now().UnixNano())
 
- 	go dataListener(tickInterval)
 
- 	go store.rankingManager()
 
- 	err := http.ListenAndServe(c.ListenInterface, r)
 
- 	log.WithError(err).Error("Dashboard server failed to start")
 
- }
 
- // Parses options in config and applies to global variables
 
- func applyConfig(c *Config) {
 
- 	config = c
 
- 	if len(config.MaxWindow) > 0 {
 
- 		mw, err := time.ParseDuration(config.MaxWindow)
 
- 		if err == nil {
 
- 			maxWindow = mw
 
- 		}
 
- 	}
 
- 	if len(config.RankingUpdateInterval) > 0 {
 
- 		rui, err := time.ParseDuration(config.RankingUpdateInterval)
 
- 		if err == nil {
 
- 			rankingUpdateInterval = rui
 
- 		}
 
- 	}
 
- 	if len(config.TickInterval) > 0 {
 
- 		ti, err := time.ParseDuration(config.TickInterval)
 
- 		if err == nil {
 
- 			tickInterval = ti
 
- 		}
 
- 	}
 
- 	if config.UniqueHeloRatioMax > 0 {
 
- 		uniqueHeloRatioMax = config.UniqueHeloRatioMax
 
- 	}
 
- 	maxTicks = int(maxWindow * tickInterval)
 
- 	nRankingBuffers = int(maxWindow / rankingUpdateInterval)
 
- }
 
- func webSocketHandler(w http.ResponseWriter, r *http.Request) {
 
- 	cookie, err := r.Cookie("SID")
 
- 	if err != nil {
 
- 		// TODO error
 
- 		w.WriteHeader(http.StatusInternalServerError)
 
- 	}
 
- 	sess, sidExists := sessions[cookie.Value]
 
- 	if !sidExists {
 
- 		// No SID cookie
 
- 		sess = startSession(w, r)
 
- 	}
 
- 	conn, err := upgrader.Upgrade(w, r, nil)
 
- 	if err != nil {
 
- 		w.WriteHeader(http.StatusInternalServerError)
 
- 		// TODO Internal error
 
- 		return
 
- 	}
 
- 	sess.ws = conn
 
- 	c := make(chan *message)
 
- 	sess.send = c
 
- 	store.subscribe(sess.id, c)
 
- 	go sess.receive()
 
- 	go sess.transmit()
 
- 	go store.initSession(sess)
 
- }
 
- func startSession(w http.ResponseWriter, r *http.Request) *session {
 
- 	sessionID := newSessionID()
 
- 	cookie := &http.Cookie{
 
- 		Name:  "SID",
 
- 		Value: sessionID,
 
- 		Path:  "/",
 
- 		// Secure: true, // TODO re-add this when TLS is set up
 
- 	}
 
- 	sess := &session{
 
- 		id: sessionID,
 
- 	}
 
- 	http.SetCookie(w, cookie)
 
- 	sessions[sessionID] = sess
 
- 	return sess
 
- }
 
 
  |