github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/poller/netpoll/handle.go (about)

     1  package netpoll
     2  
     3  import (
     4  	"net"
     5  	"os"
     6  )
     7  
     8  // filer describes an object that has ability to return os.File.
     9  type filer interface {
    10  	// File returns a copy of object's file descriptor.
    11  	File() (*os.File, error)
    12  }
    13  
    14  // Desc is a network connection within netpoll descriptor.
    15  // It's methods are not goroutine safe.
    16  type Desc struct {
    17  	file  *os.File
    18  	event Event
    19  }
    20  
    21  // NewDesc creates descriptor from custom fd.
    22  func NewDesc(fd uintptr, ev Event) *Desc {
    23  	return &Desc{os.NewFile(fd, ""), ev}
    24  }
    25  
    26  // Close closes underlying file.
    27  func (h *Desc) Close() error {
    28  	return h.file.Close()
    29  }
    30  
    31  func (h *Desc) fd() int {
    32  	return int(h.file.Fd())
    33  }
    34  
    35  // Must is a helper that wraps a call to a function returning (*Desc, error).
    36  // It panics if the error is non-nil and returns desc if not.
    37  // It is intended for use in short Desc initializations.
    38  func Must(desc *Desc, err error) *Desc {
    39  	if err != nil {
    40  		panic(err)
    41  	}
    42  	return desc
    43  }
    44  
    45  // HandleRead creates read descriptor for further use in Poller methods.
    46  // It is the same as Handle(conn, EventRead|EventEdgeTriggered).
    47  func HandleRead(conn net.Conn) (*Desc, error) {
    48  	return Handle(conn, EventRead|EventEdgeTriggered)
    49  }
    50  
    51  // HandleReadOnce creates read descriptor for further use in Poller methods.
    52  // It is the same as Handle(conn, EventRead|EventOneShot).
    53  func HandleReadOnce(conn net.Conn) (*Desc, error) {
    54  	return Handle(conn, EventRead|EventOneShot)
    55  }
    56  
    57  // HandleWrite creates write descriptor for further use in Poller methods.
    58  // It is the same as Handle(conn, EventWrite|EventEdgeTriggered).
    59  func HandleWrite(conn net.Conn) (*Desc, error) {
    60  	return Handle(conn, EventWrite|EventEdgeTriggered)
    61  }
    62  
    63  // HandleWriteOnce creates write descriptor for further use in Poller methods.
    64  // It is the same as Handle(conn, EventWrite|EventOneShot).
    65  func HandleWriteOnce(conn net.Conn) (*Desc, error) {
    66  	return Handle(conn, EventWrite|EventOneShot)
    67  }
    68  
    69  // HandleReadWrite creates read and write descriptor for further use in Poller
    70  // methods.
    71  // It is the same as Handle(conn, EventRead|EventWrite|EventEdgeTriggered).
    72  func HandleReadWrite(conn net.Conn) (*Desc, error) {
    73  	return Handle(conn, EventRead|EventWrite|EventEdgeTriggered)
    74  }
    75  
    76  // Handle creates new Desc with given conn and event.
    77  // Returned descriptor could be used as argument to Start(), Resume() and
    78  // Stop() methods of some Poller implementation.
    79  func Handle(conn net.Conn, event Event) (*Desc, error) {
    80  	desc, err := handle(conn, event)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	// Set the file back to non blocking mode since conn.File() sets underlying
    86  	// os.File to blocking mode. This is useful to get conn.Set{Read}Deadline
    87  	// methods still working on source Conn.
    88  	//
    89  	// See https://golang.org/pkg/net/#TCPConn.File
    90  	// See /usr/local/go/src/net/net.go: conn.File()
    91  	if err = setNonblock(desc.fd(), true); err != nil {
    92  		return nil, os.NewSyscallError("setnonblock", err)
    93  	}
    94  
    95  	return desc, nil
    96  }
    97  
    98  // HandleListener returns descriptor for a net.Listener.
    99  func HandleListener(ln net.Listener, event Event) (*Desc, error) {
   100  	return handle(ln, event)
   101  }
   102  
   103  func handle(x interface{}, event Event) (*Desc, error) {
   104  	f, ok := x.(filer)
   105  	if !ok {
   106  		return nil, ErrNotFiler
   107  	}
   108  
   109  	// Get a copy of fd.
   110  	file, err := f.File()
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  
   115  	return &Desc{
   116  		file:  file,
   117  		event: event,
   118  	}, nil
   119  }