Commit 8abb0aa7 authored by AlexStocks's avatar AlexStocks

add Session interface

parent f7505d10
...@@ -11,6 +11,11 @@ ...@@ -11,6 +11,11 @@
## develop history ## ## develop history ##
--- ---
- 2017/02/03
> 1 Session struct -> session struct and add Session interface
>
> 2 version: 0.7.0
- 2016/11/19 - 2016/11/19
> 1 add conn.go:(*gettyWSConn) setCompressType to add zip compress feature for ws connection > 1 add conn.go:(*gettyWSConn) setCompressType to add zip compress feature for ws connection
> >
......
...@@ -21,6 +21,7 @@ import ( ...@@ -21,6 +21,7 @@ import (
) )
import ( import (
"github.com/AlexStocks/goext/sync"
log "github.com/AlexStocks/log4go" log "github.com/AlexStocks/log4go"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
...@@ -42,10 +43,10 @@ type Client struct { ...@@ -42,10 +43,10 @@ type Client struct {
interval time.Duration interval time.Duration
addr string addr string
newSession NewSessionCallback newSession NewSessionCallback
sessionMap map[*Session]empty sessionMap map[Session]gxsync.Empty
sync.Once sync.Once
done chan empty done chan gxsync.Empty
wg sync.WaitGroup wg sync.WaitGroup
// for wss client // for wss client
...@@ -68,8 +69,8 @@ func NewClient(connNum int, connInterval time.Duration, serverAddr string) *Clie ...@@ -68,8 +69,8 @@ func NewClient(connNum int, connInterval time.Duration, serverAddr string) *Clie
number: connNum, number: connNum,
interval: connInterval, interval: connInterval,
addr: serverAddr, addr: serverAddr,
sessionMap: make(map[*Session]empty, connNum), sessionMap: make(map[Session]gxsync.Empty, connNum),
done: make(chan empty), done: make(chan gxsync.Empty),
} }
} }
...@@ -90,13 +91,13 @@ func NewWSSClient(connNum int, connInterval time.Duration, serverAddr string, ce ...@@ -90,13 +91,13 @@ func NewWSSClient(connNum int, connInterval time.Duration, serverAddr string, ce
number: connNum, number: connNum,
interval: connInterval, interval: connInterval,
addr: serverAddr, addr: serverAddr,
sessionMap: make(map[*Session]empty, connNum), sessionMap: make(map[Session]gxsync.Empty, connNum),
done: make(chan empty), done: make(chan gxsync.Empty),
certFile: cert, certFile: cert,
} }
} }
func (this *Client) dialTCP() *Session { func (this *Client) dialTCP() Session {
var ( var (
err error err error
conn net.Conn conn net.Conn
...@@ -120,12 +121,12 @@ func (this *Client) dialTCP() *Session { ...@@ -120,12 +121,12 @@ func (this *Client) dialTCP() *Session {
} }
} }
func (this *Client) dialWS() *Session { func (this *Client) dialWS() Session {
var ( var (
err error err error
dialer websocket.Dialer dialer websocket.Dialer
conn *websocket.Conn conn *websocket.Conn
session *Session session Session
) )
dialer.EnableCompression = true dialer.EnableCompression = true
...@@ -139,8 +140,8 @@ func (this *Client) dialWS() *Session { ...@@ -139,8 +140,8 @@ func (this *Client) dialWS() *Session {
} }
if err == nil { if err == nil {
session = NewWSSession(conn) session = NewWSSession(conn)
if session.maxMsgLen > 0 { if session.(*session).maxMsgLen > 0 {
conn.SetReadLimit(int64(session.maxMsgLen)) conn.SetReadLimit(int64(session.(*session).maxMsgLen))
} }
return session return session
...@@ -152,14 +153,14 @@ func (this *Client) dialWS() *Session { ...@@ -152,14 +153,14 @@ func (this *Client) dialWS() *Session {
} }
} }
func (this *Client) dialWSS() *Session { func (this *Client) dialWSS() Session {
var ( var (
err error err error
certPem []byte certPem []byte
certPool *x509.CertPool certPool *x509.CertPool
dialer websocket.Dialer dialer websocket.Dialer
conn *websocket.Conn conn *websocket.Conn
session *Session session Session
) )
dialer.EnableCompression = true dialer.EnableCompression = true
...@@ -184,8 +185,8 @@ func (this *Client) dialWSS() *Session { ...@@ -184,8 +185,8 @@ func (this *Client) dialWSS() *Session {
} }
if err == nil { if err == nil {
session = NewWSSession(conn) session = NewWSSession(conn)
if session.maxMsgLen > 0 { if session.(*session).maxMsgLen > 0 {
conn.SetReadLimit(int64(session.maxMsgLen)) conn.SetReadLimit(int64(session.(*session).maxMsgLen))
} }
return session return session
...@@ -197,7 +198,7 @@ func (this *Client) dialWSS() *Session { ...@@ -197,7 +198,7 @@ func (this *Client) dialWSS() *Session {
} }
} }
func (this *Client) dial() *Session { func (this *Client) dial() Session {
if strings.HasPrefix(this.addr, "ws") { if strings.HasPrefix(this.addr, "ws") {
return this.dialWS() return this.dialWS()
} else if strings.HasPrefix(this.addr, "wss") { } else if strings.HasPrefix(this.addr, "wss") {
...@@ -225,7 +226,7 @@ func (this *Client) sessionNum() int { ...@@ -225,7 +226,7 @@ func (this *Client) sessionNum() int {
func (this *Client) connect() { func (this *Client) connect() {
var ( var (
err error err error
session *Session session Session
) )
for { for {
...@@ -237,9 +238,9 @@ func (this *Client) connect() { ...@@ -237,9 +238,9 @@ func (this *Client) connect() {
err = this.newSession(session) err = this.newSession(session)
if err == nil { if err == nil {
// session.RunEventLoop() // session.RunEventLoop()
session.run() session.(*session).run()
this.Lock() this.Lock()
this.sessionMap[session] = empty{} this.sessionMap[session] = gxsync.Empty{}
this.Unlock() this.Unlock()
break break
} }
......
...@@ -12,19 +12,19 @@ package getty ...@@ -12,19 +12,19 @@ package getty
// NewSessionCallback will be invoked when server accepts a new client connection or client connects to server successfully. // NewSessionCallback will be invoked when server accepts a new client connection or client connects to server successfully.
// if there are too many client connections or u do not want to connect a server again, u can return non-nil error. And // if there are too many client connections or u do not want to connect a server again, u can return non-nil error. And
// then getty will close the new session. // then getty will close the new session.
type NewSessionCallback func(*Session) error type NewSessionCallback func(Session) error
// Reader is used to unmarshal a complete pkg from buffer // Reader is used to unmarshal a complete pkg from buffer
type Reader interface { type Reader interface {
// Parse tcp pkg from buffer and if possible return a complete pkg // Parse tcp pkg from buffer and if possible return a complete pkg
// If length of buf is not long enough, u should return {nil,0, nil} // If length of buf is not long enough, u should return {nil,0, nil}
// The second return value is the length of the pkg. // The second return value is the length of the pkg.
Read(*Session, []byte) (interface{}, int, error) Read(Session, []byte) (interface{}, int, error)
} }
// Writer is used to marshal pkg and write to session // Writer is used to marshal pkg and write to session
type Writer interface { type Writer interface {
Write(*Session, interface{}) error Write(Session, interface{}) error
} }
// tcp package handler interface // tcp package handler interface
...@@ -37,19 +37,19 @@ type ReadWriter interface { ...@@ -37,19 +37,19 @@ type ReadWriter interface {
type EventListener interface { type EventListener interface {
// invoked when session opened // invoked when session opened
// If the return error is not nil, @Session will be closed. // If the return error is not nil, @Session will be closed.
OnOpen(*Session) error OnOpen(Session) error
// invoked when session closed. // invoked when session closed.
OnClose(*Session) OnClose(Session)
// invoked when got error. // invoked when got error.
OnError(*Session, error) OnError(Session, error)
// invoked periodically, its period can be set by (Session)SetCronPeriod // invoked periodically, its period can be set by (Session)SetCronPeriod
OnCron(*Session) OnCron(Session)
// invoked when receive packge. Pls attention that do not handle long time logic processing in this func. // invoked when receive packge. Pls attention that do not handle long time logic processing in this func.
// Y'd better set the package's maximum length. If the message's length is greater than it, u should // Y'd better set the package's maximum length. If the message's length is greater than it, u should
// should return err in Reader{Read} and getty will close this connection soon. // should return err in Reader{Read} and getty will close this connection soon.
OnMessage(*Session, interface{}) OnMessage(Session, interface{})
} }
...@@ -48,20 +48,24 @@ const ( ...@@ -48,20 +48,24 @@ const (
// connection interfacke // connection interfacke
///////////////////////////////////////// /////////////////////////////////////////
type iConn interface { type Connection interface {
id() uint32 ID() uint32
setCompressType(t CompressType) SetCompressType(t CompressType)
localAddr() string LocalAddr() string
remoteAddr() string RemoteAddr() string
incReadPkgCount() incReadPkgCount()
incWritePkgCount() incWritePkgCount()
updateActive() // update session's active time
getActive() time.Time UpdateActive()
// get session's active time
GetActive() time.Time
readDeadline() time.Duration readDeadline() time.Duration
setReadDeadline(time.Duration) // SetReadDeadline sets deadline for the future read calls.
SetReadDeadline(time.Duration)
writeDeadline() time.Duration writeDeadline() time.Duration
setWriteDeadline(time.Duration) // SetWriteDeadlile sets deadline for the future read calls.
write(p []byte) error SetWriteDeadline(time.Duration)
Write(p []byte) error
// don't distinguish between tcp connection and websocket connection. Because // don't distinguish between tcp connection and websocket connection. Because
// gorilla/websocket/conn.go:(Conn)Close also invoke net.Conn.Close // gorilla/websocket/conn.go:(Conn)Close also invoke net.Conn.Close
close(int) close(int)
...@@ -76,7 +80,7 @@ var ( ...@@ -76,7 +80,7 @@ var (
) )
type gettyConn struct { type gettyConn struct {
ID uint32 id uint32
compress CompressType compress CompressType
padding1 uint8 padding1 uint8
padding2 uint16 padding2 uint16
...@@ -91,15 +95,15 @@ type gettyConn struct { ...@@ -91,15 +95,15 @@ type gettyConn struct {
peer string // peer address peer string // peer address
} }
func (this *gettyConn) id() uint32 { func (this *gettyConn) ID() uint32 {
return this.ID return this.id
} }
func (this *gettyConn) localAddr() string { func (this *gettyConn) LocalAddr() string {
return this.local return this.local
} }
func (this *gettyConn) remoteAddr() string { func (this *gettyConn) RemoteAddr() string {
return this.peer return this.peer
} }
...@@ -111,15 +115,15 @@ func (this *gettyConn) incWritePkgCount() { ...@@ -111,15 +115,15 @@ func (this *gettyConn) incWritePkgCount() {
atomic.AddUint32(&this.writePkgCount, 1) atomic.AddUint32(&this.writePkgCount, 1)
} }
func (this *gettyConn) updateActive() { func (this *gettyConn) UpdateActive() {
atomic.StoreInt64(&(this.active), int64(time.Since(launchTime))) atomic.StoreInt64(&(this.active), int64(time.Since(launchTime)))
} }
func (this *gettyConn) getActive() time.Time { func (this *gettyConn) GetActive() time.Time {
return launchTime.Add(time.Duration(atomic.LoadInt64(&(this.active)))) return launchTime.Add(time.Duration(atomic.LoadInt64(&(this.active))))
} }
func (this *gettyConn) write([]byte) error { func (this *gettyConn) Write([]byte) error {
return nil return nil
} }
...@@ -129,7 +133,7 @@ func (this gettyConn) readDeadline() time.Duration { ...@@ -129,7 +133,7 @@ func (this gettyConn) readDeadline() time.Duration {
return this.rDeadline return this.rDeadline
} }
func (this *gettyConn) setReadDeadline(rDeadline time.Duration) { func (this *gettyConn) SetReadDeadline(rDeadline time.Duration) {
if rDeadline < 1 { if rDeadline < 1 {
panic("@rDeadline < 1") panic("@rDeadline < 1")
} }
...@@ -144,7 +148,7 @@ func (this gettyConn) writeDeadline() time.Duration { ...@@ -144,7 +148,7 @@ func (this gettyConn) writeDeadline() time.Duration {
return this.wDeadline return this.wDeadline
} }
func (this *gettyConn) setWriteDeadline(wDeadline time.Duration) { func (this *gettyConn) SetWriteDeadline(wDeadline time.Duration) {
if wDeadline < 1 { if wDeadline < 1 {
panic("@wDeadline < 1") panic("@wDeadline < 1")
} }
...@@ -182,7 +186,7 @@ func newGettyTCPConn(conn net.Conn) *gettyTCPConn { ...@@ -182,7 +186,7 @@ func newGettyTCPConn(conn net.Conn) *gettyTCPConn {
reader: io.Reader(conn), reader: io.Reader(conn),
writer: io.Writer(conn), writer: io.Writer(conn),
gettyConn: gettyConn{ gettyConn: gettyConn{
ID: atomic.AddUint32(&connID, 1), id: atomic.AddUint32(&connID, 1),
local: localAddr, local: localAddr,
peer: peerAddr, peer: peerAddr,
compress: CompressNone, compress: CompressNone,
...@@ -213,7 +217,7 @@ func (this *writeFlusher) Write(p []byte) (int, error) { ...@@ -213,7 +217,7 @@ func (this *writeFlusher) Write(p []byte) (int, error) {
} }
// set compress type(tcp: zip/snappy, websocket:zip) // set compress type(tcp: zip/snappy, websocket:zip)
func (this *gettyTCPConn) setCompressType(t CompressType) { func (this *gettyTCPConn) SetCompressType(t CompressType) {
switch { switch {
case t == CompressZip: case t == CompressZip:
this.reader = flate.NewReader(this.conn) this.reader = flate.NewReader(this.conn)
...@@ -244,7 +248,7 @@ func (this *gettyTCPConn) read(p []byte) (int, error) { ...@@ -244,7 +248,7 @@ func (this *gettyTCPConn) read(p []byte) (int, error) {
} }
// tcp connection write // tcp connection write
func (this *gettyTCPConn) write(p []byte) error { func (this *gettyTCPConn) Write(p []byte) error {
// if this.conn == nil { // if this.conn == nil {
// return 0, ErrInvalidConnection // return 0, ErrInvalidConnection
// } // }
...@@ -296,7 +300,7 @@ func newGettyWSConn(conn *websocket.Conn) *gettyWSConn { ...@@ -296,7 +300,7 @@ func newGettyWSConn(conn *websocket.Conn) *gettyWSConn {
gettyWSConn := &gettyWSConn{ gettyWSConn := &gettyWSConn{
conn: conn, conn: conn,
gettyConn: gettyConn{ gettyConn: gettyConn{
ID: atomic.AddUint32(&connID, 1), id: atomic.AddUint32(&connID, 1),
local: localAddr, local: localAddr,
peer: peerAddr, peer: peerAddr,
}, },
...@@ -309,7 +313,7 @@ func newGettyWSConn(conn *websocket.Conn) *gettyWSConn { ...@@ -309,7 +313,7 @@ func newGettyWSConn(conn *websocket.Conn) *gettyWSConn {
} }
// set compress type(tcp: zip/snappy, websocket:zip) // set compress type(tcp: zip/snappy, websocket:zip)
func (this *gettyWSConn) setCompressType(t CompressType) { func (this *gettyWSConn) SetCompressType(t CompressType) {
switch { switch {
case t == CompressZip: case t == CompressZip:
this.conn.EnableWriteCompression(true) this.conn.EnableWriteCompression(true)
...@@ -328,14 +332,14 @@ func (this *gettyWSConn) handlePing(message string) error { ...@@ -328,14 +332,14 @@ func (this *gettyWSConn) handlePing(message string) error {
err = nil err = nil
} }
if err == nil { if err == nil {
this.updateActive() this.UpdateActive()
} }
return err return err
} }
func (this *gettyWSConn) handlePong(string) error { func (this *gettyWSConn) handlePong(string) error {
this.updateActive() this.UpdateActive()
return nil return nil
} }
...@@ -356,7 +360,7 @@ func (this *gettyWSConn) read() ([]byte, error) { ...@@ -356,7 +360,7 @@ func (this *gettyWSConn) read() ([]byte, error) {
} }
// websocket connection write // websocket connection write
func (this *gettyWSConn) write(p []byte) error { func (this *gettyWSConn) Write(p []byte) error {
// atomic.AddUint32(&this.writeCount, 1) // atomic.AddUint32(&this.writeCount, 1)
atomic.AddUint32(&this.writeCount, (uint32)(len(p))) atomic.AddUint32(&this.writeCount, (uint32)(len(p)))
// this.conn.SetWriteDeadline(time.Now().Add(this.wDeadline)) // this.conn.SetWriteDeadline(time.Now().Add(this.wDeadline))
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
import ( import (
"github.com/AlexStocks/goext/net" "github.com/AlexStocks/goext/net"
"github.com/AlexStocks/goext/sync"
log "github.com/AlexStocks/log4go" log "github.com/AlexStocks/log4go"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
...@@ -34,12 +35,12 @@ type Server struct { ...@@ -34,12 +35,12 @@ type Server struct {
listener net.Listener listener net.Listener
sync.Once sync.Once
done chan empty done chan gxsync.Empty
wg sync.WaitGroup wg sync.WaitGroup
} }
func NewServer() *Server { func NewServer() *Server {
return &Server{done: make(chan empty)} return &Server{done: make(chan gxsync.Empty)}
} }
func (this *Server) stop() { func (this *Server) stop() {
...@@ -94,7 +95,7 @@ func (this *Server) RunEventloop(newSession NewSessionCallback) { ...@@ -94,7 +95,7 @@ func (this *Server) RunEventloop(newSession NewSessionCallback) {
defer this.wg.Done() defer this.wg.Done()
var ( var (
err error err error
client *Session client Session
delay time.Duration delay time.Duration
) )
for { for {
...@@ -123,7 +124,7 @@ func (this *Server) RunEventloop(newSession NewSessionCallback) { ...@@ -123,7 +124,7 @@ func (this *Server) RunEventloop(newSession NewSessionCallback) {
} }
delay = 0 delay = 0
// client.RunEventLoop() // client.RunEventLoop()
client.run() client.(*session).run()
} }
}() }()
} }
...@@ -178,11 +179,11 @@ func (this *wsHandler) serveWSRequest(w http.ResponseWriter, r *http.Request) { ...@@ -178,11 +179,11 @@ func (this *wsHandler) serveWSRequest(w http.ResponseWriter, r *http.Request) {
log.Warn("Server{%s}.newSession(session{%#v}) = err {%#v}", this.server.addr, session, err) log.Warn("Server{%s}.newSession(session{%#v}) = err {%#v}", this.server.addr, session, err)
return return
} }
if session.maxMsgLen > 0 { if session.(*session).maxMsgLen > 0 {
conn.SetReadLimit(int64(session.maxMsgLen)) conn.SetReadLimit(int64(session.(*session).maxMsgLen))
} }
// session.RunEventLoop() // session.RunEventLoop()
session.run() session.(*session).run()
} }
// RunWSEventLoop serve websocket client request // RunWSEventLoop serve websocket client request
...@@ -253,7 +254,7 @@ func (this *Server) Listener() net.Listener { ...@@ -253,7 +254,7 @@ func (this *Server) Listener() net.Listener {
return this.listener return this.listener
} }
func (this *Server) accept(newSession NewSessionCallback) (*Session, error) { func (this *Server) accept(newSession NewSessionCallback) (Session, error) {
conn, err := this.listener.Accept() conn, err := this.listener.Accept()
if err != nil { if err != nil {
return nil, err return nil, err
......
This diff is collapsed.
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
package getty package getty
const ( const (
Version = "0.6.2" Version = "0.7.0"
DATE = "2016/11/19" DATE = "2017/02/03"
GETTY_MAJOR = 0 GETTY_MAJOR = 0
GETTY_MINOR = 6 GETTY_MINOR = 7
GETTY_BUILD = 2 GETTY_BUILD = 0
) )
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