* Fix flaky TLS test by waiting for dial outcome before closing connection
PRs #564 and #567 introduced errSignalingConn to surface TLS errors
(especially TLS 1.3 post-handshake alerts) to BlockingDial callers.
This caused a flaky test failure (reported in: https://github.com/fullstorydev/grpcurl/pull/564#issuecomment-4916344087):
```
TestBrokenTLS_RequireClientCertButNonePresented:
expecting a TLS certificate error, got: read tcp ...: use of closed
network connection
```
The race works as follows:
1. With TLS 1.3, the server rejects the connection *after* the handshake
completes (e.g. missing client cert) by sending a TLS alert, then
closing the connection.
2. Simultaneously, the client's Write fails (broken pipe) because the server already closed its side.
3. grpc-go's `NewHTTP2Client` returns the Write error and calls `t.Close()`
to tear down the transport, which calls `errSignalingConn.Close()` ->
`c.Conn.Close()`, closing the connection.
4. The reader goroutine's pending Read (which should have returned the
TLS alert (e.g. "certificate required")) instead returns
`use of closed network connection` because the connection was
closed underneath it.
5. `writeResult` surfaces the "closed network connection" error to the caller instead of the meaningful TLS alert.
The fix: delay Close on the errSignalingConn until the outcome of the
dial is known, with a 50ms timeout. This gives the reader a chance to
surface the TLS alert.
Demonstrating this by stressing the test:
**Without the fix**
```
alasia :: github/fullstorydev/grpcurl ‹master› » go test -c -o /tmp/grpcurl.test . && GOMAXPROCS=2 $HOME/go/bin/stress -p 16 -count 5000 -ignore 'assign requested address|context deadline exceeded' /tmp/grpcurl.test -test.run 'TestBrokenTLS'
/var/folders/7l/0tdjxwg912j9gqh446yk3ll40000gn/T/go-stress-20260724T113423-1710148011
--- FAIL: TestBrokenTLS_RequireClientCertButNonePresented (0.00s)
tls_settings_test.go:332: expecting a TLS certificate error, got: read tcp 127.0.0.1:52850->127.0.0.1:52848: use of closed network connection
FAIL
ERROR: exit status 1
[...]
5s: 1580 runs so far, 5 failures (0.32%), 13 active
```
**With the fix**
```
alasia :: github/fullstorydev/grpcurl ‹surface-post-dial-conn-errors› » go test -c -o /tmp/grpcurl.test . && GOMAXPROCS=2 $HOME/go/bin/stress -p 16 -count 5000 -ignore 'assign requested address|context deadline exceeded' /tmp/grpcurl.test -test.run 'TestBrokenTLS'
5s: 1594 runs so far, 0 failures, 16 active
10s: 3386 runs so far, 0 failures, 16 active
15s: 4999 runs so far, 0 failures, 1 active
15s: 5000 runs total, 0 failures
```
* Implement review comment
The JSON example in the stdin section had a typo: "foor" instead of
"foo". Surrounding examples in the same section use "foo" consistently.
Co-authored-by: maxtaran2010 <ocotifuzo727@gmail.com>
Avoid hanging on connection errors; fail fast by propagating connection
errors.
This also speeds up tests a lot (from >20s to about 3s), since the tests
included some connection timeouts.
This expands on https://github.com/fullstorydev/grpcurl/pull/564 ; it
does the same for plaintext connections.
Fixes#387
* Add support for TLS 1.3
This PR allows TLS 1.3, by removing the MaxVersion in the client config.
This would silently swallow errors, so e.g. a client without cert
dialing a server that requires client certs would lead to an error which
gets ignored, leading to retries until timeout.
In this PR, we wrap the connection and if an error occurs we send it to
the existing `result` channel.
I think this matches @jhump's comment in https://github.com/fullstorydev/grpcurl/issues/387#issuecomment-1517098394
**Testing**
```console
# Start the test server (in another tab)
go run ./internal/testing/cmd/testserver \
-cert internal/testing/tls/server.crt \
-key internal/testing/tls/server.key \
-cacert internal/testing/tls/ca.crt \
-requirecert -p 9999
# Old behavior
$ grpcurl -cacert internal/testing/tls/ca.crt \
localhost:9999 list
Failed to dial target host "localhost:9999": context deadline exceeded
# New behavior
$ go run ./cmd/grpcurl -cacert internal/testing/tls/ca.crt \
localhost:9999 list
Failed to dial target host "localhost:9999": remote error: tls: certificate required
exit status 1
```
The old behavior is to hang until we hit the deadline. The new behavior
is to return immediately with an error.
Fixes#563
* Implement review comments
Removing unnecessary sync.Once, as the channel will already drop repeated calls.
Migrate from deprecated grpc.DialContext/WithBlock to grpc.NewClient
with connectivity state polling in BlockingDial. Add passthrough:///
scheme prefix for bare addresses to preserve resolver behavior.
The error message for client certificate failures changed in Go 1.25.
Update tests to check for both the old ("bad certificate") and new
("handshake failure") error strings to support multiple Go versions.
Signed-off-by: Mikel Olasagasti Uranga <mikel@olasagasti.info>
* chore: update to Golang 1.23
* chore: configure cci to build with 1.23
Signed-off-by: Or Shachar <orchoock@gmail.com>
* Update config.yml
---------
Signed-off-by: Or Shachar <orchoock@gmail.com>
Co-authored-by: Scott Blum <dragonsinth@gmail.com>
* Add functionality to export proto files
Added a new function, `WriteProtoFiles` in `desc_source.go` which is used to generate .proto files. The process involves resolving symbols from the descriptor source and writing their definitions to a designated output directory. The corresponding flag `--proto-out` has been included in `grpcurl.go` to allow users to specify the directory path.
* Refactor file creation error handling
The code for file creation and error handling in desc_source.go has been refactored. Previously, the file closure operation was executed irrespective of whether the file was created successfully or not. Now, the file will only be closed if it was successfully created, improving error handling.
* Update 'proto-out' command to 'proto-out-dir'
The command for exporting proto files and setting the output directory has been updated from 'proto-out' to 'proto-out-dir'. This change has been made both in the README and the grpcurl go file. This makes the command name more descriptive, accurately reflecting its functionality.
* fix import sort
* Reorder file close operation in error handling
The file close operation has been moved within the error handling of the 'PrintProtoFile' function. Previously, it was being executed before this function, now it's executed immediately after. Moreover, an additional close operation has been added after the function success ensuring the file is properly closed in all scenarios.
* Update grpcurl commands in README
The grpcurl commands for exporting proto files and protoset files in the README are updated. The IP address has been changed to localhost and port number to '8787'. Also, the service name is adjusted to 'my.custom.server.Service'. Instructions for use of specific command options are added for enhanced clarity.
* Refactor error handling in file creation
The code responsible for error handling during file creation in the desc_source.go file has been streamlined. This modification simplifies the code by reducing unnecessary condition checks and redundant file closure action after an error has occurred.
* Refactor proto file writing into separate function
The file writing process for protobuf files has been extracted into a new function called writeProtoFile(). This refactoring simplifies the main function. The code is cleaner and more manageable this way, improving maintainability and readability.
* Refactor writeProtoFile function for better error handling
Streamlined the writeProtoFile function in desc_source.go file. Simplified path calculations and improved error messages for file-creation functions, making it easier to trace the exact point of failure and enhance the debugging process.
* update to latest jhump/protoreflect
* be lenient when possible if server cannot furnish all dependencies
* move linting back to go 1.21 instead of latest go 1.22
* make staticcheck happy