HFish/core/protocol/redis/redis.go
SanJin 036ffad0dc ~ 修复 Mysql 三次握手不主动关闭连接异常问题 100%
~ 日记格式完善 70%
~ 暗网钓鱼支持 80%
~ UI 优化
~ 支持分页 50%
~ 支持筛选 50%
2019-08-08 09:52:05 +08:00

132 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package redis
import (
"net"
"bufio"
"strings"
"strconv"
"HFish/utils/try"
"HFish/core/report"
"HFish/utils/log"
)
var kvData map[string]string
func Start(addr string) {
kvData = make(map[string]string)
//建立socket监听端口
netListen, _ := net.Listen("tcp", addr)
defer netListen.Close()
for {
conn, err := netListen.Accept()
if err != nil {
continue
}
arr := strings.Split(conn.RemoteAddr().String(), ":")
id := report.ReportRedis(arr[0], conn.RemoteAddr().String()+" 已经连接")
log.Pr("Redis", arr[0], "已经连接")
go handleConnection(conn, id)
}
}
//处理 Redis 连接
func handleConnection(conn net.Conn, id int64) {
for {
str := parseRESP(conn)
switch value := str.(type) {
case string:
report.ReportUpdateRedis(id, "&&"+str.(string))
if len(value) == 0 {
goto end
}
conn.Write([]byte(value))
case []string:
if value[0] == "SET" || value[0] == "set" {
// 模拟 redis set
try.Try(func() {
key := string(value[1])
val := string(value[2])
kvData[key] = val
report.ReportUpdateRedis(id, "&&"+value[0]+" "+value[1]+" "+value[2])
}).Catch(func() {
// 取不到 key 会异常
})
conn.Write([]byte("+OK\r\n"))
} else if value[0] == "GET" || value[0] == "get" {
// 模拟 redis get
key := string(value[1])
val := string(kvData[key])
valLen := strconv.Itoa(len(val))
str := "$" + valLen + "\r\n" + val + "\r\n"
report.ReportUpdateRedis(id, "&&"+value[0]+" "+value[1])
conn.Write([]byte(str))
} else {
try.Try(func() {
report.ReportUpdateRedis(id, "&&"+value[0]+" "+value[1])
}).Catch(func() {
report.ReportUpdateRedis(id, "&&"+value[0])
})
conn.Write([]byte("+OK\r\n"))
}
break
default:
}
}
end:
conn.Close()
}
// 解析 Redis 协议
func parseRESP(conn net.Conn) interface{} {
r := bufio.NewReader(conn)
line, err := r.ReadString('\n')
if err != nil {
return ""
}
cmdType := string(line[0])
cmdTxt := strings.Trim(string(line[1:]), "\r\n")
switch cmdType {
case "*":
count, _ := strconv.Atoi(cmdTxt)
var data []string
for i := 0; i < count; i++ {
line, _ := r.ReadString('\n')
cmd_txt := strings.Trim(string(line[1:]), "\r\n")
c, _ := strconv.Atoi(cmd_txt)
length := c + 2
str := ""
for length > 0 {
block, _ := r.Peek(length)
if length != len(block) {
}
r.Discard(length)
str += string(block)
length -= len(block)
}
data = append(data, strings.Trim(str, "\r\n"))
}
return data
default:
return cmdTxt
}
}