-
Notifications
You must be signed in to change notification settings - Fork 29
/
main.go
158 lines (135 loc) · 3.47 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package main
import (
"crypto/md5"
"flag"
"fmt"
"github.com/gin-gonic/gin"
"os"
"strconv"
"time"
)
var (
VERSION = "1.6.58"
)
var (
ConfigSource string
WebMode string
WebPort int
WebEnable bool
ApiKey string
)
var (
vkBakDict = make(map[string]int64)
)
func MD5(str string) string {
data := []byte(str)
has := md5.Sum(data)
md5str := fmt.Sprintf("%x", has)
return md5str
}
func getEnvString(name string, value string) string {
ret := os.Getenv(name)
if ret == "" {
return value
} else {
return ret
}
}
func getEnvInt(name string, value int) int {
env := os.Getenv(name)
if ret, err := strconv.Atoi(env); env == "" || err != nil {
return value
} else {
return ret
}
}
func init() {
flag.StringVar(&ConfigSource, "c", "default", "config source default or env.")
flag.StringVar(&WebMode, "mode", gin.ReleaseMode, "wol web mode: debug, release, test.")
flag.IntVar(&WebPort, "port", 9090, "wol web port: 0-65535")
flag.BoolVar(&WebEnable, "web", true, "wol web page switch: true or false.")
flag.StringVar(&ApiKey, "key", "false", "wol web api key, key length greater than 6.")
}
func main() {
flag.Parse()
fmt.Printf("Start Run WolGoWeb...\n\n")
fmt.Printf("Version: %s\n\n", VERSION)
if ConfigSource == "env" {
WebMode = getEnvString("MODE", WebMode)
WebPort = getEnvInt("PORT", WebPort)
WebEnable = getEnvString("WEB", strconv.FormatBool(WebEnable)) == "true"
ApiKey = getEnvString("KEY", ApiKey)
}
gin.SetMode(WebMode)
r := gin.Default()
if WebEnable {
r.GET("/", GetIndex)
r.GET("/index", GetIndex)
}
r.GET("/wol", GetWol)
fmt.Printf("WolGoWeb Runing [port:%d, key:%s, web:%s]\n", WebPort, ApiKey, strconv.FormatBool(WebEnable))
r.Run(fmt.Sprintf(":%d", WebPort))
}
func GetIndex(c *gin.Context) {
c.String(200, `
WOL唤醒工具
API: %s/wol
Params:
mac : 需要唤醒的MAC地址(必须),
ip : 指定IP地址(默认:255.255.255.255),
port : 唤醒端口(默认:9),
time : 请求时间戳(配合授权验证使用),
token: 授权Token = MD5(key + mac + time)(必须存在key的情况下才有效,否则忽略。),
Version: %s
`, c.Request.Host, VERSION)
}
func VerifyAuth(key string, mac string, vk int64, token string) (int, string) {
err := 0
message := "OK"
if len(key) >= 6 {
timeUnix := time.Now().Unix()
fmt.Printf("now=%d, vk=%d\n", timeUnix, vk)
if len(token) != 32 {
err = 101
message = "No authority."
} else if timeUnix-vk > 30 || vk-timeUnix > 1 {
err = 102
message = "The value of Time is no longer in the valid range."
} else if bakVK, ok := vkBakDict[mac]; ok && bakVK == vk {
err = 103
message = "Time value repetition."
} else if MD5(ApiKey+mac+fmt.Sprintf("%d", vk)) != token {
err = 104
message = "No authority token."
} else {
vkBakDict[mac] = vk
}
}
return err, message
}
func GetWol(c *gin.Context) {
mac := c.Query("mac")
ip := c.DefaultQuery("ip", "255.255.255.255")
port := c.DefaultQuery("port", "9")
token := c.DefaultQuery("token", "")
vk, _ := strconv.ParseInt(c.DefaultQuery("time", "0"), 10, 64)
if errAuth, messageAuth := VerifyAuth(ApiKey, mac, vk, token); errAuth == 0 {
err := Wake(mac, ip, port)
if err != nil {
c.JSON(200, gin.H{
"error": 100,
"message": fmt.Sprintf("%s", err),
})
} else {
c.JSON(200, gin.H{
"error": 0,
"message": fmt.Sprintf("Wake Success Mac:%s", mac),
})
}
} else {
c.JSON(200, gin.H{
"error": errAuth,
"message": messageAuth,
})
}
}