github.com/evdatsion/aphelion-dpos-bft@v0.32.1/abci/server/socket_server.go (about)

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