A correction to the previous commit.
[stompngo.git] / disconnect.go
blobb1e3b86c3cbd7adb842ec89260670332a9d8b93e
1 //
2 // Copyright © 2011-2019 Guy M. Allard
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
17 package stompngo
19 import "fmt"
22 Disconnect from a STOMP broker.
24 Shut down heart beats if necessary.
25 Set connection status to false to disable further actions with this
26 connection.
29 Obtain a receipt unless the client specifically indicates a receipt request
30 should be excluded. If the client actually asks for a receipt, use the
31 supplied receipt id. Otherwise generate a unique receipt id and add that
32 to the DISCONNECT headers.
34 Example:
35 h := stompngo.Headers{HK_RECEIPT, "receipt-id1"} // Ask for a receipt
36 e := c.Disconnect(h)
37 if e != nil {
38 // Do something sane ...
40 fmt.Printf("%q\n", c.DisconnectReceipt)
41 // Or:
42 h := stompngo.Headers{"noreceipt", "true"} // Ask for a receipt
43 e := c.Disconnect(h)
44 if e != nil {
45 // Do something sane ...
47 fmt.Printf("%q\n", c.DisconnectReceipt)
50 func (c *Connection) Disconnect(h Headers) error {
51 c.discLock.Lock()
52 defer c.discLock.Unlock()
54 if !c.isConnected() {
55 return ECONBAD
57 c.log(DISCONNECT, "start", h)
58 e := checkHeaders(h, c.Protocol())
59 if e != nil {
60 return e
62 ch := h.Clone()
63 // If the caller does not want a receipt do not ask for one. Otherwise,
64 // add a receipt request if caller did not specifically ask for one. This is
65 // in the spirit of the specification, and allows reasonable resource cleanup
66 // in both the client and the message broker.
67 _, cwr := ch.Contains("noreceipt")
68 if !cwr {
69 if _, ok := ch.Contains(HK_RECEIPT); !ok {
70 ch = append(ch, HK_RECEIPT, Uuid())
73 wrid := ""
74 wrid, _ = ch.Contains(HK_RECEIPT)
75 _ = wrid
77 f := Frame{DISCONNECT, ch, NULLBUFF}
79 r := make(chan error)
80 if e = c.writeWireData(wiredata{f, r}); e != nil {
81 return e
83 e = <-r
84 // Drive shutdown logic
85 // Only set DisconnectReceipt if we sucessfully received one, and it is
86 // the one we were expecting.
87 if !cwr && e == nil {
88 // Can be RECEIPT or ERROR frame
89 mds := <-c.input
91 // fmt.Println(DISCONNECT, "sanchek", mds)
93 switch mds.Message.Command {
94 case ERROR:
95 e = fmt.Errorf("DISBRKERR -> %q", mds.Message)
96 c.log(DISCONNECT, "errf", e)
97 case RECEIPT:
98 gr := mds.Message.Headers.Value(HK_RECEIPT_ID)
99 if wrid != gr {
100 e = fmt.Errorf("%s wanted:%s got:%s", EBADRID, wrid, gr)
101 c.log(DISCONNECT, "nadrid", e)
102 } else {
103 c.DisconnectReceipt = mds
105 default:
106 e = fmt.Errorf("DISBADFRM -> %q", mds.Message)
107 c.log(DISCONNECT, "badf", e)
110 c.log(DISCONNECT, "ends", ch)
111 c.shutdown()
112 c.sysAbort()
113 c.log(DISCONNECT, "system shutdown cannel closed")
114 return e