Skip to content

Commit 72bf34f

Browse files
authored
Merge pull request #19 from ninedraft/fix-server-listen-cancelation
2 parents 577f10c + 9e368ed commit 72bf34f

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Package testaddr selects free port for testing purposes.
2+
package testaddr
3+
4+
import (
5+
"fmt"
6+
"net"
7+
)
8+
9+
const localAddr = "localhost:0"
10+
11+
// Addr returns free address in form of "localhost:$FREE_PORT",
12+
// which can be used for test servers.
13+
func Addr() string {
14+
var listener, errListener = net.Listen("tcp", localAddr)
15+
if errListener != nil {
16+
var msg = fmt.Sprintf("resolving address %q: %v", localAddr, errListener)
17+
panic(msg)
18+
}
19+
var addr = listener.Addr()
20+
_ = listener.Close()
21+
var _, port, errSplit = net.SplitHostPort(addr.String())
22+
if errSplit != nil {
23+
var msg = fmt.Sprintf("parsing address %q: %v", addr, errSplit)
24+
panic(msg)
25+
}
26+
return "localhost:" + port
27+
}

gemax/server.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,18 @@ func (server *Server) init() {
4343
// ListenAndServe starts a TLS gemini server at specified server.
4444
func (server *Server) ListenAndServe(ctx context.Context, tlsCfg *tls.Config) error {
4545
server.init()
46-
var listener, errListener = tls.Listen("tcp", server.Addr, tlsCfg)
46+
ctx, cancel := context.WithCancel(ctx)
47+
defer cancel()
48+
var lc = net.ListenConfig{}
49+
var tcpListener, errListener = lc.Listen(ctx, "tcp", server.Addr)
4750
if errListener != nil {
4851
return fmt.Errorf("creating listener: %w", errListener)
4952
}
53+
var listener = tls.NewListener(tcpListener, tlsCfg)
54+
go func() {
55+
<-ctx.Done()
56+
_ = listener.Close()
57+
}()
5058
server.addListener(listener)
5159
defer ignoreErr(listener.Close)
5260
return server.Serve(ctx, listener)

gemax/server_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/ninedraft/gemax/gemax"
15+
"github.com/ninedraft/gemax/gemax/internal/testaddr"
1516
"github.com/ninedraft/gemax/gemax/status"
1617
)
1718

@@ -68,6 +69,35 @@ func TestServerInvalidHost(test *testing.T) {
6869
expectResponse(test, resp, "50 host not found\r\n")
6970
}
7071

72+
func TestServerCancelListen(test *testing.T) {
73+
var server = &gemax.Server{
74+
Addr: testaddr.Addr(),
75+
Logf: test.Logf,
76+
Handler: func(ctx context.Context, rw gemax.ResponseWriter, req gemax.IncomingRequest) {
77+
_, _ = io.WriteString(rw, "example text")
78+
},
79+
}
80+
test.Logf("loading test certs")
81+
var cert, errCert = tls.LoadX509KeyPair("testdata/cert.pem", "testdata/key.pem")
82+
if errCert != nil {
83+
test.Fatal(errCert)
84+
}
85+
var cfg = &tls.Config{
86+
MinVersion: tls.VersionTLS12,
87+
Certificates: []tls.Certificate{cert},
88+
}
89+
var ctx, cancel = context.WithCancel(context.Background())
90+
test.Cleanup(cancel)
91+
test.Logf("starting test server")
92+
test.Logf("test server: listening on %q", server.Addr)
93+
94+
time.AfterFunc(100*time.Millisecond, cancel)
95+
var err = server.ListenAndServe(ctx, cfg)
96+
if !errors.Is(err, net.ErrClosed) {
97+
test.Errorf("unexpected error %v, while %q is expected", err, net.ErrClosed)
98+
}
99+
}
100+
71101
func TestListenAndServe(test *testing.T) {
72102
var server = &gemax.Server{
73103
Addr: "localhost:40423",

0 commit comments

Comments
 (0)