Fixed a bug where a frame could be sent exceeding the maximum frame size (resulting in protocol errors) and added some optimizations
This commit is contained in:
parent
b9caf0199d
commit
45deeaa754
|
|
@ -13,6 +13,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,9 @@ protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All channels that are active
|
* All channels that are active
|
||||||
* @var map
|
* @var std::unordered_map<uint16_t, std::shared_ptr<ChannelImpl>>
|
||||||
*/
|
*/
|
||||||
std::map<uint16_t, std::shared_ptr<ChannelImpl>> _channels;
|
std::unordered_map<uint16_t, std::shared_ptr<ChannelImpl>> _channels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last unused channel ID
|
* The last unused channel ID
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,23 @@ public:
|
||||||
void setTimestamp (uint64_t value) { _timestamp = value; _bools2.set(6,true); }
|
void setTimestamp (uint64_t value) { _timestamp = value; _bools2.set(6,true); }
|
||||||
void setMessageID (const std::string &value) { _messageID = value; _bools2.set(7,true); }
|
void setMessageID (const std::string &value) { _messageID = value; _bools2.set(7,true); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the various supported fields using r-value references
|
||||||
|
*
|
||||||
|
* @param value moveable value
|
||||||
|
*/
|
||||||
|
void setExpiration (std::string &&value) { _expiration = std::move(value); _bools1.set(0,true); }
|
||||||
|
void setReplyTo (std::string &&value) { _replyTo = std::move(value); _bools1.set(1,true); }
|
||||||
|
void setCorrelationID (std::string &&value) { _correlationID = std::move(value); _bools1.set(2,true); }
|
||||||
|
void setHeaders (Table &&value) { _headers = std::move(value); _bools1.set(5,true); }
|
||||||
|
void setContentEncoding (std::string &&value) { _contentEncoding = std::move(value); _bools1.set(6,true); }
|
||||||
|
void setContentType (std::string &&value) { _contentType = std::move(value); _bools1.set(7,true); }
|
||||||
|
void setClusterID (std::string &&value) { _clusterID = std::move(value); _bools2.set(2,true); }
|
||||||
|
void setAppID (std::string &&value) { _appID = std::move(value); _bools2.set(3,true); }
|
||||||
|
void setUserID (std::string &&value) { _userID = std::move(value); _bools2.set(4,true); }
|
||||||
|
void setTypeName (std::string &&value) { _typeName = std::move(value); _bools2.set(5,true); }
|
||||||
|
void setMessageID (std::string &&value) { _messageID = std::move(value); _bools2.set(7,true); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the fields
|
* Retrieve the fields
|
||||||
* @return string
|
* @return string
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,9 @@ class OutBuffer
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Pointer to the beginning of the buffer
|
* Pointer to the beginning of the buffer
|
||||||
* @var char*
|
* @var std::unique_ptr<char[]>
|
||||||
*/
|
*/
|
||||||
char *_buffer;
|
std::unique_ptr<char[]> _buffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the buffer to be filled
|
* Pointer to the buffer to be filled
|
||||||
|
|
@ -49,56 +49,47 @@ public:
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param capacity
|
* @param capacity
|
||||||
*/
|
*/
|
||||||
OutBuffer(uint32_t capacity)
|
OutBuffer(uint32_t capacity) :
|
||||||
{
|
_buffer(new char[capacity]),
|
||||||
// initialize members
|
_current(_buffer.get()),
|
||||||
_size = 0;
|
_size(0),
|
||||||
_capacity = capacity;
|
_capacity(capacity)
|
||||||
_buffer = _current = new char[capacity];
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy constructor
|
* Copy constructor
|
||||||
* @param that
|
* @param that
|
||||||
*/
|
*/
|
||||||
OutBuffer(const OutBuffer &that)
|
OutBuffer(const OutBuffer &that) :
|
||||||
|
_buffer(new char[that._capacity]),
|
||||||
|
_current(_buffer.get() + that._size),
|
||||||
|
_size(that._size),
|
||||||
|
_capacity(that._capacity)
|
||||||
{
|
{
|
||||||
// initialize members
|
|
||||||
_size = that._size;
|
|
||||||
_capacity = that._capacity;
|
|
||||||
_buffer = new char[_capacity];
|
|
||||||
_current = _buffer + _size;
|
|
||||||
|
|
||||||
// copy memory
|
// copy memory
|
||||||
memcpy(_buffer, that._buffer, _size);
|
memcpy(_buffer.get(), that._buffer.get(), _size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move constructor
|
* Move constructor
|
||||||
* @param that
|
* @param that
|
||||||
*/
|
*/
|
||||||
OutBuffer(OutBuffer &&that)
|
OutBuffer(OutBuffer &&that) :
|
||||||
|
_buffer(std::move(that._buffer)),
|
||||||
|
_current(that._current),
|
||||||
|
_size(that._size),
|
||||||
|
_capacity(that._capacity)
|
||||||
{
|
{
|
||||||
// copy all members
|
|
||||||
_size = that._size;
|
|
||||||
_capacity = that._capacity;
|
|
||||||
_buffer = that._buffer;
|
|
||||||
_current = that._current;
|
|
||||||
|
|
||||||
// reset the other object
|
// reset the other object
|
||||||
that._size = 0;
|
that._size = 0;
|
||||||
that._capacity = 0;
|
that._capacity = 0;
|
||||||
that._buffer = nullptr;
|
|
||||||
that._current = nullptr;
|
that._current = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor
|
* Destructor
|
||||||
*/
|
*/
|
||||||
virtual ~OutBuffer()
|
virtual ~OutBuffer() {}
|
||||||
{
|
|
||||||
if (_buffer) delete[] _buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get access to the internal buffer
|
* Get access to the internal buffer
|
||||||
|
|
@ -106,7 +97,7 @@ public:
|
||||||
*/
|
*/
|
||||||
const char *data() const
|
const char *data() const
|
||||||
{
|
{
|
||||||
return _buffer;
|
return _buffer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,14 @@ public:
|
||||||
*
|
*
|
||||||
* @param value string value
|
* @param value string value
|
||||||
*/
|
*/
|
||||||
StringField(std::string value) : _data(value) {}
|
StringField(const std::string &value) : _data(value) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct based on a std::string
|
||||||
|
*
|
||||||
|
* @param value string value
|
||||||
|
*/
|
||||||
|
StringField(std::string &&value) : _data(std::move(value)) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct based on received data
|
* Construct based on received data
|
||||||
|
|
@ -69,7 +76,7 @@ public:
|
||||||
*
|
*
|
||||||
* @param value new value
|
* @param value new value
|
||||||
*/
|
*/
|
||||||
StringField& operator=(const std::string& value)
|
StringField& operator=(const std::string &value)
|
||||||
{
|
{
|
||||||
// overwrite data
|
// overwrite data
|
||||||
_data = value;
|
_data = value;
|
||||||
|
|
@ -78,6 +85,20 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign a new value
|
||||||
|
*
|
||||||
|
* @param value new value
|
||||||
|
*/
|
||||||
|
StringField& operator=(std::string &&value)
|
||||||
|
{
|
||||||
|
// overwrite data
|
||||||
|
_data = std::move(value);
|
||||||
|
|
||||||
|
// allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the size this field will take when
|
* Get the size this field will take when
|
||||||
* encoded in the AMQP wire-frame format
|
* encoded in the AMQP wire-frame format
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,10 @@ bool ConnectionImpl::send(const Frame &frame)
|
||||||
// some frames can be sent _after_ the close() function was called
|
// some frames can be sent _after_ the close() function was called
|
||||||
if (_closed && !frame.partOfShutdown()) return false;
|
if (_closed && !frame.partOfShutdown()) return false;
|
||||||
|
|
||||||
|
// if the frame is bigger than we allow on the connection
|
||||||
|
// it is impossible to send out this frame successfully
|
||||||
|
if (frame.totalSize() > _maxFrame) return false;
|
||||||
|
|
||||||
// we need an output buffer
|
// we need an output buffer
|
||||||
OutBuffer buffer(frame.buffer());
|
OutBuffer buffer(frame.buffer());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,10 @@ Table::Table(const Table &table)
|
||||||
// loop through the table records
|
// loop through the table records
|
||||||
for (auto iter = table._fields.begin(); iter != table._fields.end(); iter++)
|
for (auto iter = table._fields.begin(); iter != table._fields.end(); iter++)
|
||||||
{
|
{
|
||||||
// add the field
|
// since a map is always ordered, we know that each element will
|
||||||
_fields[iter->first] = std::shared_ptr<Field>(iter->second->clone());
|
// be inserted at the end of the new map, so we can simply use
|
||||||
|
// emplace_hint and hint at insertion at the end of the map
|
||||||
|
_fields.emplace_hint(_fields.end(), std::make_pair(iter->first, iter->second->clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue