diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..a438335 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1 @@ +*.d diff --git a/src/Makefile b/src/Makefile index 595f856..673b82e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ CPP = g++ RM = rm -f -CPPFLAGS = -Wall -c -I. -std=c++11 +CPPFLAGS = -Wall -c -I. -std=c++11 -MD LD = g++ LD_FLAGS = -Wall -shared SHARED_LIB = lib$(LIBRARY_NAME).so.$(VERSION) @@ -8,6 +8,7 @@ STATIC_LIB = lib$(LIBRARY_NAME).a.$(VERSION) SOURCES = $(wildcard *.cpp) SHARED_OBJECTS = $(SOURCES:%.cpp=%.o) STATIC_OBJECTS = $(SOURCES:%.cpp=%.s.o) +DEPENDENCIES = $(SOURCES:%.cpp=%.d) PURE_SHARED_OBJECTS = $(filter-out tcpconnection.o, $(SOURCES:%.cpp=%.o)) PURE_STATIC_OBJECTS = $(filter-out tcpconnection.s.o, $(SOURCES:%.cpp=%.s.o)) @@ -18,6 +19,7 @@ else SONAMEPARAMETER = -soname endif +-include ${DEPENDENCIES} all: CPPFLAGS += -g all: LD_FLAGS += -g diff --git a/src/connectionimpl.cpp b/src/connectionimpl.cpp index 6541744..29da84e 100644 --- a/src/connectionimpl.cpp +++ b/src/connectionimpl.cpp @@ -3,7 +3,7 @@ * * Implementation of an AMQP connection * - * @copyright 2014 Copernica BV + * @copyright 2014 - 2016 Copernica BV */ #include "includes.h" #include "protocolheaderframe.h" diff --git a/src/receivedframe.cpp b/src/receivedframe.cpp index 2c08d12..71b6eab 100644 --- a/src/receivedframe.cpp +++ b/src/receivedframe.cpp @@ -86,9 +86,10 @@ namespace AMQP { */ ReceivedFrame::ReceivedFrame(const Buffer &buffer, uint32_t max) : _buffer(buffer) { - // we need enough room for type, channel, the payload size and the end-of-frame byte - if (buffer.size() < 8) return; - + // we need enough room for type, channel, the payload size, + // the the end-of-frame byte is not yet necessary + if (buffer.size() < 7) return; + // get the information _type = nextUint8(); _channel = nextUint16(); @@ -98,18 +99,13 @@ ReceivedFrame::ReceivedFrame(const Buffer &buffer, uint32_t max) : _buffer(buffe if (max > 0 && _payloadSize > max - 8) throw ProtocolException("frame size exceeded"); // check if the buffer is big enough to contain all data - if (buffer.size() >= _payloadSize + 8) - { - // buffer is big enough, check for a valid end-of-frame marker - if ((int)buffer.byte(_payloadSize+7) != END_OF_FRAME) throw ProtocolException("invalid end of frame marker"); - } - else - { - // frame is not yet valid - _type = TYPE_INVALID; - _channel = 0; - _payloadSize = 0; - } + if (!complete()) return; + + // buffer is big enough, check for a valid end-of-frame marker + if ((int)buffer.byte(_payloadSize+7) == END_OF_FRAME) return; + + // the frame is invalid because it does not end with the expected char + throw ProtocolException("invalid end of frame marker"); } /** @@ -127,7 +123,7 @@ bool ReceivedFrame::header() const */ bool ReceivedFrame::complete() const { - return _type != TYPE_INVALID; + return _buffer.size() >= _payloadSize + 8; } /** diff --git a/src/tcpconnected.h b/src/tcpconnected.h index 57ed133..b50b3b1 100644 --- a/src/tcpconnected.h +++ b/src/tcpconnected.h @@ -146,7 +146,7 @@ public: // are we in an error state? if (result < 0 && reportError()) return nextState(monitor); - + // we need a local copy of the buffer - because it is possible that "this" // object gets destructed halfway through the call to the parse() method TcpInBuffer buffer(std::move(_in)); @@ -161,7 +161,7 @@ public: buffer.shrink(processed); // restore the buffer as member - std::swap(_in, buffer); + _in = std::move(buffer); } // keep same object diff --git a/src/tcpinbuffer.h b/src/tcpinbuffer.h index 13cb070..65971ec 100644 --- a/src/tcpinbuffer.h +++ b/src/tcpinbuffer.h @@ -22,19 +22,13 @@ namespace AMQP { */ class TcpInBuffer : public ByteBuffer { -private: - /** - * Number of bytes already filled - * @var size_t - */ - size_t _filled = 0; - public: /** * Constructor - * @param size initial size + * Note that we pass 0 to the constructor because the buffer seems to be empty + * @param size initial size to allocated */ - TcpInBuffer(size_t size) : ByteBuffer((char *)malloc(size), size) {} + TcpInBuffer(size_t size) : ByteBuffer((char *)malloc(size), 0) {} /** * No copy'ing @@ -46,11 +40,7 @@ public: * Move constructor * @param that */ - TcpInBuffer(TcpInBuffer &&that) : ByteBuffer(std::move(that)), _filled(that._filled) - { - // reset other object - that._filled = 0; - } + TcpInBuffer(TcpInBuffer &&that) : ByteBuffer(std::move(that)) {} /** * Destructor @@ -70,14 +60,8 @@ public: // skip self-assignment if (this == &that) return *this; - // copy the filled paramteer - _filled = that._filled; - - // reset other object - that._filled = 0; - // call base - ByteBuffer::operator=(std::move(*this)); + ByteBuffer::operator=(std::move(that)); // done return *this; @@ -91,10 +75,7 @@ public: { // update data _data = (char *)realloc((void *)_data, size); - - // update size - _size = size; - } + } /** * Receive data from a socket @@ -109,19 +90,19 @@ public: // check the number of bytes that are available if (ioctl(socket, FIONREAD, &available) != 0) return -1; - + // if no bytes are available, it could mean that the connection was closed // by the remote client, so we do have to call read() anyway, assume a default buffer if (available == 0) available = 1; // number of bytes to read - size_t bytes = std::min(expected, available); + size_t bytes = std::min((uint32_t)(expected - _size), available); // read data into the buffer - auto result = read(socket, (void *)(_data + _filled), bytes); + auto result = read(socket, (void *)(_data + _size), bytes); // update total buffer size - if (result > 0) _filled += result; + if (result > 0) _size += result; // done return result; @@ -133,8 +114,8 @@ public: */ void shrink(size_t size) { - // update filled bytes - _filled -= size; + // update size + _size -= size; } }; diff --git a/tests/libev.cpp b/tests/libev.cpp index 06277f0..1bb610b 100644 --- a/tests/libev.cpp +++ b/tests/libev.cpp @@ -4,7 +4,7 @@ * Test program to check AMQP functionality based on LibEV * * @author Emiel Bruijntjes - * @copyright 2015 Copernica BV + * @copyright 2015 - 2016 Copernica BV */ /** @@ -27,7 +27,7 @@ int main() AMQP::LibEvHandler handler(loop); // make a connection - AMQP::TcpConnection connection(&handler, AMQP::Address("amqp://localhost/")); + AMQP::TcpConnection connection(&handler, AMQP::Address("amqp://guest:guest@localhost/")); // we need a channel too AMQP::TcpChannel channel(&connection);