github.com/wangyougui/gf/v2@v2.6.5/net/gtcp/gtcp_server.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/wangyougui/gf.
     6  
     7  package gtcp
     8  
     9  import (
    10  	"crypto/tls"
    11  	"fmt"
    12  	"net"
    13  	"sync"
    14  
    15  	"github.com/wangyougui/gf/v2/container/gmap"
    16  	"github.com/wangyougui/gf/v2/errors/gcode"
    17  	"github.com/wangyougui/gf/v2/errors/gerror"
    18  	"github.com/wangyougui/gf/v2/text/gstr"
    19  	"github.com/wangyougui/gf/v2/util/gconv"
    20  )
    21  
    22  const (
    23  	// FreePortAddress marks the server listens using random free port.
    24  	FreePortAddress = ":0"
    25  )
    26  
    27  const (
    28  	defaultServer = "default"
    29  )
    30  
    31  // Server is a TCP server.
    32  type Server struct {
    33  	mu        sync.Mutex   // Used for Server.listen concurrent safety. -- The golang test with data race checks this.
    34  	listen    net.Listener // TCP address listener.
    35  	address   string       // Server listening address.
    36  	handler   func(*Conn)  // Connection handler.
    37  	tlsConfig *tls.Config  // TLS configuration.
    38  }
    39  
    40  // Map for name to server, for singleton purpose.
    41  var serverMapping = gmap.NewStrAnyMap(true)
    42  
    43  // GetServer returns the TCP server with specified `name`,
    44  // or it returns a new normal TCP server named `name` if it does not exist.
    45  // The parameter `name` is used to specify the TCP server
    46  func GetServer(name ...interface{}) *Server {
    47  	serverName := defaultServer
    48  	if len(name) > 0 && name[0] != "" {
    49  		serverName = gconv.String(name[0])
    50  	}
    51  	return serverMapping.GetOrSetFuncLock(serverName, func() interface{} {
    52  		return NewServer("", nil)
    53  	}).(*Server)
    54  }
    55  
    56  // NewServer creates and returns a new normal TCP server.
    57  // The parameter `name` is optional, which is used to specify the instance name of the server.
    58  func NewServer(address string, handler func(*Conn), name ...string) *Server {
    59  	s := &Server{
    60  		address: address,
    61  		handler: handler,
    62  	}
    63  	if len(name) > 0 && name[0] != "" {
    64  		serverMapping.Set(name[0], s)
    65  	}
    66  	return s
    67  }
    68  
    69  // NewServerTLS creates and returns a new TCP server with TLS support.
    70  // The parameter `name` is optional, which is used to specify the instance name of the server.
    71  func NewServerTLS(address string, tlsConfig *tls.Config, handler func(*Conn), name ...string) *Server {
    72  	s := NewServer(address, handler, name...)
    73  	s.SetTLSConfig(tlsConfig)
    74  	return s
    75  }
    76  
    77  // NewServerKeyCrt creates and returns a new TCP server with TLS support.
    78  // The parameter `name` is optional, which is used to specify the instance name of the server.
    79  func NewServerKeyCrt(address, crtFile, keyFile string, handler func(*Conn), name ...string) (*Server, error) {
    80  	s := NewServer(address, handler, name...)
    81  	if err := s.SetTLSKeyCrt(crtFile, keyFile); err != nil {
    82  		return nil, err
    83  	}
    84  	return s, nil
    85  }
    86  
    87  // SetAddress sets the listening address for server.
    88  func (s *Server) SetAddress(address string) {
    89  	s.address = address
    90  }
    91  
    92  // GetAddress get the listening address for server.
    93  func (s *Server) GetAddress() string {
    94  	return s.address
    95  }
    96  
    97  // SetHandler sets the connection handler for server.
    98  func (s *Server) SetHandler(handler func(*Conn)) {
    99  	s.handler = handler
   100  }
   101  
   102  // SetTLSKeyCrt sets the certificate and key file for TLS configuration of server.
   103  func (s *Server) SetTLSKeyCrt(crtFile, keyFile string) error {
   104  	tlsConfig, err := LoadKeyCrt(crtFile, keyFile)
   105  	if err != nil {
   106  		return err
   107  	}
   108  	s.tlsConfig = tlsConfig
   109  	return nil
   110  }
   111  
   112  // SetTLSConfig sets the TLS configuration of server.
   113  func (s *Server) SetTLSConfig(tlsConfig *tls.Config) {
   114  	s.tlsConfig = tlsConfig
   115  }
   116  
   117  // Close closes the listener and shutdowns the server.
   118  func (s *Server) Close() error {
   119  	s.mu.Lock()
   120  	defer s.mu.Unlock()
   121  	if s.listen == nil {
   122  		return nil
   123  	}
   124  	return s.listen.Close()
   125  }
   126  
   127  // Run starts running the TCP Server.
   128  func (s *Server) Run() (err error) {
   129  	if s.handler == nil {
   130  		err = gerror.NewCode(gcode.CodeMissingConfiguration, "start running failed: socket handler not defined")
   131  		return
   132  	}
   133  	if s.tlsConfig != nil {
   134  		// TLS Server
   135  		s.mu.Lock()
   136  		s.listen, err = tls.Listen("tcp", s.address, s.tlsConfig)
   137  		s.mu.Unlock()
   138  		if err != nil {
   139  			err = gerror.Wrapf(err, `tls.Listen failed for address "%s"`, s.address)
   140  			return
   141  		}
   142  	} else {
   143  		// Normal Server
   144  		var tcpAddr *net.TCPAddr
   145  		if tcpAddr, err = net.ResolveTCPAddr("tcp", s.address); err != nil {
   146  			err = gerror.Wrapf(err, `net.ResolveTCPAddr failed for address "%s"`, s.address)
   147  			return err
   148  		}
   149  		s.mu.Lock()
   150  		s.listen, err = net.ListenTCP("tcp", tcpAddr)
   151  		s.mu.Unlock()
   152  		if err != nil {
   153  			err = gerror.Wrapf(err, `net.ListenTCP failed for address "%s"`, s.address)
   154  			return err
   155  		}
   156  	}
   157  	// Listening loop.
   158  	for {
   159  		var conn net.Conn
   160  		if conn, err = s.listen.Accept(); err != nil {
   161  			err = gerror.Wrapf(err, `Listener.Accept failed`)
   162  			return err
   163  		} else if conn != nil {
   164  			go s.handler(NewConnByNetConn(conn))
   165  		}
   166  	}
   167  }
   168  
   169  // GetListenedAddress retrieves and returns the address string which are listened by current server.
   170  func (s *Server) GetListenedAddress() string {
   171  	if !gstr.Contains(s.address, FreePortAddress) {
   172  		return s.address
   173  	}
   174  	var (
   175  		address      = s.address
   176  		listenedPort = s.GetListenedPort()
   177  	)
   178  	address = gstr.Replace(address, FreePortAddress, fmt.Sprintf(`:%d`, listenedPort))
   179  	return address
   180  }
   181  
   182  // GetListenedPort retrieves and returns one port which is listened to by current server.
   183  func (s *Server) GetListenedPort() int {
   184  	s.mu.Lock()
   185  	defer s.mu.Unlock()
   186  	if ln := s.listen; ln != nil {
   187  		return ln.Addr().(*net.TCPAddr).Port
   188  	}
   189  	return -1
   190  }