diff --git a/app.go b/app.go index 7edb974..d909898 100644 --- a/app.go +++ b/app.go @@ -9,14 +9,35 @@ import ( "q5" ) -type App_ struct { - nodeId int - instanceId int +type App interface { + GetPkgName() string + NewUuid() int64 + GetInstanceId() int32 + GetNodeId() int32 + GetZoneId() int32 + HasFlag(int32) bool + AddIMMsg(uint16, q5.Args) + RegisterIMMsgHandle(uint16, func(q5.Args)) + NotifyLoopCond() + NowUnix() int64 + NowUnixMilli() int64 +} + +type UserApp interface { + GetPkgName() string + Init() + Update() + UnInit() +} + +type app struct { + zoneId int32 + nodeId int32 + instanceId int32 terminated bool - pkgName string flags map[int32]int32 servicing bool - contextHash map[int32]q5.XParams + contextHash map[int32]q5.Args loopCond *sync.Cond imTopNode *IMMsgNode imBotNode *IMMsgNode @@ -26,69 +47,62 @@ type App_ struct { chGoLoopWait chan int64 nowTime time.Time nowUnixNano int64 - imMsgHandlers [1024]func(int16,*q5.XParams) + imMsgHandlers [1024]func(q5.Args) maxRunDelay int64 maxScheduleTime int64 - updateFunc func () + userApp UserApp } -func (this *App_) Init(updateFunc func ()) { - this.updateFunc = updateFunc +func (this *app) init(userApp UserApp) { + this.userApp = userApp this.nowTime = time.Now() atomic.StoreInt64(&this.nowUnixNano, this.nowTime.UnixNano()) - _Timer = &q5.Timer{} - _Timer.Init( - func (context interface{}) int64 { - return q5.GetTickCount() - }, - func (context interface{}, isFirstAdd bool, milliSeconds int32, tick int64) int64 { - nowTime := time.Now().Unix() - todayPassedSeconds := nowTime - q5.GetDaySeconds(nowTime) - expires := (tick - todayPassedSeconds * 1000) + int64(milliSeconds) - if isFirstAdd { - if expires <= tick { - expires += 1000 * 3600 * 24 - } - } - return expires - }, - nil, - 1000 * 60, - 5000) - _SysLog = new(SysLog_) - _SysLog.Init() - _TgLog = new(TGLog_) - _TgLog.Init() - flag.IntVar(&this.nodeId, "n", 0, "node id") - flag.IntVar(&this.instanceId, "i", 0, "instance id") - flag.Parse() + _timer = &Timer{} + _timer.init() + _sysLog = new(SysLog_) + _sysLog.init() + _tgLog = new(TGLog_) + _tgLog.init() + _httpCliMgr = new(HttpCliMgr) + _httpCliMgr.init() + { + var tmpNodeId, tmpInstanceId int + flag.IntVar(&tmpNodeId, "n", 0, "node id") + flag.IntVar(&tmpInstanceId, "i", 0, "instance id") + this.nodeId = int32(tmpNodeId) + this.instanceId = int32(tmpInstanceId) + flag.Parse() + } this.loopCond = sync.NewCond(new(sync.Mutex)) this.chGoLoopTimerExit = make(chan int) this.chGoLoopWait = make(chan int64) this.outputRuningLog() - SysLog().Info("node_id:%d instance_id:%d pid:%d", + GetSysLog().Info("node_id:%d instance_id:%d pid:%d", this.nodeId, this.instanceId, os.Getpid()) this.installTimer() go this.goLoopTimer() + this.userApp.Init() } -func (this *App_) UnInit() { +func (this *app) unInit() { this.chGoLoopTimerExit <- 1 - _Timer.UnInit() - _Timer = nil + _httpCliMgr.unInit() + _timer.unInit() + _timer = nil + this.userApp.UnInit() } -func (this *App_) Run() { +func (this *app) run() { for !this.terminated { this.nowTime = time.Now() atomic.StoreInt64(&this.nowUnixNano, this.nowTime.UnixNano()) beginTick := q5.GetTickCount() - _Timer.Update() + _timer.update() this.dispatchIMMsg() - this.updateFunc() + this.userApp.Update() this.schedule() endTick := q5.GetTickCount() @@ -98,32 +112,32 @@ func (this *App_) Run() { } } -func (this *App_) NewUuid() int64 { +func (this *app) NewUuid() int64 { return 0 } -func (this *App_) GetInstanceId() uint32 { - return uint32(this.instanceId) +func (this *app) GetInstanceId() int32 { + return this.instanceId } -func (this *App_) GetNodeId() uint32 { - return uint32(this.nodeId) +func (this *app) GetNodeId() int32 { + return this.nodeId } -func (this *App_) GetPkgName() string { - return this.pkgName +func (this *app) GetZoneId() int32 { + return this.nodeId } -func (this *App_) SetPkgName(pkgName string) { - this.pkgName = pkgName +func (this *app) GetPkgName() string { + return this.userApp.GetPkgName() } -func (this *App_) HasFlag(flag int32) bool { +func (this *app) HasFlag(flag int32) bool { _, ok := this.flags[flag] return ok } -func (this *App_) AddIMMsg(msgId int16, params *q5.XParams) { +func (this *app) AddIMMsg(msgId uint16, params q5.Args) { p := new(IMMsgNode) p.msgId = msgId p.params = params @@ -141,11 +155,11 @@ func (this *App_) AddIMMsg(msgId int16, params *q5.XParams) { this.loopCond.Broadcast() } -func (this *App_) RegisterIMMsgHandle(msgId int16, handle func(int16,*q5.XParams)) { +func (this *app) RegisterIMMsgHandle(msgId uint16, handle func(q5.Args)) { this.imMsgHandlers[msgId] = handle } -func (this *App_) goLoopTimer() { +func (this *app) goLoopTimer() { var waitMs int64 = 1000 * 10 for { select { @@ -162,36 +176,33 @@ func (this *App_) goLoopTimer() { } } -func (this *App_) schedule() { - this.chGoLoopWait <- Timer().GetIdleTime() +func (this *app) schedule() { + this.chGoLoopWait <- GetTimer().GetIdleTime() this.loopCond.L.Lock() this.loopCond.Wait() this.loopCond.L.Unlock() } -func (this *App_) NotifyLoopCond() { +func (this *app) NotifyLoopCond() { this.loopCond.Broadcast() } -func (this *App_) NowUnix() int64 { +func (this *app) NowUnix() int64 { return this.nowUnixNano / int64(time.Second) } -func (this *App_) NowUnixMilli() int64 { +func (this *app) NowUnixMilli() int64 { return this.nowUnixNano / int64(time.Millisecond) } -func (this *App_) NowUnixNano() int64 { +func (this *app) NowUnixNano() int64 { return this.nowUnixNano } -func (this *App_) outputRuningLog() { - for _, val := range q5.GetInitLogs() { - SysLog().Info("%s", val) - } +func (this *app) outputRuningLog() { } -func (this *App_) dispatchIMMsg() { +func (this *app) dispatchIMMsg() { this.imMsgMutex.Lock() this.imWorkNode = this.imTopNode this.imTopNode = nil @@ -202,21 +213,20 @@ func (this *App_) dispatchIMMsg() { currNode := this.imWorkNode this.imWorkNode = this.imWorkNode.next if this.imMsgHandlers[currNode.msgId] != nil { - this.imMsgHandlers[currNode.msgId](currNode.msgId, currNode.params) + this.imMsgHandlers[currNode.msgId](currNode.params) } } } -func (this *App_) installTimer() { - Timer().AddRepeatTimer(1000 * 60, - func (params* q5.XParams) { - - }, - func (params* q5.XParams) { - SysLog().Info("max_run_delay:%d max_schedule_time:%d", - App.maxRunDelay, - App.maxScheduleTime) - App.maxRunDelay = 0 - App.maxScheduleTime = 0 +func (this *app) installTimer() { + GetTimer().SetInterval(1000 * 60, + func (ev int32, params *q5.Args) { + if ev == q5.TIMER_EXEC_EVENT { + GetSysLog().Info("max_run_delay:%d max_schedule_time:%d", + _app.maxRunDelay, + _app.maxScheduleTime) + _app.maxRunDelay = 0 + _app.maxScheduleTime = 0 + } }) } diff --git a/constant.go b/constant.go new file mode 100644 index 0000000..cc9af9a --- /dev/null +++ b/constant.go @@ -0,0 +1,5 @@ +package f5 + +const ( + IM_HTTP_CLI_MGR_RESPONSE = 1 +) diff --git a/context.go b/context.go index c9cab19..1ed8c7f 100644 --- a/context.go +++ b/context.go @@ -49,11 +49,11 @@ func (this *Context) GetRemoteAddr() string { return q5.GetRequestRemoteAddr(this.r) } -func (this *Context) Request(name string) *q5.XValue { +func (this *Context) Request(name string) string { return q5.Request(this.r, name) } -func (this *Context) GetBody() *q5.XValue { +func (this *Context) GetBody() string { return q5.GetPostBody(this.r) } @@ -70,10 +70,7 @@ func (this *Context) Response(data string) { } func (this *Context)ResponseErr(errCode int32, errMsg string) { - respObj := q5.NewMxoObject() - respObj.SetXValue("errcode", q5.NewXInt32(errCode)) - respObj.SetXValue("errmsg", q5.NewXString(errMsg)) - q5.Response(this.w, respObj.ToJsonStr()) + q5.ResponseErr(this.w, errCode, errMsg) } func (this *Context) ResponseOk() { diff --git a/dataset.go b/dataset.go new file mode 100644 index 0000000..26460d7 --- /dev/null +++ b/dataset.go @@ -0,0 +1,51 @@ +package f5 + +import ( + "database/sql" +) + +type DataSet struct { + rows *sql.Rows + columns []string + values []interface{} +} + +func (this *DataSet) Next() bool { + this.GetColumns() + this.values = []interface{}{} + for i := 0 ; i < len(this.columns); i++ { + str := "" + this.values = append(this.values, &str) + } + this.rows.Scan(this.values...) + return this.rows.Next() +} + +func (this *DataSet) GetColumns() []string { + if len(this.columns) <= 0 { + columns, err := this.rows.Columns() + if err == nil { + this.columns = columns + } + } + return this.columns +} + +func (this *DataSet) GetByName(name string) *string { + for i := 0; i < len(this.columns); i++ { + if this.columns[i] == name { + return this.GetByIndex(int32(i)) + } + } + return nil +} + +func (this *DataSet) GetByIndex(index int32) *string { + return this.values[index].(*string); +} + +func NewDataSet(rows *sql.Rows) *DataSet { + dataSet := new(DataSet) + dataSet.rows = rows + return dataSet +} diff --git a/export.go b/export.go new file mode 100644 index 0000000..b5d134c --- /dev/null +++ b/export.go @@ -0,0 +1,34 @@ +package f5 + +var _app *app +var _timer *Timer +var _sysLog *SysLog_ +var _tgLog *TGLog_ +var _httpCliMgr *HttpCliMgr + +func GetApp() App { + return _app +} + +func GetTimer() *Timer { + return _timer +} + +func GetSysLog() *SysLog_ { + return _sysLog +} + +func GetTgLog() *TGLog_ { + return _tgLog +} + +func GetHttpCliMgr() *HttpCliMgr { + return _httpCliMgr +} + +func Run(userApp UserApp) { + _app = new(app) + _app.init(userApp) + _app.run() + _app.unInit() +} diff --git a/global.go b/global.go deleted file mode 100644 index 785e401..0000000 --- a/global.go +++ /dev/null @@ -1,20 +0,0 @@ -package f5 - -import "q5" - -var App *App_ -var _Timer *q5.Timer -var _SysLog *SysLog_ -var _TgLog *TGLog_ - -func Timer() *q5.Timer { - return _Timer -} - -func SysLog() *SysLog_ { - return _SysLog -} - -func TgLog() *TGLog_ { - return _TgLog -} diff --git a/go.mod b/go.mod index 6abfb84..81cd5d7 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module f5 -go 1.14 +go 1.20 require q5 v1.0.0 // indirect diff --git a/httpclimgr.go b/httpclimgr.go new file mode 100644 index 0000000..13a175a --- /dev/null +++ b/httpclimgr.go @@ -0,0 +1,144 @@ +package f5 + +import ( + "q5" +) + +/* + http的请求分为两种风格 + go like: go风格回调的时候不会join主线程,被回调方需要处理线程同步问题 + js like: js风格回调时候会自动join主线程,被回调方无需处理线程同步问题 + */ + +const ( + GO_LIKE_REQUEST = 1 + JS_LIKE_REQUEST = 2 + + NORMAL_CHANNEL = 1 + QUICK_CHANNEL = 2 +) + +type HttpCliResponse interface { + GetErr() error + GetJsonData() map[string]interface{} + GetRawData() string + IsTimeOut() bool +} + +type httpCliResponse struct { + err error + data map[string]interface{} + rawData string + isTimeOut bool +} + +type HttpCliMgr struct { + +} + +func (this *HttpCliMgr) init() { + _app.RegisterIMMsgHandle( + IM_HTTP_CLI_MGR_RESPONSE, + func (args q5.Args) { + cb := args[0].(func (HttpCliResponse)) + rsp := args[1].(*httpCliResponse) + cb(rsp) + }) +} + +func (this *HttpCliMgr) unInit() { +} + +func (this *HttpCliMgr) SendGoLikeRequest( + url string, params map[string]string, + cb func (HttpCliResponse)) { + this.internalSendRequest( + GO_LIKE_REQUEST, + NORMAL_CHANNEL, + url, + params, + cb) +} + +func (this *HttpCliMgr) SendJsLikeRequest( + url string, params map[string]string, + cb func (HttpCliResponse)) { + this.internalSendRequest( + JS_LIKE_REQUEST, + NORMAL_CHANNEL, + url, + params, + cb) +} + +func (this *HttpCliMgr) SendQuickChannelGoLikeRequest( + url string, params map[string]string, + cb func (HttpCliResponse)) { + this.internalSendRequest( + GO_LIKE_REQUEST, + QUICK_CHANNEL, + url, + params, + cb) +} + +func (this *HttpCliMgr) SendQuickChannelJsLikeRequest( + url string, params map[string]string, + cb func (HttpCliResponse)) { + this.internalSendRequest( + JS_LIKE_REQUEST, + QUICK_CHANNEL, + url, + params, + cb) +} + +func (this *HttpCliMgr) internalSendRequest( + style int32, channel int32, + url string, params map[string]string, + cb func (HttpCliResponse)) { + if !(style == GO_LIKE_REQUEST || style == JS_LIKE_REQUEST) { + panic("HttpCliMgr sytel error") + } + if !(channel == NORMAL_CHANNEL || channel == QUICK_CHANNEL) { + panic("HttpCliMgr channel error") + } + doFunc := func() { + data, err := q5.HttpGet(url, params) + if cb == nil { + return + } + rsp := new(httpCliResponse) + rsp.init(data, err) + if style == GO_LIKE_REQUEST { + cb(rsp) + } else { + _app.AddIMMsg(IM_HTTP_CLI_MGR_RESPONSE, []interface{} { + cb, + rsp, + }) + } + } + go doFunc() +} + +func (this *httpCliResponse) init(data string, err error) { + this.err = err + this.rawData = data +} + +func (this *httpCliResponse) GetErr() error { + return this.err +} + +func (this *httpCliResponse) GetJsonData() map[string]interface{} { + return this.data +} + +func (this *httpCliResponse) GetRawData() string { + return this.rawData +} + +func (this *httpCliResponse) IsTimeOut() bool { + return this.isTimeOut +} diff --git a/httpserver.go b/httpserver.go index 703502c..d4bd48b 100644 --- a/httpserver.go +++ b/httpserver.go @@ -40,42 +40,41 @@ func (this *HttpServer) Init(serviceName string, logOutputTime int32) *HttpServe func (c *Context) { c.Response(`{"errcode":0, "errmsg":"", "healthy":1, "max_rundelay":10}`) }) - SysLog().Info("HttpServer.Init") + GetSysLog().Info("HttpServer.Init") if logOutputTime > 0 { - Timer().AddRepeatTimer( + GetTimer().SetInterval( logOutputTime, - func (params* q5.XParams) { - params.Sender.SetString(serviceName) - }, - func (params* q5.XParams) { - SysLog().Info("%s maxHandleTime:%d totalRequestTimes:%d okTimes:%d pageNotFoundTimes:%d", - params.Sender.GetString(), - this.maxHandleTime, - this.totalRequestTimes, - this.okTimes, - this.pageNotFoundTimes) - this.maxHandleTime = 0 - this.okTimes = 0 - this.pageNotFoundTimes = 0 + func (ev int32, params *q5.Args) { + if ev == q5.TIMER_EXEC_EVENT { + GetSysLog().Info("%s maxHandleTime:%d totalRequestTimes:%d okTimes:%d pageNotFoundTimes:%d", + serviceName, + this.maxHandleTime, + this.totalRequestTimes, + this.okTimes, + this.pageNotFoundTimes) + this.maxHandleTime = 0 + this.okTimes = 0 + this.pageNotFoundTimes = 0 + } }) } return this } func (this *HttpServer) UnInit() { - SysLog().Info("HttpServer.UnInit") + GetSysLog().Info("HttpServer.UnInit") } func (this *HttpServer) Start(listen_port int32) { atomic.AddInt64(&this.totalRequestTimes, 1) this.installGlobalMiddleware() - SysLog().Info("HttpServer.Start listen_port:%d", listen_port) + GetSysLog().Info("HttpServer.Start listen_port:%d", listen_port) go http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", listen_port), nil) } func (this *HttpServer) dispatchRequest(c *Context) { atomic.AddInt64(&this.totalRequestTimes, 1) - handleName := c.Request("c").GetString() + "$" + c.Request("a").GetString() + handleName := c.Request("c") + "$" + c.Request("a") handle := this.getHandle(handleName) if handle != nil { beginTick := q5.GetTickCount() @@ -86,7 +85,7 @@ func (this *HttpServer) dispatchRequest(c *Context) { } atomic.AddInt64(&this.okTimes, 1) if err := recover(); err != nil { - SysLog().Error("handle name:%s error:%s", handleName, err) + GetSysLog().Error("handle name:%s error:%s", handleName, err) c.Response(`{"errcode":500, "errmsg":"server internal error"}`) } }() diff --git a/im/go.mod b/im/go.mod deleted file mode 100644 index 9f48406..0000000 --- a/im/go.mod +++ /dev/null @@ -1 +0,0 @@ -package im diff --git a/im/im_base_listener.go b/im/im_base_listener.go deleted file mode 100644 index f8371f7..0000000 --- a/im/im_base_listener.go +++ /dev/null @@ -1,14 +0,0 @@ -package im - -type BaseIMListener struct { -} - - -func (this *BaseIMListener) _IMSocketConnect(msg *IMSocketConnect) { - -} - -func (this *BaseIMListener) _IMSocketDisconnect(msg *IMSocketDisconnect) { - - -} diff --git a/im/im_listener.go b/im/im_listener.go deleted file mode 100644 index cf39fe7..0000000 --- a/im/im_listener.go +++ /dev/null @@ -1,8 +0,0 @@ -package im - -type IMListener interface { - - _IMSocketConnect(msg *IMSocketConnect) - _IMSocketDisconnect(msg *IMSocketDisconnect) - -} diff --git a/im/im_msgid.pb.go b/im/im_msgid.pb.go deleted file mode 100644 index 6ee2c53..0000000 --- a/im/im_msgid.pb.go +++ /dev/null @@ -1,83 +0,0 @@ -// Code generated by protoc-gen-go. -// source: im_msgid.proto -// DO NOT EDIT! - -/* -Package im is a generated protocol buffer package. - -It is generated from these files: - im_msgid.proto - im_proto.proto - -It has these top-level messages: - MFTuple - IMSocketConnect - IMSocketDisconnect -*/ -package im - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -// 消息id定义 -type IMMessageIdE int32 - -const ( - IMMessageIdE__IMSocketConnect IMMessageIdE = 1 - IMMessageIdE__IMSocketDisconnect IMMessageIdE = 2 -) - -var IMMessageIdE_name = map[int32]string{ - 1: "_IMSocketConnect", - 2: "_IMSocketDisconnect", -} -var IMMessageIdE_value = map[string]int32{ - "_IMSocketConnect": 1, - "_IMSocketDisconnect": 2, -} - -func (x IMMessageIdE) Enum() *IMMessageIdE { - p := new(IMMessageIdE) - *p = x - return p -} -func (x IMMessageIdE) String() string { - return proto.EnumName(IMMessageIdE_name, int32(x)) -} -func (x *IMMessageIdE) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(IMMessageIdE_value, data, "IMMessageIdE") - if err != nil { - return err - } - *x = IMMessageIdE(value) - return nil -} -func (IMMessageIdE) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -func init() { - proto.RegisterEnum("im.IMMessageIdE", IMMessageIdE_name, IMMessageIdE_value) -} - -func init() { proto.RegisterFile("im_msgid.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 96 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcb, 0xcc, 0x8d, 0xcf, - 0x2d, 0x4e, 0xcf, 0x4c, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xca, 0xcc, 0xd5, 0xb2, - 0xe3, 0xe2, 0xf5, 0xf4, 0xf5, 0x4d, 0x2d, 0x2e, 0x4e, 0x4c, 0x4f, 0xf5, 0x4c, 0x89, 0x4f, 0x15, - 0x12, 0xe1, 0x12, 0x88, 0xf7, 0xf4, 0x0d, 0xce, 0x4f, 0xce, 0x4e, 0x2d, 0x71, 0xce, 0xcf, 0xcb, - 0x4b, 0x4d, 0x2e, 0x11, 0x60, 0x14, 0x12, 0xe7, 0x12, 0x86, 0x8b, 0xba, 0x64, 0x16, 0x27, 0x43, - 0x25, 0x98, 0x00, 0x01, 0x00, 0x00, 0xff, 0xff, 0x15, 0xd2, 0xef, 0x38, 0x54, 0x00, 0x00, 0x00, -} diff --git a/im/im_msgid.proto b/im/im_msgid.proto deleted file mode 100644 index 24f0f4e..0000000 --- a/im/im_msgid.proto +++ /dev/null @@ -1,8 +0,0 @@ -package im; - -//消息id定义 -enum IMMessageId_e -{ - _IMSocketConnect = 1; - _IMSocketDisconnect = 2; -} diff --git a/im/im_proto.pb.go b/im/im_proto.pb.go deleted file mode 100644 index b724f68..0000000 --- a/im/im_proto.pb.go +++ /dev/null @@ -1,147 +0,0 @@ -// Code generated by protoc-gen-go. -// source: im_proto.proto -// DO NOT EDIT! - -package im - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// 常量 -type ConstantE int32 - -const ( - ConstantE_MaxIMMsgId ConstantE = 7 -) - -var ConstantE_name = map[int32]string{ - 7: "MaxIMMsgId", -} -var ConstantE_value = map[string]int32{ - "MaxIMMsgId": 7, -} - -func (x ConstantE) Enum() *ConstantE { - p := new(ConstantE) - *p = x - return p -} -func (x ConstantE) String() string { - return proto.EnumName(ConstantE_name, int32(x)) -} -func (x *ConstantE) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(ConstantE_value, data, "ConstantE") - if err != nil { - return err - } - *x = ConstantE(value) - return nil -} -func (ConstantE) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } - -type MFTuple struct { - Values []string `protobuf:"bytes,1,rep,name=values" json:"values,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MFTuple) Reset() { *m = MFTuple{} } -func (m *MFTuple) String() string { return proto.CompactTextString(m) } -func (*MFTuple) ProtoMessage() {} -func (*MFTuple) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } - -func (m *MFTuple) GetValues() []string { - if m != nil { - return m.Values - } - return nil -} - -type IMSocketConnect struct { - IsWebsocket *bool `protobuf:"varint,1,opt,name=is_websocket" json:"is_websocket,omitempty"` - Host *string `protobuf:"bytes,2,opt,name=host" json:"host,omitempty"` - Url *string `protobuf:"bytes,3,opt,name=url" json:"url,omitempty"` - QueryStr *string `protobuf:"bytes,4,opt,name=query_str" json:"query_str,omitempty"` - Tuples []*MFTuple `protobuf:"bytes,5,rep,name=tuples" json:"tuples,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *IMSocketConnect) Reset() { *m = IMSocketConnect{} } -func (m *IMSocketConnect) String() string { return proto.CompactTextString(m) } -func (*IMSocketConnect) ProtoMessage() {} -func (*IMSocketConnect) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } - -func (m *IMSocketConnect) GetIsWebsocket() bool { - if m != nil && m.IsWebsocket != nil { - return *m.IsWebsocket - } - return false -} - -func (m *IMSocketConnect) GetHost() string { - if m != nil && m.Host != nil { - return *m.Host - } - return "" -} - -func (m *IMSocketConnect) GetUrl() string { - if m != nil && m.Url != nil { - return *m.Url - } - return "" -} - -func (m *IMSocketConnect) GetQueryStr() string { - if m != nil && m.QueryStr != nil { - return *m.QueryStr - } - return "" -} - -func (m *IMSocketConnect) GetTuples() []*MFTuple { - if m != nil { - return m.Tuples - } - return nil -} - -type IMSocketDisconnect struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *IMSocketDisconnect) Reset() { *m = IMSocketDisconnect{} } -func (m *IMSocketDisconnect) String() string { return proto.CompactTextString(m) } -func (*IMSocketDisconnect) ProtoMessage() {} -func (*IMSocketDisconnect) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } - -func init() { - proto.RegisterType((*MFTuple)(nil), "im.MFTuple") - proto.RegisterType((*IMSocketConnect)(nil), "im.IMSocketConnect") - proto.RegisterType((*IMSocketDisconnect)(nil), "im.IMSocketDisconnect") - proto.RegisterEnum("im.ConstantE", ConstantE_name, ConstantE_value) -} - -func init() { proto.RegisterFile("im_proto.proto", fileDescriptor1) } - -var fileDescriptor1 = []byte{ - // 204 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x34, 0x8e, 0xbd, 0x4e, 0xc3, 0x30, - 0x14, 0x46, 0xe5, 0xba, 0xb4, 0xe4, 0xa6, 0x2a, 0x60, 0x75, 0x30, 0x82, 0xc1, 0xca, 0x64, 0x31, - 0x64, 0xe0, 0x15, 0x8a, 0x90, 0x32, 0x78, 0x82, 0xdd, 0x0a, 0xc1, 0x02, 0x8b, 0xc4, 0x0e, 0xbe, - 0xd7, 0xfc, 0xbc, 0x3d, 0x8a, 0x81, 0xe5, 0x93, 0xbe, 0xb3, 0x9c, 0x03, 0x7b, 0x3f, 0xd9, 0x39, - 0x45, 0x8a, 0x6d, 0x59, 0xb1, 0xf2, 0x53, 0x73, 0x09, 0x5b, 0x73, 0xff, 0x98, 0xe7, 0xd1, 0x89, - 0x3d, 0x6c, 0x3e, 0xfa, 0x31, 0x3b, 0x94, 0x4c, 0x71, 0x5d, 0x35, 0x09, 0xce, 0x3a, 0xf3, 0x10, - 0x87, 0x37, 0x47, 0xc7, 0x18, 0x82, 0x1b, 0x48, 0x1c, 0x60, 0xe7, 0xd1, 0x7e, 0xba, 0x27, 0x2c, - 0x58, 0x32, 0xc5, 0xf4, 0xa9, 0xd8, 0xc1, 0xfa, 0x35, 0x22, 0xc9, 0x95, 0x62, 0xba, 0x12, 0x35, - 0xf0, 0x9c, 0x46, 0xc9, 0xcb, 0xb9, 0x80, 0xea, 0x3d, 0xbb, 0xf4, 0x6d, 0x91, 0x92, 0x5c, 0x17, - 0x74, 0x05, 0x1b, 0x5a, 0x7c, 0x28, 0x4f, 0x14, 0xd7, 0xf5, 0x6d, 0xdd, 0xfa, 0xa9, 0xfd, 0x6b, - 0x68, 0x0e, 0x20, 0xfe, 0x9d, 0x77, 0x1e, 0x87, 0x5f, 0xed, 0xcd, 0x35, 0xc0, 0x31, 0x06, 0xa4, - 0x3e, 0x90, 0x5d, 0x3a, 0xc1, 0xf4, 0x5f, 0x9d, 0x31, 0xf8, 0xd2, 0x3d, 0x9f, 0x6f, 0x7f, 0x02, - 0x00, 0x00, 0xff, 0xff, 0xef, 0x03, 0x9f, 0xae, 0xd7, 0x00, 0x00, 0x00, -} diff --git a/im/im_proto.proto b/im/im_proto.proto deleted file mode 100644 index 56f3b26..0000000 --- a/im/im_proto.proto +++ /dev/null @@ -1,26 +0,0 @@ -package im; - -//常量 -enum Constant_e -{ - MaxIMMsgId = 7; -} - -message MFTuple -{ - repeated string values = 1; -} - -message IMSocketConnect -{ - optional bool is_websocket = 1; - optional string host = 2; - optional string url = 3; - optional string query_str = 4; - repeated MFTuple tuples = 5; -} - -message IMSocketDisconnect -{ - -} diff --git a/im/im_sender.go b/im/im_sender.go deleted file mode 100644 index 5334f64..0000000 --- a/im/im_sender.go +++ /dev/null @@ -1,18 +0,0 @@ -package im - -import "fmt" - -type IMSender struct { -} - -func (this *IMSender) SendMsg(msgid int16, msg interface{}) { - fmt.Println("IMSender.SendMsg\n") -} - -func (this *IMSender) SendIMSocketConnect(msg *IMSocketConnect) { - this.SendMsg(100, msg) -} - -func (this *IMSender) SendIMSocketDisconnect(msg *IMSocketDisconnect) { - this.SendMsg(100, msg) -} diff --git a/metamgr.go b/metamgr.go deleted file mode 100644 index 6ca8e4d..0000000 --- a/metamgr.go +++ /dev/null @@ -1,316 +0,0 @@ -package f5 - -import ( - "os" - "bufio" - "strings" - "reflect" - "fmt" - "strconv" - "encoding/json" - "q5" - - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/jsonpb" - "google.golang.org/protobuf/reflect/protoreflect" -) - -type MetaClass struct { - FileName string - Idx int - RawMeta interface{} - WrapMeta interface{} - PrimKey string - SecKey string - eleMeta reflect.Type -} - -type MetaMgr struct { - metaClasses *[]MetaClass - rawList []interface{} - wrapList []interface{} - wrapIdHash []map[int64]interface{} - wrapNameHash []map[string]interface{} -} - -func (this *MetaMgr) Init() { - -} - -func (this *MetaMgr) UnInit() { - -} - -func (this *MetaMgr) RegisterMetaClasses(metaClasses *[]MetaClass) { - for i := 0; i < len(*metaClasses); i++ { - metaClass := &(*metaClasses)[i] - msgType := reflect.TypeOf(metaClass.RawMeta).Elem() - msg := reflect.New(msgType) - metaClass.eleMeta = reflect.TypeOf(msg.Elem().FieldByName("Values").Interface()).Elem().Elem() - if metaClass.eleMeta == nil { - panic(fmt.Sprintf( - "registerMetaClasses error not found Values field %s", - metaClass.FileName)) - } - } - this.metaClasses = metaClasses -} - -func (this *MetaMgr) Load() { - this.rawList = make([]interface{}, len(*this.metaClasses)) - this.wrapList = make([]interface{}, len(*this.metaClasses)) - this.wrapIdHash = make([]map[int64]interface{}, len(*this.metaClasses)) - this.wrapNameHash = make([]map[string]interface{}, len(*this.metaClasses)) - this.loadRawMetaTable() - this.bindPrimKey() - this.firstInitMetaList() - this.secondInitMetaList() -} - -func (this *MetaMgr) loadRawMetaTable() { - for _, metaClass := range *this.metaClasses { - rawMeta, _ := this.loadJson(&metaClass) - values := rawMeta.Elem().FieldByName("Values") - wrapMetaType := reflect.TypeOf(metaClass.WrapMeta) - wrapMetaList := reflect.MakeSlice(reflect.SliceOf(wrapMetaType), 0, values.Len()) - for i := 0; i < values.Len(); i++ { - val := values.Index(i) - - wrapMeta := reflect.New(reflect.TypeOf(wrapMetaList.Interface()).Elem().Elem()) - clsName := reflect.TypeOf(val.Elem().Interface()).Name() - clsField := wrapMeta.Elem().FieldByName(clsName) - clsField.Set(val) - - wrapMetaList = reflect.Append(wrapMetaList, wrapMeta) - } - - this.rawList[metaClass.Idx] = rawMeta - this.wrapList[metaClass.Idx] = wrapMetaList.Interface() - this.wrapIdHash[metaClass.Idx] = map[int64]interface{}{} - this.wrapNameHash[metaClass.Idx] = map[string]interface{}{} - } -} - -func (this *MetaMgr) bindPrimKey() { - bindFunc := func (metaClass *MetaClass, wrapMeta reflect.Value) { - primVal := wrapMeta.Elem().FieldByName(metaClass.PrimKey) - secVal := wrapMeta.Elem().FieldByName(metaClass.SecKey) - nameHash := this.wrapNameHash[metaClass.Idx] - idHash := this.wrapIdHash[metaClass.Idx] - if fieldVal, ok := primVal.Interface().(*string); ok { - if _, ok := nameHash[*fieldVal]; ok { - panic(fmt.Sprintf( - "bindPrimKey duplicated key error %s %s", - metaClass.FileName, - *fieldVal)) - } - nameHash[*fieldVal] = wrapMeta - } else if fieldVal, ok := primVal.Interface().(*int32); ok { - if metaClass.SecKey == "" { - if _, ok := idHash[int64(*fieldVal)]; ok { - panic(fmt.Sprintf( - "bindPrimKey duplicated key error %s %s", - metaClass.FileName, - *fieldVal)) - } - idHash[int64(*fieldVal)] = wrapMeta.Interface() - } else { - if subFieldVal, ok := secVal.Interface().(*int32); ok { - if _, ok := idHash[q5.MkInt64(*fieldVal, *subFieldVal)]; ok { - panic(fmt.Sprintf( - "bindPrimKey duplicated key error %s %s", - metaClass.FileName, - q5.MkInt64(*fieldVal, *subFieldVal))) - } - idHash[q5.MkInt64(*fieldVal, *subFieldVal)] = wrapMeta.Interface() - } else { - panic(fmt.Sprintf("bindPrimKey subField error %s", metaClass.FileName)) - } - } - } else { - panic(fmt.Sprintf("bindPrimKey primKey error %s", metaClass.FileName)) - } - } - for _, metaClass := range *this.metaClasses { - wrapMetaList := reflect.ValueOf(this.wrapList[metaClass.Idx]) - for i := 0; i < wrapMetaList.Len(); i++ { - wrapMeta := wrapMetaList.Index(i) - if metaClass.PrimKey == "" { - this.wrapIdHash[metaClass.Idx][int64(i + 1)] = wrapMeta.Interface() - } else { - bindFunc(&metaClass, wrapMeta) - } - } - } -} - -func (this *MetaMgr) loadJson(metaClass *MetaClass) (reflect.Value, error) { - if f, err := os.Open(metaClass.FileName); err == nil { - data, _ := bufio.NewReader(f).ReadString(0) - switch q5.JsonStrType(data) { - case q5.JSON_ARRAY: - break - case q5.JSON_OBJECT: - data = "[" + data + "]" - default: - panic(fmt.Sprintf("error json format %s", metaClass.FileName)) - } - data = this.adjustJsonForamt(metaClass, data) - data = "{\"values\":" + data + "}" - - msgType := reflect.TypeOf(metaClass.RawMeta).Elem() - msg := reflect.New(msgType) - msgPb := msg.Interface().(proto.Message) - u := jsonpb.Unmarshaler{AllowUnknownFields: true} - err := u.Unmarshal(strings.NewReader(data), msgPb) - if err != nil { - panic(fmt.Sprintf( - "parse json error %s %s %s", - err, - metaClass.FileName, - msgType.Name())) - } - return msg, err - } else { - panic(fmt.Sprintf("open metafile error %s %s", metaClass.FileName, err)) - } -} - -func (this *MetaMgr) GetMetaById(idx int, id int32) interface{} { - return this.GetMetaById64(idx, int64(id)) -} - -func (this *MetaMgr) GetMetaById64(idx int, id int64) interface{} { - if idx >=0 && idx < len(this.wrapIdHash) { - idHash := this.wrapIdHash[idx] - if v, ok := idHash[id]; ok { - return reflect.ValueOf(v).Interface() - } else { - return nil - } - } - return nil -} - -func (this *MetaMgr) GetMetaByName(idx int, name string) interface{} { - if idx >=0 && idx < len(this.wrapNameHash) { - nameHash := this.wrapNameHash[idx] - if v, ok := nameHash[name]; ok { - return v - } else { - return nil - } - } - return nil -} - -func (this *MetaMgr) GetMetaList(idx int) interface{} { - if idx >=0 && idx < len(this.wrapList) { - return this.wrapList[idx] - } - return nil -} - -func (this *MetaMgr) adjustJsonForamt(metaClass *MetaClass, rawData string) string { - adjustFieldFunc := func(msg map[string]interface{}, key string, val interface{}, field protoreflect.FieldDescriptor) { - switch field.Kind() { - case - protoreflect.Int32Kind, - protoreflect.Sint32Kind, - protoreflect.Int64Kind, - protoreflect.Sint64Kind, - protoreflect.Uint64Kind, - protoreflect.Sfixed32Kind, - protoreflect.Fixed32Kind, - protoreflect.FloatKind, - protoreflect.Sfixed64Kind, - protoreflect.Fixed64Kind, - protoreflect.DoubleKind: - if q5.IsNumberType(val) { - } else if reflect.TypeOf(val).Kind() == reflect.String { - strVal := val.(string) - if strVal == "" { - msg[key] = 0 - } else { - intVal, err := strconv.ParseInt(strVal, 10, 64) - if err == nil { - msg[key] = intVal - } else { - floatVal, err := strconv.ParseFloat(strVal, 64) - if err == nil { - msg[key] = floatVal - } else { - panic(fmt.Sprintf( - "adjustJsonFormat error %s %s %s", - metaClass.FileName, - key, - val)) - } - } - } - } - case - protoreflect.BoolKind, - protoreflect.EnumKind, - protoreflect.BytesKind, - //protoreflect.MessageKind, - protoreflect.GroupKind: - panic(fmt.Sprintf( - "adjustJsonFormat error %s %s %s", - metaClass.FileName, - key, - val)) - case protoreflect.MessageKind: - break - } - } - var rawJson []map[string]interface{} - err := json.Unmarshal([]byte(rawData), &rawJson) - if err != nil { - panic(fmt.Sprintf("adjustJsonFormat unmarshal error %s %s", metaClass.FileName, err)) - } - msgType := proto.MessageReflect(reflect.New(metaClass.eleMeta).Interface().(proto.Message)) - for i := 0; i < len(rawJson); i++ { - msg := rawJson[i] - for key, val := range msg { - field := msgType.Descriptor().Fields().ByName(protoreflect.Name(key)) - if field != nil { - adjustFieldFunc(msg, key, val, field) - } - } - } - - newData, err := json.Marshal(rawJson) - //fmt.Println("rawData ", string(rawData)) - //fmt.Println("newData ", string(newData)) - if err != nil { - panic(fmt.Sprintf("adjustJsonFormat marshal error %s %s", metaClass.FileName, err)) - } - return string(newData) -} - -func (this *MetaMgr) firstInitMetaList() { - for i := 0; i < len(this.wrapList); i++ { - metaList := reflect.ValueOf(this.wrapList[i]) - for ii := 0; ii < metaList.Len(); ii++ { - meta := metaList.Index(ii) - initFunc := meta.MethodByName("Init") - if initFunc.IsValid() { - initFunc.Call(nil) - } - } - } -} - -func (this *MetaMgr) secondInitMetaList() { - for i := 0; i < len(this.wrapList); i++ { - metaList := reflect.ValueOf(this.wrapList[i]) - for i := 0; i < metaList.Len(); i++ { - meta := metaList.Index(i) - init2Func := meta.MethodByName("Init2") - if init2Func.IsValid() { - init2Func.Call(nil) - } - } - } -} diff --git a/metatable.go b/metatable.go new file mode 100644 index 0000000..09019ea --- /dev/null +++ b/metatable.go @@ -0,0 +1,213 @@ +package f5 + +import ( + "reflect" + "q5" + "os" + "bufio" + "fmt" + "encoding/json" +) + +type MetaTable interface { + IsNoLoad() bool + Load() + PreInit1() + ElementsInit(int) + PostInit1() +} + +type LoadFromKeyValue interface { + LoadFromKv(map[string]interface{}) +} + +type RawMetaTable[T any] struct { + FileName string + PrimKey string + NoLoad bool + rawList []*T +} + +type IdMetaTable[T any] struct { + RawMetaTable[T] + idHash map[int64]*T +} + +type NameMetaTable[T any] struct { + RawMetaTable[T] + nameHash map[string]*T +} + +func (this *RawMetaTable[T]) Traverse(cb func (*T) bool) { + for _, val := range this.rawList { + if !cb(val) { + break + } + } +} + +func (this *RawMetaTable[T]) IsNoLoad() bool { + return this.NoLoad +} + +func (this *RawMetaTable[T]) PreInit1() { +} + +func (this *RawMetaTable[T]) PostInit1() { +} + +func (this *RawMetaTable[T]) ElementsInit(round int) { + type RoundInit1 interface { + Init1() + } + type RoundInit2 interface { + Init2() + } + type RoundInit3 interface { + Init3() + } + this.Traverse(func (obj *T) bool { + var x interface{} = obj + switch round { + case 0: + if init, ok := x.(RoundInit1); ok { + init.Init1() + } + case 1: + if init, ok := x.(RoundInit2); ok { + init.Init2() + } + case 2: + if init, ok := x.(RoundInit3); ok { + init.Init3() + } + } + return true + }) +} + +func (this *IdMetaTable[T]) GetById(id int64) *T { + if v, ok := this.idHash[id]; ok { + return v + } else { + return nil + } +} + +func (this *RawMetaTable[T]) Load() { + if this.NoLoad { + return + } + if f, err := os.Open(this.FileName); err == nil { + jsonStr, _ := bufio.NewReader(f).ReadString(0) + switch q5.JsonStrType(jsonStr) { + case q5.JSON_ARRAY: + break + case q5.JSON_OBJECT: + jsonStr = "[" + jsonStr + "]" + default: + panic(fmt.Sprintf("error json format %s", this.FileName)) + } + var rows []map[string]interface{} + json.Unmarshal([]byte(jsonStr), &rows) + for _, row := range rows { + var obj = new(T) + var x interface{} = obj + if loader, ok := x.(LoadFromKeyValue); ok { + loader.LoadFromKv(row) + } + this.rawList = append(this.rawList, obj) + } + } else { + panic(fmt.Sprintf("load metafile error %s %s", this.FileName, err)) + } +} + +func (this *IdMetaTable[T]) Load() { + this.RawMetaTable.Load() + this.idHash = make(map[int64]*T) + i := int64(0) + getFuncName := "Get" + q5.ConvertUpperCamelCase(this.PrimKey) + this.Traverse(func (obj *T) bool { + if this.PrimKey == "" { + this.idHash[i] = obj + } else { + in := []reflect.Value{} + method := reflect.ValueOf(obj).MethodByName(getFuncName) + out := method.Call(in) + if key, err := q5.ToInt64Ex(out[0].Interface()); err == nil { + this.idHash[key] = obj + } else { + panic("IdMetaTable load PrimKey error") + } + } + i++ + return true + }) +} + +func (this *NameMetaTable[T]) GetByName(name string) *T { + if v, ok := this.nameHash[name]; ok { + return v + } else { + return nil + } +} + +func (this *NameMetaTable[T]) Load() { + this.RawMetaTable.Load() + this.nameHash = make(map[string]*T) + i := int64(0) + getFuncName := "Get" + q5.ConvertUpperCamelCase(this.PrimKey) + this.Traverse(func (obj *T) bool { + in := []reflect.Value{} + method := reflect.ValueOf(obj).MethodByName(getFuncName) + out := method.Call(in) + if key, err := q5.ToStringEx(out[0].Interface()); err == nil { + this.nameHash[key] = obj + } else { + panic("NameMetaTable load PrimKey error") + } + i++ + return true + }) +} + +func ReadMetaTableField[T string | int | int32 | int64 | float32 | float64]( + fieldPtr *T, fieldName string, flags *uint64, flagIdx uint64, + kv map[string]interface{}) { + if val, ok := kv[fieldName]; ok { + if !q5.DuckToSimple(val, fieldPtr) { + panic("ReadMetaTableField error") + } + *flags |= uint64(1) << flagIdx + } +} + +func LoadMetaTable(table interface{}) { + ele := reflect.ValueOf(table).Elem() + for i := 0; i < ele.NumField(); i++ { + var tbl MetaTable = ele.Field(i).Interface().(MetaTable) + if !tbl.IsNoLoad() { + tbl.PreInit1() + } + } + for i := 0; i < ele.NumField(); i++ { + var tbl MetaTable = ele.Field(i).Interface().(MetaTable) + if !tbl.IsNoLoad() { + tbl.Load() + } + } + for i := 0; i < 3; i++ { + for ii := 0; ii < ele.NumField(); ii++ { + var tbl MetaTable = ele.Field(ii).Interface().(MetaTable) + tbl.ElementsInit(i) + } + } + for i := 0; i < ele.NumField(); i++ { + var tbl MetaTable = ele.Field(i).Interface().(MetaTable) + if !tbl.IsNoLoad() { + tbl.PostInit1() + } + } +} diff --git a/prototils.go b/prototils.go new file mode 100644 index 0000000..eb700ba --- /dev/null +++ b/prototils.go @@ -0,0 +1,89 @@ +package f5 + +import ( + "q5" + "net" +) + +type MsgHdr struct { + MsgId uint16 + SeqId uint32 + SocketHandle uint16 + IpSaddr uint32 + + Conn net.Conn + Data []byte + Msg interface{} + Entry q5.ListHead +} + +type NetMsg interface { + GetNetMsgId() uint16 +} + +/* + struct WSProxyPackHead_C + { + unsigned short packlen; + unsigned short msgid; + unsigned int seqid; + unsigned short magic_code; + + unsigned short socket_handle; + unsigned long ip_saddr; + }; +*/ +type WSProxyPackHead_C struct { + PackLen uint16 + MsgId uint16 + SeqId uint32 + MagicCode uint16 + SocketHandle uint16 + + IpSaddr uint64 +} + +/* + struct WSProxyPackHead_S + { + unsigned short packlen; + unsigned short msgid; + unsigned int seqid; + unsigned short magic_code; + unsigned short rpc_error_code; + + unsigned short socket_handle; + unsigned short ext_len; + }; +*/ +type WSProxyPackHead_S struct { + PackLen uint16 + MsgId uint16 + SeqId uint32 + MagicCode uint16 + RpcErrCode uint16 + + SocketHandle uint16 + ExtLen uint16 +} + +func (this *WSProxyPackHead_C) Read(data []byte, offset int) { + this.PackLen = q5.MkUInt16(data[offset + 0], data[offset + 1]) + this.MsgId = q5.MkUInt16(data[offset + 2], data[offset + 3]) + this.SeqId = q5.MkUInt32(data[offset + 4], data[offset + 5], + data[offset + 6], data[offset + 7]) + this.MagicCode = q5.MkUInt16(data[offset + 8], data[offset + 9]) + this.SocketHandle = q5.MkUInt16(data[offset + 10], data[offset + 11]) +} + +func (this *WSProxyPackHead_S) Write(data []byte, offset int) { + data[offset + 0] = byte(this.PackLen & 0xFF) + data[offset + 1] = byte(this.PackLen >> 8) + data[offset + 2] = byte(this.MsgId & 0xFF) + data[offset + 3] = byte(this.MsgId >> 8) + data[offset + 8] = byte('K') + data[offset + 9] = byte('S') + + data[offset + 12] = byte(this.SocketHandle & 0xFF) + data[offset + 13] = byte(this.SocketHandle >> 8) +} diff --git a/syslog.go b/syslog.go index edfeb04..eb7fd73 100644 --- a/syslog.go +++ b/syslog.go @@ -22,6 +22,7 @@ const SYS_LOG_ROOT = "/data/logs/%s/logs/" const SYS_LOG_FILENAME = "log_%d_%s.log" type LogMsgNode struct { + category int32 logMsg string next *LogMsgNode } @@ -34,12 +35,12 @@ type SysLog_ struct { chGoSaveExit chan int } -func (this *SysLog_) Init() { +func (this *SysLog_) init() { this.chGoSaveExit = make(chan int) go this.goSaveToFile() } -func (this *SysLog_) UnInit() { +func (this *SysLog_) unInit() { this.chGoSaveExit <- 1 } @@ -47,57 +48,59 @@ func (this *SysLog_) Emergency(format string, args ...interface{}) { if this.logLevel > LOG_EMERGENCY { return } - this.addLog("[EMERGENCY]", format, args...) + this.addLog(LOG_EMERGENCY, "[EMERGENCY]", format, args...) } func (this *SysLog_) Alert(format string, args ...interface{}) { if this.logLevel > LOG_ALERT { return } - this.addLog("[ALERT]", format, args...) + this.addLog(LOG_ALERT, "[ALERT]", format, args...) } func (this *SysLog_) Error(format string, args ...interface{}) { if this.logLevel > LOG_ERROR { return } - this.addLog("[ERROR]", format, args...) + this.addLog(LOG_ERROR, "[ERROR]", format, args...) } func (this *SysLog_) Warning(format string, args ...interface{}) { if this.logLevel > LOG_WARNING { return } - this.addLog("[WARNING]", format, args...) + this.addLog(LOG_WARNING, "[WARNING]", format, args...) } func (this *SysLog_) Notice(format string, args ...interface{}) { if this.logLevel > LOG_NOTICE { return } - this.addLog("[NOTICE]", format, args...) + this.addLog(LOG_NOTICE, "[NOTICE]", format, args...) } func (this *SysLog_) Info(format string, args ...interface{}) { if this.logLevel > LOG_INFO { return } - this.addLog("[INFO]", format, args...) + this.addLog(LOG_INFO, "[INFO]", format, args...) } func (this *SysLog_) Debug(format string, args ...interface{}) { if this.logLevel > LOG_DEBUG { return } - this.addLog("[DEBUG]", format, args...) + this.addLog(LOG_DEBUG, "[DEBUG]", format, args...) } -func (this *SysLog_) addLog(category string, format string, args ...interface{}) { +func (this *SysLog_) addLog(category int32, prefixStr string, + format string, args ...interface{}) { p := &LogMsgNode{} + p.category = category p.logMsg = time.Now().Format("2006-01-02 15:04:05") + - category + " " + + prefixStr + " " + fmt.Sprintf(format, args...) + "\n" - if q5.Debug() { + if category == LOG_INFO { fmt.Print(p.logMsg) } this.msgMutex.Lock() @@ -125,7 +128,7 @@ func (this *SysLog_) goSaveToFile() { this.botNode = nil this.msgMutex.Unlock() if workNode != nil { - logDir := fmt.Sprintf(SYS_LOG_ROOT, App.GetPkgName()) + logDir := fmt.Sprintf(SYS_LOG_ROOT, GetApp().GetPkgName()) fileName := fmt.Sprintf(TGLOG_FILENAME, os.Getpid(), time.Now().Format("20060102")) q5.ForceCreateDir(logDir) if f, err := os.OpenFile(logDir + fileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666); err == nil { diff --git a/sysutils.go b/sysutils.go index dd69f9a..1335c52 100644 --- a/sysutils.go +++ b/sysutils.go @@ -2,8 +2,8 @@ package f5 import ( "os" - "strings" - "q5" + //"strings" + //"q5" ) const ( @@ -26,19 +26,7 @@ func IsDevEnv() bool { return serverEnv == DEV_ENV } -func IsValidSessionId(accountId string, sessionId string, key string) bool { - tmpStrings := strings.Split(sessionId, "_") - if len(tmpStrings) < 4 { - return false - } - sessionCreateTime := new(q5.XValue).SetString(tmpStrings[0]).GetString() - registerTime := new(q5.XValue).SetString(tmpStrings[1]).GetString() - md5Str := new(q5.XValue).SetString(tmpStrings[2]).GetString() - //SysLog().Debug("%s", accountId + key + registerTime + sessionCreateTime) - //SysLog().Debug("md51=%s md52=%s", q5.Md5Str(accountId + key + registerTime + sessionCreateTime), md5Str) - return q5.Md5Str(accountId + key + registerTime + sessionCreateTime) == md5Str -} - +/* func ExtractRegisterTimeFromSessionId(sessionId string) int64 { tmpStrings := strings.Split(sessionId, "_") if len(tmpStrings) < 4 { @@ -70,6 +58,12 @@ func ExtractOpenIdFromAccountId(accountId string) string { } return strings.Join(tmpStrings[2:], "_") } +*/ +func New[T any](cb func(*T)) *T { + obj := new(T) + cb(obj) + return obj +} func init() { switch os.Getenv("SERVER_ENV") { diff --git a/tglog.go b/tglog.go index 629593b..c8a8d81 100644 --- a/tglog.go +++ b/tglog.go @@ -1,10 +1,10 @@ package f5 -import "os" -import "fmt" +//import "os" +//import "fmt" import "sync" -import "time" -import "q5" +//import "time" +//import "q5" const TGLOG_ROOT = "/data/logs/%s/upload/" const POLY_TGLOG_ROOT = "/data/logs/%s/%d/upload/" @@ -24,12 +24,12 @@ type TGLog_ struct { chGoSaveExit chan int } -func (this *TGLog_) Init() { +func (this *TGLog_) init() { this.chGoSaveExit = make(chan int) - go this.goSaveToFile() + //go this.goSaveToFile() } -func (this *TGLog_) UnInit() { +func (this *TGLog_) unInit() { this.chGoSaveExit <- 1 } @@ -37,6 +37,7 @@ func (this *TGLog_) SetPolyLog(isPolyLog bool) { this.isPolyLog = isPolyLog } +/* func (this *TGLog_) AddTrackLog( gameId int32, accountId string, @@ -75,8 +76,9 @@ func (this *TGLog_) AddTrackLogEx( this.topNode = p this.botNode = p } -} - +//} +*/ + /* func (this *TGLog_) goSaveToFile() { var workNode *TGLogMsgNode for { @@ -119,3 +121,5 @@ func (this *TGLog_) getLogFile(gameId int32) *os.File { return nil } } + + */ diff --git a/timer.go b/timer.go new file mode 100644 index 0000000..b2a7f8b --- /dev/null +++ b/timer.go @@ -0,0 +1,99 @@ +package f5 + +import ( + "q5" +) + +type TimerWp struct { + *q5.XTimerWp +} + +type TimerAttacher struct { + *q5.XTimerAttacher +} + +type Timer struct { + timer *q5.XTimer +} + +func (this *Timer) init() { + this.timer = new(q5.XTimer) + this.timer.Init( + func (context interface{}) int64 { + return q5.GetTickCount() + }, + nil, + 1000 * 60, + 5000) +} + +func (this *Timer) update() { + this.timer.Update() +} + +func (this *Timer) unInit() { + this.timer.UnInit() + this.timer = nil +} + +func (this *Timer) NewTimerAttacher() *TimerAttacher { + ac := TimerAttacher{} + ac.XTimerAttacher = this.timer.NewTimerAttacher() + return &ac +} + +func (this *Timer) SetTimeout(expireTime int32, cb q5.TimerCb) { + this.timer.SetTimeout(expireTime, cb) +} + +func (this *Timer) SetTimeoutEx(expireTime int32, cb q5.TimerCb, ac *TimerAttacher) { + this.timer.SetTimeoutEx(expireTime, cb, ac.XTimerAttacher) +} + +func (this *Timer) SetTimeoutWp(expireTime int32, cb q5.TimerCb) *TimerWp { + wp := TimerWp{} + wp.XTimerWp = this.timer.SetTimeoutWp(expireTime, cb) + return &wp +} + +func (this *Timer) SetTimeoutExWp(expireTime int32, cb q5.TimerCb, ac *TimerAttacher) *TimerWp { + wp := TimerWp{} + wp.XTimerWp = this.timer.SetTimeoutExWp(expireTime, cb, ac.XTimerAttacher) + return &wp +} + +func (this *Timer) SetInterval(expireTime int32, cb q5.TimerCb) { + this.timer.SetInterval(expireTime, cb) +} + +func (this *Timer) SetIntervalEx(expireTime int32, cb q5.TimerCb, ac *TimerAttacher) { + this.timer.SetIntervalEx(expireTime, cb, ac.XTimerAttacher) +} + +func (this *Timer) SetIntervalWp(expireTime int32, cb q5.TimerCb) *TimerWp { + wp := TimerWp{} + wp.XTimerWp = this.timer.SetIntervalWp(expireTime, cb) + return &wp +} + +func (this *Timer) SetIntervalExWp(expireTime int32, cb q5.TimerCb, ac *TimerAttacher) *TimerWp { + wp := TimerWp{} + wp.XTimerWp = this.timer.SetIntervalExWp(expireTime, cb, ac.XTimerAttacher) + return &wp +} + +func (this *Timer) GetIdleTime() int64 { + return this.timer.GetIdleTime() +} + +func (this *Timer) ModifyTimer(timerWp *TimerWp, expireTime int32) { + this.timer.ModifyTimer(timerWp.XTimerWp, expireTime) +} + +func (this *Timer) Delete(timerWp *TimerWp) { + this.timer.Delete(timerWp.XTimerWp) +} + +func (this *Timer) GetRemainTime(timerWp *TimerWp) int64 { + return this.timer.GetRemainTime(timerWp.XTimerWp) +} diff --git a/types.go b/types.go index 0a14770..0df2727 100644 --- a/types.go +++ b/types.go @@ -2,7 +2,6 @@ package f5 import ( "q5" - "net" ) const ( @@ -16,8 +15,8 @@ type MsgNode struct { } type IMMsgNode struct { - msgId int16 - params *q5.XParams + msgId uint16 + params q5.Args next *IMMsgNode } @@ -28,86 +27,3 @@ type middleware struct { handlerFunc HandlerFunc entry q5.ListHead } - -type MsgHdr struct { - MsgId uint16 - SeqId uint32 - SocketHandle uint16 - IpSaddr uint32 - - Conn net.Conn - Data []byte - Msg interface{} - Entry q5.ListHead -} - -type NetMsg interface { - GetNetMsgId() uint16 -} - -/* - struct WSProxyPackHead_C - { - unsigned short packlen; - unsigned short msgid; - unsigned int seqid; - unsigned short magic_code; - - unsigned short socket_handle; - unsigned long ip_saddr; - }; -*/ -type WSProxyPackHead_C struct { - PackLen uint16 - MsgId uint16 - SeqId uint32 - MagicCode uint16 - SocketHandle uint16 - - IpSaddr uint64 -} - -/* - struct WSProxyPackHead_S - { - unsigned short packlen; - unsigned short msgid; - unsigned int seqid; - unsigned short magic_code; - unsigned short rpc_error_code; - - unsigned short socket_handle; - unsigned short ext_len; - }; -*/ -type WSProxyPackHead_S struct { - PackLen uint16 - MsgId uint16 - SeqId uint32 - MagicCode uint16 - RpcErrCode uint16 - - SocketHandle uint16 - ExtLen uint16 -} - -func (this *WSProxyPackHead_C) Read(data []byte, offset int) { - this.PackLen = q5.MkUInt16(data[offset + 0], data[offset + 1]) - this.MsgId = q5.MkUInt16(data[offset + 2], data[offset + 3]) - this.SeqId = q5.MkUInt32(data[offset + 4], data[offset + 5], - data[offset + 6], data[offset + 7]) - this.MagicCode = q5.MkUInt16(data[offset + 8], data[offset + 9]) - this.SocketHandle = q5.MkUInt16(data[offset + 10], data[offset + 11]) -} - -func (this *WSProxyPackHead_S) Write(data []byte, offset int) { - data[offset + 0] = byte(this.PackLen & 0xFF) - data[offset + 1] = byte(this.PackLen >> 8) - data[offset + 2] = byte(this.MsgId & 0xFF) - data[offset + 3] = byte(this.MsgId >> 8) - data[offset + 8] = byte('K') - data[offset + 9] = byte('S') - - data[offset + 12] = byte(this.SocketHandle & 0xFF) - data[offset + 13] = byte(this.SocketHandle >> 8) -}