Skip to content

Commit 6cfead9

Browse files
{auto} if connection.close() was called before the connection was set up, the instructions that were called between setting up the connection and the call to close() were lost. This forced users to always use the onConnected() handler to wait for the first instruction to be sent. But this is not according to the library design, so now the instructions that are given before the close() will be executed too;
1 parent 8ae54cc commit 6cfead9

File tree

3 files changed

+46
-8
lines changed

3 files changed

+46
-8
lines changed

include/connectionimpl.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@ class ConnectionImpl : public Watchable
4343
state_closing, // connection is busy closing (we have sent the close frame)
4444
state_closed // connection is closed
4545
} _state = state_protocol;
46-
46+
47+
/**
48+
* Has the close() method been called?
49+
* @var bool
50+
*/
51+
bool _closed = false;
52+
4753
/**
4854
* All channels that are active
4955
* @var map
@@ -85,6 +91,13 @@ class ConnectionImpl : public Watchable
8591
* @var queue
8692
*/
8793
std::queue<OutBuffer> _queue;
94+
95+
/**
96+
* Helper method to send the close frame
97+
* Return value tells if the connection is still valid
98+
* @return bool
99+
*/
100+
bool sendClose();
88101

89102

90103
private:

include/stringfield.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class StringField : public Field
8080
/**
8181
* Get the size this field will take when
8282
* encoded in the AMQP wire-frame format
83+
* @return size_t
8384
*/
8485
virtual size_t size() const override
8586
{

src/connectionimpl.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,28 @@ size_t ConnectionImpl::parse(char *buffer, size_t size)
157157
bool ConnectionImpl::close()
158158
{
159159
// leap out if already closed or closing
160-
if (_state == state_closed || _state == state_closing) return false;
160+
if (_closed) return false;
161161

162+
// mark that the object is closed
163+
_closed = true;
164+
165+
// if still busy with handshake, we delay closing for a while
166+
if (_state == state_handshake || _state == state_protocol) return true;
167+
168+
// perform the close operation
169+
sendClose();
170+
171+
// done
172+
return true;
173+
}
174+
175+
/**
176+
* Method to send the close frames
177+
* Returns true if object still exists
178+
* @return bool
179+
*/
180+
bool ConnectionImpl::sendClose()
181+
{
162182
// after the send operation the object could be dead
163183
Monitor monitor(this);
164184

@@ -169,14 +189,14 @@ bool ConnectionImpl::close()
169189
iter->second->close();
170190

171191
// we could be dead now
172-
if (!monitor.valid()) return true;
192+
if (!monitor.valid()) return false;
173193
}
174194

175195
// send the close frame
176-
if (!send(ConnectionCloseFrame(0, "shutdown"))) return false;
196+
send(ConnectionCloseFrame(0, "shutdown"));
177197

178198
// leap out if object no longer is alive
179-
if (!monitor.valid()) return true;
199+
if (!monitor.valid()) return false;
180200

181201
// we're in a new state
182202
_state = state_closing;
@@ -192,10 +212,14 @@ void ConnectionImpl::setConnected()
192212
{
193213
// store connected state
194214
_state = state_connected;
215+
216+
// if the close operation was already called, we do that again now again
217+
// so that the actual messages to close down the connection and the channel
218+
// are appended to the queue
219+
if (_closed && !sendClose()) return;
195220

196221
// we're going to call the handler, which can destruct the connection,
197-
// so we must monitor if the queue object is still valid after calling the
198-
// handler
222+
// so we must monitor if the queue object is still valid after calling
199223
Monitor monitor(this);
200224

201225
// inform handler
@@ -241,7 +265,7 @@ bool ConnectionImpl::send(const Frame &frame)
241265
if (frame.needsSeparator()) buffer.add((uint8_t)206);
242266

243267
// are we still setting up the connection?
244-
if (_state == state_connected || frame.partOfHandshake())
268+
if ((_state == state_connected && _queue.size() == 0) || frame.partOfHandshake())
245269
{
246270
// send the buffer
247271
_handler->onData(_parent, buffer.data(), buffer.size());

0 commit comments

Comments
 (0)