func NetPipe(t testing.TB) (net.Conn, net.Conn) { l, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatal(err) } defer l.Close() client_future := utils.NewFuture() go func() { client_future.Set(net.Dial(l.Addr().Network(), l.Addr().String())) }() var errs utils.ErrorGroup server_conn, err := l.Accept() errs.Add(err) client_conn, err := client_future.Get() errs.Add(err) err = errs.Finalize() if err != nil { if server_conn != nil { server_conn.Close() } if client_conn != nil { client_conn.(net.Conn).Close() } t.Fatal(err) } return server_conn, client_conn.(net.Conn) }
func (c *Conn) getErrorHandler(rv C.int, errno error) func() error { errcode := C.SSL_get_error(c.ssl, rv) switch errcode { case C.SSL_ERROR_ZERO_RETURN: return func() error { c.Close() return io.ErrUnexpectedEOF } case C.SSL_ERROR_WANT_READ: go c.flushOutputBuffer() if c.want_read_future != nil { want_read_future := c.want_read_future return func() error { _, err := want_read_future.Get() return err } } c.want_read_future = utils.NewFuture() want_read_future := c.want_read_future return func() (err error) { defer func() { c.mtx.Lock() c.want_read_future = nil c.mtx.Unlock() want_read_future.Set(nil, err) }() err = c.fillInputBuffer() if err != nil { return err } return tryAgain } case C.SSL_ERROR_WANT_WRITE: return func() error { err := c.flushOutputBuffer() if err != nil { return err } return tryAgain } case C.SSL_ERROR_SYSCALL: var err error if C.ERR_peek_error() == 0 { switch rv { case 0: err = errors.New("protocol-violating EOF") case -1: err = errno default: err = errorFromErrorQueue() } } else { err = errorFromErrorQueue() } return func() error { return err } default: err := errorFromErrorQueue() return func() error { return err } } }
func (c *Conn) ioErrorHandler(rv C.int, errno error, funcErr *C.SSLFuncError) func() error { errorString := "" if funcErr.error_message != nil { errorString = C.GoStringN(funcErr.error_message, 255) C.free(unsafe.Pointer(funcErr.error_message)) funcErr.error_message = nil } errcode := C.int(funcErr.error_code) switch errcode { case C.SSL_ERROR_ZERO_RETURN: return func() error { c.Close() return io.ErrUnexpectedEOF } case C.SSL_ERROR_WANT_READ: go c.flushOutputBuffer() if c.want_read_future != nil { want_read_future := c.want_read_future return func() error { _, err := want_read_future.Get() return err } } c.want_read_future = utils.NewFuture() want_read_future := c.want_read_future return func() (err error) { defer func() { c.mtx.Lock() c.want_read_future = nil c.mtx.Unlock() want_read_future.Set(nil, err) }() err = c.fillInputBuffer() if err != nil { return err } return tryAgain } case C.SSL_ERROR_WANT_WRITE: return func() error { err := c.flushOutputBuffer() if err != nil { return err } return tryAgain } case C.SSL_ERROR_NONE: return func() error { return nil } case C.SSL_ERROR_SYSCALL: var retErr error if funcErr.has_errno != 0 { switch rv { case 0: retErr = errors.New("protocol-violating EOF") case -1: retErr = errno } } else { retErr = errors.New(errorString) } return func() error { return retErr } default: return func() error { return errors.New(errorString) } } }