Tuesday, October 8, 2024
HomeGolangCorrupted buffer on high-load - Code Assessment

Corrupted buffer on high-load – Code Assessment


Hey, I’m writing easy server to hook up with dlms meters and get readings from them, however faceing with corrupted buffer downside on high-load, however every thing wonderful on few connections. It’s all what i’m doing.
(Don’t take note of the exhausting code, the thought was to check)

bundle inner

import (
	"encoding/hex"
	"fmt"
	"internet"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
)

kind Meter struct {
	socket      *internet.TCPConn
	state       State
	meterSerial string
	mutex       sync.Mutex
}


func NewMeter(socket *internet.TCPConn) *Meter {
	return &Meter{
		socket: socket,
		state:  Linked,
	}
}

func (m *Meter) Learn() {
	for {
		information := make([]byte, 1024)
		m.mutex.Lock()
		n, err := m.socket.Learn(information)
		m.mutex.Unlock()
		if err == internet.ErrClosed {
			m.socket.Shut()
			return
		}
		if n > 0 {
			hexString := hex.EncodeToString(information[:n])
			fmt.Printf("Learn %d bytesnData: %sn", n, hexString)
			m.OnData(hexString)
		}
	}
}

func (m *Meter) OnData(hexString string) {
	if hexString == Handshake {
		if m.state == Linked {
			response, err := hex.DecodeString(AARE)
			if err != nil {
				fmt.Println(err)
			}
			go m.socket.Write(response)
			m.state = ReadAARQ
			return
		} else {
			response, err := hex.DecodeString(Handshake)
			if err != nil {
				fmt.Println(err)
			}
			go m.socket.Write(response)
			return
		}
	}

	if m.state == ReadAARQ {
		if hexString == AARQ {
			response, err := hex.DecodeString(GetSerialRequest)
			if err != nil {
				fmt.Println(err)
			}
			go m.socket.Write(response)
			m.state = ReadSerial
			return
		}
	}

	if m.state == ReadSerial {
		m.meterSerial = parseSerial(hexString)
		from := time.Date(2023, 1, 1, 0, 0, 0, 0, time.Native)
		m.getDailyBilling(from, time.Now())
		return
	}

	if m.state == ReadDailyBilling {
		parseDailyBilling(hexString)

		if hexString[18:20] == "02" && hexString[22:24] != "01" {
			response, _ := hex.DecodeString(fmt.Sprintf("0001001100010007c002c1percents", hexString[24:32]))
			go m.socket.Write(response)
			return
		}

		m.state = Idle
	}
}

func parseSerial(hexData string) string {
	if !strings.HasPrefix(hexData, "0001000100110012c401c100090c") {
		return ""
	}

	bytes, err := hex.DecodeString(hexData[28:])
	if err != nil {
		fmt.Println(err)
	}

	return string(bytes)
}

func (m *Meter) getDailyBilling(dates ...time.Time) {
	var from, to time.Time
	if len(dates) > 2 || len(dates) == 0 {
		return
	}
	if len(dates) == 1 {
		from = dates[0]
		to = dates[0].AddDate(0, 0, 1)
	}
	if len(dates) == 2 {
		from = dates[0]
		to = dates[1]
	}

	response, err := hex.DecodeString(fmt.Sprintf("0001001100010040c001c100070000620200ff0201010204020412000809060000010000ff0f02120000090cpercents090cpercents0100", dateToHex(from), dateToHex(to)))
	if err != nil {
		fmt.Println(err)
	}
	go m.socket.Write(response)
	m.state = ReadDailyBilling
}

func parseDailyBilling(hexData string) []map[string]interface{} {
	information := strings.Cut up(hexData, "0216090c")
	if len(information) == 0 {
		return nil
	}

	end result := make([]map[string]interface{}, 0)

	for _, dailyData := vary information[1:] {
		legitimate := true
		if !strings.HasPrefix(dailyData, "07") {
			legitimate = false
		}
		date := dlmsHexToDate(dailyData[0:24])
		vals := regexp.MustCompile(".{1,10}").FindAllString(dailyData[24:234], -1)

		studying := make([]int, 0)

		for _, val := vary vals {
			if !strings.HasPrefix(val, "06") {
				legitimate = false
			}
			decVal, _ := hex.DecodeString(val[2:])
			studying = append(studying, int(decVal[0]))
		}

		if !legitimate {
			fmt.Println("complete buff:", information)
			fmt.Println("date:", dailyData[0:24])
			fmt.Println("vals:", vals)
			panic("Bleeeee")
		}

		if legitimate {
			end result = append(end result, map[string]interface{}{
				"date":    date,
				"studying": studying,
			})
		}
	}
	return end result
}

func dateToHex(date time.Time) string {
	return fmt.Sprintf("0percent02xpercent02xpercent02xpercent02xpercent02xpercent02xpercent02xFFFED400", date.12 months(), int(date.Month()), date.Day(), int(date.Weekday()), date.Hour(), date.Minute(), date.Second())
}

func dlmsHexToDate(hexString string) time.Time {
	hexyear, _ := hex.DecodeString(hexString[0:4])
	hexmonth, _ := hex.DecodeString(hexString[4:6])
	hexday, _ := hex.DecodeString(hexString[6:8])
	hexhour, _ := hex.DecodeString(hexString[10:12])
	hexminute, _ := hex.DecodeString(hexString[12:14])
	hexsecond, _ := hex.DecodeString(hexString[14:16])

	yr, _ := strconv.ParseInt(string(hexyear), 0, 16)
	month, _ := strconv.ParseInt(string(hexmonth), 0, 16)
	day, _ := strconv.ParseInt(string(hexday), 0, 16)
	hour, _ := strconv.ParseInt(string(hexhour), 0, 16)
	minute, _ := strconv.ParseInt(string(hexminute), 0, 16)
	second, _ := strconv.ParseInt(string(hexsecond), 0, 16)

	return time.Date(int(yr), time.Month(month), int(day), int(hour), int(minute), int(second), 0, time.UTC)
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments