diff --git a/go.mod b/go.mod index a5a189d..045868d 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,7 @@ require ( github.com/mattn/go-isatty v0.0.19 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/panjf2000/gnet/v2 v2.3.6 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/samber/do/v2 v2.0.0-beta.5 // indirect @@ -60,16 +61,17 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - go.uber.org/multierr v1.7.0 // indirect - go.uber.org/zap v1.19.1 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.3.0 // indirect golang.org/x/exp v0.0.0-20221031165847-c99f073a8326 // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect google.golang.org/protobuf v1.33.0 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 20d695c..11c264d 100644 --- a/go.sum +++ b/go.sum @@ -113,6 +113,8 @@ github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0t github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= github.com/panjf2000/gnet v1.6.7 h1:zv1k6kw80sG5ZQrLpbbFDheNCm50zm3z2e3ck5GwMOM= github.com/panjf2000/gnet v1.6.7/go.mod h1:KcOU7QsCaCBjeD5kyshBIamG3d9kAQtlob4Y0v0E+sc= +github.com/panjf2000/gnet/v2 v2.3.6 h1:BUHjMPJaNO8N5rQZmhKce9/Iu2ryeMjhKPEOi+ecisQ= +github.com/panjf2000/gnet/v2 v2.3.6/go.mod h1:R+X5M5YBpOGMVP/92OJ02P35SbmoHjiL7GnaBhht6GE= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= @@ -192,8 +194,12 @@ go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpK 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/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -241,6 +247,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= @@ -260,6 +268,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -324,6 +334,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/server/v2/event_handler.go b/server/v2/event_handler.go new file mode 100644 index 0000000..37cb6b8 --- /dev/null +++ b/server/v2/event_handler.go @@ -0,0 +1,69 @@ +package server + +import ( + "fmt" + "github.com/panjf2000/ants/v2" + "github.com/panjf2000/gnet/v2" + "time" +) + +func newEventHandler(trafficker Trafficker) (handler *eventHandler, err error) { + var wp *ants.Pool + if wp, err = ants.NewPool(ants.DefaultAntsPoolSize, ants.WithNonblocking(true)); err != nil { + return + } + handler = &eventHandler{ + trafficker: trafficker, + workerPool: wp, + } + return +} + +type ( + Trafficker interface { + OnBoot() error + OnTraffic(c gnet.Conn, packet []byte) + } + eventHandler struct { + trafficker Trafficker + workerPool *ants.Pool + } +) + +func (e *eventHandler) OnBoot(eng gnet.Engine) (action gnet.Action) { + if err := e.trafficker.OnBoot(); err != nil { + action = gnet.Shutdown + } + return +} + +func (e *eventHandler) OnShutdown(eng gnet.Engine) { + return +} + +func (e *eventHandler) OnOpen(c gnet.Conn) (out []byte, action gnet.Action) { + return +} + +func (e *eventHandler) OnClose(c gnet.Conn, err error) (action gnet.Action) { + fmt.Println("断开") + return +} + +func (e *eventHandler) OnTraffic(c gnet.Conn) (action gnet.Action) { + buf, err := c.Next(-1) + if err != nil { + return + } + var packet = make([]byte, len(buf)) + copy(packet, buf) + err = e.workerPool.Submit(func() { + e.trafficker.OnTraffic(c, packet) + }) + + return +} + +func (e *eventHandler) OnTick() (delay time.Duration, action gnet.Action) { + return +} diff --git a/server/v2/server.go b/server/v2/server.go new file mode 100644 index 0000000..02e50fd --- /dev/null +++ b/server/v2/server.go @@ -0,0 +1,20 @@ +package server + +import "github.com/panjf2000/gnet/v2" + +func NewServer(trafficker Trafficker) *Server { + srv := &Server{ + trafficker: trafficker, + } + return srv +} + +type Server struct { + trafficker Trafficker +} + +func (s *Server) Run(protoAddr string) (err error) { + var handler *eventHandler + handler, err = newEventHandler(s.trafficker) + return gnet.Run(handler, protoAddr) +} diff --git a/server/v2/traffickers/http.go b/server/v2/traffickers/http.go new file mode 100644 index 0000000..179e294 --- /dev/null +++ b/server/v2/traffickers/http.go @@ -0,0 +1,42 @@ +package traffickers + +import ( + "bufio" + "bytes" + "github.com/kercylan98/minotaur/server/v2" + "github.com/kercylan98/minotaur/utils/hub" + "github.com/panjf2000/gnet/v2" + netHttp "net/http" +) + +func Http(handler netHttp.Handler) server.Trafficker { + return &http{ + handler: handler, + } +} + +type http struct { + handler netHttp.Handler + rwp *hub.ObjectPool[*httpResponseWriter] +} + +func (h *http) OnBoot() error { + h.rwp = hub.NewObjectPool[httpResponseWriter](func() *httpResponseWriter { + return new(httpResponseWriter) + }, func(data *httpResponseWriter) { + data.reset() + }) + return nil +} + +func (h *http) OnTraffic(c gnet.Conn, packet []byte) { + httpRequest, err := netHttp.ReadRequest(bufio.NewReader(bytes.NewReader(packet))) + if err != nil { + return + } + + responseWriter := h.rwp.Get() + responseWriter.init(c) + + h.handler.ServeHTTP(responseWriter, httpRequest) +} diff --git a/server/v2/traffickers/http_response_writer.go b/server/v2/traffickers/http_response_writer.go new file mode 100644 index 0000000..fcff5ac --- /dev/null +++ b/server/v2/traffickers/http_response_writer.go @@ -0,0 +1,58 @@ +package traffickers + +import ( + "bytes" + "github.com/panjf2000/gnet/v2" + netHttp "net/http" + "strconv" + "sync" +) + +type httpResponseWriter struct { + c gnet.Conn + statusCode int + header netHttp.Header +} + +func (w *httpResponseWriter) init(c gnet.Conn) { + w.c = c + w.statusCode = 200 + w.header = make(netHttp.Header) +} + +func (w *httpResponseWriter) reset() { + w.c = nil + w.statusCode = 200 + w.header = nil +} + +func (w *httpResponseWriter) Header() netHttp.Header { + return w.header +} + +func (w *httpResponseWriter) Write(b []byte) (n int, err error) { + var buf bytes.Buffer + buf.WriteString("HTTP/1.1 ") + buf.WriteString(netHttp.StatusText(w.statusCode)) + buf.WriteString("\r\n") + w.header.Set("Content-Length", strconv.Itoa(len(b))) + if err = w.header.Write(&buf); err != nil { + return + } + buf.WriteString("\r\n") + buf.Write(b) + res := buf.Bytes() + var wg sync.WaitGroup + wg.Add(1) + err = w.c.AsyncWrite(res, func(c gnet.Conn, e error) error { + err = e + wg.Done() + return nil + }) + wg.Wait() + return len(res), err +} + +func (w *httpResponseWriter) WriteHeader(statusCode int) { + w.statusCode = statusCode +}