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 }