github.com/goplus/gop@v1.2.6/x/jsonrpc2/jsonrpc2test/pipe.go (about)

     1  /*
     2   * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  // Copyright 2018 The Go Authors. All rights reserved.
    18  // Use of this source code is governed by a BSD-style
    19  // license that can be found in the LICENSE file.
    20  
    21  package jsonrpc2test
    22  
    23  import (
    24  	"context"
    25  	"io"
    26  	"net"
    27  
    28  	"github.com/goplus/gop/x/jsonrpc2"
    29  )
    30  
    31  // NetPipeListener returns a new Listener that listens using net.Pipe.
    32  // It is only possibly to connect to it using the Dialer returned by the
    33  // Dialer method, each call to that method will generate a new pipe the other
    34  // side of which will be returned from the Accept call.
    35  func NetPipeListener() jsonrpc2.Listener {
    36  	return &netPiper{
    37  		done:   make(chan struct{}),
    38  		dialed: make(chan io.ReadWriteCloser),
    39  	}
    40  }
    41  
    42  // netPiper is the implementation of Listener build on top of net.Pipes.
    43  type netPiper struct {
    44  	done   chan struct{}
    45  	dialed chan io.ReadWriteCloser
    46  }
    47  
    48  // Accept blocks waiting for an incoming connection to the listener.
    49  func (l *netPiper) Accept(context.Context) (io.ReadWriteCloser, error) {
    50  	// Block until the pipe is dialed or the listener is closed,
    51  	// preferring the latter if already closed at the start of Accept.
    52  	select {
    53  	case <-l.done:
    54  		return nil, net.ErrClosed
    55  	default:
    56  	}
    57  	select {
    58  	case rwc := <-l.dialed:
    59  		return rwc, nil
    60  	case <-l.done:
    61  		return nil, net.ErrClosed
    62  	}
    63  }
    64  
    65  // Close will cause the listener to stop listening. It will not close any connections that have
    66  // already been accepted.
    67  func (l *netPiper) Close() error {
    68  	// unblock any accept calls that are pending
    69  	close(l.done)
    70  	return nil
    71  }
    72  
    73  func (l *netPiper) Dialer() jsonrpc2.Dialer {
    74  	return l
    75  }
    76  
    77  func (l *netPiper) Dial(ctx context.Context) (io.ReadWriteCloser, error) {
    78  	client, server := net.Pipe()
    79  
    80  	select {
    81  	case l.dialed <- server:
    82  		return client, nil
    83  
    84  	case <-l.done:
    85  		client.Close()
    86  		server.Close()
    87  		return nil, net.ErrClosed
    88  	}
    89  }