NewNonBlocking returns a ReadyReader if the passed reader supports non-memory-pinning reads, else nil.
(r io.Reader)
| 66 | // NewNonBlocking returns a ReadyReader if the passed reader supports |
| 67 | // non-memory-pinning reads, else nil. |
| 68 | func NewNonBlocking(r io.Reader) Reader { |
| 69 | if rr, ok := r.(Reader); ok { |
| 70 | return rr |
| 71 | } |
| 72 | if !isRawConnSupported() { |
| 73 | return nil |
| 74 | } |
| 75 | // We restrict the types before asserting syscall.Conn. The credentials |
| 76 | // package may return a wrapper that implements syscall.Conn by embedding |
| 77 | // both the raw connection and the encrypted connection. If the code |
| 78 | // attempts to read directly from the raw syscall.RawConn, it would read |
| 79 | // encrypted data. |
| 80 | switch r.(type) { |
| 81 | case *net.TCPConn, *net.UDPConn, *net.UnixConn, *net.IPConn: |
| 82 | default: |
| 83 | return nil |
| 84 | } |
| 85 | sysConn, ok := r.(syscall.Conn) |
| 86 | if !ok { |
| 87 | return nil |
| 88 | } |
| 89 | raw, err := sysConn.SyscallConn() |
| 90 | if err != nil { |
| 91 | return nil |
| 92 | } |
| 93 | rr := &nonBlockingReader{raw: raw} |
| 94 | rr.doRead = func(fd uintptr) bool { |
| 95 | s := &rr.state |
| 96 | |
| 97 | s.buf = s.pool.Get(s.bufSize) |
| 98 | s.bytesRead, s.readError = sysRead(fd, *s.buf) |
| 99 | |
| 100 | if s.readError != nil { |
| 101 | s.pool.Put(s.buf) |
| 102 | s.buf = nil |
| 103 | } |
| 104 | return !wouldBlock(s.readError) |
| 105 | } |
| 106 | return rr |
| 107 | } |
| 108 | |
| 109 | func (c *nonBlockingReader) ReadOnReady(bufSize int, pool mem.BufferPool) (*[]byte, int, error) { |
| 110 | c.state = readState{ |
no test coverage detected