diff --git a/src/qamqpclient.cpp b/src/qamqpclient.cpp index 3d0df6c..d3ceb98 100644 --- a/src/qamqpclient.cpp +++ b/src/qamqpclient.cpp @@ -189,90 +189,87 @@ void ClientPrivate::_q_socketError(QAbstractSocket::SocketError error) void ClientPrivate::_q_readyRead() { while (socket->bytesAvailable() >= Frame::HEADER_SIZE) { - char headerData[Frame::HEADER_SIZE]; - socket->peek(headerData, Frame::HEADER_SIZE); - // FIXME: This is not the correct way of reading payloadSize - // gcc: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] - const quint32 payloadSize = qFromBigEndian(*(quint32*)&headerData[3]); + unsigned char headerData[Frame::HEADER_SIZE]; + socket->peek((char*)headerData, Frame::HEADER_SIZE); + const quint32 payloadSize = qFromBigEndian(headerData + 3); const qint64 readSize = Frame::HEADER_SIZE + payloadSize + Frame::FRAME_END_SIZE; - if (socket->bytesAvailable() >= readSize) { - buffer.resize(readSize); - socket->read(buffer.data(), readSize); - const char *bufferData = buffer.constData(); - const quint8 type = *(quint8*)&bufferData[0]; - const quint8 magic = *(quint8*)&bufferData[Frame::HEADER_SIZE + payloadSize]; - if (magic != Frame::FRAME_END) { - close(UnexpectedFrameError, "wrong end of frame"); + if (socket->bytesAvailable() < readSize) + return; + + buffer.resize(readSize); + socket->read(buffer.data(), readSize); + const char *bufferData = buffer.constData(); + const quint8 type = *(quint8*)&bufferData[0]; + const quint8 magic = *(quint8*)&bufferData[Frame::HEADER_SIZE + payloadSize]; + if (magic != Frame::FRAME_END) { + close(UnexpectedFrameError, "wrong end of frame"); + return; + } + + QDataStream streamB(&buffer, QIODevice::ReadOnly); + switch(Frame::Type(type)) { + case Frame::ftMethod: + { + Frame::Method frame(streamB); + if (frame.size() > frameMax) { + close(FrameError, "frame size too large"); return; } - QDataStream streamB(&buffer, QIODevice::ReadOnly); - switch(Frame::Type(type)) { - case Frame::ftMethod: - { - Frame::Method frame(streamB); - if (frame.size() > frameMax) { - close(FrameError, "frame size too large"); - return; - } - - if (frame.methodClass() == Frame::fcConnection) { - _q_method(frame); - } else { - foreach (Frame::MethodHandler *methodHandler, methodHandlersByChannel[frame.channel()]) - methodHandler->_q_method(frame); - } + if (frame.methodClass() == Frame::fcConnection) { + _q_method(frame); + } else { + foreach (Frame::MethodHandler *methodHandler, methodHandlersByChannel[frame.channel()]) + methodHandler->_q_method(frame); } - break; - case Frame::ftHeader: - { - Frame::Content frame(streamB); - if (frame.size() > frameMax) { - close(FrameError, "frame size too large"); - return; - } else if (frame.channel() <= 0) { - close(ChannelError, "channel number must be greater than zero"); - return; - } - - foreach (Frame::ContentHandler *methodHandler, contentHandlerByChannel[frame.channel()]) - methodHandler->_q_content(frame); - } - break; - case Frame::ftBody: - { - Frame::ContentBody frame(streamB); - if (frame.size() > frameMax) { - close(FrameError, "frame size too large"); - return; - } else if (frame.channel() <= 0) { - close(ChannelError, "channel number must be greater than zero"); - return; - } - - foreach (Frame::ContentBodyHandler *methodHandler, bodyHandlersByChannel[frame.channel()]) - methodHandler->_q_body(frame); - } - break; - case Frame::ftHeartbeat: - { - Frame::Method frame(streamB); - if (frame.channel() != 0) { - close(FrameError, "heartbeat must have channel id zero"); - return; - } - - qAmqpDebug("AMQP: Heartbeat"); - } - break; - default: - qAmqpDebug() << "AMQP: Unknown frame type: " << type; - close(FrameError, "invalid frame type"); - return; - } - } else { + } break; + case Frame::ftHeader: + { + Frame::Content frame(streamB); + if (frame.size() > frameMax) { + close(FrameError, "frame size too large"); + return; + } else if (frame.channel() <= 0) { + close(ChannelError, "channel number must be greater than zero"); + return; + } + + foreach (Frame::ContentHandler *methodHandler, contentHandlerByChannel[frame.channel()]) + methodHandler->_q_content(frame); + } + break; + case Frame::ftBody: + { + Frame::ContentBody frame(streamB); + if (frame.size() > frameMax) { + close(FrameError, "frame size too large"); + return; + } else if (frame.channel() <= 0) { + close(ChannelError, "channel number must be greater than zero"); + return; + } + + foreach (Frame::ContentBodyHandler *methodHandler, bodyHandlersByChannel[frame.channel()]) + methodHandler->_q_body(frame); + } + break; + case Frame::ftHeartbeat: + { + Frame::Method frame(streamB); + if (frame.channel() != 0) { + close(FrameError, "heartbeat must have channel id zero"); + return; + } + + qAmqpDebug("AMQP: Heartbeat"); + } + break; + default: + qAmqpDebug() << "AMQP: Unknown frame type: " << type; + close(FrameError, "invalid frame type"); + return; } } }