github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/net.go (about)

     1  package net
     2  
     3  import (
     4  	"log"
     5  	nt "net"
     6  	"os"
     7  	"runtime"
     8  	"strings"
     9  	"sync/atomic"
    10  	"time"
    11  
    12  	"github.com/angenalZZZ/gofunc/net/internal/netpoll"
    13  )
    14  
    15  // Action is an action that occurs after the completion of an event.
    16  type Action int
    17  
    18  const (
    19  	// None indicates that no action should occur following an event.
    20  	None Action = iota
    21  
    22  	// Close closes the connection.
    23  	Close
    24  
    25  	// Shutdown shutdowns the server.
    26  	Shutdown
    27  )
    28  
    29  var defaultLogger = Logger(log.New(os.Stderr, "", log.LstdFlags))
    30  
    31  // Logger is used for logging formatted messages.
    32  type Logger interface {
    33  	// Printf must have the same semantics as log.Printf.
    34  	Printf(format string, args ...interface{})
    35  }
    36  
    37  // Server represents a server context which provides information about the
    38  // running server and has control functions for managing state.
    39  type Server struct {
    40  	// svr is the internal server struct.
    41  	svr *server
    42  	// Multicore indicates whether the server will be effectively created with multi-cores, if so,
    43  	// then you must take care of synchronizing the shared data between all event callbacks, otherwise,
    44  	// it will run the server with single thread. The number of threads in the server will be automatically
    45  	// assigned to the value of runtime.NumCPU().
    46  	Multicore bool
    47  
    48  	// The Addr parameter is the listening address that align
    49  	// with the addr string passed to the Serve function.
    50  	Addr nt.Addr
    51  
    52  	// NumEventLoop is the number of event-loops that the server is using.
    53  	NumEventLoop int
    54  
    55  	// ReusePort indicates whether SO_REUSEPORT is enable.
    56  	ReusePort bool
    57  
    58  	// TCPKeepAlive (SO_KEEPALIVE) socket option.
    59  	TCPKeepAlive time.Duration
    60  }
    61  
    62  // CountConnections counts the number of currently active connections and returns it.
    63  func (s Server) CountConnections() (count int) {
    64  	s.svr.subEventLoopSet.iterate(func(i int, el *eventloop) bool {
    65  		count += int(atomic.LoadInt32(&el.connCount))
    66  		return true
    67  	})
    68  	return
    69  }
    70  
    71  // Conn is a interface of gnet connection.
    72  type Conn interface {
    73  	// Context returns a user-defined context.
    74  	Context() (ctx interface{})
    75  
    76  	// SetContext sets a user-defined context.
    77  	SetContext(ctx interface{})
    78  
    79  	// LocalAddr is the connection's local socket address.
    80  	LocalAddr() (addr nt.Addr)
    81  
    82  	// RemoteAddr is the connection's remote peer address.
    83  	RemoteAddr() (addr nt.Addr)
    84  
    85  	// Read reads all data from inbound ring-buffer and event-loop-buffer without moving "read" pointer, which means
    86  	// it does not evict the data from buffers actually and those data will present in buffers until the
    87  	// ResetBuffer method is called.
    88  	Read() (buf []byte)
    89  
    90  	// ResetBuffer resets the buffers, which means all data in inbound ring-buffer and event-loop-buffer will be evicted.
    91  	ResetBuffer()
    92  
    93  	// ReadN reads bytes with the given length from inbound ring-buffer and event-loop-buffer without moving
    94  	// "read" pointer, which means it will not evict the data from buffers until the ShiftN method is called,
    95  	// it reads data from the inbound ring-buffer and event-loop-buffer and returns both bytes and the size of it.
    96  	// If the length of the available data is less than the given "n", ReadN will return all available data, so you
    97  	// should make use of the variable "size" returned by it to be aware of the exact length of the returned data.
    98  	ReadN(n int) (size int, buf []byte)
    99  
   100  	// ShiftN shifts "read" pointer in the internal buffers with the given length.
   101  	ShiftN(n int) (size int)
   102  
   103  	// BufferLength returns the length of available data in the internal buffers.
   104  	BufferLength() (size int)
   105  
   106  	// InboundBuffer returns the inbound ring-buffer.
   107  	//InboundBuffer() *ringbuffer.RingBuffer
   108  
   109  	// SendTo writes data for UDP sockets, it allows you to send data back to UDP socket in individual goroutines.
   110  	SendTo(buf []byte) error
   111  
   112  	// AsyncWrite writes data to client/connection asynchronously, usually you would call it in individual goroutines
   113  	// instead of the event-loop goroutines.
   114  	AsyncWrite(buf []byte) error
   115  
   116  	// Wake triggers a React event for this connection.
   117  	Wake() error
   118  
   119  	// Close closes the current connection.
   120  	Close() error
   121  }
   122  
   123  type (
   124  	// EventHandler represents the server events' callbacks for the Serve call.
   125  	// Each event has an Action return value that is used manage the state
   126  	// of the connection and server.
   127  	EventHandler interface {
   128  		// OnInitComplete fires when the server is ready for accepting connections.
   129  		// The parameter:server has information and various utilities.
   130  		OnInitComplete(server Server) (action Action)
   131  
   132  		// OnShutdown fires when the server is being shut down, it is called right after
   133  		// all event-loops and connections are closed.
   134  		OnShutdown(server Server)
   135  
   136  		// OnOpened fires when a new connection has been opened.
   137  		// The parameter:c has information about the connection such as it's local and remote address.
   138  		// Parameter:out is the return value which is going to be sent back to the client.
   139  		OnOpened(c Conn) (out []byte, action Action)
   140  
   141  		// OnClosed fires when a connection has been closed.
   142  		// The parameter:err is the last known connection error.
   143  		OnClosed(c Conn, err error) (action Action)
   144  
   145  		// PreWrite fires just before any data is written to any client socket, this event function is usually used to
   146  		// put some code of logging/counting/reporting or any prepositive operations before writing data to client.
   147  		PreWrite()
   148  
   149  		// React fires when a connection sends the server data.
   150  		// Call c.Read() or c.ReadN(n) within the parameter:c to read incoming data from client.
   151  		// Parameter:out is the return value which is going to be sent back to the client.
   152  		React(frame []byte, c Conn) (out []byte, action Action)
   153  
   154  		// Tick fires immediately after the server starts and will fire again
   155  		// following the duration specified by the delay return value.
   156  		Tick() (delay time.Duration, action Action)
   157  	}
   158  
   159  	// EventServer is a built-in implementation of EventHandler which sets up each method with a default implementation,
   160  	// you can compose it with your own implementation of EventHandler when you don't want to implement all methods
   161  	// in EventHandler.
   162  	EventServer struct {
   163  	}
   164  )
   165  
   166  // OnInitComplete fires when the server is ready for accepting connections.
   167  // The parameter:server has information and various utilities.
   168  func (es *EventServer) OnInitComplete(svr Server) (action Action) {
   169  	return
   170  }
   171  
   172  // OnShutdown fires when the server is being shut down, it is called right after
   173  // all event-loops and connections are closed.
   174  func (es *EventServer) OnShutdown(svr Server) {
   175  }
   176  
   177  // OnOpened fires when a new connection has been opened.
   178  // The parameter:c has information about the connection such as it's local and remote address.
   179  // Parameter:out is the return value which is going to be sent back to the client.
   180  func (es *EventServer) OnOpened(c Conn) (out []byte, action Action) {
   181  	return
   182  }
   183  
   184  // OnClosed fires when a connection has been closed.
   185  // The parameter:err is the last known connection error.
   186  func (es *EventServer) OnClosed(c Conn, err error) (action Action) {
   187  	return
   188  }
   189  
   190  // PreWrite fires just before any data is written to any client socket, this event function is usually used to
   191  // put some code of logging/counting/reporting or any prepositive operations before writing data to client.
   192  func (es *EventServer) PreWrite() {
   193  }
   194  
   195  // React fires when a connection sends the server data.
   196  // Call c.Read() or c.ReadN(n) within the parameter:c to read incoming data from client.
   197  // Parameter:out is the return value which is going to be sent back to the client.
   198  func (es *EventServer) React(frame []byte, c Conn) (out []byte, action Action) {
   199  	return
   200  }
   201  
   202  // Tick fires immediately after the server starts and will fire again
   203  // following the duration specified by the delay return value.
   204  func (es *EventServer) Tick() (delay time.Duration, action Action) {
   205  	return
   206  }
   207  
   208  // Serve starts handling events for the specified address.
   209  //
   210  // Address should use a scheme prefix and be formatted
   211  // like `tcp://192.168.0.10:9851` or `unix://socket`.
   212  // Valid network schemes:
   213  //  tcp   - bind to both IPv4 and IPv6
   214  //  tcp4  - IPv4
   215  //  tcp6  - IPv6
   216  //  udp   - bind to both IPv4 and IPv6
   217  //  udp4  - IPv4
   218  //  udp6  - IPv6
   219  //  unix  - Unix Domain Socket
   220  //
   221  // The "tcp" network scheme is assumed when one is not specified.
   222  func Serve(eventHandler EventHandler, addr string, opts ...Option) (err error) {
   223  	var ln listener
   224  	defer func() {
   225  		ln.close()
   226  		if ln.network == "unix" {
   227  			sniffErrorAndLog(os.RemoveAll(ln.addr))
   228  		}
   229  	}()
   230  
   231  	options := loadOptions(opts...)
   232  
   233  	if options.Logger != nil {
   234  		defaultLogger = options.Logger
   235  	}
   236  
   237  	ln.network, ln.addr = parseAddr(addr)
   238  	switch ln.network {
   239  	case "udp", "udp4", "udp6":
   240  		if options.ReusePort {
   241  			ln.pconn, err = netpoll.ReusePortListenPacket(ln.network, ln.addr)
   242  		} else {
   243  			ln.pconn, err = nt.ListenPacket(ln.network, ln.addr)
   244  		}
   245  	case "unix":
   246  		sniffErrorAndLog(os.RemoveAll(ln.addr))
   247  		if runtime.GOOS == "windows" {
   248  			err = ErrUnsupportedProtocol
   249  			break
   250  		}
   251  		fallthrough
   252  	case "tcp", "tcp4", "tcp6":
   253  		if options.ReusePort {
   254  			ln.ln, err = netpoll.ReusePortListen(ln.network, ln.addr)
   255  		} else {
   256  			ln.ln, err = nt.Listen(ln.network, ln.addr)
   257  		}
   258  	default:
   259  		err = ErrUnsupportedProtocol
   260  	}
   261  	if err != nil {
   262  		return
   263  	}
   264  
   265  	if ln.pconn != nil {
   266  		ln.lnaddr = ln.pconn.LocalAddr()
   267  	} else {
   268  		ln.lnaddr = ln.ln.Addr()
   269  	}
   270  
   271  	if err = ln.renormalize(); err != nil {
   272  		return
   273  	}
   274  
   275  	return serve(eventHandler, &ln, options)
   276  }
   277  
   278  func parseAddr(addr string) (network, address string) {
   279  	network = "tcp"
   280  	address = strings.ToLower(addr)
   281  	if strings.Contains(address, "://") {
   282  		pair := strings.Split(address, "://")
   283  		network = pair[0]
   284  		address = pair[1]
   285  	}
   286  	return
   287  }
   288  
   289  func sniffErrorAndLog(err error) {
   290  	if err != nil {
   291  		defaultLogger.Printf(err.Error())
   292  	}
   293  }