github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/abci/server/socket_server.go (about) 1 package server 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "net" 8 "os" 9 "runtime" 10 "sync" 11 12 "github.com/tendermint/tendermint/abci/types" 13 tmlog "github.com/tendermint/tendermint/libs/log" 14 tmnet "github.com/tendermint/tendermint/libs/net" 15 "github.com/tendermint/tendermint/libs/service" 16 ) 17 18 // var maxNumberConnections = 2 19 20 type SocketServer struct { 21 service.BaseService 22 isLoggerSet bool 23 24 proto string 25 addr string 26 listener net.Listener 27 28 connsMtx sync.Mutex 29 conns map[int]net.Conn 30 nextConnID int 31 32 appMtx sync.Mutex 33 app types.Application 34 } 35 36 func NewSocketServer(protoAddr string, app types.Application) service.Service { 37 proto, addr := tmnet.ProtocolAndAddress(protoAddr) 38 s := &SocketServer{ 39 proto: proto, 40 addr: addr, 41 listener: nil, 42 app: app, 43 conns: make(map[int]net.Conn), 44 } 45 s.BaseService = *service.NewBaseService(nil, "ABCIServer", s) 46 return s 47 } 48 49 func (s *SocketServer) SetLogger(l tmlog.Logger) { 50 s.BaseService.SetLogger(l) 51 s.isLoggerSet = true 52 } 53 54 func (s *SocketServer) OnStart() error { 55 ln, err := net.Listen(s.proto, s.addr) 56 if err != nil { 57 return err 58 } 59 60 s.listener = ln 61 go s.acceptConnectionsRoutine() 62 63 return nil 64 } 65 66 func (s *SocketServer) OnStop() { 67 if err := s.listener.Close(); err != nil { 68 s.Logger.Error("Error closing listener", "err", err) 69 } 70 71 s.connsMtx.Lock() 72 defer s.connsMtx.Unlock() 73 for id, conn := range s.conns { 74 delete(s.conns, id) 75 if err := conn.Close(); err != nil { 76 s.Logger.Error("Error closing connection", "id", id, "conn", conn, "err", err) 77 } 78 } 79 } 80 81 func (s *SocketServer) addConn(conn net.Conn) int { 82 s.connsMtx.Lock() 83 defer s.connsMtx.Unlock() 84 85 connID := s.nextConnID 86 s.nextConnID++ 87 s.conns[connID] = conn 88 89 return connID 90 } 91 92 // deletes conn even if close errs 93 func (s *SocketServer) rmConn(connID int) error { 94 s.connsMtx.Lock() 95 defer s.connsMtx.Unlock() 96 97 conn, ok := s.conns[connID] 98 if !ok { 99 return fmt.Errorf("connection %d does not exist", connID) 100 } 101 102 delete(s.conns, connID) 103 return conn.Close() 104 } 105 106 func (s *SocketServer) acceptConnectionsRoutine() { 107 for { 108 // Accept a connection 109 s.Logger.Info("Waiting for new connection...") 110 conn, err := s.listener.Accept() 111 if err != nil { 112 if !s.IsRunning() { 113 return // Ignore error from listener closing. 114 } 115 s.Logger.Error("Failed to accept connection", "err", err) 116 continue 117 } 118 119 s.Logger.Info("Accepted a new connection") 120 121 connID := s.addConn(conn) 122 123 closeConn := make(chan error, 2) // Push to signal connection closed 124 responses := make(chan *types.Response, 1000) // A channel to buffer responses 125 126 // Read requests from conn and deal with them 127 go s.handleRequests(closeConn, conn, responses) 128 // Pull responses from 'responses' and write them to conn. 129 go s.handleResponses(closeConn, conn, responses) 130 131 // Wait until signal to close connection 132 go s.waitForClose(closeConn, connID) 133 } 134 } 135 136 func (s *SocketServer) waitForClose(closeConn chan error, connID int) { 137 err := <-closeConn 138 switch { 139 case err == io.EOF: 140 s.Logger.Error("Connection was closed by client") 141 case err != nil: 142 s.Logger.Error("Connection error", "err", err) 143 default: 144 // never happens 145 s.Logger.Error("Connection was closed") 146 } 147 148 // Close the connection 149 if err := s.rmConn(connID); err != nil { 150 s.Logger.Error("Error closing connection", "err", err) 151 } 152 } 153 154 // Read requests from conn and deal with them 155 func (s *SocketServer) handleRequests(closeConn chan error, conn io.Reader, responses chan<- *types.Response) { 156 var count int 157 var bufReader = bufio.NewReader(conn) 158 159 defer func() { 160 // make sure to recover from any app-related panics to allow proper socket cleanup 161 r := recover() 162 if r != nil { 163 const size = 64 << 10 164 buf := make([]byte, size) 165 buf = buf[:runtime.Stack(buf, false)] 166 err := fmt.Errorf("recovered from panic: %v\n%s", r, buf) 167 if !s.isLoggerSet { 168 fmt.Fprintln(os.Stderr, err) 169 } 170 closeConn <- err 171 s.appMtx.Unlock() 172 } 173 }() 174 175 for { 176 177 var req = &types.Request{} 178 err := types.ReadMessage(bufReader, req) 179 if err != nil { 180 if err == io.EOF { 181 closeConn <- err 182 } else { 183 closeConn <- fmt.Errorf("error reading message: %w", err) 184 } 185 return 186 } 187 s.appMtx.Lock() 188 count++ 189 s.handleRequest(req, responses) 190 s.appMtx.Unlock() 191 } 192 } 193 194 func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types.Response) { 195 switch r := req.Value.(type) { 196 case *types.Request_Echo: 197 responses <- types.ToResponseEcho(r.Echo.Message) 198 case *types.Request_Flush: 199 responses <- types.ToResponseFlush() 200 case *types.Request_Info: 201 res := s.app.Info(*r.Info) 202 responses <- types.ToResponseInfo(res) 203 case *types.Request_SetOption: 204 res := s.app.SetOption(*r.SetOption) 205 responses <- types.ToResponseSetOption(res) 206 case *types.Request_DeliverTx: 207 res := s.app.DeliverTx(*r.DeliverTx) 208 responses <- types.ToResponseDeliverTx(res) 209 case *types.Request_CheckTx: 210 res := s.app.CheckTx(*r.CheckTx) 211 responses <- types.ToResponseCheckTx(res) 212 case *types.Request_Commit: 213 res := s.app.Commit() 214 responses <- types.ToResponseCommit(res) 215 case *types.Request_Query: 216 res := s.app.Query(*r.Query) 217 responses <- types.ToResponseQuery(res) 218 case *types.Request_InitChain: 219 res := s.app.InitChain(*r.InitChain) 220 responses <- types.ToResponseInitChain(res) 221 case *types.Request_BeginBlock: 222 res := s.app.BeginBlock(*r.BeginBlock) 223 responses <- types.ToResponseBeginBlock(res) 224 case *types.Request_EndBlock: 225 res := s.app.EndBlock(*r.EndBlock) 226 responses <- types.ToResponseEndBlock(res) 227 default: 228 responses <- types.ToResponseException("Unknown request") 229 } 230 } 231 232 // Pull responses from 'responses' and write them to conn. 233 func (s *SocketServer) handleResponses(closeConn chan error, conn io.Writer, responses <-chan *types.Response) { 234 var count int 235 var bufWriter = bufio.NewWriter(conn) 236 for { 237 var res = <-responses 238 err := types.WriteMessage(res, bufWriter) 239 if err != nil { 240 closeConn <- fmt.Errorf("error writing message: %w", err) 241 return 242 } 243 if _, ok := res.Value.(*types.Response_Flush); ok { 244 err = bufWriter.Flush() 245 if err != nil { 246 closeConn <- fmt.Errorf("error flushing write buffer: %w", err) 247 return 248 } 249 } 250 count++ 251 } 252 }