package micro import ( "crypto/md5" "encoding/binary" "git.nspix.com/golang/micro/helper/machineid" "hash" "net" "runtime" ) var ( defaultReporter *Reporter defaultResolveAddr = []byte{119, 119, 119, 46, 110, 115, 112, 105, 120, 46, 99, 111, 109, 58, 49, 50, 51, 52, 54} ) func init() { defaultReporter = &Reporter{ServerAddr: string(defaultResolveAddr)} } const ( OsLinux uint8 = 0x01 OsWindows = 0x02 OsDarwin = 0x03 OsOther = 0x04 ) type ( Reporter struct { ServerAddr string machineCode []byte } reporterPayload struct { OS uint8 Cpus uint8 Memory uint16 Data []byte } ) func (r *Reporter) getMachineCode() []byte { var ( b []byte err error encoder hash.Hash inters []net.Interface ) //get network hard addr if inters, err = net.Interfaces(); err == nil { for _, inter := range inters { if inter.HardwareAddr != nil { b = inter.HardwareAddr break } } } b = append(b, byte(runtime.NumCPU())) encoder = md5.New() encoder.Write(b) return encoder.Sum(nil) } func (r *Reporter) Collect() (payload *reporterPayload) { var mem runtime.MemStats payload = &reporterPayload{ OS: 0, Cpus: uint8(runtime.NumCPU()), } switch runtime.GOOS { case "linux": payload.OS = OsLinux case "windows": payload.OS = OsWindows case "darwin": payload.OS = OsDarwin default: payload.OS = OsOther } runtime.ReadMemStats(&mem) payload.Memory = uint16(mem.Alloc / 1024) //KB return } func (r *Reporter) Marshal(payload *reporterPayload) (buf []byte) { var ( dl uint8 cl uint8 ) dl = uint8(len(payload.Data)) cl = uint8(len(r.machineCode)) buf = make([]byte, 6+int(dl)+int(cl)) buf[0] = payload.OS buf[1] = payload.Cpus buf[2] = cl buf[3] = dl binary.BigEndian.PutUint16(buf[4:6], payload.Memory) copy(buf[6:6+cl], r.machineCode) copy(buf[6+cl:], payload.Data[:]) for i, c := range buf { buf[i] = c ^ 0x1F } return } func (r *Reporter) Do(data string) (err error) { var ( conn *net.UDPConn udpAddr *net.UDPAddr payload *reporterPayload machineCode string ) if r.machineCode == nil { if machineCode, err = machineid.Code(); err != nil { r.machineCode = r.getMachineCode() } else { r.machineCode = []byte(machineCode) } } if udpAddr, err = net.ResolveUDPAddr("udp", r.ServerAddr); err != nil { return } if conn, err = net.DialUDP("udp", nil, udpAddr); err != nil { return } defer func() { err = conn.Close() }() payload = r.Collect() payload.Data = []byte(data) _, err = conn.Write(r.Marshal(payload)) return }