wip: 又加了一些新东西。
							parent
							
								
									dca483dc32
								
							
						
					
					
						commit
						5779bb7989
					
				@ -0,0 +1,20 @@
 | 
			
		||||
package component
 | 
			
		||||
 | 
			
		||||
type CompWithOptions struct {
 | 
			
		||||
	Comp Component
 | 
			
		||||
	Opts []Option
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Components struct {
 | 
			
		||||
	comps []CompWithOptions
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Register 全局注册组件,必须在服务启动之前初始化
 | 
			
		||||
func (cs *Components) Register(c Component, options ...Option) {
 | 
			
		||||
	cs.comps = append(cs.comps, CompWithOptions{c, options})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List 获取所有已注册组件
 | 
			
		||||
func (cs *Components) List() []CompWithOptions {
 | 
			
		||||
	return cs.comps
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
package interfaces
 | 
			
		||||
 | 
			
		||||
type IMessage interface {
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,88 @@
 | 
			
		||||
package log
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Logger interface {
 | 
			
		||||
	Debugf(format string, v ...interface{})
 | 
			
		||||
	Debug(v ...interface{})
 | 
			
		||||
	Info(v ...interface{})
 | 
			
		||||
	Infof(format string, v ...interface{})
 | 
			
		||||
	Error(v ...interface{})
 | 
			
		||||
	Errorf(format string, v ...interface{})
 | 
			
		||||
	Panic(v ...interface{})
 | 
			
		||||
	Panicf(format string, v ...interface{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	SetLogger(newInnerLogger())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	Debugf func(format string, v ...interface{})
 | 
			
		||||
	Debug  func(v ...interface{})
 | 
			
		||||
	Info   func(v ...interface{})
 | 
			
		||||
	Infof  func(format string, v ...interface{})
 | 
			
		||||
	Error  func(v ...interface{})
 | 
			
		||||
	Errorf func(format string, v ...interface{})
 | 
			
		||||
	Panic  func(v ...interface{})
 | 
			
		||||
	Panicf func(format string, v ...interface{})
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func SetLogger(logger Logger) {
 | 
			
		||||
	if logger == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	Debugf = logger.Debugf
 | 
			
		||||
	Debug = logger.Debug
 | 
			
		||||
	Info = logger.Info
 | 
			
		||||
	Infof = logger.Infof
 | 
			
		||||
	Error = logger.Error
 | 
			
		||||
	Errorf = logger.Errorf
 | 
			
		||||
	Panic = logger.Panic
 | 
			
		||||
	Panicf = logger.Panicf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type innerLogger struct {
 | 
			
		||||
	log *log.Logger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newInnerLogger() Logger {
 | 
			
		||||
	return &innerLogger{
 | 
			
		||||
		log: log.New(os.Stderr, "[N-Net] ", log.LstdFlags|log.Lshortfile),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *innerLogger) Debugf(format string, v ...interface{}) {
 | 
			
		||||
	i.log.Printf(format, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *innerLogger) Debug(v ...interface{}) {
 | 
			
		||||
	i.log.Println(v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *innerLogger) Info(v ...interface{}) {
 | 
			
		||||
	i.log.Println(v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *innerLogger) Infof(format string, v ...interface{}) {
 | 
			
		||||
	i.log.Printf(format, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *innerLogger) Error(v ...interface{}) {
 | 
			
		||||
	i.log.Println(v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *innerLogger) Errorf(format string, v ...interface{}) {
 | 
			
		||||
	i.log.Printf(format, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *innerLogger) Panic(v ...interface{}) {
 | 
			
		||||
	i.log.Panic(v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *innerLogger) Panicf(format string, v ...interface{}) {
 | 
			
		||||
	i.log.Panicf(format, v)
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,11 @@
 | 
			
		||||
package message
 | 
			
		||||
 | 
			
		||||
type Header struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Message struct {
 | 
			
		||||
	Type    byte   // 消息类型
 | 
			
		||||
	ID      uint64 // 消息ID
 | 
			
		||||
	Header  []byte // 消息头原始数据
 | 
			
		||||
	Payload []byte // 数据
 | 
			
		||||
}
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
package net
 | 
			
		||||
 | 
			
		||||
type Option func(server *Server)
 | 
			
		||||
 | 
			
		||||
func WithXXX() Option {
 | 
			
		||||
	return func(server *Server) {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,37 +0,0 @@
 | 
			
		||||
package net
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"git.noahlan.cn/northlan/nnet/interfaces"
 | 
			
		||||
	"net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Request struct {
 | 
			
		||||
	session interfaces.ISession // Session
 | 
			
		||||
 | 
			
		||||
	server *Server  // Server reference
 | 
			
		||||
	conn   net.Conn // low-level conn fd
 | 
			
		||||
	status Status   // 连接状态
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newRequest(server *Server, conn net.Conn) *Request {
 | 
			
		||||
	r := &Request{
 | 
			
		||||
		server: server,
 | 
			
		||||
		conn:   conn,
 | 
			
		||||
		status: StatusStart,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r.session = newSession()
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Request) Status() Status {
 | 
			
		||||
	return r.status
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Request) ID() int64 {
 | 
			
		||||
	return r.session.ID()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Request) Session() interfaces.ISession {
 | 
			
		||||
	return r.session
 | 
			
		||||
}
 | 
			
		||||
@ -1,40 +0,0 @@
 | 
			
		||||
package net
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"git.noahlan.cn/northlan/nnet/interfaces"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type SessionMgr struct {
 | 
			
		||||
	sync.RWMutex
 | 
			
		||||
	sessions map[int64]interfaces.ISession
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *SessionMgr) storeSession(s interfaces.ISession) {
 | 
			
		||||
	m.Lock()
 | 
			
		||||
	defer m.Unlock()
 | 
			
		||||
 | 
			
		||||
	m.sessions[s.ID()] = s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *SessionMgr) findSession(sid int64) interfaces.ISession {
 | 
			
		||||
	m.RLock()
 | 
			
		||||
	defer m.RUnlock()
 | 
			
		||||
 | 
			
		||||
	return m.sessions[sid]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *SessionMgr) findOrCreateSession(sid int64) interfaces.ISession {
 | 
			
		||||
	m.RLock()
 | 
			
		||||
	s, ok := m.sessions[sid]
 | 
			
		||||
	m.RUnlock()
 | 
			
		||||
 | 
			
		||||
	if !ok {
 | 
			
		||||
		s = newSession()
 | 
			
		||||
 | 
			
		||||
		m.Lock()
 | 
			
		||||
		m.sessions[s.ID()] = s
 | 
			
		||||
		m.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
package interfaces
 | 
			
		||||
package nface
 | 
			
		||||
 | 
			
		||||
// IRouter 路由接口
 | 
			
		||||
type IRouter interface {
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
package interfaces
 | 
			
		||||
package nface
 | 
			
		||||
 | 
			
		||||
// ISessionAttribute Session数据接口
 | 
			
		||||
type ISessionAttribute interface {
 | 
			
		||||
@ -0,0 +1,57 @@
 | 
			
		||||
package nnet
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"git.noahlan.cn/northlan/nnet/component"
 | 
			
		||||
	"git.noahlan.cn/northlan/nnet/log"
 | 
			
		||||
	"git.noahlan.cn/northlan/nnet/pipeline"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Option func(options *Options)
 | 
			
		||||
type WSOption func(opts *WSOptions)
 | 
			
		||||
 | 
			
		||||
func WithLogger(logger log.Logger) Option {
 | 
			
		||||
	return func(_ *Options) {
 | 
			
		||||
		log.SetLogger(logger)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithPipeline(pipeline pipeline.Pipeline) Option {
 | 
			
		||||
	return func(options *Options) {
 | 
			
		||||
		options.Pipeline = pipeline
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithComponents(components *component.Components) Option {
 | 
			
		||||
	return func(options *Options) {
 | 
			
		||||
		options.Components = components
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithHeartbeatInterval(d time.Duration) Option {
 | 
			
		||||
	return func(options *Options) {
 | 
			
		||||
		options.HeartbeatInterval = d
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithWebsocket(wsOpts ...WSOption) Option {
 | 
			
		||||
	return func(options *Options) {
 | 
			
		||||
		for _, opt := range wsOpts {
 | 
			
		||||
			opt(&options.WS)
 | 
			
		||||
		}
 | 
			
		||||
		options.WS.IsWebsocket = true
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithWSPath(path string) WSOption {
 | 
			
		||||
	return func(opts *WSOptions) {
 | 
			
		||||
		opts.WebsocketPath = path
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithWSTLS(certificate, key string) WSOption {
 | 
			
		||||
	return func(opts *WSOptions) {
 | 
			
		||||
		opts.TLSCertificate = certificate
 | 
			
		||||
		opts.TLSKey = key
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,27 @@
 | 
			
		||||
package nnet
 | 
			
		||||
 | 
			
		||||
import "github.com/panjf2000/ants/v2"
 | 
			
		||||
 | 
			
		||||
var pool *Pool
 | 
			
		||||
 | 
			
		||||
type Pool struct {
 | 
			
		||||
	connPool   *ants.Pool
 | 
			
		||||
	workerPool *ants.Pool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initPool(size int) {
 | 
			
		||||
	p := &Pool{}
 | 
			
		||||
 | 
			
		||||
	p.connPool, _ = ants.NewPool(size, ants.WithNonblocking(true))
 | 
			
		||||
	p.workerPool, _ = ants.NewPool(size*2, ants.WithNonblocking(true))
 | 
			
		||||
 | 
			
		||||
	pool = p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Pool) SubmitConn(h func()) error {
 | 
			
		||||
	return p.connPool.Submit(h)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Pool) SubmitWorker(h func()) error {
 | 
			
		||||
	return p.workerPool.Submit(h)
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,63 @@
 | 
			
		||||
package nnet
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"git.noahlan.cn/northlan/nnet/nface"
 | 
			
		||||
	"git.noahlan.cn/northlan/nnet/pipeline"
 | 
			
		||||
	"git.noahlan.cn/northlan/nnet/session"
 | 
			
		||||
	"github.com/gorilla/websocket"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Request struct {
 | 
			
		||||
	session nface.ISession // Session
 | 
			
		||||
 | 
			
		||||
	conn            net.Conn // low-level conn fd
 | 
			
		||||
	status          Status   // 连接状态
 | 
			
		||||
	lastMid         uint64   // 最近一次消息ID
 | 
			
		||||
	lastHeartbeatAt int64    // 最近一次心跳时间
 | 
			
		||||
 | 
			
		||||
	chDie  chan struct{} // 停止通道
 | 
			
		||||
	chSend chan []byte   // 消息发送通道
 | 
			
		||||
 | 
			
		||||
	pipeline pipeline.Pipeline // 消息管道
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newRequest(conn net.Conn, pipeline pipeline.Pipeline) *Request {
 | 
			
		||||
	r := &Request{
 | 
			
		||||
		conn:   conn,
 | 
			
		||||
		status: StatusStart,
 | 
			
		||||
 | 
			
		||||
		lastHeartbeatAt: time.Now().Unix(),
 | 
			
		||||
 | 
			
		||||
		chDie:  make(chan struct{}),
 | 
			
		||||
		chSend: make(chan []byte),
 | 
			
		||||
 | 
			
		||||
		pipeline: pipeline,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// binding session
 | 
			
		||||
	r.session = session.New()
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newRequestWS(conn *websocket.Conn, pipeline pipeline.Pipeline) *Request {
 | 
			
		||||
	c, err := newWSConn(conn)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// TODO panic ?
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return newRequest(c, pipeline)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Request) Status() Status {
 | 
			
		||||
	return r.status
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Request) ID() int64 {
 | 
			
		||||
	return r.session.ID()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Request) Session() nface.ISession {
 | 
			
		||||
	return r.session
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
package net
 | 
			
		||||
package nnet
 | 
			
		||||
 | 
			
		||||
type Status uint8
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,114 @@
 | 
			
		||||
package nnet
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gorilla/websocket"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// wsConn 封装 websocket.Conn 并实现所有 net.Conn 接口
 | 
			
		||||
// 兼容所有使用 net.Conn 的方法
 | 
			
		||||
type wsConn struct {
 | 
			
		||||
	conn   *websocket.Conn
 | 
			
		||||
	typ    int // message type
 | 
			
		||||
	reader io.Reader
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newWSConn 新建wsConn
 | 
			
		||||
func newWSConn(conn *websocket.Conn) (*wsConn, error) {
 | 
			
		||||
	c := &wsConn{conn: conn}
 | 
			
		||||
 | 
			
		||||
	t, r, err := conn.NextReader()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	c.typ = t
 | 
			
		||||
	c.reader = r
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read reads data from the connection.
 | 
			
		||||
// Read can be made to time out and return an Error with Timeout() == true
 | 
			
		||||
// after a fixed time limit; see SetDeadline and SetReadDeadline.
 | 
			
		||||
func (c *wsConn) Read(b []byte) (int, error) {
 | 
			
		||||
	n, err := c.reader.Read(b)
 | 
			
		||||
	if err != nil && err != io.EOF {
 | 
			
		||||
		return n, err
 | 
			
		||||
	} else if err == io.EOF {
 | 
			
		||||
		_, r, err := c.conn.NextReader()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		c.reader = r
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return n, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write writes data to the connection.
 | 
			
		||||
// Write can be made to time out and return an Error with Timeout() == true
 | 
			
		||||
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
 | 
			
		||||
func (c *wsConn) Write(b []byte) (int, error) {
 | 
			
		||||
	err := c.conn.WriteMessage(websocket.BinaryMessage, b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return len(b), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close closes the connection.
 | 
			
		||||
// Any blocked Read or Write operations will be unblocked and return errors.
 | 
			
		||||
func (c *wsConn) Close() error {
 | 
			
		||||
	return c.conn.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LocalAddr returns the local network address.
 | 
			
		||||
func (c *wsConn) LocalAddr() net.Addr {
 | 
			
		||||
	return c.conn.LocalAddr()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoteAddr returns the remote network address.
 | 
			
		||||
func (c *wsConn) RemoteAddr() net.Addr {
 | 
			
		||||
	return c.conn.RemoteAddr()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetDeadline sets the read and write deadlines associated
 | 
			
		||||
// with the connection. It is equivalent to calling both
 | 
			
		||||
// SetReadDeadline and SetWriteDeadline.
 | 
			
		||||
//
 | 
			
		||||
// A deadline is an absolute time after which I/O operations
 | 
			
		||||
// fail with a timeout (see type Error) instead of
 | 
			
		||||
// blocking. The deadline applies to all future and pending
 | 
			
		||||
// I/O, not just the immediately following call to Read or
 | 
			
		||||
// Write. After a deadline has been exceeded, the connection
 | 
			
		||||
// can be refreshed by setting a deadline in the future.
 | 
			
		||||
//
 | 
			
		||||
// An idle timeout can be implemented by repeatedly extending
 | 
			
		||||
// the deadline after successful Read or Write calls.
 | 
			
		||||
//
 | 
			
		||||
// A zero value for t means I/O operations will not time out.
 | 
			
		||||
func (c *wsConn) SetDeadline(t time.Time) error {
 | 
			
		||||
	if err := c.conn.SetReadDeadline(t); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.conn.SetWriteDeadline(t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetReadDeadline sets the deadline for future Read calls
 | 
			
		||||
// and any currently-blocked Read call.
 | 
			
		||||
// A zero value for t means Read will not time out.
 | 
			
		||||
func (c *wsConn) SetReadDeadline(t time.Time) error {
 | 
			
		||||
	return c.conn.SetReadDeadline(t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetWriteDeadline sets the deadline for future Write calls
 | 
			
		||||
// and any currently-blocked Write call.
 | 
			
		||||
// Even if write times out, it may return n > 0, indicating that
 | 
			
		||||
// some data was successfully written.
 | 
			
		||||
// A zero value for t means Write will not time out.
 | 
			
		||||
func (c *wsConn) SetWriteDeadline(t time.Time) error {
 | 
			
		||||
	return c.conn.SetWriteDeadline(t)
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,48 @@
 | 
			
		||||
package packet
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Type 数据帧类型,如:握手,心跳,数据等
 | 
			
		||||
type Type byte
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Default 默认,暂无意义
 | 
			
		||||
	Default Type = iota
 | 
			
		||||
 | 
			
		||||
	// Handshake 握手数据(服务端主动发起)
 | 
			
		||||
	Handshake = 0x01
 | 
			
		||||
 | 
			
		||||
	// HandshakeAck 握手回复(客户端回复)
 | 
			
		||||
	HandshakeAck = 0x02
 | 
			
		||||
 | 
			
		||||
	// Heartbeat 心跳(服务端发起)
 | 
			
		||||
	Heartbeat = 0x03
 | 
			
		||||
 | 
			
		||||
	// Data 数据传输
 | 
			
		||||
	Data = 0x04
 | 
			
		||||
 | 
			
		||||
	// Kick 服务端主动断开连接
 | 
			
		||||
	Kick = 0x05
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Packet struct {
 | 
			
		||||
	Type Type // 数据帧 类型
 | 
			
		||||
 | 
			
		||||
	HeaderLen uint32 // 数据帧头 长度
 | 
			
		||||
	HeaderRaw []byte // 头原始数据
 | 
			
		||||
 | 
			
		||||
	DataLen uint32 // 数据长度
 | 
			
		||||
	DataRaw []byte // 原始数据
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func New() *Packet {
 | 
			
		||||
	return &Packet{
 | 
			
		||||
		Type: Default,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Packet) String() string {
 | 
			
		||||
	return fmt.Sprintf("Type: %d, HeaderLen: %d, DataLen: %d, Header: %s, Data: %s", p.Type, p.HeaderLen, p.DataLen, string(p.HeaderRaw), string(p.DataRaw))
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,83 @@
 | 
			
		||||
package pipeline
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type (
 | 
			
		||||
	Func func(request *nnet.Request) error
 | 
			
		||||
 | 
			
		||||
	// Pipeline 消息管道
 | 
			
		||||
	Pipeline interface {
 | 
			
		||||
		Outbound() Channel
 | 
			
		||||
		Inbound() Channel
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pipeline struct {
 | 
			
		||||
		outbound, inbound *pipelineChannel
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Channel interface {
 | 
			
		||||
		PushFront(h Func)
 | 
			
		||||
		PushBack(h Func)
 | 
			
		||||
		Process(request *nnet.Request) error
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pipelineChannel struct {
 | 
			
		||||
		mu       sync.RWMutex
 | 
			
		||||
		handlers []Func
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func New() Pipeline {
 | 
			
		||||
	return &pipeline{
 | 
			
		||||
		outbound: &pipelineChannel{},
 | 
			
		||||
		inbound:  &pipelineChannel{},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *pipeline) Outbound() Channel {
 | 
			
		||||
	return p.outbound
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *pipeline) Inbound() Channel {
 | 
			
		||||
	return p.inbound
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PushFront 将func压入slice首位
 | 
			
		||||
func (p *pipelineChannel) PushFront(h Func) {
 | 
			
		||||
	p.mu.Lock()
 | 
			
		||||
	defer p.mu.Unlock()
 | 
			
		||||
 | 
			
		||||
	handlers := make([]Func, len(p.handlers)+1)
 | 
			
		||||
	handlers[0] = h
 | 
			
		||||
	copy(handlers[1:], p.handlers)
 | 
			
		||||
 | 
			
		||||
	p.handlers = handlers
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PushBack 将func压入slice末位
 | 
			
		||||
func (p *pipelineChannel) PushBack(h Func) {
 | 
			
		||||
	p.mu.Lock()
 | 
			
		||||
	defer p.mu.Unlock()
 | 
			
		||||
 | 
			
		||||
	p.handlers = append(p.handlers, h)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Process 处理所有的pipeline方法
 | 
			
		||||
func (p *pipelineChannel) Process(request *nnet.Request) error {
 | 
			
		||||
	p.mu.RLock()
 | 
			
		||||
	defer p.mu.RUnlock()
 | 
			
		||||
 | 
			
		||||
	if len(p.handlers) < 1 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, handler := range p.handlers {
 | 
			
		||||
		err := handler(request)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,47 @@
 | 
			
		||||
package session
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"git.noahlan.cn/northlan/nnet/nface"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Manager struct {
 | 
			
		||||
	sync.RWMutex
 | 
			
		||||
	sessions map[int64]nface.ISession
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewManager() *Manager {
 | 
			
		||||
	return &Manager{
 | 
			
		||||
		RWMutex:  sync.RWMutex{},
 | 
			
		||||
		sessions: make(map[int64]nface.ISession),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Manager) storeSession(s nface.ISession) {
 | 
			
		||||
	m.Lock()
 | 
			
		||||
	defer m.Unlock()
 | 
			
		||||
 | 
			
		||||
	m.sessions[s.ID()] = s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Manager) findSession(sid int64) nface.ISession {
 | 
			
		||||
	m.RLock()
 | 
			
		||||
	defer m.RUnlock()
 | 
			
		||||
 | 
			
		||||
	return m.sessions[sid]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Manager) findOrCreateSession(sid int64) nface.ISession {
 | 
			
		||||
	m.RLock()
 | 
			
		||||
	s, ok := m.sessions[sid]
 | 
			
		||||
	m.RUnlock()
 | 
			
		||||
 | 
			
		||||
	if !ok {
 | 
			
		||||
		s = New()
 | 
			
		||||
 | 
			
		||||
		m.Lock()
 | 
			
		||||
		m.sessions[s.ID()] = s
 | 
			
		||||
		m.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue