reporter.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package micro
  2. import (
  3. "crypto/md5"
  4. "encoding/binary"
  5. "hash"
  6. "net"
  7. "runtime"
  8. )
  9. var (
  10. defaultReporter *Reporter
  11. defaultResolveAddr = []byte{119, 119, 119, 46, 110, 115, 112, 105, 120, 46, 99, 111, 109, 58, 49, 50, 51, 52, 54}
  12. )
  13. func init() {
  14. defaultReporter = &Reporter{ServerAddr: string(defaultResolveAddr)}
  15. }
  16. const (
  17. OsLinux uint8 = 0x01
  18. OsWindows = 0x02
  19. OsDarwin = 0x03
  20. OsOther = 0x04
  21. )
  22. type (
  23. Reporter struct {
  24. ServerAddr string
  25. machineCode []byte
  26. }
  27. reporterPayload struct {
  28. OS uint8
  29. Cpus uint8
  30. Memory uint16
  31. Data []byte
  32. }
  33. )
  34. func (r *Reporter) getMachineCode() []byte {
  35. var (
  36. b []byte
  37. err error
  38. encoder hash.Hash
  39. inters []net.Interface
  40. )
  41. //get network hard addr
  42. if inters, err = net.Interfaces(); err == nil {
  43. for _, inter := range inters {
  44. if inter.HardwareAddr != nil {
  45. b = inter.HardwareAddr
  46. break
  47. }
  48. }
  49. }
  50. b = append(b, byte(runtime.NumCPU()))
  51. encoder = md5.New()
  52. encoder.Write(b)
  53. return encoder.Sum(nil)
  54. }
  55. func (r *Reporter) Collect() (payload *reporterPayload) {
  56. var mem runtime.MemStats
  57. payload = &reporterPayload{
  58. OS: 0,
  59. Cpus: uint8(runtime.NumCPU()),
  60. }
  61. switch runtime.GOOS {
  62. case "linux":
  63. payload.OS = OsLinux
  64. case "windows":
  65. payload.OS = OsWindows
  66. case "darwin":
  67. payload.OS = OsDarwin
  68. default:
  69. payload.OS = OsOther
  70. }
  71. runtime.ReadMemStats(&mem)
  72. payload.Memory = uint16(mem.Alloc / 1024) //KB
  73. return
  74. }
  75. func (r *Reporter) Marshal(payload *reporterPayload) (buf []byte) {
  76. var (
  77. dl uint8
  78. cl uint8
  79. )
  80. dl = uint8(len(payload.Data))
  81. cl = uint8(len(r.machineCode))
  82. buf = make([]byte, 6+int(dl)+int(cl))
  83. buf[0] = payload.OS
  84. buf[1] = payload.Cpus
  85. buf[2] = cl
  86. buf[3] = dl
  87. binary.BigEndian.PutUint16(buf[4:6], payload.Memory)
  88. copy(buf[6:6+cl], r.machineCode)
  89. copy(buf[6+cl:], payload.Data[:])
  90. for i, c := range buf {
  91. buf[i] = c ^ 0x1F
  92. }
  93. return
  94. }
  95. func (r *Reporter) Do(data string) (err error) {
  96. var (
  97. conn *net.UDPConn
  98. udpAddr *net.UDPAddr
  99. payload *reporterPayload
  100. )
  101. if r.machineCode == nil {
  102. r.machineCode = r.getMachineCode()
  103. }
  104. if udpAddr, err = net.ResolveUDPAddr("udp", r.ServerAddr); err != nil {
  105. return
  106. }
  107. if conn, err = net.DialUDP("udp", nil, udpAddr); err != nil {
  108. return
  109. }
  110. defer func() {
  111. err = conn.Close()
  112. }()
  113. payload = r.Collect()
  114. payload.Data = []byte(data)
  115. _, err = conn.Write(r.Marshal(payload))
  116. return
  117. }