1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
diff --git a/README.md b/README.md
index a06939182cbbf6b0d32724aef3336b6c77c1a3e3..bc382f43dba8b8e384fe2e2245075bb0799906be 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ |-------------------|---------------|-------------|----------|
| CAPABILITIES | mandatory | 🗸 | RFC3977 |
| HEAD | mandatory | 🗸 | RFC3977 |
| HELP | mandatory | 🗸 | RFC3977 |
-| QUIT | mandatory | ☓ | RFC3977 |
+| QUIT | mandatory | 🗸 | RFC3977 |
| STAT | mandatory | ☓ | RFC3977 |
| AUTHINFO USER | AUTHINFO USER | 🗸 | RFC4643 |
| AUTHINFO PASS | AUTHINFO USER | 🗸 | RFC4643 |
diff --git a/authinfo_test.go b/authinfo_test.go
index a54dcc279b4c0be6dd39ac804a6590e9f977f75f..0f7c7fb62722507c144bac0a869de26bfb426e0d 100644
--- a/authinfo_test.go
+++ b/authinfo_test.go
@@ -36,6 +36,7 @@ c, err := nntp.Dial(NewsServerPlain, nntp.OptionUnencrypted)
if err != nil {
t.Skipf("connection to '%s' failed: %v", NewsServerSecure, err)
}
+ defer c.Close(context.Background())
if test.passwordOverride == "" {
test.passwordOverride = NewsServerPassword
diff --git a/capabilities_test.go b/capabilities_test.go
index 519bcb853caaa7602a622fa2d1fe9108a438a879..3aa08d177a45b4986fcc86aadba22997e2e123b0 100644
--- a/capabilities_test.go
+++ b/capabilities_test.go
@@ -57,6 +57,7 @@ if err != nil {
t.Logf("failed to connect to host: %v", err)
t.SkipNow()
}
+ defer c.Close(context.Background())
err = test.preSteps(c)
if err != nil {
diff --git a/conn.go b/conn.go
index 455c002a21599a1362513cdc4511acf00c52132f..02db7d58ff8b086608d26b5add1b618c14752eb3 100644
--- a/conn.go
+++ b/conn.go
@@ -90,11 +90,16 @@ func (c *Conn) Close(ctx context.Context) error {
c.cancel()
defer c.c.Close()
- _, err := c.CmdNoBody(ctx, "QUIT")
+ resp, err := c.CmdNoBody(ctx, "QUIT")
if err != nil {
return fmt.Errorf("failed to send QUIT to server: %w", err)
}
- return nil
+ switch resp.Status.Code {
+ case StatusConnectionClosing:
+ return nil
+ default:
+ return ErrUnexpectedResponse
+ }
}
// Cmd runs a command on the given connection and does not parse headers
diff --git a/mandatory_test.go b/mandatory_test.go
index d97fe725e12639a4d88354443eca4e89e6fac8b8..6d96493b318c20c44b8ca3117bac9d406752483f 100644
--- a/mandatory_test.go
+++ b/mandatory_test.go
@@ -76,6 +76,7 @@ c, err := nntp.Dial(NewsServerPlain, nntp.OptionUnencrypted)
if err != nil {
t.Skipf("connection to '%s' failed: %v", NewsServerSecure, err)
}
+ defer c.Close(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
@@ -120,6 +121,7 @@ c, err := nntp.Dial(NewsServerPlain, nntp.OptionUnencrypted)
if err != nil {
t.Skipf("connection to '%s' failed: %v", NewsServerSecure, err)
}
+ defer c.Close(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
diff --git a/reader_test.go b/reader_test.go
index bf927953e9b669349ecffb8c3d436ac871b6b3f0..ad92bfb64fb5d9e5e8593b7957cac89609e9fe0e 100644
--- a/reader_test.go
+++ b/reader_test.go
@@ -37,6 +37,7 @@ c, err := nntp.Dial(NewsServerSecure)
if err != nil {
t.Skipf("connection to '%s' failed: %v", NewsServerSecure, err)
}
+ defer c.Close(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
diff --git a/status.go b/status.go
index b62a344a58fac463e2109568f4b5530792dba5f3..fb97f19682c7a797acf0abccc99e8129794f9dc8 100644
--- a/status.go
+++ b/status.go
@@ -6,6 +6,7 @@ const (
StatusHelpTextFollows = 100
StatusServiceAvailable = 200
StatusServiceNoPosting = 201
+ StatusConnectionClosing = 205
StatusGroupSelected = 211
StatusHeadersFollow = 221
StatusAuthAccepted = 281
|