2014-01-06 01:50:41 +08:00
|
|
|
/**
|
|
|
|
|
* Message.h
|
|
|
|
|
*
|
|
|
|
|
* An incoming message has the same sort of information as an outgoing
|
|
|
|
|
* message, plus some additional information.
|
|
|
|
|
*
|
|
|
|
|
* Message objects can not be constructed by end users, they are only constructed
|
2015-01-26 21:47:30 +08:00
|
|
|
* by the AMQP library, and passed to user callbacks.
|
2014-01-06 01:50:41 +08:00
|
|
|
*
|
2018-02-27 12:08:21 +08:00
|
|
|
* @copyright 2014 - 2018 Copernica BV
|
2014-01-06 01:50:41 +08:00
|
|
|
*/
|
|
|
|
|
|
2015-11-01 17:48:13 +08:00
|
|
|
/**
|
|
|
|
|
* Include guard
|
|
|
|
|
*/
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2016-06-23 20:42:50 +08:00
|
|
|
/**
|
|
|
|
|
* Dependencies
|
|
|
|
|
*/
|
|
|
|
|
#include "envelope.h"
|
|
|
|
|
#include <limits>
|
2016-07-01 16:07:01 +08:00
|
|
|
#include <stdexcept>
|
2018-01-23 23:47:53 +08:00
|
|
|
#include <algorithm>
|
2016-06-23 20:42:50 +08:00
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
/**
|
|
|
|
|
* Set up namespace
|
|
|
|
|
*/
|
2015-04-28 16:58:49 +08:00
|
|
|
namespace AMQP {
|
2014-01-06 01:50:41 +08:00
|
|
|
|
2016-06-23 20:42:50 +08:00
|
|
|
/**
|
|
|
|
|
* Forward declarations
|
|
|
|
|
*/
|
2018-02-27 12:08:21 +08:00
|
|
|
class DeferredReceiver;
|
2016-06-23 20:42:50 +08:00
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
/**
|
|
|
|
|
* Class definition
|
|
|
|
|
*/
|
|
|
|
|
class Message : public Envelope
|
|
|
|
|
{
|
2018-04-21 07:20:17 +08:00
|
|
|
private:
|
|
|
|
|
/**
|
|
|
|
|
* An allocated and mutable block of memory underlying _body
|
|
|
|
|
* @var char *
|
|
|
|
|
*/
|
|
|
|
|
char *_mutableBody = nullptr;
|
|
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
protected:
|
|
|
|
|
/**
|
|
|
|
|
* The exchange to which it was originally published
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
std::string _exchange;
|
2015-04-28 16:58:49 +08:00
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
/**
|
|
|
|
|
* The routing key that was originally used
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
2017-03-08 20:32:51 +08:00
|
|
|
std::string _routingkey;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Number of bytes already filled
|
|
|
|
|
* @var size_t
|
|
|
|
|
*/
|
|
|
|
|
size_t _filled = 0;
|
2015-04-28 16:58:49 +08:00
|
|
|
|
2017-03-08 20:32:51 +08:00
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
/**
|
2016-06-23 20:42:50 +08:00
|
|
|
* We are an open book to the consumer handler
|
|
|
|
|
*/
|
2018-02-27 12:08:21 +08:00
|
|
|
friend class DeferredReceiver;
|
2016-06-23 20:42:50 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the body size
|
|
|
|
|
* This field is set when the header is received
|
|
|
|
|
* @param uint64_t
|
|
|
|
|
*/
|
|
|
|
|
void setBodySize(uint64_t size)
|
|
|
|
|
{
|
|
|
|
|
// safety-check: on 32-bit platforms size_t is obviously also a 32-bit dword
|
|
|
|
|
// in which case casting the uint64_t to a size_t could result in truncation
|
|
|
|
|
// here we check whether the given size fits inside a size_t
|
|
|
|
|
if (std::numeric_limits<size_t>::max() < size) throw std::runtime_error("message is too big for this system");
|
|
|
|
|
|
|
|
|
|
// store the new size
|
|
|
|
|
_bodySize = size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Append data
|
|
|
|
|
* @param buffer incoming data
|
|
|
|
|
* @param size size of the data
|
|
|
|
|
* @return bool true if the message is now complete
|
|
|
|
|
*/
|
|
|
|
|
bool append(const char *buffer, uint64_t size)
|
|
|
|
|
{
|
2017-03-08 20:32:51 +08:00
|
|
|
// is the body already allocated?
|
2018-04-21 07:20:17 +08:00
|
|
|
if (_mutableBody)
|
2016-06-23 20:42:50 +08:00
|
|
|
{
|
2017-03-08 20:32:51 +08:00
|
|
|
// prevent overflow
|
|
|
|
|
size = std::min(size, _bodySize - _filled);
|
|
|
|
|
|
|
|
|
|
// append more data
|
2018-04-21 07:20:17 +08:00
|
|
|
memcpy(_mutableBody + _filled, buffer, (size_t)size);
|
2017-03-08 20:32:51 +08:00
|
|
|
|
|
|
|
|
// update filled data
|
2018-01-24 07:38:07 +08:00
|
|
|
_filled += (size_t)size;
|
2017-03-08 20:32:51 +08:00
|
|
|
}
|
|
|
|
|
else if (size >= _bodySize)
|
|
|
|
|
{
|
|
|
|
|
// we do not have to combine multiple frames, so we can store
|
|
|
|
|
// the buffer pointer in the message
|
2018-04-21 07:20:17 +08:00
|
|
|
_body = buffer;
|
2016-06-23 20:42:50 +08:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-03-08 20:32:51 +08:00
|
|
|
// allocate the buffer
|
2018-04-21 07:20:17 +08:00
|
|
|
_mutableBody = (char *)malloc((size_t)_bodySize);
|
2017-03-08 20:32:51 +08:00
|
|
|
|
2018-04-21 07:20:17 +08:00
|
|
|
// expose the body in its immutable form
|
|
|
|
|
_body = _mutableBody;
|
2017-03-08 20:32:51 +08:00
|
|
|
|
2018-04-21 07:20:17 +08:00
|
|
|
// store the initial data
|
2018-01-24 07:38:07 +08:00
|
|
|
_filled = std::min((size_t)size, (size_t)_bodySize);
|
2018-04-21 07:20:17 +08:00
|
|
|
memcpy(_mutableBody, buffer, _filled);
|
2016-06-23 20:42:50 +08:00
|
|
|
}
|
2017-03-08 20:32:51 +08:00
|
|
|
|
|
|
|
|
// check if we're done
|
|
|
|
|
return _filled >= _bodySize;
|
2016-06-23 20:42:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* Constructor
|
|
|
|
|
*
|
2014-01-06 01:50:41 +08:00
|
|
|
* @param exchange
|
|
|
|
|
* @param routingKey
|
|
|
|
|
*/
|
2017-03-08 20:32:51 +08:00
|
|
|
Message(std::string exchange, std::string routingkey) :
|
|
|
|
|
Envelope(nullptr, 0), _exchange(std::move(exchange)), _routingkey(std::move(routingkey))
|
2014-01-06 01:50:41 +08:00
|
|
|
{}
|
2015-04-28 16:58:49 +08:00
|
|
|
|
|
|
|
|
/**
|
2017-03-08 20:32:51 +08:00
|
|
|
* Disabled copy constructor
|
2015-04-28 16:58:49 +08:00
|
|
|
* @param message the message to copy
|
|
|
|
|
*/
|
2017-03-08 20:32:51 +08:00
|
|
|
Message(const Message &message) = delete;
|
2015-04-28 16:58:49 +08:00
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
/**
|
|
|
|
|
* Destructor
|
|
|
|
|
*/
|
2018-04-21 07:20:17 +08:00
|
|
|
virtual ~Message()
|
|
|
|
|
{
|
|
|
|
|
if (_mutableBody) free(_mutableBody);
|
|
|
|
|
}
|
2014-01-06 01:50:41 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The exchange to which it was originally published
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
2014-01-06 04:21:09 +08:00
|
|
|
const std::string &exchange() const
|
2014-01-06 01:50:41 +08:00
|
|
|
{
|
2017-03-08 20:32:51 +08:00
|
|
|
// expose member
|
2014-01-06 01:50:41 +08:00
|
|
|
return _exchange;
|
|
|
|
|
}
|
2015-04-28 16:58:49 +08:00
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
/**
|
|
|
|
|
* The routing key that was originally used
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
2017-03-08 20:32:51 +08:00
|
|
|
const std::string &routingkey() const
|
2014-01-06 01:50:41 +08:00
|
|
|
{
|
2017-03-08 20:32:51 +08:00
|
|
|
// expose member
|
|
|
|
|
return _routingkey;
|
2014-01-06 01:50:41 +08:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* End of namespace
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|