Browse Source

auto update script executed

Toby Chui 1 year ago
parent
commit
1b0e639849
4 changed files with 94 additions and 66 deletions
  1. 15 8
      mod/dynamicproxy/dynamicproxy.go
  2. 77 56
      mod/netstat/netstat.go
  3. 2 2
      mod/statistic/statistic.go
  4. BIN
      sys.db_backup

+ 15 - 8
mod/dynamicproxy/dynamicproxy.go

@@ -147,21 +147,28 @@ func (router *Router) StartProxyService() error {
 
 
 			//Create a redirection stop channel
 			//Create a redirection stop channel
 			stopChan := make(chan bool)
 			stopChan := make(chan bool)
+
+			//Start a blocking wait for shutting down the http to https redirection server
+			go func() {
+				<-stopChan
+				ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+				defer cancel()
+				httpServer.Shutdown(ctx)
+				log.Println("HTTP to HTTPS redirection listener stopped")
+			}()
+
+			//Start the http server that listens to port 80 and redirect to 443
 			go func() {
 			go func() {
-				//Start another router to check if the router.server is killed. If yes, kill this server as well
-				go func() {
-					<-stopChan
-					ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-					defer cancel()
-					httpServer.Shutdown(ctx)
-					log.Println("HTTP to HTTPS redirection listener stopped")
-				}()
 				if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
 				if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+					//Unable to startup port 80 listener. Handle shutdown process gracefully
+					stopChan <- true
 					log.Fatalf("Could not start server: %v\n", err)
 					log.Fatalf("Could not start server: %v\n", err)
 				}
 				}
 			}()
 			}()
 			router.tlsRedirectStop = stopChan
 			router.tlsRedirectStop = stopChan
 		}
 		}
+
+		//Start the TLS server
 		log.Println("Reverse proxy service started in the background (TLS mode)")
 		log.Println("Reverse proxy service started in the background (TLS mode)")
 		go func() {
 		go func() {
 			if err := router.server.Serve(ln); err != nil && err != http.ErrServerClosed {
 			if err := router.server.Serve(ln); err != nil && err != http.ErrServerClosed {

+ 77 - 56
mod/netstat/netstat.go

@@ -69,29 +69,26 @@ func NewNetStatBuffer(recordCount int) (*NetStatBuffers, error) {
 	}
 	}
 
 
 	//Get the initial measurements of netstats
 	//Get the initial measurements of netstats
-	go func(n *NetStatBuffers) {
-		rx, tx, err := GetNetworkInterfaceStats()
+	rx, tx, err := GetNetworkInterfaceStats()
+	if err != nil {
+		log.Println("Unable to get NIC stats: ", err.Error())
+	}
+
+	retryCount := 0
+	for rx == 0 && tx == 0 && retryCount < 10 {
+		//Strange. Retry
+		log.Println("NIC stats return all 0. Retrying...")
+		rx, tx, err = GetNetworkInterfaceStats()
 		if err != nil {
 		if err != nil {
 			log.Println("Unable to get NIC stats: ", err.Error())
 			log.Println("Unable to get NIC stats: ", err.Error())
 		}
 		}
+		retryCount++
+	}
 
 
-		retryCount := 0
-		for rx == 0 && tx == 0 && retryCount < 10 {
-			//Strange. Retry
-			log.Println("NIC stats return all 0. Retrying...")
-			rx, tx, err = GetNetworkInterfaceStats()
-			if err != nil {
-				log.Println("Unable to get NIC stats: ", err.Error())
-			}
-			retryCount++
-		}
-
-		n.PreviousStat = &RawFlowStat{
-			RX: rx,
-			TX: tx,
-		}
-
-	}(&thisNetBuffer)
+	thisNetBuffer.PreviousStat = &RawFlowStat{
+		RX: rx,
+		TX: tx,
+	}
 
 
 	// Update the buffer every second
 	// Update the buffer every second
 	go func(n *NetStatBuffers) {
 	go func(n *NetStatBuffers) {
@@ -199,51 +196,75 @@ func HandleGetNetworkInterfaceStats(w http.ResponseWriter, r *http.Request) {
 // Get network interface stats, return accumulated rx bits, tx bits and error if any
 // Get network interface stats, return accumulated rx bits, tx bits and error if any
 func GetNetworkInterfaceStats() (int64, int64, error) {
 func GetNetworkInterfaceStats() (int64, int64, error) {
 	if runtime.GOOS == "windows" {
 	if runtime.GOOS == "windows" {
-		cmd := exec.Command("wmic", "path", "Win32_PerfRawData_Tcpip_NetworkInterface", "Get", "BytesReceivedPersec,BytesSentPersec,BytesTotalPersec")
-		out, err := cmd.Output()
-		if err != nil {
-			return 0, 0, err
+		//Windows wmic sometime freeze and not respond.
+		//The safer way is to make a bypass mechanism
+		//when timeout with channel
+
+		type wmicResult struct {
+			RX  int64
+			TX  int64
+			Err error
 		}
 		}
 
 
-		//Spawn a timer to terminate the cmd process if timeout
-		var timer *time.Timer
-		timer = time.AfterFunc(3*time.Second, func() {
-			timer.Stop()
-			cmd.Process.Kill()
-		})
-
-		//Filter out the first line
-		lines := strings.Split(strings.ReplaceAll(string(out), "\r\n", "\n"), "\n")
-		if len(lines) >= 2 && len(lines[1]) >= 0 {
-			dataLine := lines[1]
-			for strings.Contains(dataLine, "  ") {
-				dataLine = strings.ReplaceAll(dataLine, "  ", " ")
-			}
-			dataLine = strings.TrimSpace(dataLine)
-			info := strings.Split(dataLine, " ")
-			if len(info) != 3 {
-				return 0, 0, errors.New("Invalid wmic results")
+		callbackChan := make(chan wmicResult)
+		cmd := exec.Command("wmic", "path", "Win32_PerfRawData_Tcpip_NetworkInterface", "Get", "BytesReceivedPersec,BytesSentPersec,BytesTotalPersec")
+		//Execute the cmd in goroutine
+		go func() {
+			out, err := cmd.Output()
+			if err != nil {
+				callbackChan <- wmicResult{0, 0, err}
 			}
 			}
-			rxString := info[0]
-			txString := info[1]
 
 
-			rx := int64(0)
-			tx := int64(0)
-			if s, err := strconv.ParseInt(rxString, 10, 64); err == nil {
-				rx = s
-			}
+			//Filter out the first line
+			lines := strings.Split(strings.ReplaceAll(string(out), "\r\n", "\n"), "\n")
+			if len(lines) >= 2 && len(lines[1]) >= 0 {
+				dataLine := lines[1]
+				for strings.Contains(dataLine, "  ") {
+					dataLine = strings.ReplaceAll(dataLine, "  ", " ")
+				}
+				dataLine = strings.TrimSpace(dataLine)
+				info := strings.Split(dataLine, " ")
+				if len(info) != 3 {
+					callbackChan <- wmicResult{0, 0, errors.New("invalid wmic results length")}
+				}
+				rxString := info[0]
+				txString := info[1]
+
+				rx := int64(0)
+				tx := int64(0)
+				if s, err := strconv.ParseInt(rxString, 10, 64); err == nil {
+					rx = s
+				}
 
 
-			if s, err := strconv.ParseInt(txString, 10, 64); err == nil {
-				tx = s
+				if s, err := strconv.ParseInt(txString, 10, 64); err == nil {
+					tx = s
+				}
+
+				time.Sleep(100 * time.Millisecond)
+				callbackChan <- wmicResult{rx * 4, tx * 4, nil}
+			} else {
+				//Invalid data
+				callbackChan <- wmicResult{0, 0, errors.New("invalid wmic results")}
 			}
 			}
 
 
-			time.Sleep(100 * time.Millisecond)
-			return rx * 4, tx * 4, nil
-		} else {
-			//Invalid data
-			return 0, 0, errors.New("Invalid wmic results")
+		}()
+
+		go func() {
+			//Spawn a timer to terminate the cmd process if timeout
+			var timer *time.Timer
+			timer = time.AfterFunc(3*time.Second, func() {
+				timer.Stop()
+				cmd.Process.Kill()
+				callbackChan <- wmicResult{0, 0, errors.New("wmic execution timeout")}
+			})
+		}()
+
+		result := wmicResult{}
+		result = <-callbackChan
+		if result.Err != nil {
+			log.Println("Unable to extract NIC info from wmic: " + result.Err.Error())
 		}
 		}
-
+		return result.RX, result.TX, result.Err
 	} else if runtime.GOOS == "linux" {
 	} else if runtime.GOOS == "linux" {
 		allIfaceRxByteFiles, err := filepath.Glob("/sys/class/net/*/statistics/rx_bytes")
 		allIfaceRxByteFiles, err := filepath.Glob("/sys/class/net/*/statistics/rx_bytes")
 		if err != nil {
 		if err != nil {

+ 2 - 2
mod/statistic/statistic.go

@@ -80,7 +80,7 @@ func NewStatisticCollector(option CollectorOption) (*Collector, error) {
 func (c *Collector) SaveSummaryOfDay() {
 func (c *Collector) SaveSummaryOfDay() {
 	//When it is called in 0:00am, make sure it is stored as yesterday key
 	//When it is called in 0:00am, make sure it is stored as yesterday key
 	t := time.Now().Add(-30 * time.Second)
 	t := time.Now().Add(-30 * time.Second)
-	summaryKey := t.Format("02_01_2006")
+	summaryKey := t.Format("2006_01_02")
 	saveData := DailySummaryToExport(*c.DailySummary)
 	saveData := DailySummaryToExport(*c.DailySummary)
 	c.Option.Database.Write("stats", summaryKey, saveData)
 	c.Option.Database.Write("stats", summaryKey, saveData)
 }
 }
@@ -88,7 +88,7 @@ func (c *Collector) SaveSummaryOfDay() {
 // Load the summary of a day given
 // Load the summary of a day given
 func (c *Collector) LoadSummaryOfDay(year int, month time.Month, day int) *DailySummary {
 func (c *Collector) LoadSummaryOfDay(year int, month time.Month, day int) *DailySummary {
 	date := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)
 	date := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)
-	summaryKey := date.Format("02_01_2006")
+	summaryKey := date.Format("2006_01_02")
 	targetSummaryExport := DailySummaryExport{}
 	targetSummaryExport := DailySummaryExport{}
 	c.Option.Database.Read("stats", summaryKey, &targetSummaryExport)
 	c.Option.Database.Read("stats", summaryKey, &targetSummaryExport)
 	targetSummary := DailySummaryExportToSummary(targetSummaryExport)
 	targetSummary := DailySummaryExportToSummary(targetSummaryExport)

BIN
sys.db_backup