Commit ca8e0ad0 by zhangjiec

初始工程

parents
# 默认忽略的文件
/shelf/
/workspace.xml
# 数据源本地存储已忽略文件
/dataSources/
/dataSources.local.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/dc_golang_server_1.iml" filepath="$PROJECT_DIR$/.idea/dc_golang_server_1.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
一、管理后台接口
1. 后台用户登录
传:LoginAccount、Password、验证码
成功则进入首页
成功回:token,Name, 菜单按钮权限,首页展示内容(后面做统计内容,现在先全为空)
2.
\ No newline at end of file
package api
import (
"dc_golang_server_1/config"
"dc_golang_server_1/logger"
"dc_golang_server_1/middleware"
"fmt"
"github.com/gin-gonic/gin"
)
func InitRouter() { //*gin.Engine{
gin.SetMode(config.HttpServerMode)
r := gin.New()
r.Use(logger.HttpGinLog(), gin.Recovery())
r.Use(middleware.Cors()) //全局跨域 局部跨域的话在路由组里面去添加
r.Use(middleware.JwtToken()) //jwt 还是在对应需要token的路由组添加
user := r.Group("user/")
user.Use(middleware.JwtToken())
{ // 需要token的
//user.GET("users",GetUsers)
}
// 登录:用户名,密码,验证码 返回token 返回用户信息、账号、token、菜单权限
//
// 会员管理:
//家长信息(ID,微信UNIONID,手机号,昵称,注册时间,最后一次登录时间,卡用户绑定状态)
//学生信息(ID, 家长ID, 区域, 名字, 性别, 生日,年级,班级,学号,注册时间) 校区ID、家长ID、家长手机、学生名字
// 基础数据
// 区域
//router := r.Group("api/")
{
//router.POST()
}
err := r.Run(config.HttpServerPort)
if err != nil {
panic(err)
}
fmt.Println("GAME OVER")
}
package cache
import (
"sync"
)
/*****************************************************后台管理账户*/
//var adminMap sync.Map //后台管理账户
//type AdminStruct struct {
// AdminID int
//
//}
/*---------------------------------------------------------------*/
/*********************************************************代理商**/
//// AgentMap 代理商
//var AgentMap sync.Map
/*---------------------------------------------------------------*/
/*********************************************************运营商**/
var operatorMap sync.Map //运营商id作为KEY
type OperatorStruct struct {
ShortName string
AreaID []int //区域ID
// 可再添加运营商属性
}
/*---------------------------------------------------------------*/
/******************************************************区域(校区)服务信息**/
var areaServiceMap sync.Map //area_service_id 作为KEY AreaStruct 作为VALUE
type AreaServiceStruct struct { //
AreaID int
ServiceID uint8 //服务项目 1公话 2定位 3饮水 4POS .........
OperatorID int32 //运营商ID
Name string //服务名字(例宿舍135栋饮水)name
Status bool //状态
}
/*---------------------------------------------------------------*/
/******************************************************后台管理用户**/
var adminMap sync.Map //后台管理用户 LoginAccount(string) 作为KEY
type AdminStruct struct {
Password [16]byte
tokenCreatTime uint32
Name string
//Phone string
//OperatorID []int
SystemAuth int //系统角色权限
AreaServiceAuth [][]int //area_service_id,role_id
}
/*---------------------------------------------------------------*/
// roleAuthMap /****************************角色权限(包含区域和系统角色)*/
var roleAuthMap sync.Map //role_id 作为KEY
type RoleAuthStruct struct {
Name string
// 考虑接口、菜单、按钮权限
}
/*---------------------------------------------------------------*/
/******************************************************区域(校区)**/
var areaMap sync.Map //area_id 作为KEY AreaStruct 作为VALUE
type AreaStruct struct { // AreaStruct 区域信息缓存,通过区域ID查出,后续再加支付信息
// OperatorID int32 //运营商ID
Name string
Status bool //校区状态
ServicePhone bool
ServiceWater bool
ServiceLocation bool
ServicePos bool
}
/*---------------------------------------------------------------*/
/***************************************************微信用户(家长)**/
var wechatCustomerMap sync.Map //微信的WechatUnionID(string)作为KEY
type WechatCustomerStruct struct {
tokenCreatTime uint32
CardUserID []int
}
/****************************************************************/
/***************************************************卡用户(学生)**/
var cardUserMap sync.Map //卡用户 CardUserID卡用户ID(int) 作为KEY
type CardUserType struct {
// WechatUnionID string
// AreaID int
AreaServiceID int
Name string
Sex uint8
// Birthday
Grade uint8
Class uint8
StudentNo string
Card CardStruct
}
type CardStruct struct {
Sim []string //电话卡 这里考虑下是否允许多张
Water []uint32 //水卡
Location []uint32 //定位卡
Pos []uint32 //pos消费卡
}
/*---------------------------------------------------------------*/
/*******************************************************电话设备**/
var phone20DeviceMap sync.Map //device_id 作为KEY Phone20DeviceStruct 作为VALUE
type Phone20DeviceStruct struct {
AreaServiceID int
AllowCallTime uint8 //允许通话时长,255表示不限制时长
Status bool
}
/*---------------------------------------------------------------*/
/********************************************************Sim卡信息**/
var simInfoMap sync.Map //card_id 作为KEY
type SimInfoStruct struct {
CardUserID int //卡用户ID
Status int8 //0没得这个数据 1 正常使用 其他各种异常
MonthTalkMinutes uint16
MonthPackageMinutes uint16
FamilyNum []FamilyOnePerson
}
type FamilyOnePerson struct {
Phone string
Nickname string
}
/*---------------------------------------------------------------*/
///********************************************************Sim卡信息(允许一卡多校区使用)**/
//var simInfoMap sync.Map //card_id 作为KEY
//type SimInfoStruct struct {
// Status int8 //0没得这个数据 1 正常使用 其他各种异常
// MonthTalkMinutes uint16
// MonthPackageMinutes uint16
// AreaFamilyNum []sync.Map //area_id为KEY , []familyOnePerson 为 VALUE
//}
//type FamilyOnePerson struct {
// Phone string
// Nickname string
//}
///*---------------------------------------------------------------*/
///*******************************************************定位设备**/
//var phone20DeviceMap sync.Map //device_id 作为KEY DeviceStruct 作为VALUE
//type Phone20DeviceStruct struct {
// AreaID int32
// AllowCallTime uint8 //允许通话时长,255表示不限制时长
// Status bool
//}
///*---------------------------------------------------------------*/
//
//
///*******************************************************饮水设备**/
//var phone20DeviceMap sync.Map //device_id 作为KEY DeviceStruct 作为VALUE
//type Phone20DeviceStruct struct {
// AreaID int32
// AllowCallTime uint8 //允许通话时长,255表示不限制时长
// Status bool
//}
///*---------------------------------------------------------------*/
func Init() {
initOperatorMap()
initWechatCustomerMap()
initCardUserMap()
initAreaMap()
initPhone20DeviceMap()
initSimFamilyNumMap()
}
package cache
import (
"dc_golang_server_1/dbmodel"
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"log"
"time"
)
func initAreaMap() {
fmt.Println(time.Now(), "cache: initDeviceMap begin")
var areaID int32
var temp AreaStruct
rows, err := dbmodel.PgDb.Query("SELECT id,name,status FROM b_area")
defer rows.Close()
if err != nil {
log.Panicln("SelectAreaToMap rows", err)
}
for rows.Next() {
err = rows.Scan(&areaID, &temp.Name, &temp.Status)
if err != nil {
log.Panicln("SelectAreaToMap rows.Scan", err)
}
phone20DeviceMap.Store(areaID, temp)
}
// 处理完毕后,需要判断一次遍历过程中是否有错误产生
if err = rows.Err(); err != nil {
logger.Log.Error("rows.Err()",
zap.Error(err),
zap.String("src", "initAreaMap"))
fmt.Println(time.Now(), "initAreaMap rows.Err()", err)
} else {
fmt.Println(time.Now(), "cache: initAreaMap end")
}
}
func GetAreaInfo(areaID int32) AreaStruct {
if info, ok := areaMap.Load(areaID); ok { //map有
if v, ok2 := info.(AreaStruct); ok2 { //类型断言正确
return v //,true
} else { //类型断言失败
areaMap.Delete(areaID)
logger.Log.Error("AreaMap 类型断言错误",
zap.Int32("areaID", areaID),
zap.String("src", "GetAreaInfo"))
}
}
var temp AreaStruct
var err error
for i := 0; i < 100; i++ {
err = dbmodel.PgDb.QueryRow("SELECT name,status FROM b_area WHERE id=$1",
areaID).Scan(&temp.Name, &temp.Status)
if err != nil {
fmt.Println("GetAreaInfo SELECT:", i, err)
time.Sleep(3 * time.Millisecond)
continue
}
areaMap.Store(areaID, temp)
logger.Log.Error("数据库有而缓存没有 GetAreaInfo",
zap.Int32("areaID", areaID),
zap.Error(err),
zap.String("src", "GetAreaInfo"))
return temp //,true
}
logger.Log.Error("GetAreaInfo SELECT operator_id,status FROM b_area WHERE id=$1",
zap.Int32("areaID", areaID),
zap.Error(err),
zap.String("src", "getDeviceInfo"))
return temp //,false
}
package cache
func initCardUserMap() {
}
package cache
func initOperatorMap() { //todo 查询b_operator表得到ID和short_name; 查询b_area表得到AreaID
}
func GetOperatorMap(id int) OperatorStruct {
var temp OperatorStruct
return temp
}
package cache
import (
"dc_golang_server_1/dbmodel"
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"log"
"time"
)
func initPhone20DeviceMap() {
fmt.Println(time.Now(), "cache: initDeviceMap begin")
var devID uint32
var temp Phone20DeviceStruct
rows, err := dbmodel.PgDb.Query("SELECT id,area_service_id,allow_call_time,status FROM d_device")
defer rows.Close()
if err != nil {
log.Panicln("SelectDeviceToMap rows", err)
}
for rows.Next() {
err = rows.Scan(&devID, &temp.AreaServiceID, &temp.AllowCallTime, &temp.Status)
if err != nil {
log.Panicln("SelectDeviceToMap rows.Scan", err)
}
phone20DeviceMap.Store(devID, temp)
}
// 处理完毕后,需要判断一次遍历过程中是否有错误产生
if err = rows.Err(); err != nil {
logger.Log.Error("rows.Err()",
zap.Error(err),
zap.String("src", "initDeviceMap"))
fmt.Println(time.Now(), "initDeviceMap rows.Err()", err)
} else {
fmt.Println(time.Now(), "cache: initDeviceMap end")
}
}
func GetDeviceInfo(devID uint32) Phone20DeviceStruct {
if info, ok := phone20DeviceMap.Load(devID); ok { //map有
if v, ok2 := info.(Phone20DeviceStruct); ok2 { //类型断言正确
return v //,true
} else { //类型断言失败
phone20DeviceMap.Delete(devID)
logger.Log.Error("DeviceMap 类型断言错误",
zap.Uint32("devID", devID),
zap.String("src", "getDeviceInfo"))
}
}
var temp Phone20DeviceStruct
var err error
for i := 0; i < 100; i++ {
err = dbmodel.PgDb.QueryRow("SELECT area_service_id,allow_call_time,status FROM d_device WHERE id=$1",
devID).Scan(&temp.AreaServiceID, &temp.AllowCallTime, &temp.Status)
if err != nil {
fmt.Println("getDeviceInfo SELECT:", i, err)
time.Sleep(3 * time.Millisecond)
continue
}
phone20DeviceMap.Store(devID, temp)
logger.Log.Error("数据库有而缓存没有 getDeviceInfo",
zap.Uint32("devID", devID),
zap.Error(err),
zap.String("src", "getDeviceInfo"))
return temp //,true
}
logger.Log.Error("getDeviceInfo SELECT area_id,allow_call_time,status FROM d_device WHERE id=$1",
zap.Uint32("devID", devID),
zap.Error(err),
zap.String("src", "getDeviceInfo"))
return temp //,false
}
package cache
func initSimFamilyNumMap() {
//fmt.Println(time.Now(),"cache: initSimFamilyNumMap begin")
//var keyTemp simFamilyNumMapKeyStruct
//var newValue familyOnePerson
//var ok bool
//rows, err := model.PgDb.Query("SELECT card_id,phone,nickname,area_id FROM u_sim_family_num ORDER BY create_at")
//defer rows.Close()
//if err != nil{
// log.Panicln("SelectUserSimFamilyNumToMap rows",err)
//}
//for rows.Next() {
// var bufStruct SimFamilyNumStruct
// err = rows.Scan(&keyTemp.CardId,&newValue.Phone,&newValue.Nickname,&keyTemp.AreaId)
// if err != nil{
// log.Panicln("SelectUserSimFamilyNumToMap rows.Scan",err)
// }
// if bo,ok2 := simFamilyNumMap.Load(keyTemp); ok2 { //map已经有了,就不去查u_sim_info了
// if bufStruct, ok = bo.(SimFamilyNumStruct); ok == false { //类型断言错误
// simFamilyNumMap.Delete(keyTemp)
// logger.Log.Error("SimFamilyNumMap 类型断言错误",
// zap.String("cardId", keyTemp.CardId),
// zap.Int32("area_id", keyTemp.AreaId),
// zap.String("src", "InitSimFamilyNumMap"))
// err = model.PgDb.QueryRow("SELECT month_talk_minutes,month_package_minutes,status FROM u_sim_info WHERE card_id=$1",
// keyTemp.CardId).Scan(&bufStruct.MonthTalkMinutes,&bufStruct.MonthPackageMinutes,&bufStruct.Status)
// if err != nil {
// logger.Log.Error("已绑定亲情号码的卡号居然在u_sim_info查不到",
// zap.String("cardId", keyTemp.CardId),
// zap.Int32("area_id", keyTemp.AreaId),
// zap.String("src", "InitSimFamilyNumMap"))
// continue
// }
// }
// } else {
// err = model.PgDb.QueryRow("SELECT month_talk_minutes,month_package_minutes,status FROM u_sim_info WHERE card_id=$1",
// keyTemp.CardId).Scan(&bufStruct.MonthTalkMinutes,&bufStruct.MonthPackageMinutes,&bufStruct.Status)
// if err != nil {
// logger.Log.Error("已绑定亲情号码的卡号居然在u_sim_info查不到",
// zap.String("cardId", keyTemp.CardId),
// zap.Int32("area_id", keyTemp.AreaId),
// zap.String("src", "InitSimFamilyNumMap"))
// continue
// }
// }
// //map里还没有,新存一条
// bufStruct.Family = append(bufStruct.Family,newValue)
// simFamilyNumMap.Store(keyTemp,bufStruct)
//}
//// 处理完毕后,需要判断一次遍历过程中是否有错误产生
//if err = rows.Err();err != nil{
// logger.Log.Error("rows.Err()",
// zap.Error(err),
// zap.String("src", "InitSimFamilyNumMap"))
// fmt.Println(time.Now(),"initSimFamilyNumMap rows.Err()",err)
//} else {
// fmt.Println(time.Now(),"cache: initSimFamilyNumMap end")
//}
}
func GetSimFamilyNum(areaId int32, cardId string) []FamilyOnePerson {
//if s,ok := simFamilyNumMap.Load(simFamilyNumMapKeyStruct{
// areaId,
// cardId,
//});ok{ // map有
// if sim,ok4 := s.(SimFamilyNumStruct);ok4 { //类型断言正确
// return sim
// } else { //类型断言失败
// simFamilyNumMap.Delete(simFamilyNumMapKeyStruct{
// areaId,
// cardId,
// })
// logger.Log.Error("simFamilyNumMap 类型断言错误",
// zap.String("cardId", cardId),
// zap.Int32("area_id", areaId),
// zap.String("src", "GetSimFamilyNum"))
// }
//}
//
var temp []FamilyOnePerson
//
//// todo 再去查一盘库
return temp
}
// AddSimMonthTalkMinutes 缓存里增加本月通话分钟数
func AddSimMonthTalkMinutes(AreaId int32, CardId string) {
}
package cache
func initWechatCustomerMap() {
}
[database]
#阿里云9.9 外网
dbDSN = "user=higher password=hj^&bhjb789j$^* dbname=dctest1 host=pgm-2ze3yp0bss39cxvh1o.pg.rds.aliyuncs.com port=1921 sslmode=disable"
#阿里云9.9 内网 pgm-2ze3yp0bss39cxvh129210.pg.rds.aliyuncs.com
#dbDSN = "user=higher password=hj^&bhjb789j$^* dbname=jeff_study host=pgm-2ze3yp0bss39cxvh129210.pg.rds.aliyuncs.com port=1921 sslmode=disable"
#chengdu-office 内网 192.168.1.42:5432
#dbDSN = "user=postgres password=buzhidao123. dbname=dctest1 host=192.168.1.42 port=5432 sslmode=disable"
#chengdu-office 外网 to-chengdu-office.168cad.top:50032
#dbDSN = "user=postgres password=buzhidao123 dbname=dctest1 host=to-chengdu-office.168cad.top port=50032 sslmode=disable"
#ECS外网
#DbDSN = "user=postgres password=buzhidao123. dbname=testlog host=60.205.190.129 port=5432 sslmode=disable"
#ECS内网
#DbDSN = "user=postgres password=buzhidao123. dbname=testlog host=127.0.0.1 port=5432 sslmode=disable"
[http_server]
#debug release
ServerMode = release
ServerPort = :50000
[tcp_long_server]
#TCP服务监听的端口号
TcpPort = 60000
#TCP 最大连接数限制,建议设置实际设备数量的2.5倍
MaxConnections = 20000
#新建立的TCP连接,连上后多久完全没收到数据就判断为非法设备断掉,单位秒
NewConnReadDeadline = 60
#新建立的TCP连接,连上后多久没收到合法完整数据就判断为非法设备断掉,单位秒
NewConnRightfulTimeout = 120
#老连接(已验证通过确实是合法设备的tcp连接),多久没收到数据就断掉,这里设置为3倍心跳时间(若同一台设备建立了新连接,系统会立即释放老连接)
OldConnReadDeadline = 180
[log]
#debug info warn error 只允许设置这3个等级,以保证至少记录error DPanic Panci Fatal
#debug info: 记录流水数据(都存在info.log里)
#warn: 应检查原因,主要来自外部
#error DPanic Panci Fatal: 应立即检查原因来内部或硬件设备或业务服务器
Level = warn
#log文件的存储路径
Path = ./log/
#单个日志文件大小限制,单位MB
FileMaxSize = 10
#info级别日志最多保存多少份
InfoMaxFileNum = 30
#info日志最长保留天数
InfoWithMaxAge = 30
#warn级别日志最多保存多少份
WarnMaxFileNum = 30
#warn日志最长保留天数
WarnWithMaxAge = 90
#Error级别日志最多保存多少份
ErrorMaxFileNum = 10
#Error日志最长保留天数s
ErrorWithMaxAge = 180
package config
import (
"go.uber.org/zap/zapcore"
"gopkg.in/ini.v1"
"time"
)
var (
DbDSN string
HttpServerMode string
HttpServerPort string
TcpLongPort string
TcpLongMaxConnections int32
TcpLongNewConnReadDeadline time.Duration
TcpLongNewConnRightfulTimeout int64
TcpLongOldConnReadDeadline time.Duration
LogLevel zapcore.Level
LogPath string
LogFileMaxSize int // 单个日志文件的最大MB
LogInfoMaxFileNum int
LogInfoMaxFileDay int
LogWarnMaxFileNum int
LogWarnMaxFileDay int
LogErrorMaxFileNum int
LogErrorMaxFileDay int
)
func ConfigInit() {
file, err := ini.Load("./config.ini")
if err != nil {
// logger.Log.Panic("配置文件读取错误")
panic("配置文件读取错误")
}
DbDSN = file.Section("database").Key("dbDSN").MustString("user=higher password=hj^&bhjb789j$^* dbname=jeff_study host=pgm-2ze3yp0bss39cxvh1o.pg.rds.aliyuncs.com port=1921 sslmode=disable")
HttpServerMode = file.Section("http_server").Key("ServerMode").In("release", []string{"release", "debug"})
HttpServerPort = file.Section("http_server").Key("ServerPort").MustString(":50000")
TcpLongPort = file.Section("tcp_long_server").Key("TcpPort").MustString("60000")
TcpLongMaxConnections = int32(file.Section("tcp_long_server").Key("MaxConnections").MustUint(20000))
TcpLongNewConnReadDeadline = time.Duration(file.Section("tcp_long_server").Key("NewConnReadDeadline").MustInt(60)) * time.Second
TcpLongNewConnRightfulTimeout = file.Section("tcp_long_server").Key("NewConnRightfulTimeout").MustInt64(120)
TcpLongOldConnReadDeadline = time.Duration(file.Section("tcp_long_server").Key("OldConnReadDeadline").MustInt(180)) * time.Second
logLvlStr := file.Section("log").Key("Level").In("warn", []string{"trace", "debug", "info", "warn", "error"})
switch logLvlStr {
case "debug":
LogLevel = zapcore.DebugLevel
case "info":
LogLevel = zapcore.InfoLevel
case "warn":
LogLevel = zapcore.WarnLevel
case "error":
LogLevel = zapcore.ErrorLevel
}
LogPath = file.Section("log").Key("Path").MustString(".log")
LogFileMaxSize = file.Section("log").Key("FileMaxSize").MustInt(10)
LogInfoMaxFileNum = file.Section("log").Key("InfoMaxFileNum").MustInt(10)
LogInfoMaxFileDay = file.Section("log").Key("InfoWithMaxAge").MustInt(30)
LogWarnMaxFileNum = file.Section("log").Key("WarnMaxFileNum").MustInt(10)
LogWarnMaxFileDay = file.Section("log").Key("WarnWithMaxAge").MustInt(90)
LogErrorMaxFileNum = file.Section("log").Key("ErrorMaxFileNum").MustInt(10)
LogErrorMaxFileDay = file.Section("log").Key("ErrorWithMaxAge").MustInt(180)
}
package dbmodel
//CREATE TABLE IF NOT EXISTS public.d_device
//(
//id bigint NOT NULL,
//area_id integer,
//service_code smallint,
//version_code character varying(3) COLLATE pg_catalog."default",
//place character varying(32) COLLATE pg_catalog."default",
//rate_id integer,
//status boolean,
//create_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
//update_at timestamp without time zone,
//CONSTRAINT d_device_pkey PRIMARY KEY (id)
//)
package dbmodel
import (
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"time"
)
//CREATE TABLE IF NOT EXISTS public.d_hex_command_err
//(
//device_id bigint NOT NULL,
//ciphertext character varying(512) COLLATE pg_catalog."default" NOT NULL,
//err character varying(32) COLLATE pg_catalog."default" NOT NULL,
//create_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
//)
//type TableDevHexCommandErr struct {
// devId uint32
// ciphertext string
// errMsg string
// createAt timestamp.Timestamp
//}
func InsertDevHexCommandErr(devId uint32, ciphertext string, errMsg string) {
var err error
for i := 0; i < 10; i++ {
_, err = PgDb.Exec("INSERT INTO d_hex_command_err VALUES($1,$2,$3)", devId, ciphertext, errMsg)
if err == nil {
return
}
fmt.Println("InsertDevHexCommandErr:", i, err)
time.Sleep(3 * time.Second)
}
logger.Log.Error("InsertDevHexCommandErr Err",
zap.Error(err))
}
package dbmodel
import (
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"time"
)
//CREATE TABLE IF NOT EXISTS public.d_hex_command_record
//(
//device_id bigint NOT NULL,
//dev_utc bigint NOT NULL,
//ctrl_code character(2) COLLATE pg_catalog."default" NOT NULL,
//data_len smallint NOT NULL,
//data_hex character varying(512) COLLATE pg_catalog."default",
//ciphertext character varying(512) COLLATE pg_catalog."default",
//direction smallint NOT NULL,
//create_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
//)
type TableDevHexCommandRecord struct {
DevID uint32
DevUtc uint32
CtrlCode string
DataLen uint8
DataHex string
Ciphertext string
Direction uint8
createAt time.Time
retry uint8 //测试用字段,后面压测完了可以删他妈的
}
func InsertDevHexCommandRecord(insertData TableDevHexCommandRecord) {
var err error
for i := 0; i < 10; i++ {
// _, err = StmtDevHexRecord.Exec(rData.DevID, rData.TimeUtc, strconv.FormatUint(uint64(rData.CtrlCode), 16), rData.Length, hex.EncodeToString(rData.Data[:rData.Length]), ciphertext, direction)
_, err = stmtInsertDevHexCommandRecord.Exec(insertData.DevID,
insertData.DevUtc,
insertData.CtrlCode,
insertData.DataLen,
insertData.DataHex,
insertData.Ciphertext,
insertData.Direction,
i,
)
if err == nil {
return
}
fmt.Println("InsertDevHexCommandRecord:", i, err)
time.Sleep(100 * time.Millisecond)
}
logger.Log.Error("InsertDevHexCommandRecord Error",
zap.Error(err))
}
package dbmodel
import (
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"time"
)
//CREATE TABLE IF NOT EXISTS public.d_hex_connect_record
//(
//dev_id bigint NOT NULL,
//state smallint NOT NULL,
//create_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
//)
// state 0:新连接来了 1:设备正常离线 2:正常离线 3:新连接挤掉就连接 4:未知异常(连接池类型断言失败)
func DevHexConnectRecord(devId uint32, state uint8) {
var err error
for i := 0; i < 100; i++ {
_, err = stmtInsertDevHexConnectRecord.Exec(devId, state)
if err == nil {
return
}
fmt.Println("DevHexConnectRecord:", i, err)
time.Sleep(20 * time.Millisecond)
}
logger.Log.Error("DevHexConnectRecord Err",
zap.Error(err))
}
package dbmodel
import (
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"time"
)
//CREATE TABLE IF NOT EXISTS public.d_hex_reset_record
//(
//device_id bigint NOT NULL,
//dev_utc bigint NOT NULL,
//reset_reason smallint NOT NULL,
//reset_code character varying(2) COLLATE pg_catalog."default",
//location point,
//firmware character varying(20) COLLATE pg_catalog."default",
//create_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
//)
type TableDevHexResetRecord struct {
DevId uint32
DevUtc uint32
ResetReason uint8
ResetCode string
Location [2]uint32
Firmware string
createAt time.Time
}
func InsertDevHexResetRecord(insertData TableDevHexResetRecord) {
var err error
for i := 0; i < 100; i++ {
_, err = stmtInsertDevHexCommandRecord.Exec(
insertData.DevId,
insertData.DevUtc,
insertData.ResetReason,
insertData.ResetCode,
insertData.Location[0],
insertData.Location[1],
insertData.Firmware,
)
if err == nil {
return
}
fmt.Println("InsertDevHexResetRecord:", i, err)
time.Sleep(100 * time.Millisecond)
}
logger.Log.Error("InsertDevHexResetRecord Err",
zap.Error(err))
}
package dbmodel
import (
"database/sql"
"dc_golang_server_1/config"
_ "github.com/lib/pq"
)
var PgDb *sql.DB
var stmtInsertDevHexCommandRecord *sql.Stmt
var stmtInsertDevHexConnectRecord *sql.Stmt
var stmtInsertDevHexResetRecord *sql.Stmt
// var stmtInsertUCallRecordAndUpdateUSimInfo *sql.Stmt //用事务处理
var stmtInsertUserCardUser *sql.Stmt
func InitDb() {
var err error
PgDb, err = sql.Open("postgres", config.DbDSN)
if err != nil {
panic("数据库连接失败" + err.Error())
}
//PgDb.SetConnMaxLifetime()
//PgDb.SetConnMaxIdleTime()
//PgDb.SetMaxOpenConns()
//PgDb.Stats()
// 建立常用的预处理
stmtInsertDevHexCommandRecord, err = PgDb.Prepare("INSERT INTO d_command_record VALUES($1,$2,$3,$4,$5,$6,$7,$8)") //("INSERT INTO d_hex_command_record(device_id,ctrl_code,data_len,data_hex,ciphertext)VALUES($1,$2,$3,$4,$5)")
if err != nil {
panic("建立stmtDevHexCommandRecord失败:" + err.Error())
}
stmtInsertDevHexConnectRecord, err = PgDb.Prepare("INSERT INTO d_connect_record VALUES($1,$2)")
if err != nil {
panic("建立stmtDevHexConnectRecord失败:" + err.Error())
}
stmtInsertDevHexResetRecord, err = PgDb.Prepare("INSERT INTO d_reset_record VALUES($1,$2,$3,$4,point($5,$6),$7)")
if err != nil {
panic("建立stmtDevHexConnectRecord失败:" + err.Error())
}
//stmtInsertUserCallRecord, err = PgDb.Prepare("INSERT INTO u_call_record VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16)")
//if err != nil {
// panic("建立stmtUserCallRecord失败:" + err.Error())
//}
stmtInsertUserCardUser, err = PgDb.Prepare("INSERT INTO u_card_user VALUES($1,$2,$3,$4,$5,$6,$7,$8)")
if err != nil {
panic("建立stmtUserCardUser失败:" + err.Error())
}
}
func CloseDb() {
_ = stmtInsertDevHexCommandRecord.Close()
_ = stmtInsertDevHexConnectRecord.Close()
_ = stmtInsertDevHexResetRecord.Close()
//_ = stmtInsertUCallRecordAndUpdateUSimInfo.Close()
_ = stmtInsertUserCardUser.Close()
_ = PgDb.Close()
}
package dbmodel
import (
"database/sql"
"dc_golang_server_1/logger"
"go.uber.org/zap"
"strings"
"time"
)
//CREATE TABLE IF NOT EXISTS public.u_call_record
//(
//customer_id integer,
//customer_name character varying(64) COLLATE pg_catalog."default",
//customer_phone character varying(12) COLLATE pg_catalog."default",
//card_user_id integer,
//card_user_name character varying(32) COLLATE pg_catalog."default",
//card_code character varying(32) COLLATE pg_catalog."default",
//card_type smallint,
//called_number character varying(12) COLLATE pg_catalog."default",
//called_nickname character varying(32) COLLATE pg_catalog."default",
//call_start_at timestamp without time zone,
//talk_time smallint,
//area_id integer,
//operator_id integer,
//device_id bigint,
//telephone_package_id integer,
//state smallint,
//create_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP
//)
type TableUserCallRecord struct {
CustomerId int32 //会员ID
CustomerPhone string //会员手机号 //character varying(11) COLLATE pg_catalog."default",
CardUserId int32 //卡用户ID //integer,
CardUserName string //卡用户姓名 character varying(32) COLLATE pg_catalog."default",
CardID string //卡ID character varying(32) COLLATE pg_catalog."default",
CardType int8 //卡类型 smallint,
CalledNumber string //被叫号码 character varying(12) COLLATE pg_catalog."default",
CalledNickname string //被叫昵称 character varying(32) COLLATE pg_catalog."default",
CallStartAt string //time.Time //通话开始时间 without time zone, .Format("2006-01-02 15:04:05.000"),
TalkTime int16 //通话时长 //integer,
AreaId int32 //区域(校区)ID //integer,
OperatorId int32 //运营商ID //integer,
DeviceId uint32 //设备ID //bigint,
Status uint8 //通话状态 //smallint,
CreateAt time.Time // timestamp without time zone DEFAULT CURRENT_TIMESTAMP
}
func clearTransaction(tx *sql.Tx) {
err := tx.Rollback()
if err != sql.ErrTxDone && err != nil {
logger.Log.Panic("InsertUCallRecordAndUpdateUSimInfo clearTransaction",
zap.Error(err))
}
}
func InsertUCallRecordAndUpdateUSimInfo(insertData TableUserCallRecord) uint8 { //0 成功 1 唯一约束重复 9 系统繁忙
tx, err := PgDb.Begin()
if err != nil {
logger.Log.Error("InsertUCallRecordAndUpdateUSimInfo PgDb.Begin():",
zap.Error(err))
return 9
}
defer clearTransaction(tx)
//先InsertUCallRecord
_, err = tx.Exec("INSERT INTO u_call_record(customer_id,customer_phone,card_user_id,card_user_name,card_id,card_type,called_number,called_nickname,call_start_at,talk_time,area_id,operator_id,device_id,status)VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14)",
insertData.CustomerId,
insertData.CustomerPhone,
insertData.CardUserId,
insertData.CardUserName,
insertData.CardID,
insertData.CardType,
insertData.CalledNumber,
insertData.CalledNickname,
insertData.CallStartAt,
insertData.TalkTime,
insertData.AreaId,
insertData.OperatorId,
insertData.DeviceId,
insertData.Status,
)
if err != nil {
if strings.Contains(err.Error(), "duplicate key value") { //todo 这里应考虑去查出来看看内容是不是一样的
//fmt.Println("InsertUserCallRecord唯一约束重复", err)
return 1
}
logger.Log.Error("InsertUCallRecordAndUpdateUSimInfo InsertUserCallRecord:",
zap.Error(err))
return 9
}
//rowAffected, err := rs.RowsAffected()
//if err != nil {
// fmt.Println("插入电话记录表:rs.RowsAffected()", err)
// panic("反正是测试,先退出2")
//}
//fmt.Println(rowAffected)
_, err = tx.Exec("UPDATE u_sim_info SET total_talk_minutes=total_talk_minutes+$1 WHERE card_id=$2", (insertData.TalkTime+59)/60, insertData.CardID)
if err != nil {
logger.Log.Error("InsertUCallRecordAndUpdateUSimInfo UPDATE u_sim_info:",
zap.Error(err))
return 9
}
//rowAffected, err = rs.RowsAffected()
//if err != nil {
// fmt.Println("UPDATE u_sim_info:rs.RowsAffected()", err)
// panic("反正是测试,先退出4")
//}
//fmt.Println(rowAffected)
if err = tx.Commit(); err != nil {
logger.Log.Error("InsertUCallRecordAndUpdateUSimInfo Commit:",
zap.Error(err))
return 9
}
return 0
}
package dbmodel
import "time"
//CREATE TABLE IF NOT EXISTS public.u_card_user
//(
//id integer NOT NULL DEFAULT nextval('u_card_user_id_seq'::regclass),
//customer_id integer,
//area_id integer,
//name character varying(32) COLLATE pg_catalog."default",
//sex smallint,
//birthday date,
//grade smallint,
//class smallint,
//student_no character varying(32) COLLATE pg_catalog."default",
//create_at timestamp without time zone,
//update_at timestamp without time zone,
//CONSTRAINT u_card_user_pkey PRIMARY KEY (id)
//)
type TableUserCardUser struct {
Id int32 //integer NOT NULL DEFAULT nextval('u_card_user_id_seq'::regclass),
CustomerId int32 //integer,
AreaId int32 //integer,
Name string //character varying(32) COLLATE pg_catalog."default",
Sex int8 //smallint,
Birthday time.Time
Grade int8 //smallint,
Class int8 //smallint,
StudentNo string //character varying(32) COLLATE pg_catalog."default",
CreateAt time.Time //timestamp without time zone,
UpdateAt time.Time //timestamp without time zone,
}
func InsertUserCardUser(insertData TableUserCardUser) int8 {
_, err := stmtInsertUserCardUser.Exec(
insertData.CustomerId,
insertData.AreaId,
insertData.Name,
insertData.Sex,
insertData.Birthday,
insertData.Grade,
insertData.Class,
insertData.StudentNo,
)
if err == nil {
return 0
}
return 1 //1
}
package dbmodel
import (
"time"
)
//CREATE TABLE IF NOT EXISTS public.u_sim_family_num
//(
//card_id character varying(32) COLLATE pg_catalog."default" NOT NULL,
//phone character varying(12) COLLATE pg_catalog."default",
//nickname character varying(32) COLLATE pg_catalog."default",
//area_id integer NOT NULL,
//create_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
//CONSTRAINT u_sim_family_num_pkey PRIMARY KEY (card_id, area_id)
//)
type TableUserSimFamilyNum struct {
CardId string //character varying(32) COLLATE pg_catalog."default",
Phone string //character varying(12) COLLATE pg_catalog."default",
Nickname string //character varying(32) COLLATE pg_catalog."default",
AreaId int32
CreateAt time.Time //timestamp without time zone DEFAULT CURRENT_TIMESTAMP
}
package dbmodel
//CREATE TABLE IF NOT EXISTS public.u_sim_info
//(
//card_id character varying(20) COLLATE pg_catalog."default",
//total_talk_minutes integer,
//month_talk_minutes integer,
//month_package_minutes integer,
//status smallint
//)
//type TableUserSimInfo struct {
// CardID string
//
//}
package devproduct
import (
"dc_golang_server_1/dbmodel"
"dc_golang_server_1/logger"
"dc_golang_server_1/util"
"encoding/hex"
"go.uber.org/zap"
"net"
"strconv"
"time"
)
//type IDCLongTCPHex interface {
// receiveResponse(conn *net.TCPConn, data []byte, cnt int) bool
//}
type DCLongTCPHex struct {
TCPLongServer
password string
iv string
devType uint8
protocolAnalysis func(data *HexData) //HexData
}
//type Connection struct {
// conn *net.TCPConn
//}
type HexData struct {
TimeUtc uint32
//DevType uint8
DevID uint32
CtrlCode uint8
Length uint8
Data []byte
}
func /*(d *DCLongTCPHex)*/ insertDevHexCommandRecord(data *HexData, ciphertext string, direction uint8) {
go dbmodel.InsertDevHexCommandRecord(dbmodel.TableDevHexCommandRecord{
DevID: data.DevID,
DevUtc: data.TimeUtc,
CtrlCode: strconv.FormatUint(uint64(data.CtrlCode), 16),
DataLen: data.Length,
DataHex: hex.EncodeToString(data.Data[:data.Length]),
Ciphertext: ciphertext,
Direction: direction,
})
}
func (d *DCLongTCPHex) receiveResponse(conn *net.TCPConn, data []byte, nowConnDevID uint32) uint32 {
c, err := util.DecryptBase64ToBytes(data, d.password, d.iv)
if err != nil {
if nowConnDevID != 0 {
dbmodel.InsertDevHexCommandErr(nowConnDevID, string(data), "Decrypt err")
}
return 0
}
if util.CheckCRC(c) == false {
dbmodel.InsertDevHexCommandErr(nowConnDevID, string(data), "CheckCRC err")
return 0
}
cLen := len(c)
if cLen < 12 {
dbmodel.InsertDevHexCommandErr(nowConnDevID, string(data), "cLen<12")
return 0
} else if int(c[9])+12 != cLen {
dbmodel.InsertDevHexCommandErr(nowConnDevID, string(data), "cLen!=c[9]+12")
return 0
}
var rData HexData
rData.TimeUtc = uint32(c[3])<<24 | uint32(c[2])<<16 | uint32(c[1])<<8 | uint32(c[0]) // binary.Read(bytes.NewBuffer(cleartext[:4]), binary.BigEndian, &rData.timeUtc) 肯定效率低下,还是自己拼
// 时间有效性判断
nowTimeUtc := uint32(time.Now().Unix())
if nowTimeUtc > rData.TimeUtc+300 || rData.TimeUtc > nowTimeUtc+300 {
dbmodel.InsertDevHexCommandErr(nowConnDevID, string(data), "utc err:"+strconv.FormatUint(uint64(rData.TimeUtc), 10))
return 0
}
// 设备类型判断
if c[4] != d.devType {
dbmodel.InsertDevHexCommandErr(nowConnDevID, string(data), "devType error")
return 0
}
rData.DevID = uint32(c[4])<<24 | uint32(c[5])<<16 | uint32(c[6])<<8 | uint32(c[7])
rData.CtrlCode = c[8]
rData.Length = c[9]
rData.Data = c[10 : cLen-2]
if rData.CtrlCode != 0x41 && rData.CtrlCode != 0x3f { //心跳不记 开机注册不记
insertDevHexCommandRecord(&rData, string(data), 0) //0接收 1回复 2主动下发 异步去搞
}
/*sBuf := */ d.protocolAnalysis(&rData)
if rData.CtrlCode > 0x80 { // 用来判断返回不为空 被动响应都大于0x80
sendStr := d.packageSendData(&rData)
sendStr[0] = '['
sendStr[len(sendStr)-1] = ']'
//if sendFlag {time.Sleep(20*time.Millisecond)} //这句话是为了多帧发送间隔20MS,可以不加试试
if _, err = conn.Write(sendStr); err != nil {
//logger.Log.Debug("conn.Write(sendStr) error", // 刚收到发来的,现在居然发不回去了
// zap.String("Src", "TCP-SERVER-receive"),
// zap.Uint32("DevID", rData.DevID),
// zap.String("RData", string(data)),
// zap.String("SendStr", string(sendStr)),
// zap.String("Conn", conn.RemoteAddr().String()))
//if nowConnDevID == 0 { //刚才没有ID的在这里记
// model.InsertDevHexCommandErr(rData.DevID,string(data),"A error")
//}
return 0
}
if rData.CtrlCode != 0xc1 && rData.CtrlCode != 0xbf { //心跳不记 开机注册不记
insertDevHexCommandRecord(&rData, string(sendStr), 1) //0接收 1回复 2主动下发 异步去搞
}
}
return rData.DevID //解密成功且CRC校验成功,设备类型一致,解析长度正确,则为合法设备
}
func (d *DCLongTCPHex) TCPSend(data *HexData) bool {
//d.ConnectMapRWMutex.RLock()
//c,ok := d.ConnectMap[data.DevID]// conn,ok := d.ConnectMap.Load(data.DevID)
//d.ConnectMapRWMutex.RUnlock()
if conn, ok := d.ConnectMap.Load(data.DevID); ok {
if c, ok := conn.(*net.TCPConn); ok { // 类型断言
sendStr := d.packageSendData(data)
sendStr[0] = '['
sendStr[len(sendStr)-1] = ']'
if _, err := c.Write(sendStr); err != nil {
//d.ConnectMapRWMutex.Lock()
//delete(d.ConnectMap,data.DevID)// d.ConnectMap.Delete(data.DevID)
//d.ConnectMapRWMutex.Unlock()
/*errC*/
_ = c.Close()
d.ConnectMap.Delete(data.DevID)
/*if errC != nil {
model.DevHexConnectRecord(data.DevID,false,'W')
} else {
model.DevHexConnectRecord(data.DevID,false,'w')
}*/
//logger.Log.Debug("conn.Write(sendStr) error", //
// zap.String("Src", "TCP-SERVER-TCPSend"),
// zap.Uint32("DevID", data.DevID),
// zap.Error(err),
// zap.String("SendStr", string(sendStr)),
// zap.String("Conn", c.RemoteAddr().String()),
// zap.String("State", "offline"))
return false
}
insertDevHexCommandRecord(data, string(sendStr), 2) //0接收 1回复 2主动下发
return true
} else {
// ntodo logger map里面存的内容居然类型不对
d.ConnectMap.Delete(data.DevID)
logger.Log.Error("conn.(*net.TCPConn) != ok", //
zap.String("Src", "TCP-SERVER-TCPSend"),
zap.Uint32("DevID", data.DevID),
zap.String("Conn", c.RemoteAddr().String()),
zap.String("State", "offline"))
}
}
return false
}
func (d *DCLongTCPHex) InitNewDCLongTCPHex(password string, iv string, devType uint8, f func(data *HexData)) {
d.password = password
d.iv = iv
d.devType = devType
d.protocolAnalysis = f
d.TCPReceive = d.receiveResponse
// d.ConnectMap = make(map[uint32]*net.TCPConn)
}
// 组装并加密数据
func (d *DCLongTCPHex) packageSendData(sData *HexData) []byte {
hexBuf := make([]byte, sData.Length+12)
sData.TimeUtc = uint32(time.Now().Unix())
hexBuf[0] = byte(sData.TimeUtc)
hexBuf[1] = byte(sData.TimeUtc >> 8)
hexBuf[2] = byte(sData.TimeUtc >> 16)
hexBuf[3] = byte(sData.TimeUtc >> 24)
hexBuf[4] = d.devType
hexBuf[5] = byte(sData.DevID >> 16)
hexBuf[6] = byte(sData.DevID >> 8)
hexBuf[7] = byte(sData.DevID)
hexBuf[8] = sData.CtrlCode
hexBuf[9] = sData.Length
//if sData.Length>0 {
copy(hexBuf[10:], sData.Data[:sData.Length])
//}
util.GetCRC(hexBuf, int(sData.Length)+10)
return util.EncryptBytesToBase64(hexBuf, d.password, d.iv)
}
package dcphone20
import (
"dc_golang_server_1/config"
)
func NewDCPhone20() {
var dcPhone20TCP DCPhone20
dcPhone20TCP.NewDCPhone20("DCRYM-2018-pswd.", "I can't tell YOU", 0x5B) // config
dcPhone20TCP.TCPStart(config.TcpLongPort)
// dcPhone10TCP.NewDCPhone20API(r)
}
package dcphone20
import (
"dc_golang_server_1/dbmodel"
"dc_golang_server_1/devproduct"
"dc_golang_server_1/logger"
"go.uber.org/zap"
"strconv"
"strings"
"sync"
"time"
)
//type DCPhone10StateStruct struct{
// rTime time.Time
// csq0 uint8
// csq1 uint8
// state uint8
// m1state uint8
// m2state uint8
// errCode uint8
//}
type DevStateStruct struct {
Csq0 byte `json:"csq0"`
Csq1 byte `json:"csq1"`
CallModuleStatus byte `json:"call_module_status"`
DevErrorCode byte `json:"dev_error_code"`
EnableKeyboard bool `json:"enable_keyboard"`
CallIn bool `json:"call_in"`
EnableSos bool `json:"enable_sos"`
EnableCall bool `json:"enable_call"`
EnableMsg bool `json:"enable_msg"`
UpdateTime time.Time `json:"update_time"`
}
type DCPhone20 struct {
devproduct.DCLongTCPHex
MapDCPhone10State sync.Map
}
func (dev *DCPhone20) NewDCPhone20(password string, iv string, devType uint8) {
dev.InitNewDCLongTCPHex(password, iv, devType, dev.response)
}
//TCP收到的协议解析
func (dev *DCPhone20) response(data *devproduct.HexData) {
ctrlCode := data.CtrlCode
data.CtrlCode = 0
switch ctrlCode {
// 参数类 para
case 0x03 | 0x80: // "tcp_server_addr", // 硬件连接tcp服务器地址端口 //"\"water-tcp-short.dcrym.com\",8013"
if data.Length > 10 { // len(string(data.Data))
//stringsTemp := strings.SplitN(string(data.Data)[1:], "\",", 2) // [1:data.Length]
//ip := "error"
//var port uint16
//if len(stringsTemp) == 2 {
// if p, err := strconv.ParseUint(stringsTemp[1], 10, 16); err == nil {
// port = uint16(p)
// ip = stringsTemp[0]
// }
//}
//jsonStruct := paraTcpServerAddr{
// data.TimeUtc,
// []uint32{data.DevID},
// struct {
// IP string `json:"ip"`
// Port uint16 `json:"port"`
// }{ip, port},
//}
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x04 | 0x80: // "heart", // 心跳间隔次数 和 心跳间隔时间
if data.Length == 3 {
//jsonStruct := paraHeart{
// data.TimeUtc,
// []uint32{data.DevID},
// struct {
// Time uint16 `json:"time"` // 推荐60
// VoidCount byte `json:"void_count"` // 推荐0
// }{uint16(data.Data[0]) + (uint16(data.Data[1]) << 8), data.Data[2]},
//}
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x05 | 0x80, 0x06 | 0x80, 0x07 | 0x80: //"beep_volume", // 蜂鸣器音量 0-100
// 0x06|0x80, //"speech_volume", // 通话音量 0-10
// 0x07|0x80:// "speech_speed", // 语速 0-9
if data.Length == 1 {
//jsonStruct := paraOneByte{
// data.TimeUtc,
// []uint32{data.DevID},
// data.Data[0],
//}
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x08 | 0x80:
if data.Length == 1 {
//jsonStruct := paraSelectSimModule{
// data.TimeUtc,
// []uint32{data.DevID},
// struct {
// Net byte `json:"net"` // 0/1
// Call byte `json:"call"` // 0/1
// }{0, 0},
//}
//
//if data.Data[0]&1 != 0 {
// jsonStruct.Value.Call = 1
//}
//if data.Data[0]&2 != 0 {
// jsonStruct.Value.Net = 1
//}
//
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x09 | 0x80: // "work_time", //工作时段
//groupNum := data.Length / 6
//workTimeTemp := make([]struct {
// Start uint16 `json:"start"`
// Stop uint16 `json:"stop"`
// EnableKeyboard bool `json:"enable_keyboard"`
// CallIn bool `json:"call_in"`
// EnableSos bool `json:"enable_sos"`
// EnableCall bool `json:"enable_call"`
// EnableMsg bool `json:"enable_msg"`
// WeekDay []bool `json:"week_day"`
//}, groupNum)
//var i uint8
//for i = 0; i < groupNum; i++ {
// workTimeTemp[i].Start = uint16(data.Data[0+i*6]) + uint16(data.Data[1+i*6])<<8
// workTimeTemp[i].Stop = uint16(data.Data[2+i*6]) + uint16(data.Data[3+i*6])<<8
// if (data.Data[4+i*6] & 1) != 0 {
// workTimeTemp[i].EnableCall = true
// } // 允许刷卡
// if (data.Data[4+i*6] & (1 << 1)) != 0 {
// workTimeTemp[i].CallIn = true
// } // 允许呼入
// if (data.Data[4+i*6] & (1 << 2)) != 0 {
// workTimeTemp[i].EnableKeyboard = true
// } // 允许键盘拨号
// if (data.Data[4+i*6] & (1 << 3)) != 0 {
// workTimeTemp[i].EnableMsg = true
// } // 允许留言
// if (data.Data[4+i*6] & (1 << 4)) != 0 {
// workTimeTemp[i].EnableSos = true
// } // 允许紧急呼叫
// workTimeTemp[i].WeekDay = make([]bool, 7)
// for j := 0; j < 7; j++ {
// if (data.Data[5+i*6] & (1 << j)) != 0 {
// workTimeTemp[i].WeekDay[j] = true
// }
// }
// //fmt.Println(workTimeTemp[i].WeekDay)
//}
//
//jsonStruct := paraWorkTime{
// DevTime: data.TimeUtc,
// DevID: []uint32{data.DevID},
//}
//jsonStruct.Value = workTimeTemp
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
case 0x0a | 0x80: // "key_password", // 最长10个字符(数字加*#)
//jsonStruct := paraOneString{
// data.TimeUtc,
// []uint32{data.DevID},
// string(data.Data),
//}
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
// 设备控制类ctrl
case 0x32 | 0x80: // 0x32|0x80:"ctrl/restart_device", // 重启设备 上下行均空
//jsonStruct := paraNoValue{
// data.TimeUtc,
// []uint32{data.DevID},
//}
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
case 0x70 | 0x80: // 0x70|0x80:"ctrl/read_firmware_version", // 读取固件版本
if data.Length > 22 {
//jsonStruct := devUpFirmwareInfo{
// data.TimeUtc,
// []uint32{data.DevID},
// struct {
// MD5 []byte `json:"md5"`
// Length uint32 `json:"length"`
// Version string `json:"version"`
// }{
// data.Data[0:16],
// uint32(data.Data[16]) + (uint32(data.Data[17]) << 8) + (uint32(data.Data[18]) << 16) + (uint32(data.Data[19]) << 24),
// string(data.Data[20:]),
// },
//}
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x71 | 0x80: // "ctrl/update_firmware", // 启动远程更新
if data.Length > 2 {
//jsonStruct := devUpRespondUpdateFirmware{
// DevTime: data.TimeUtc,
// DevID: []uint32{data.DevID},
//}
//
//if data.Data[0] == 1 {
// jsonStruct.Value.RespondUpdateFirmware = true
// jsonStruct.Value.Version = string(data.Data[1 : data.Length-1])
//} else if data.Data[0] == 2 && data.Length > 23 {
// jsonStruct.Value.MD5 = data.Data[1:17]
// jsonStruct.Value.Length = uint32(data.Data[17]) + (uint32(data.Data[18]) << 8) + (uint32(data.Data[19]) << 16) + (uint32(data.Data[20]) << 24)
// jsonStruct.Value.Version = string(data.Data[20:])
//} else {
// logger.Log.Error("data.Data error",
// zap.String("Src", "TCP-SERVER-response"),
// zap.Uint32("DevID", data.DevID),
// zap.Uint8("CtrlCode", ctrlCode),
// zap.Uint8("data.Data[0]", data.Data[0]),
// zap.Uint8s("RecvData", data.Data))
//}
//
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x30 | 0x80:
//jsonStruct := structOnlineDial{
// data.TimeUtc,
// []uint32{data.DevID},
// struct {
// Result uint8 `json:"result"`
// Time uint8 `json:"time"`
// Number string `json:"number"`
// }{
// data.Data[0],
// data.Data[1],
// string(data.Data[2:]),
// },
//}
//x, _ := json.Marshal(jsonStruct)
//_, _ = jeffhttprequest.Post(config.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
case 0x3f: // 0x3f:"ctrl/dev_restart_login",// 开机注册
if data.Length > 75 {
// todoN 考虑第0字节增加模组选择
insertDevHexResetRecord(data)
data.CtrlCode = ctrlCode | 0x80
data.Length = 0
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x41: // "ctrl/dev_up_status",// 心跳上报状态 更新DCPhone10State
if data.Length > 2 { // 至少3个字节
newState := DevStateStruct{
UpdateTime: time.Now(), //.Format("2006-01-02 15:04:05.000000"),
Csq0: data.Data[0],
Csq1: data.Data[1],
}
for i := 0; i < 5; i++ {
if (data.Data[2] & 1) != 0 {
newState.EnableCall = true
} // 允许刷卡
if (data.Data[2] & (1 << 1)) != 0 {
newState.CallIn = true
} // 允许呼入
if (data.Data[2] & (1 << 2)) != 0 {
newState.EnableKeyboard = true
} // 允许键盘拨号
if (data.Data[2] & (1 << 3)) != 0 {
newState.EnableMsg = true
} // 允许留言
if (data.Data[2] & (1 << 4)) != 0 {
newState.EnableSos = true
} // 允许紧急呼叫
}
data.CtrlCode = ctrlCode | 0x80
data.Length = 0
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
//设备使用类 usedevice
case 0x20: // "usedevice/dev_get_family_num",// 查询亲情号码 IC卡
if data.Length == 5 {
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x25: // 查询亲情号码 SIM ICCID
if data.Length == 21 {
// data.CtrlCode = ctrlCode | 0x80
// enc := mahonia.NewEncoder("gbk")
// // 根据设备编号查status area_id,根据area_id和iccid查status family_num
// v := cache.GetDeviceInfo(data.DevID)
// if v.AreaID == 0 { // 后台没添加该设备,返回显示 话机设备未注册
// data.Data[0] = 0xff
// data.Length = 21 + byte(copy(data.Data[21:], enc.ConvertString("话机设备未注册")))
// return
// } // 后台没添加该设备,返回显示 话机设备未注册
// if v.Status == false {//设备已停用,返回显示 设备暂停使用
// data.Data[0] = 0xff
// data.Length = 21 + byte(copy(data.Data[21:], enc.ConvertString("设备暂停使用")))
// return
// } //设备已停用,返回显示 设备暂停使用
// s := cache.GetSimFamilyNum(v.AreaID,string(data.Data[1:]))
// if s.Status == 0{ // 这张卡不对,显示 未查询到亲情号码
// data.Data[0] = 0xff
// data.Length = 21 + byte(copy(data.Data[21:], enc.ConvertString("未查询到亲情号码")))
// return
// } // 这张卡不对,显示 未查询到亲情号码
// if s.Status > 1 { //用户卡暂停使用
// data.Data[0] = 0xff
// data.Length = 21 + byte(copy(data.Data[21:], enc.ConvertString("用户卡暂停使用")))
// return
// } //用户卡暂停使用
// if s.MonthTalkMinutes >= s.MonthPackageMinutes { //本月套餐无剩余通话分钟数
// data.Data[0] = 0xff
// data.Length = 21 + byte(copy(data.Data[21:], enc.ConvertString("本月套餐无剩余通话分钟数")))
// return
// } //本月套餐无剩余通话分钟数
//
// tempIccId := make([]byte,20)
// copy(tempIccId,data.Data[1:])
// data.Data = make([]byte, 255)
// userCanUseTime := v.AllowCallTime
// if (s.MonthPackageMinutes - s.MonthTalkMinutes)<uint16(userCanUseTime){
// userCanUseTime = uint8(s.MonthPackageMinutes - s.MonthTalkMinutes)
// }
// if len(s.Family) > 3 {
// logger.Log.Error("len(sim.Family)>3",
// zap.Int32("AreaID", v.AreaID),
// zap.Uint32("DevID", data.DevID),
// zap.Uint8("CtrlCode", ctrlCode),
// zap.Uint8("DataLen", data.Length),
// zap.Uint8s("RecvData", data.Data),
// zap.String("src", "tcp case 0x25"))
// data.Data[0] = 3
// } else {
// data.Data[0] = uint8(len(s.Family))
// }
// copy(data.Data[1:],tempIccId)
// var i uint8
// data.Length = 21
// for ;i<data.Data[0];i++ {
// if i != 0 {
// data.Data[data.Length] = '-'
// data.Length++
// }
// data.Length += byte(copy(data.Data[data.Length:], s.Family[i].Phone))
// data.Data[data.Length] = '_'
// data.Length++
// data.Length += byte(copy(data.Data[data.Length:], strconv.Itoa(int(userCanUseTime))))
// data.Data[data.Length] = '_'
// data.Length++
// strNickname := enc.ConvertString(s.Family[i].Nickname)
// if len(strNickname) < 17 {
// data.Length += byte(copy(data.Data[data.Length:], strNickname))
// }
// }
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x23: // 0x23:"usedevice/dev_get_family_msg",// 查询留言
if data.Length == 4 {
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x24: // 上报已读留言
if data.Length == 8 {
} else {
data.CtrlCode = ctrlCode | 0x80
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x21: // 0x21:"usedevice/dev_get_call_time",// 获取自由拨号允许时长
if data.Length > 4 {
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x22: // 0x22:"usedevice/dev_post_call_log",// 上报通话记录
if data.Length > 11 {
} else {
data.CtrlCode = ctrlCode | 0x80 //还是回硬件
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x26: // 0x22:"usedevice/dev_post_call_log",// 上报通话记录 SIM ICCID
if data.Length > 27 {
//devInfo := cache.GetDeviceInfo(data.DevID)
//var areaInfo cache.AreaStruct
//if devInfo.AreaID > 0 {
// areaInfo = cache.GetAreaInfo(devInfo.AreaID)
//}
//familyInfo := cache.GetSimFamilyNum(devInfo.AreaID,string(data.Data[1:21]))
//calledNum := string(data.Data[27:])
//var nickname string
//for i:=0;i < len(familyInfo.Family);i++{
// if calledNum == familyInfo.Family[i].Phone {
// nickname = familyInfo.Family[i].Nickname
// break
// }
//}
//// 以事务方式存2张表
//if result := model.InsertUCallRecordAndUpdateUSimInfo(model.TableUserCallRecord{
// //CustomerId:
// //CardUserId:
// //CardUserName:
// CardID: string(data.Data[1:21]),
// CardType:0,
// CalledNumber: calledNum,
// CalledNickname: nickname,
// CallStartAt: time.Unix(int64(data.Data[21]) + int64(data.Data[22])<<8 + int64(data.Data[23])<<16 + int64(data.Data[24])<<24,0).Format("2006-01-02 15:04:05"),
// TalkTime: int16(data.Data[25]) + int16(data.Data[26]<<8),
// AreaId: devInfo.AreaID,
// OperatorId: areaInfo.OperatorID,
// DeviceId: data.DevID,
// Status: data.Data[0],
//});result > 1 {
// return
//} else if result == 0 { //扣套餐分钟数
//
//}
//data.CtrlCode = ctrlCode | 0x80
} else {
data.CtrlCode = ctrlCode | 0x80 //还是回硬件
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0xff: // 硬件被动上报异常
logger.Log.Warn("dev up error 0xff",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
default:
logger.Log.Error("ctrlCode error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
}
func insertDevHexResetRecord(data *devproduct.HexData) {
var resetReason byte
if data.Data[0]&0x03 == 0x03 {
resetReason = 0 // 正常上电
} else if data.Data[0] == 0x40 {
resetReason = 1 // 软件复位
} else {
resetReason = 2 // 异常复位
}
//imei0 := string(data.Data[1:16]) //从索引1到索引16(不包含)
//iccid0 := string(data.Data[16:36])
//imei1 := string(data.Data[36:51])
//iccid1 := string(data.Data[51:71])
var firmwareVersion string
var longitude, latitude uint32
strTemp := strings.Split(string(data.Data[71:]), "-") //data.Data[71:data.Length]
if len(strTemp) == 3 {
d, err := strconv.ParseFloat(strTemp[0], 64)
if err != nil {
logger.Log.Error("Longitude ParseFloat error",
zap.String("Src", "InsertDevHexResetRecord"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.Uint32("DevUtc", data.TimeUtc))
} else {
longitude = uint32(d * 1000000)
}
d, err = strconv.ParseFloat(strTemp[1], 64)
if err != nil {
logger.Log.Error("Latitude ParseFloat error",
zap.String("Src", "InsertDevHexResetRecord"),
zap.Uint32("DevID", data.DevID),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.Uint32("DevUtc", data.TimeUtc))
} else {
latitude = uint32(d * 1000000)
}
firmwareVersion = strTemp[2] //
}
go dbmodel.InsertDevHexResetRecord(dbmodel.TableDevHexResetRecord{
DevId: data.DevID,
DevUtc: data.TimeUtc,
ResetReason: resetReason,
ResetCode: strconv.FormatUint(uint64(data.Data[0]), 16),
Location: [2]uint32{longitude, latitude},
Firmware: firmwareVersion,
})
}
package devproduct
import (
"dc_golang_server_1/config"
"dc_golang_server_1/dbmodel"
"dc_golang_server_1/logger"
"go.uber.org/zap"
"net"
"strconv"
"sync"
"sync/atomic"
"time"
)
type ITCPLongServer interface {
TCPStart(port string)
}
type receiveCallbackFunc func(*net.TCPConn, []byte, uint32) uint32 //定义接收到数据的回调函数的函数类型
type TCPLongServer struct {
TCPReceive receiveCallbackFunc
ConnSocketCount int32
ConnectMap sync.Map // 用这个可能性能不行,测试下,不行就用map加锁
// rwConnSocketCount chan int // 20210815 将对ConnSocketCount的操作修改为原子操作
// ConnectMapRWMutex sync.RWMutex
// ConnectMap map[uint32]*net.TCPConn // Connection
}
func (s *TCPLongServer) TCPStart(port string) {
go func() {
// 获取一个TCP的Addr
addr, err := net.ResolveTCPAddr("tcp4", "0.0.0.0:"+port)
if err != nil {
panic("error: net.ResolveTCPAddr " + port + err.Error())
}
// 监听服务器地址
listener, err := net.ListenTCP("tcp4", addr)
if err != nil {
logger.Log.Panic("net.ListenTCP:"+port,
zap.String("Src", "TCP-SERVER"),
zap.Error(err))
}
// 启动server
for {
conn, err1 := listener.AcceptTCP() // 阻塞等待客户端建立连接请求
if err1 != nil {
logger.Log.Warn("listener.AcceptTCP()",
zap.String("Src", "TCP-SERVER"),
zap.Error(err1))
continue
}
go s.connectionHandle(conn, s.TCPReceive)
}
}()
}
// 主动断开某链接,其实在新连接上来的时候,可以查下如果map里面有现在的设备号,就可以把旧的断掉
//func (s *TCPLongServer) DeleteConnection(key uint32){
// if conn,ok := s.ConnectMap.Load(key);ok {
// if c,ok := conn.(*net.TCPConn);ok{ // 类型断言
// c.Close()
// }
// }
// s.ConnectMap.Delete(key)
// log.WithFields(log.Fields{
// "Src": "TCP-SERVER-DeleteConnection",
// "DevID": key,
// "Conn":conn.RemoteAddr(),
// "State": "offline",
// }).Debugln("conn.Write(sendStr) error")
//}
func (s *TCPLongServer) connectionHandle(conn *net.TCPConn, callBack receiveCallbackFunc) {
var myDevID uint32 // golang 默认0
atomic.AddInt32(&s.ConnSocketCount, 1)
defer func() {
//s.rwConnSocketCount <- -1
if s.ConnSocketCount > 0 {
atomic.AddInt32(&s.ConnSocketCount, -1)
} else {
logger.Log.Error("s.ConnSocketCount error",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Int32("ConnSocketCount", s.ConnSocketCount))
}
if myDevID != 0 {
if connMyID, ok := s.ConnectMap.Load(myDevID); ok { //查一下设备旧链接还在的话,关掉
if co, ok := connMyID.(*net.TCPConn); ok { // 类型断言
if co == conn {
s.ConnectMap.Delete(myDevID)
dbmodel.DevHexConnectRecord(myDevID, 1) // state 0:新连接来了 1:设备正常离线 2:正常离线 3:新连接挤掉就连接 4:未知异常(连接池类型断言失败)
//logger.Log.Debug("device offline",
// zap.String("Src", "TCP-SERVER-connectionHandle"),
// zap.Uint32("DevID", myDevID),
// zap.String("Conn", conn.RemoteAddr().String()),
// zap.String("State", "offline"))
} else {
// s.ConnectMap.Delete(myDevID) 这里人家存了新的,不能去删了噻
dbmodel.DevHexConnectRecord(myDevID, 3) // state 0:新连接来了 1:设备正常离线 2:正常离线 3:新连接挤掉就连接 4:未知异常(连接池类型断言失败)
//logger.Log.Debug("have a new link,close old link",
// zap.String("Src", "TCP-SERVER-connectionHandle"),
// zap.Uint32("DevID", myDevID),
// zap.String("Conn", conn.RemoteAddr().String()),
// zap.String("State", "offline"))
}
} else {
s.ConnectMap.Delete(myDevID)
//logger.Log.Error("connMyID.(*net.TCPConn) != ok",
// zap.String("Src", "TCP-SERVER-connectionHandle"),
// zap.Uint32("DevID", myDevID),
// zap.String("Conn", conn.RemoteAddr().String()),
// zap.String("State", "offline")) // 类型断言失败
dbmodel.DevHexConnectRecord(myDevID, 4) // state 0:新连接来了 1:设备正常离线 2:正常离线 3:新连接挤掉就连接 4:未知异常(连接池类型断言失败)
}
} else {
//logger.Log.Debug("map no have myDevID",
// zap.String("Src", "TCP-SERVER-connectionHandle"),
// zap.Uint32("DevID", myDevID),
// zap.String("Conn", conn.RemoteAddr().String()),
// zap.String("State", "offline"))
dbmodel.DevHexConnectRecord(myDevID, 2) // state 0:新连接来了 1:设备正常离线 2:正常离线 3:新连接挤掉就连接 4:未知异常(连接池类型断言失败)
}
}
// _ = conn.SetReadDeadline(time.Time{}) // 设置回去,但是不知道需不需要这句话
_ = conn.Close()
// fmt.Println("-----------------------------------Out ConnSocketCount:", s.ConnSocketCount)
}()
if s.ConnSocketCount > config.TcpLongMaxConnections { //限制最大连接数2万个配置文件 最大连接限制数添加到配置文件
logger.Log.Error("ConnSocketCount overrun:"+strconv.Itoa(int(config.TcpLongMaxConnections)),
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Int32("ConnSocketCount", s.ConnSocketCount))
return
}
_ = conn.SetKeepAlive(false)
buf := make([]byte, 512)
rBuf := make([]byte, 512)
rLen := 0
i := 0
timeConn := time.Now().Unix() + config.TcpLongNewConnRightfulTimeout //配置文件 120秒
for {
if myDevID == 0 {
if time.Now().Unix() > timeConn { // 连上来2分钟都没整个正确的数据来,就给它断球
logger.Log.Warn("NewConnRightfulTimeout:"+strconv.Itoa(int(config.TcpLongNewConnRightfulTimeout)), // 超时没收到合法的指令
zap.String("Src", "TCP-SERVER-connectionHandle"),
// zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Int32("ConnSocketCount", s.ConnSocketCount))
return
}
if err := conn.SetReadDeadline(time.Now().Add(config.TcpLongNewConnReadDeadline)); err != nil { // 配置文件 新连接1分钟超时未收到数据(配置文件用秒)
logger.Log.Warn("conn.SetReadDeadline:new", //
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Error(err),
zap.Int32("ConnSocketCount", s.ConnSocketCount))
return
}
} else {
if err := conn.SetReadDeadline(time.Now().Add(config.TcpLongOldConnReadDeadline)); err != nil { // 配置文件 老连接3分钟超时未收到数据(配置文件用秒)
logger.Log.Warn("conn.SetReadDeadline:old", //
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Error(err),
zap.Int32("ConnSocketCount", s.ConnSocketCount))
return
}
}
cnt, err := conn.Read(buf)
if err != nil {
// fmt.Println("conn.Read:", err)
// logger debug 其中存在超时,或新连接来关闭了旧链接
logger.Log.Debug("read error",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Error(err))
return
}
for i = 0; i < cnt; i++ {
if rBuf[0] != '{' || rLen == 0 {
if buf[i] == '{' {
rBuf[0] = '{'
rLen = 1
} else {
rLen = 0
}
} else if buf[i] == '}' {
if rLen == 1 {
if i+1 == cnt { //只有当后面没跟其他数据的时候,才回空心跳
if _, err2 := conn.Write([]byte("[]")); err2 != nil {
return
}
}
} else {
newID := callBack(conn, rBuf[1:rLen], myDevID)
if newID == 0 {
return
} else if newID != myDevID {
if myDevID == 0 {
if connOld, ok := s.ConnectMap.Load(newID); ok { //查一下设备旧链接还在的话,关掉
if co, ok1 := connOld.(*net.TCPConn); ok1 { // 类型断言
s.ConnectMap.Store(newID, conn) //先存新的再关
_ = co.Close()
} /* else {
s.ConnectMap.Delete(newID)
fmt.Printf("newID : s.ConnectMap.类型断言(%08X)错误\n",newID)
// logger 类型断言不OK
}*/
}
// logger 新链接来的合法设备
dbmodel.DevHexConnectRecord(newID, 0)
//logger.Log.Debug("a new link is coming",
// zap.String("Src", "TCP-SERVER-connectionHandle"),
// zap.Uint32("DevID", newID),
// zap.String("Conn", conn.RemoteAddr().String()),
// zap.String("State", "online"))
} else {
s.ConnectMap.Delete(myDevID)
logger.Log.Error("DevID changed",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("OldDevId", myDevID),
zap.Uint32("NewDevId", newID),
zap.String("Conn", conn.RemoteAddr().String()))
}
s.ConnectMap.Store(newID, conn)
myDevID = newID
} else { //这个地方应该查下map里面有没有,没有就是没对
if connMyID, ok := s.ConnectMap.Load(myDevID); ok { //
if co, ok2 := connMyID.(*net.TCPConn); ok2 { // 类型断言
if co != conn {
s.ConnectMap.Store(myDevID, conn)
logger.Log.Error("co != conn",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "restore myDevId"))
}
} else {
s.ConnectMap.Store(myDevID, conn)
logger.Log.Error("connMyID.(*net.TCPConn) != ok",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "restore myDevId")) // 类型断言失败
}
} else {
s.ConnectMap.Store(myDevID, conn)
logger.Log.Error("map no myDevID",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "restore myDevId"))
}
}
}
rLen = 0
} else if buf[i] == '{' {
rBuf[0] = '{'
rLen = 1
} else {
rBuf[rLen] = buf[i]
if rLen < 512 {
rLen++
} else {
logger.Log.Warn("rBufOverrun:512",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint8s("RBuf", rBuf),
zap.Int("RLen", rLen),
// zap.Uint32("DevID", myDevID),
zap.String("Conn", conn.RemoteAddr().String()))
rLen = 0
}
}
}
}
}
module dc_golang_server_1
go 1.17
require (
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.7.4 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.9.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/lib/pq v1.10.3 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
github.com/ugorji/go/codec v1.2.6 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
go.uber.org/zap v1.19.1 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect
golang.org/x/text v0.3.6 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/ini.v1 v1.63.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM=
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A=
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg=
github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c=
gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
panic: SelectAreaToMap rows pq: column "status" does not exist
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x6f7cce]
goroutine 1 [running]:
database/sql.(*Rows).close(0x0, {0x0, 0x0})
C:/Users/Administrator/go/go1.17/src/database/sql/sql.go:3267 +0x8e
database/sql.(*Rows).Close(0x2f9620)
C:/Users/Administrator/go/go1.17/src/database/sql/sql.go:3263 +0x1d
panic({0x7681e0, 0xc0003851e0})
C:/Users/Administrator/go/go1.17/src/runtime/panic.go:1038 +0x215
log.Panicln({0xc00029fdf0, 0x902f30, 0xc0000aa1b0})
C:/Users/Administrator/go/go1.17/src/log/log.go:368 +0x65
dc_golang_server_1/cache.initAreaMap()
D:/work/SoftwareGroup/goland_project/dc_golang_server_1/cache/cmap_area.go:19 +0x1c8
dc_golang_server_1/cache.Init()
D:/work/SoftwareGroup/goland_project/dc_golang_server_1/cache/cache.go:165 +0x17
main.main()
D:/work/SoftwareGroup/goland_project/dc_golang_server_1/main.go:75 +0x51
package logger
import (
config2 "dc_golang_server_1/config"
"github.com/gin-gonic/gin"
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"os"
"time"
)
var Log *zap.Logger
func InitLogger() {
config := zapcore.EncoderConfig{
MessageKey: "msg", //结构化(json)输出:msg的key
LevelKey: "level", //结构化(json)输出:日志级别的key(INFO,WARN,ERROR等)
TimeKey: "ts", //结构化(json)输出:时间的key(INFO,WARN,ERROR等)
CallerKey: "file", //结构化(json)输出:打印日志的文件对应的Key
EncodeLevel: zapcore.CapitalLevelEncoder, //将日志级别转换成大写(INFO,WARN,ERROR等)
EncodeCaller: zapcore.ShortCallerEncoder, //采用短文件路径编码输出(test/main.go:14 )
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
}, //输出的时间格式
//EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
// enc.AppendInt64(int64(d) / 1000000)
//},//
}
//debug info
infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl < zapcore.WarnLevel && lvl >= config2.LogLevel
})
//warn
warnLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl == zapcore.WarnLevel && lvl >= config2.LogLevel
})
//error DPanic Panci Fatal
errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl > zapcore.WarnLevel && lvl >= config2.LogLevel
})
infoWriter := &lumberjack.Logger{
Filename: config2.LogPath + "info.log",
MaxSize: config2.LogFileMaxSize, //最大M数,超过则切割
MaxBackups: config2.LogInfoMaxFileNum, //最大文件保留数,超过就删除最老的日志文件
MaxAge: config2.LogInfoMaxFileDay, //保存30天
Compress: false, //是否压缩
}
warnWriter := &lumberjack.Logger{
Filename: config2.LogPath + "warn.log",
MaxSize: config2.LogFileMaxSize, //最大M数,超过则切割
MaxBackups: config2.LogWarnMaxFileNum, //最大文件保留数,超过就删除最老的日志文件
MaxAge: config2.LogWarnMaxFileDay, //保存30天
Compress: false, //是否压缩
}
errorWriter := &lumberjack.Logger{
Filename: config2.LogPath + "error.log",
MaxSize: config2.LogFileMaxSize, //最大M数,超过则切割
MaxBackups: config2.LogErrorMaxFileNum, //最大文件保留数,超过就删除最老的日志文件
MaxAge: config2.LogErrorMaxFileDay, //保存30天
Compress: false, //是否压缩
}
core := zapcore.NewTee(
zapcore.NewCore(zapcore.NewJSONEncoder(config), zapcore.AddSync(infoWriter), infoLevel), // zapcore.NewConsoleEncoder(encoder)
zapcore.NewCore(zapcore.NewJSONEncoder(config), zapcore.AddSync(warnWriter), warnLevel), //
zapcore.NewCore(zapcore.NewJSONEncoder(config), zapcore.AddSync(errorWriter), errorLevel), //
//zapcore.NewCore(zapcore.NewJSONEncoder(encoder), zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)), logLevel),//同时将日志输出到控制台,NewJSONEncoder 是结构化输出
)
Log = zap.New(core, zap.AddStacktrace(zap.ErrorLevel))
}
func HttpGinLog() gin.HandlerFunc { //logger *log.Log
return func(c *gin.Context) {
startTime := time.Now().UnixNano()
c.Next()
// stopTime := time.Since(startTime)
// spendTime := stopTime.Nanoseconds()/1000000///fmt.Sprintf("%d ms", (stopTime.Nanoseconds()+500000)/1000000)
spendTime := time.Now().UnixNano() - startTime
hostName, err := os.Hostname()
if err != nil {
hostName = "unknown"
}
statusCode := c.Writer.Status()
clientIp := c.ClientIP()
userAgent := c.Request.UserAgent()
dataSize := c.Writer.Size()
if dataSize < 0 {
dataSize = 0
}
method := c.Request.Method
path := c.Request.RequestURI
//c.Request.Body.Read()
//body := c.Request.Body
//para := c.Params
//entry := Log.WithFields(log.Fields{
// "HostName": hostName,
// "Status": statusCode,
// "SpendNanoS": spendTime,
// "Ip": clientIp,
// "Method": method,
// "Path": path,
// "DataSize": dataSize,
// "Agent": userAgent,
//})
if len(c.Errors) > 0 {
//entry.Error(c.Errors.ByType(gin.ErrorTypePrivate).String())
Log.Error(c.Errors.ByType(gin.ErrorTypePrivate).String(),
zap.String("HostName", hostName),
zap.Int("Status", statusCode),
zap.Int64("SpendNanoS", spendTime),
zap.String("Ip", clientIp),
zap.String("Method", method),
zap.String("Path", path),
zap.Int("DataSize", dataSize),
zap.String("Agent", userAgent))
}
if statusCode >= 500 {
Log.Error("",
zap.String("HostName", hostName),
zap.Int("Status", statusCode),
zap.Int64("SpendNanoS", spendTime),
zap.String("Ip", clientIp),
zap.String("Method", method),
zap.String("Path", path),
zap.Int("DataSize", dataSize),
zap.String("Agent", userAgent))
} else if statusCode >= 400 {
Log.Warn("",
zap.String("HostName", hostName),
zap.Int("Status", statusCode),
zap.Int64("SpendNanoS", spendTime),
zap.String("Ip", clientIp),
zap.String("Method", method),
zap.String("Path", path),
zap.Int("DataSize", dataSize),
zap.String("Agent", userAgent))
} else {
Log.Info("",
zap.String("HostName", hostName),
zap.Int("Status", statusCode),
zap.Int64("SpendNanoS", spendTime),
zap.String("Ip", clientIp),
zap.String("Method", method),
zap.String("Path", path),
zap.Int("DataSize", dataSize),
zap.String("Agent", userAgent))
}
}
}
//import (
// "github.com/gin-gonic/gin"
// rotatelogs "github.com/lestrrat-go/file-rotatelogs"
// "github.com/rifflock/lfshook"
// log "github.com/sirupsen/logrus"
// "jeff_workstation_1/util"
// "os"
// "time"
//)
//
//func InitLogger(filePath string){
//
// // log.SetOutput(colorable.NewColorableStdout())
//
// // log.SetOutput(f)
// log.SetLevel(util.LogLevel)
//
// TraceLogWriter,_ := rotatelogs.New(
// filePath+"Trace_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(util.LogTraceWithMaxAge),
// rotatelogs.WithRotationTime(util.LogTraceWithRotationTime),
// //rotatelogs.WithLinkName(linkName),
// )
// DebugLogWriter,_ := rotatelogs.New(
// filePath+"Debug_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(util.LogDebugWithMaxAge),
// rotatelogs.WithRotationTime(util.LogDebugWithRotationTime),
// //rotatelogs.WithLinkName(linkName),
// )
// infoLogWriter,_ := rotatelogs.New(
// filePath+"Info_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(util.LogInfoWithMaxAge),
// rotatelogs.WithRotationTime(util.LogInfoWithRotationTime),
// //rotatelogs.WithLinkName("tcp_info.log"),
// )
// WarnLogWriter,_ := rotatelogs.New(
// filePath+"Warn_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(util.LogWarnWithMaxAge),
// rotatelogs.WithRotationTime(util.LogWarnWithRotationTime),
// //rotatelogs.WithLinkName("tcp_warn.log"),
// )
// ErrorLogWriter,_ := rotatelogs.New(
// filePath+"Error_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(util.LogErrorWithMaxAge),
// rotatelogs.WithRotationTime(util.LogErrorWithRotationTime),
// //rotatelogs.WithLinkName("tcp_error.log"),
// )
//
// writeMap := lfshook.WriterMap{
// log.TraceLevel: TraceLogWriter,
// log.DebugLevel: DebugLogWriter,
// log.InfoLevel: infoLogWriter,
// log.WarnLevel: WarnLogWriter,
// log.ErrorLevel: ErrorLogWriter,
// log.PanicLevel: ErrorLogWriter,
// log.FatalLevel: ErrorLogWriter,
// }
// hook := lfshook.NewHook(writeMap,&log.JSONFormatter{
// TimestampFormat: "2006-01-02 15:04:05.000000",
// })
//
// log.AddHook(hook)
// return
//}
//
//func HttpGinLog() gin.HandlerFunc{ //logger *log.Log
// return func(c *gin.Context) {
// startTime := time.Now().UnixNano()
// c.Next()
// //stopTime := time.Since(startTime)
// //spendTime := stopTime.Nanoseconds()/1000000///fmt.Sprintf("%d ms", (stopTime.Nanoseconds()+500000)/1000000)
// spendTime := time.Now().UnixNano() - startTime
// hostName, err := os.Hostname()
// if err != nil {
// hostName = "unknown"
// }
// statusCode := c.Writer.Status()
// clientIp := c.ClientIP()
// userAgent := c.Request.UserAgent()
// dataSize := c.Writer.Size()
// if dataSize < 0 {
// dataSize = 0
// }
// method := c.Request.Method
// path := c.Request.RequestURI
//
// //c.Request.Body.Read()
// //body := c.Request.Body
// //para := c.Params
//
// entry := log.WithFields(log.Fields{
// "HostName": hostName,
// "Status": statusCode,
// "SpendNanoS": spendTime,
// "Ip": clientIp,
// "Method": method,
// "Path": path,
// "DataSize": dataSize,
// "Agent": userAgent,
// })
//
// if len(c.Errors) > 0 {
// entry.Error(c.Errors.ByType(gin.ErrorTypePrivate).String())
// }
// if statusCode >= 500 {
// entry.Error()
// } else if statusCode >= 400 {
// entry.Warn()
// } else {
// entry.Info()
// }
// }
//}
package main
import (
"dc_golang_server_1/api"
"dc_golang_server_1/cache"
"dc_golang_server_1/config"
"dc_golang_server_1/dbmodel"
"dc_golang_server_1/devproduct/dcphone20"
"dc_golang_server_1/logger"
"os"
"runtime"
"syscall"
)
//windows
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
)
func setStdHandle(stdhandle int32, handle syscall.Handle) error {
r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
if r0 == 0 {
if e1 != 0 {
return error(e1)
}
return syscall.EINVAL
}
return nil
}
// redirectStderr to the file passed in
func redirectStderrWindows(f *os.File) {
err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
if err != nil {
logger.Log.Panic(err.Error())
}
// SetStdHandle does not affect prior references to stderr
os.Stderr = f
}
//windows end
//func redirectStderrLinux(f *os.File) {
// err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
// if err != nil {
// logger.Log.Panic(err.Error())
// }
//}
//func init() {
//
//}
func initConfigAndLogger() {
config.ConfigInit()
logger.InitLogger()
f, err := os.OpenFile(config.LogPath+"panic.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
if err != nil {
logger.Log.Panic(err.Error())
}
redirectStderrWindows(f)
//redirectStderrLinux(f)
}
func main() { //
runtime.GOMAXPROCS(runtime.NumCPU())
initConfigAndLogger()
dbmodel.InitDb()
defer dbmodel.CloseDb()
cache.Init()
dcphone20.NewDCPhone20()
//dcdrinking60.NewDCDrinking60()
api.InitRouter()
}
package middleware
import (
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
func Cors() gin.HandlerFunc {
return func(context *gin.Context) {
if context.Request.Method == "OPTIONS" {
origin := context.Request.Header.Get("Origin")
var headerKeys []string
for k, _ := range context.Request.Header {
headerKeys = append(headerKeys, k)
}
headerStr := strings.Join(headerKeys, ",")
if headerStr != "" {
headerStr = "access-control-allow-origin, access-control-allow-headers, " + headerStr //fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %s", headerStr) 测试了下,速度忆氧
} else {
headerStr = "access-control-allow-origin, access-control-allow-headers"
}
if origin != "" {
context.Writer.Header().Set("Access-Control-Allow-Origin", "*")
context.Header("Access-Control-Allow-Origin", "*") // 设置允许访问所有域
context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
context.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")
context.Header("Access-Control-Max-Age", "172800")
context.Header("Access-Control-Allow-Credentials", "false")
context.Set("content-type", "application/json") //// 设置返回格式是json
}
context.JSON(http.StatusOK, "Options Request!")
}
context.Next()
}
}
//func Cors() gin.HandlerFunc {
// return func(context *gin.Context) {
// method := context.Request.Method
// origin := context.Request.Header.Get("Origin")
// var headerKeys []string
// for k, _ := range context.Request.Header {
// headerKeys = append(headerKeys, k)
// }
// headerStr := strings.Join(headerKeys, ",")
// if headerStr != "" {
// headerStr = fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %s", headerStr)
// } else {
// headerStr = "access-control-allow-origin, access-control-allow-headers"
// }
//
// if origin != "" {
// context.Writer.Header().Set("Access-Control-Allow-Origin", "*")
// context.Header("Access-Control-Allow-Origin", "*") // 设置允许访问所有域
// context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
// context.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
// context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")
// context.Header("Access-Control-Max-Age", "172800")
// context.Header("Access-Control-Allow-Credentials", "false")
// context.Set("content-type", "application/json") //// 设置返回格式是json
// }
//
// if method == "OPTIONS" {
// context.JSON(http.StatusOK, "Options Request!")
// }
//
// context.Next()
// }
//}
package middleware
import (
"dc_golang_server_1/util"
"fmt"
"github.com/gin-gonic/gin"
"math/rand"
"time"
)
const jeffWTKey = "jeffWT@666%b;'~+"
const jeffWTTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
type JeffWTInfo struct {
UID int32
UserName string // 最长32字节
CreatTime uint64
ExpireTime uint64
}
// 定义错误
//var (
// TokenExpired error = errors.New("Token已过期,请重新登录")
// TokenNotValidYet error = errors.New("Token无效,请重新登录")
// TokenMalformed error = errors.New("Token不正确,请重新登录")
// TokenInvalid error = errors.New("这不是一个token,请重新登录")
//)
// CreateToken 生成token
func CreateToken(info JeffWTInfo) string {
info.UID = ^info.UID
info.CreatTime = ^info.CreatTime
info.ExpireTime = ^info.ExpireTime
var clear [52]byte //= make([]byte, 20)
var str [30]byte
for i := 0; i < len(info.UserName); i++ {
str[i] = info.UserName[i] + (uint8(i) << 2)
}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
clear[0] = str[18] + 76
clear[1] = byte(info.CreatTime >> 16)
clear[2] = byte(info.ExpireTime >> 8)
clear[3] = byte(info.UID >> 24)
clear[4] = str[29] + 60
clear[5] = byte(r.Intn(256))
clear[6] = byte(info.UID >> 8)
clear[7] = byte(info.ExpireTime)
clear[8] = byte(r.Intn(256))
clear[9] = str[9]
clear[10] = byte(r.Intn(256))
clear[11] = byte(info.CreatTime >> 24)
clear[12] = byte(info.CreatTime)
clear[13] = byte(info.ExpireTime >> 24)
clear[14] = 0x16 + clear[2] - clear[0] + clear[11] - clear[7] - clear[12] + clear[10]
clear[15] = byte(r.Intn(256))
clear[16] = byte(info.UID >> 16)
clear[17] = byte(info.CreatTime >> 8)
clear[18] = byte(info.ExpireTime >> 16)
clear[19] = str[0] + 90
clear[29] = str[28] + clear[10] + clear[8]
clear[29] = str[25]
clear[29] = str[22]
clear[29] = str[13]
clear[29] = str[12]
clear[29] = byte(info.UID)
clear[29] = str[0]
clear[29] = str[1]
clear[29] = str[2]
clear[29] = str[3]
clear[29] = str[4]
clear[29] = str[5]
clear[29] = str[6]
clear[29] = str[7]
clear[29] = str[8]
clear[29] = str[9]
clear[29] = str[10]
clear[29] = str[11]
clear[29] = str[12]
clear[29] = str[13]
clear[29] = str[14]
// todo 根据缓存来,记得CRC
fmt.Println(clear[:19])
util.GetCRC(clear[:19], 19)
s := util.EncryptBytesToBase64URL(clear[:], jeffWTKey)
//fmt.Println(s)
result := make([]byte, 32)
copy(result[:8], s[20:])
copy(result[11:], s[:20])
result[8] = jeffWTTable[r.Intn(64)]
result[9] = jeffWTTable[r.Intn(64)]
result[10] = jeffWTTable[r.Intn(64)]
result[31] = jeffWTTable[r.Intn(64)]
return string(result)
}
// ParserToken 解析token
//func (j *JWT) ParserToken(tokenString string) (*MyClaims, error) {
// token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
// return j.JwtKey, nil
// })
//
// if err != nil {
// if ve, ok := err.(*jwt.ValidationError); ok {
// if ve.Errors&jwt.ValidationErrorMalformed != 0 {
// return nil, errors.New("Token不正确,请重新登录")
// } else if ve.Errors&jwt.ValidationErrorExpired != 0 {
// // Token is expired
// return nil, errors.New("Token已过期,请重新登录")
// } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
// return nil, errors.New("Token无效,请重新登录")
// } else {
// return nil, errors.New("这不是一个token,请重新登录")
// }
// }
// }
//
// if token != nil {
// if claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
// return claims, nil
// }
// return nil, errors.New("这不是一个token,请重新登录")
// }
//
// return nil, errors.New("这不是一个token,请重新登录")
//}
// JwtToken jwt中间件
func JwtToken() gin.HandlerFunc {
return func(c *gin.Context) {
//tokenHeader := c.Request.Header.Get("Authorization")
//if tokenHeader == "" {
// c.JSON(http.StatusOK, gin.H{
// "status": 1004,
// "message": "TOKEN不存在",
// })
// c.Abort()
// return
//}
//
//checkToken := strings.Split(tokenHeader, " ")
//if len(checkToken) == 0 {
// c.JSON(http.StatusOK, gin.H{
// "status": 1007,
// "message": "TOKEN格式错误",
// })
// c.Abort()
// return
//}
//
//if len(checkToken) != 2 || checkToken[0] != "Bearer" {
// c.JSON(http.StatusOK, gin.H{
// "status": 1007,
// "message": "TOKEN格式错误",
// })
// c.Abort()
// return
//}
//
//j := NewJWT()
//// 解析token
//claims, err := j.ParserToken(checkToken[1])
//if err != nil {
// //if err == TokenExpired {
// // c.JSON(http.StatusOK, gin.H{
// // "status": 500,
// // "message": "token授权已过期,请重新登录",
// // "data": nil,
// // })
// // c.Abort()
// // return
// //}
//
// c.JSON(http.StatusOK, gin.H{
// "status": 500,
// "message": err.Error(),
// "data": nil,
// })
// c.Abort()
// return
//}
//
//c.Set("username", claims)
c.Next()
}
}
//var JwtKey = []byte(utils.JwtKey)
//
//type MyClaims struct {
// Username string `json:"username"`
// jwt.StandardClaims
//}
//
//// 生成token
//func SetToken(username string) (string,int){
// setClaims := MyClaims{
// username,
// jwt.StandardClaims{
// ExpiresAt: time.Now().Add(10*time.Hour).Unix(),
// Issuer: "ginblog",
// },
// }
//
// reqClaim := jwt.NewWithClaims(jwt.SigningMethodHS256, setClaims)
// token,err := reqClaim.SignedString(JwtKey)
// if err != nil {
// return "",errmsg.ERROR
// }
// return token,errmsg.SUCCSE
//}
//
//// 验证token
//func CheckToken(token string) (*MyClaims, int){
// if token == "" || token == "null"{
// return nil,errmsg.ERROR
// }
// setToken,_ := jwt.ParseWithClaims(token, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
// return JwtKey, nil
// })
// if key,_ := setToken.Claims.(*MyClaims); setToken.Valid{
// return key,errmsg.SUCCSE
// }
// return nil,errmsg.ERROR
//}
//
//// jwt中间件
//func JwtToken() gin.HandlerFunc{
// var code int
// return func(c *gin.Context) {
// tokenHeader := c.Request.Header.Get("Authorization")
//
// if tokenHeader == "" {
// code = errmsg.ERROR_TOKEN_EXIST
// c.JSON(http.StatusOK,gin.H{
// "code":code,
// "message":errmsg.GetErrMsg(code),
// })
// c.Abort()
// return
// }
// checkToken := strings.SplitN(tokenHeader, " ", 2)
// if len(checkToken) != 2 && checkToken[0] != "Bearer" {
// code = errmsg.ERROR_TOKEN_TYPE_WRONG
// c.JSON(http.StatusOK,gin.H{
// "code":code,
// "message":errmsg.GetErrMsg(code),
// })
// c.Abort()
// return
// }
// key,tCode := CheckToken(checkToken[1])
// if tCode == errmsg.ERROR {
// code = errmsg.ERROR_TOKEN_WRONG
// c.JSON(http.StatusOK,gin.H{
// "code":code,
// "message":errmsg.GetErrMsg(code),
// })
// c.Abort()
// return
// }
// if time.Now().Unix() > key.ExpiresAt {
// code = errmsg.ERROR_TOKEN_RUNTIME
// c.JSON(http.StatusOK,gin.H{
// "code":code,
// "message":errmsg.GetErrMsg(code),
// })
// c.Abort()
// return
// }
//
// c.Set("username",key.Username)
// c.Next()
// }
//}
package util
// 全角转换半角
func DBCtoSBC(s string) string {
retstr := ""
for _, i := range s {
inside_code := i
if inside_code == 12288 {
inside_code = 32
} else {
inside_code -= 65248
}
if inside_code < 32 || inside_code > 126 {
retstr += string(i)
} else {
retstr += string(inside_code)
}
}
return retstr
}
//import (
// "sort"
// "strings"
//)
//
//type dict struct {
// x, y rune
//}
//
//var toSBC = []dict{
// {0x00A2, 0xFFE0},
// {0x00A3, 0xFFE1},
// {0x00A5, 0xFFE5},
// {0x00A6, 0xFFE4},
// {0x00AC, 0xFFE2},
// {0x00AF, 0xFFE3},
// {0xFF61, 0x3002},
// {0xFF62, 0x300C},
// {0xFF63, 0x300D},
// {0xFF64, 0x3001},
// {0xFF65, 0x30FB},
// {0xFF66, 0x30F2},
// {0xFF67, 0x30A1},
// {0xFF68, 0x30A3},
// {0xFF69, 0x30A5},
// {0xFF6A, 0x30A7},
// {0xFF6B, 0x30A9},
// {0xFF6C, 0x30E3},
// {0xFF6D, 0x30E5},
// {0xFF6E, 0x30E7},
// {0xFF6F, 0x30C3},
// {0xFF70, 0x30FC},
// {0xFF71, 0x30A2},
// {0xFF72, 0x30A4},
// {0xFF73, 0x30A6},
// {0xFF74, 0x30A8},
// {0xFF75, 0x30AA},
// {0xFF76, 0x30AB},
// {0xFF77, 0x30AD},
// {0xFF78, 0x30AF},
// {0xFF79, 0x30B1},
// {0xFF7A, 0x30B3},
// {0xFF7B, 0x30B5},
// {0xFF7C, 0x30B7},
// {0xFF7D, 0x30B9},
// {0xFF7E, 0x30BB},
// {0xFF7F, 0x30BD},
// {0xFF80, 0x30BF},
// {0xFF81, 0x30C1},
// {0xFF82, 0x30C4},
// {0xFF83, 0x30C6},
// {0xFF84, 0x30C8},
// {0xFF85, 0x30CA},
// {0xFF86, 0x30CB},
// {0xFF87, 0x30CC},
// {0xFF88, 0x30CD},
// {0xFF89, 0x30CE},
// {0xFF8A, 0x30CF},
// {0xFF8B, 0x30D2},
// {0xFF8C, 0x30D5},
// {0xFF8D, 0x30D8},
// {0xFF8E, 0x30DB},
// {0xFF8F, 0x30DE},
// {0xFF90, 0x30DF},
// {0xFF91, 0x30E0},
// {0xFF92, 0x30E1},
// {0xFF93, 0x30E2},
// {0xFF94, 0x30E4},
// {0xFF95, 0x30E6},
// {0xFF96, 0x30E8},
// {0xFF97, 0x30E9},
// {0xFF98, 0x30EA},
// {0xFF99, 0x30EB},
// {0xFF9A, 0x30EC},
// {0xFF9B, 0x30ED},
// {0xFF9C, 0x30EF},
// {0xFF9D, 0x30F3},
// {0xFF9E, 0x309B},
// {0xFF9F, 0x309C},
// {0xFFA0, 0x3164},
// {0xFFC2, 0x314F},
// {0xFFC3, 0x3150},
// {0xFFC4, 0x3151},
// {0xFFC5, 0x3152},
// {0xFFC6, 0x3153},
// {0xFFC7, 0x3154},
// {0xFFCA, 0x3155},
// {0xFFCB, 0x3156},
// {0xFFCC, 0x3157},
// {0xFFCD, 0x3158},
// {0xFFCE, 0x3159},
// {0xFFCF, 0x315A},
// {0xFFD2, 0x315B},
// {0xFFD3, 0x315C},
// {0xFFD4, 0x315D},
// {0xFFD5, 0x315E},
// {0xFFD6, 0x315F},
// {0xFFD7, 0x3160},
// {0xFFDA, 0x3161},
// {0xFFDB, 0x3162},
// {0xFFDC, 0x3163},
// {0xFFE8, 0x2502},
// {0xFFE9, 0x2190},
// {0xFFEA, 0x2191},
// {0xFFEB, 0x2192},
// {0xFFEC, 0x2193},
// {0xFFED, 0x25A0},
// {0xFFEE, 0x25CB},
//}
//
//var toDBC = []dict{
// {0x2190, 0xFFE9},
// {0x2191, 0xFFEA},
// {0x2192, 0xFFEB},
// {0x2193, 0xFFEC},
// {0x3000, 0x0020},
// {0x3001, 0xFF64},
// {0x3002, 0xFF61},
// {0x300C, 0xFF62},
// {0x300D, 0xFF63},
// {0x309B, 0xFF9E},
// {0x309C, 0xFF9F},
// {0x30A1, 0xFF67},
// {0x30A2, 0xFF71},
// {0x30A3, 0xFF68},
// {0x30A4, 0xFF72},
// {0x30A5, 0xFF69},
// {0x30A6, 0xFF73},
// {0x30A7, 0xFF6A},
// {0x30A8, 0xFF74},
// {0x30A9, 0xFF6B},
// {0x30AA, 0xFF75},
// {0x30AB, 0xFF76},
// {0x30AD, 0xFF77},
// {0x30AF, 0xFF78},
// {0x30B1, 0xFF79},
// {0x30B3, 0xFF7A},
// {0x30B5, 0xFF7B},
// {0x30B7, 0xFF7C},
// {0x30B9, 0xFF7D},
// {0x30BB, 0xFF7E},
// {0x30BD, 0xFF7F},
// {0x30BF, 0xFF80},
// {0x30C1, 0xFF81},
// {0x30C3, 0xFF6F},
// {0x30C4, 0xFF82},
// {0x30C6, 0xFF83},
// {0x30C8, 0xFF84},
// {0x30CA, 0xFF85},
// {0x30CB, 0xFF86},
// {0x30CC, 0xFF87},
// {0x30CD, 0xFF88},
// {0x30CE, 0xFF89},
// {0x30CF, 0xFF8A},
// {0x30D2, 0xFF8B},
// {0x30D5, 0xFF8C},
// {0x30D8, 0xFF8D},
// {0x30DB, 0xFF8E},
// {0x30DE, 0xFF8F},
// {0x30DF, 0xFF90},
// {0x30E0, 0xFF91},
// {0x30E1, 0xFF92},
// {0x30E2, 0xFF93},
// {0x30E3, 0xFF6C},
// {0x30E4, 0xFF94},
// {0x30E5, 0xFF6D},
// {0x30E6, 0xFF95},
// {0x30E7, 0xFF6E},
// {0x30E8, 0xFF96},
// {0x30E9, 0xFF97},
// {0x30EA, 0xFF98},
// {0x30EB, 0xFF99},
// {0x30EC, 0xFF9A},
// {0x30ED, 0xFF9B},
// {0x30EF, 0xFF9C},
// {0x30F2, 0xFF66},
// {0x30F3, 0xFF9D},
// {0x30FB, 0xFF65},
// {0x30FC, 0xFF70},
// {0x314F, 0xFFC2},
// {0x3150, 0xFFC3},
// {0x3151, 0xFFC4},
// {0x3152, 0xFFC5},
// {0x3153, 0xFFC6},
// {0x3154, 0xFFC7},
// {0x3155, 0xFFCA},
// {0x3156, 0xFFCB},
// {0x3157, 0xFFCC},
// {0x3158, 0xFFCD},
// {0x3159, 0xFFCE},
// {0x315A, 0xFFCF},
// {0x315B, 0xFFD2},
// {0x315C, 0xFFD3},
// {0x315D, 0xFFD4},
// {0x315E, 0xFFD5},
// {0x315F, 0xFFD6},
// {0x3160, 0xFFD7},
// {0x3161, 0xFFDA},
// {0x3162, 0xFFDB},
// {0x3163, 0xFFDC},
// {0x3164, 0xFFA0},
// {0xFF5F, 0x2985},
// {0xFF60, 0x2986},
// {0xFFE0, 0x00A2},
// {0xFFE1, 0x00A3},
// {0xFFE2, 0x00AC},
// {0xFFE3, 0x00AF},
// {0xFFE4, 0x00A6},
// {0xFFE5, 0x00A5},
// {0xFFE6, 0x20A9},
//}
//
//// 从strings包拷贝,因此不必导入strings包即可使用本函数。
//var Map = strings.Map
//
//// 判断一个字符是否是半角字符
//func IsSBC(c rune) bool {
// switch {
// case c <= 0x007E:
// case c == 0x00A2 || c == 0x00A3:
// case c == 0x00A5 || c == 0x00A6:
// case c == 0x00AC || c == 0x00AF:
// case c == 0x20A9:
// case c == 0x2985 || c == 0x2986:
// case c >= 0xFF61 && c <= 0xFF9F:
// case c >= 0xFFA0 && c <= 0xFFBE:
// case c >= 0xFFC2 && c <= 0xFFC7:
// case c >= 0xFFCA && c <= 0xFFCF:
// case c >= 0xFFD2 && c <= 0xFFD7:
// case c >= 0xFFDA && c <= 0xFFDC:
// case c >= 0xFFE8 && c <= 0xFFEE:
// default:
// return false
// }
// return true
//}
//
//// 如果字符c为全角字符,返回对应半角字符(如有);否则返回c。
//func ToDBC(c rune) rune {
// switch {
// case c <= 0x218F:
// return c
// case c <= 0x2193:
// case c == 0x2502:
// return 0xFFE8
// case c == 0x25A0:
// return 0xFFED
// case c == 0x25CB:
// return 0xFFEE
// case c <= 0x2FFF:
// return c
// case c <= 0x30FC:
// case c <= 0x3130:
// return c
// case c <= 0x314E:
// return c + 0xCE70
// case c <= 0x3164:
// case c <= 0xFF00:
// return c
// case c <= 0xFF5E:
// return c - 0xFEE0
// case c >= 0xFFE7:
// return c
// }
// i := sort.Search(len(toDBC), func(i int) bool { return toDBC[i].x >= c })
// if toDBC[i].x == c {
// return toDBC[i].y
// } else {
// return c
// }
//}
//
//// 如果字符c为半角字符,返回对应全角字符(如有);否则返回c。
//func ToSBC(c rune) rune {
// switch {
// case c <= 0x001F:
// return c
// case c == 0x0020:
// return 0x3000
// case c <= 0x007E:
// return c + 0xFEE0
// case c <= 0x00AF:
// case c == 0x20A9:
// return 0xFFE6
// case c == 0x2985:
// return 0xFF5F
// case c == 0x2986:
// return 0xFF60
// case c <= 0xFF60:
// return c
// case c <= 0xFFA0:
// case c <= 0xFFBE:
// return c - 0xCE70
// case c >= 0xFFEF:
// return c
// }
// i := sort.Search(len(toSBC), func(i int) bool { return toSBC[i].x >= c })
// if toSBC[i].x == c {
// return toSBC[i].y
// } else {
// return c
// }
//}
//
//// 如果字符c为全角ASCII字符,返回对应的半角字符;否则返回c。
//func ToASCIIDBC(r rune) rune {
// if r == 0x3000 {
// return 0x3000
// }
// if r >= 0xFF01 && r <= 0xFF5E {
// return r - 0xFEE0
// }
// return r
//}
//
//// 如果字符c为半角ASCII字符,返回对应的全角字符;否则返回c。
//func ToASCIISBC(r rune) rune {
// if r == 0x0020 {
// return 0x3000
// }
// if r >= 0x0021 && r <= 0x007E {
// return r + 0xFEE0
// }
// return r
//}
package util
func CheckCRC(buf []byte) bool {
var wCrcData uint16 = 0xffff
for _, v := range buf {
wCrcData ^= uint16(v)
for j := 0; j < 8; j++ {
if wCrcData&1 != 0 {
wCrcData >>= 1
wCrcData ^= 0xa001
} else {
wCrcData >>= 1
}
}
}
return wCrcData == 0
}
// GetCRC 获取2个字节的CRC16
func GetCRC(buf []byte, len int) { //传入的切片必须装得下
var wCrcData uint16 = 0xffff
for i := 0; i < len; i++ {
wCrcData ^= uint16(buf[i])
for j := 0; j < 8; j++ {
if wCrcData&1 != 0 {
wCrcData >>= 1
wCrcData ^= 0xa001
} else {
wCrcData >>= 1
}
}
}
buf[len] = byte(wCrcData)
buf[len+1] = byte(wCrcData >> 8)
}
package util
import (
"encoding/base64"
"errors"
)
func EncryptBytesToBase64(cleartext []byte, pswd string, iv string) (base64Result []byte) { //看base64库,返回切片更快,本来tcp发送也是切片,不过这里面string也是切片
var pswdIv [16]byte
var pswdSum byte
var i int
cleartextLen := len(cleartext)
var result = make([]byte, cleartextLen+1)
for i = 0; i < 16; i++ {
pswdIv[i] = ((pswd[i] & 0xaa) | (pswd[15-i] & 0x55)) + iv[15-i] + byte(i)
if i%2 == 0 {
pswdSum += pswd[i] + iv[i]
} else {
pswdSum -= pswd[i] - iv[i]
}
}
for i = 0; i < 16; i++ {
if i%2 == 0 {
pswdIv[i] = ^pswdIv[i] + pswdSum
} else {
pswdIv[i] = pswdIv[i] - ^pswdSum
}
}
result[cleartextLen] = ^pswdSum
for i = 0; i < cleartextLen; i++ {
result[cleartextLen] += cleartext[i]
}
for i = 0; i < cleartextLen; i++ {
result[i] = ^((cleartext[i] & 0x72) | (cleartext[cleartextLen-1-i] & 0x8d))
if i%2 == 0 {
result[i] += pswdIv[i%16] - result[cleartextLen]
} else {
result[i] -= pswdIv[i%16] + result[cleartextLen]
}
}
base64Result = make([]byte, base64.StdEncoding.EncodedLen(cleartextLen+1)+2) //多出两个用来装起始结束符
base64.StdEncoding.Encode(base64Result[1:], result)
return
//return base64.StdEncoding.EncodeToString(result)
}
// DecryptBase64ToBytes 解密并转换为bytes
func DecryptBase64ToBytes(ciphertext []byte, pswd string, iv string) ([]byte, error) { //看base64库,传入切片更快,本来tcp接收也是切片,不过这里面string也是切片
var pswdIv [16]byte
var pswdSum byte
var i int
cipherBytes := make([]byte, base64.StdEncoding.DecodedLen(len(ciphertext)))
hexLen, err := base64.StdEncoding.Decode(cipherBytes, ciphertext)
//cipherBytes, err := base64.StdEncoding.DecodeString(ciphertext)
if err != nil {
return nil, err
}
clearLen := hexLen - 1
var resultBytes = make([]byte, clearLen)
var resultBytesTemp = make([]byte, clearLen)
for i = 0; i < 16; i++ {
pswdIv[i] = ((pswd[i] & 0xaa) | (pswd[15-i] & 0x55)) + iv[15-i] + byte(i)
if i%2 == 0 {
pswdSum += pswd[i] + iv[i]
} else {
pswdSum -= pswd[i] - iv[i]
}
}
for i = 0; i < 16; i++ {
if i%2 == 0 {
pswdIv[i] = ^pswdIv[i] + pswdSum
} else {
pswdIv[i] = pswdIv[i] - ^pswdSum
}
}
for i = 0; i < clearLen; i++ {
if i%2 == 0 {
resultBytesTemp[i] = ^(cipherBytes[i] - (pswdIv[i%16] - cipherBytes[clearLen]))
} else {
resultBytesTemp[i] = ^(cipherBytes[i] + (pswdIv[i%16] + cipherBytes[clearLen]))
}
}
var sum byte
for i = 0; i < clearLen; i++ {
resultBytes[i] = (resultBytesTemp[i] & 0x72) | (resultBytesTemp[clearLen-1-i] & 0x8d)
sum += resultBytes[i]
}
sum += ^pswdSum
if sum != cipherBytes[clearLen] {
return nil, errors.New("密文校验错误")
}
return resultBytes, nil
}
func EncryptBytesToBase64URL(cleartext []byte, pswd string) string {
var i int
cleartextLen := len(cleartext)
var result = make([]byte, cleartextLen+1)
result[cleartextLen] = 0x11
for i = 0; i < cleartextLen; i++ {
if i%2 == 0 {
result[cleartextLen] -= cleartext[i] | 0x23
} else {
result[cleartextLen] += cleartext[i] & 0x36
}
result[cleartextLen] += ^((cleartext[i] >> 3) | (cleartext[i] << 5))
}
for i = 0; i < cleartextLen; i++ {
result[i] = ^((cleartext[i] & 0x72) | (cleartext[cleartextLen-1-i] & 0x8d))
if i%2 == 0 {
result[i] += pswd[i%16] - result[cleartextLen]
} else {
result[i] -= pswd[i%16] + result[cleartextLen]
}
}
return base64.URLEncoding.EncodeToString(result)
}
func DecryptBase64URLToBytes(ciphertext string, pswd string) ([]byte, error) { //
var i int
hex, err := base64.URLEncoding.DecodeString(ciphertext)
if err != nil {
return nil, err
}
clearLen := len(hex) - 1
var resultBytes = make([]byte, clearLen)
var resultBytesTemp = make([]byte, clearLen)
for i = 0; i < clearLen; i++ {
if i%2 == 0 {
resultBytesTemp[i] = ^(hex[i] - (pswd[i%16] - hex[clearLen]))
} else {
resultBytesTemp[i] = ^(hex[i] + (pswd[i%16] + hex[clearLen]))
}
}
var sum byte
for i = 0; i < clearLen; i++ {
resultBytes[i] = (resultBytesTemp[i] & 0x72) | (resultBytesTemp[clearLen-1-i] & 0x8d)
//sum += resultBytes[i]
if i%2 == 0 {
sum -= resultBytes[i] | 0x23
} else {
sum += resultBytes[i] & 0x36
}
sum += ^((resultBytes[i] >> 3) | (resultBytes[i] << 5))
}
sum += 0x11
if sum != hex[clearLen] {
return nil, errors.New("密文校验错误")
}
return resultBytes, nil
}
package util
import (
"fmt"
"testing"
)
//测试用例文件使用 go test 指令来执行,没有也不需要 main() 作为函数入口
//所有在以_test结尾的源码内以Test开头的函数会自动被执行。
func TestHex2Cipher(t *testing.T) {
//test := []byte{0x22, 0x64, 0x65, 0x76, 0x2E, 0x6C, 0x65, 0x7A, 0x68, 0x69, 0x78, 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x22, 0x2C, 0x34, 0x39, 0x39, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x0A, 0x64, 0x31, 0x31, 0x30, 0x2F, 0x31, 0x32, 0x30, 0x2F, 0x31, 0x31, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x09, 0x09, 0x7F, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x02, 0x38, 0x35, 0x34, 0x30, 0x35, 0x35, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x57, 0x41, 0x59, 0x32, 0x31,0,0}
//GetCRC(test, 254)
//for j:=0;j< len(test);{
// for i:=0;i<16;i++{
// fmt.Printf("%02X",test[j])
// j++
// }
// fmt.Println()
//}
var b [3]byte
for i := 10002; i <= 11001; i++ {
b[0] = byte(i)
b[1] = byte(i >> 8)
b[2] = byte(i >> 16)
fmt.Printf("3D%02X%02X%02X,", b[0], b[1], b[2])
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment