github.com/Uptycs/basequery-go@v0.8.0/transport/transport_windows.go (about)

     1  package transport
     2  
     3  import (
     4  	"net"
     5  	"sync"
     6  	"time"
     7  
     8  	"github.com/Microsoft/go-winio"
     9  	"github.com/pkg/errors"
    10  
    11  	"github.com/apache/thrift/lib/go/thrift"
    12  )
    13  
    14  // Open opens the named pipe with the provided path and timeout,
    15  // returning a TTransport.
    16  func Open(path string, timeout time.Duration) (*thrift.TSocket, error) {
    17  	conn, err := winio.DialPipe(path, &timeout)
    18  	if err != nil {
    19  		return nil, errors.Wrapf(err, "dialing pipe '%s'", path)
    20  	}
    21  	return thrift.NewTSocketFromConnTimeout(conn, timeout), nil
    22  }
    23  
    24  func OpenServer(pipePath string, timeout time.Duration) (*TServerPipe, error) {
    25  	return NewTServerPipeTimeout(pipePath, timeout)
    26  }
    27  
    28  // TServerPipe is a windows named pipe implementation of the
    29  type TServerPipe struct {
    30  	listener      net.Listener
    31  	pipePath      string
    32  	clientTimeout time.Duration
    33  
    34  	// Protects the interrupted value to make it thread safe.
    35  	mu          sync.RWMutex
    36  	interrupted bool
    37  }
    38  
    39  func NewTServerPipeTimeout(pipePath string, clientTimeout time.Duration) (*TServerPipe, error) {
    40  	return &TServerPipe{pipePath: pipePath, clientTimeout: clientTimeout}, nil
    41  }
    42  
    43  func (p *TServerPipe) Listen() error {
    44  	p.mu.Lock()
    45  	defer p.mu.Unlock()
    46  
    47  	if p.IsListening() {
    48  		return nil
    49  	}
    50  
    51  	l, err := winio.ListenPipe(p.pipePath, nil)
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	p.listener = l
    57  	return nil
    58  }
    59  
    60  // IsListening returns whether the server transport is currently listening.
    61  func (p *TServerPipe) IsListening() bool {
    62  	return p.listener != nil
    63  }
    64  
    65  // Accept wraps the standard net.Listener accept to return a thrift.TTransport.
    66  func (p *TServerPipe) Accept() (thrift.TTransport, error) {
    67  	p.mu.RLock()
    68  	interrupted := p.interrupted
    69  	listener := p.listener
    70  	p.mu.RUnlock()
    71  
    72  	if interrupted {
    73  		return nil, errors.New("transport interrupted")
    74  	}
    75  
    76  	conn, err := listener.Accept()
    77  	if err != nil {
    78  		return nil, thrift.NewTTransportExceptionFromError(err)
    79  	}
    80  	return thrift.NewTSocketFromConnTimeout(conn, p.clientTimeout), nil
    81  }
    82  
    83  func (p *TServerPipe) Close() error {
    84  	defer func() {
    85  		p.listener = nil
    86  	}()
    87  	if p.IsListening() {
    88  		return p.listener.Close()
    89  	}
    90  	return nil
    91  }
    92  
    93  // Interrupt is a noop for this implementation
    94  func (p *TServerPipe) Interrupt() error {
    95  	p.mu.Lock()
    96  	defer p.mu.Unlock()
    97  
    98  	p.interrupted = true
    99  	p.Close()
   100  
   101  	return nil
   102  }