github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/gonet/trans_server.go (about) 1 /* 2 * Copyright 2022 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Package gonet contains server and client implementation for go net. 18 package gonet 19 20 import ( 21 "context" 22 "errors" 23 "net" 24 "os" 25 "runtime/debug" 26 "sync" 27 "time" 28 29 "github.com/cloudwego/netpoll" 30 31 "github.com/cloudwego/kitex/pkg/remote/trans" 32 33 "github.com/cloudwego/kitex/pkg/klog" 34 "github.com/cloudwego/kitex/pkg/remote" 35 "github.com/cloudwego/kitex/pkg/rpcinfo" 36 "github.com/cloudwego/kitex/pkg/utils" 37 ) 38 39 // NewTransServerFactory creates a default go net transport server factory. 40 func NewTransServerFactory() remote.TransServerFactory { 41 return &gonetTransServerFactory{} 42 } 43 44 type gonetTransServerFactory struct{} 45 46 // NewTransServer implements the remote.TransServerFactory interface. 47 func (f *gonetTransServerFactory) NewTransServer(opt *remote.ServerOption, transHdlr remote.ServerTransHandler) remote.TransServer { 48 return &transServer{ 49 opt: opt, 50 transHdlr: transHdlr, 51 lncfg: trans.NewListenConfig(opt), 52 } 53 } 54 55 type transServer struct { 56 opt *remote.ServerOption 57 transHdlr remote.ServerTransHandler 58 ln net.Listener 59 lncfg net.ListenConfig 60 connCount utils.AtomicInt 61 sync.Mutex 62 } 63 64 var _ remote.TransServer = &transServer{} 65 66 // CreateListener implements the remote.TransServer interface. 67 // The network must be "tcp", "tcp4", "tcp6" or "unix". 68 func (ts *transServer) CreateListener(addr net.Addr) (ln net.Listener, err error) { 69 ln, err = ts.lncfg.Listen(context.Background(), addr.Network(), addr.String()) 70 return ln, err 71 } 72 73 // BootstrapServer implements the remote.TransServer interface. 74 func (ts *transServer) BootstrapServer(ln net.Listener) (err error) { 75 if ln == nil { 76 return errors.New("listener is nil in gonet transport server") 77 } 78 ts.ln = ln 79 for { 80 conn, err := ts.ln.Accept() 81 if err != nil { 82 klog.Errorf("KITEX: BootstrapServer accept failed, err=%s", err.Error()) 83 os.Exit(1) 84 } 85 go func() { 86 var ( 87 ctx = context.Background() 88 err error 89 ) 90 defer func() { 91 transRecover(ctx, conn, "OnRead") 92 }() 93 bc := newBufioConn(conn) 94 ctx, err = ts.transHdlr.OnActive(ctx, bc) 95 if err != nil { 96 klog.CtxErrorf(ctx, "KITEX: OnActive error=%s", err) 97 return 98 } 99 for { 100 ts.refreshDeadline(rpcinfo.GetRPCInfo(ctx), bc) 101 err := ts.transHdlr.OnRead(ctx, bc) 102 if err != nil { 103 ts.onError(ctx, err, bc) 104 _ = bc.Close() 105 return 106 } 107 } 108 }() 109 } 110 } 111 112 // Shutdown implements the remote.TransServer interface. 113 func (ts *transServer) Shutdown() (err error) { 114 ts.Lock() 115 defer ts.Unlock() 116 117 ctx, cancel := context.WithTimeout(context.Background(), ts.opt.ExitWaitTime) 118 defer cancel() 119 if g, ok := ts.transHdlr.(remote.GracefulShutdown); ok { 120 if ts.ln != nil { 121 // 1. stop listener 122 _ = ts.ln.Close() 123 124 // 2. signal all active connections to close gracefully 125 _ = g.GracefulShutdown(ctx) 126 } 127 } 128 return 129 } 130 131 // ConnCount implements the remote.TransServer interface. 132 func (ts *transServer) ConnCount() utils.AtomicInt { 133 return ts.connCount 134 } 135 136 func (ts *transServer) onError(ctx context.Context, err error, conn net.Conn) { 137 ts.transHdlr.OnError(ctx, err, conn) 138 } 139 140 func (ts *transServer) refreshDeadline(ri rpcinfo.RPCInfo, conn net.Conn) { 141 readTimeout := ri.Config().ReadWriteTimeout() 142 _ = conn.SetReadDeadline(time.Now().Add(readTimeout)) 143 } 144 145 // bufioConn implements the net.Conn interface. 146 type bufioConn struct { 147 conn net.Conn 148 r netpoll.Reader 149 } 150 151 func newBufioConn(c net.Conn) *bufioConn { 152 return &bufioConn{ 153 conn: c, 154 r: netpoll.NewReader(c), 155 } 156 } 157 158 func (bc *bufioConn) RawConn() net.Conn { 159 return bc.conn 160 } 161 162 func (bc *bufioConn) Read(b []byte) (int, error) { 163 buf, err := bc.r.Next(len(b)) 164 if err != nil { 165 return 0, err 166 } 167 copy(b, buf) 168 return len(b), nil 169 } 170 171 func (bc *bufioConn) Write(b []byte) (int, error) { 172 return bc.conn.Write(b) 173 } 174 175 func (bc *bufioConn) Close() error { 176 bc.r.Release() 177 return bc.conn.Close() 178 } 179 180 func (bc *bufioConn) LocalAddr() net.Addr { 181 return bc.conn.LocalAddr() 182 } 183 184 func (bc *bufioConn) RemoteAddr() net.Addr { 185 return bc.conn.RemoteAddr() 186 } 187 188 func (bc *bufioConn) SetDeadline(t time.Time) error { 189 return bc.conn.SetDeadline(t) 190 } 191 192 func (bc *bufioConn) SetReadDeadline(t time.Time) error { 193 return bc.conn.SetReadDeadline(t) 194 } 195 196 func (bc *bufioConn) SetWriteDeadline(t time.Time) error { 197 return bc.conn.SetWriteDeadline(t) 198 } 199 200 func (bc *bufioConn) Reader() netpoll.Reader { 201 return bc.r 202 } 203 204 func transRecover(ctx context.Context, conn net.Conn, funcName string) { 205 panicErr := recover() 206 if panicErr != nil { 207 if conn != nil { 208 klog.CtxErrorf(ctx, "KITEX: panic happened in %s, remoteAddress=%s, error=%v\nstack=%s", funcName, conn.RemoteAddr(), panicErr, string(debug.Stack())) 209 } else { 210 klog.CtxErrorf(ctx, "KITEX: panic happened in %s, error=%v\nstack=%s", funcName, panicErr, string(debug.Stack())) 211 } 212 } 213 }