diff options
author | Alan Conway <aconway@apache.org> | 2007-03-21 02:08:18 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2007-03-21 02:08:18 +0000 |
commit | d2eb3361494710466280341c98f76c03536d2ebe (patch) | |
tree | f16ec2eacd8383e388657e54a22fc0214a0ce023 /qpid/cpp/lib/common/framing | |
parent | 732544fe86089ab86c03fcc48d5ca4c72667c275 (diff) | |
download | qpid-python-d2eb3361494710466280341c98f76c03536d2ebe.tar.gz |
Renamed cpp-0-9 to cpp
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@520706 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/cpp/lib/common/framing')
53 files changed, 3567 insertions, 0 deletions
diff --git a/qpid/cpp/lib/common/framing/AMQBody.cpp b/qpid/cpp/lib/common/framing/AMQBody.cpp new file mode 100644 index 0000000000..c7c253beda --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQBody.cpp @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include <AMQBody.h> +#include <iostream> + +std::ostream& qpid::framing::operator<<(std::ostream& out, const qpid::framing::AMQBody& body) +{ + body.print(out); + return out; +} + +qpid::framing::AMQBody::~AMQBody() {} + + diff --git a/qpid/cpp/lib/common/framing/AMQBody.h b/qpid/cpp/lib/common/framing/AMQBody.h new file mode 100644 index 0000000000..26076956ca --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQBody.h @@ -0,0 +1,59 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <boost/shared_ptr.hpp> +#include <amqp_types.h> +#include <Buffer.h> + +#ifndef _AMQBody_ +#define _AMQBody_ + +namespace qpid { + namespace framing { + + class AMQBody + { + public: + typedef boost::shared_ptr<AMQBody> shared_ptr; + + virtual ~AMQBody(); + virtual uint32_t size() const = 0; + virtual uint8_t type() const = 0; + virtual void encode(Buffer& buffer) const = 0; + virtual void decode(Buffer& buffer, uint32_t size) = 0; + + virtual void print(std::ostream& out) const = 0; + }; + + std::ostream& operator<<(std::ostream& out, const AMQBody& body) ; + + enum BodyTypes { + METHOD_BODY = 1, + HEADER_BODY = 2, + CONTENT_BODY = 3, + HEARTBEAT_BODY = 8, + REQUEST_BODY = 9, + RESPONSE_BODY = 10 + }; + } +} + + +#endif diff --git a/qpid/cpp/lib/common/framing/AMQContentBody.cpp b/qpid/cpp/lib/common/framing/AMQContentBody.cpp new file mode 100644 index 0000000000..573c17dade --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQContentBody.cpp @@ -0,0 +1,43 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <AMQContentBody.h> +#include <iostream> + +qpid::framing::AMQContentBody::AMQContentBody(){ +} + +qpid::framing::AMQContentBody::AMQContentBody(const string& _data) : data(_data){ +} + +uint32_t qpid::framing::AMQContentBody::size() const{ + return data.size(); +} +void qpid::framing::AMQContentBody::encode(Buffer& buffer) const{ + buffer.putRawData(data); +} +void qpid::framing::AMQContentBody::decode(Buffer& buffer, uint32_t _size){ + buffer.getRawData(data, _size); +} + +void qpid::framing::AMQContentBody::print(std::ostream& out) const +{ + out << "content (" << size() << " bytes)"; +} diff --git a/qpid/cpp/lib/common/framing/AMQContentBody.h b/qpid/cpp/lib/common/framing/AMQContentBody.h new file mode 100644 index 0000000000..c9fa7cde5c --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQContentBody.h @@ -0,0 +1,53 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <amqp_types.h> +#include <AMQBody.h> +#include <Buffer.h> + +#ifndef _AMQContentBody_ +#define _AMQContentBody_ + +namespace qpid { +namespace framing { + +class AMQContentBody : public AMQBody +{ + string data; + +public: + typedef boost::shared_ptr<AMQContentBody> shared_ptr; + + AMQContentBody(); + AMQContentBody(const string& data); + inline virtual ~AMQContentBody(){} + inline uint8_t type() const { return CONTENT_BODY; }; + inline string& getData(){ return data; } + uint32_t size() const; + void encode(Buffer& buffer) const; + void decode(Buffer& buffer, uint32_t size); + void print(std::ostream& out) const; +}; + +} +} + + +#endif diff --git a/qpid/cpp/lib/common/framing/AMQDataBlock.h b/qpid/cpp/lib/common/framing/AMQDataBlock.h new file mode 100644 index 0000000000..2a6f843f1e --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQDataBlock.h @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <Buffer.h> + +#ifndef _AMQDataBlock_ +#define _AMQDataBlock_ + +namespace qpid { +namespace framing { + +class AMQDataBlock +{ +public: + virtual ~AMQDataBlock() {} + virtual void encode(Buffer& buffer) = 0; + virtual bool decode(Buffer& buffer) = 0; + virtual uint32_t size() const = 0; +}; + +} +} + + +#endif diff --git a/qpid/cpp/lib/common/framing/AMQFrame.cpp b/qpid/cpp/lib/common/framing/AMQFrame.cpp new file mode 100644 index 0000000000..bc9061b169 --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQFrame.cpp @@ -0,0 +1,139 @@ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <boost/format.hpp> + +#include <AMQFrame.h> +#include <QpidError.h> +#include "AMQRequestBody.h" +#include "AMQResponseBody.h" + + +namespace qpid { +namespace framing { + + +AMQP_MethodVersionMap AMQFrame::versionMap; + +AMQFrame::AMQFrame(ProtocolVersion _version): +version(_version) + { + assert(version != ProtocolVersion(0,0)); + } + +AMQFrame::AMQFrame(ProtocolVersion _version, uint16_t _channel, AMQBody* _body) : +version(_version), channel(_channel), body(_body) +{} + +AMQFrame::AMQFrame(ProtocolVersion _version, uint16_t _channel, const AMQBody::shared_ptr& _body) : +version(_version), channel(_channel), body(_body) +{} + +AMQFrame::~AMQFrame() {} + +uint16_t AMQFrame::getChannel(){ + return channel; +} + +AMQBody::shared_ptr AMQFrame::getBody(){ + return body; +} + +void AMQFrame::encode(Buffer& buffer) +{ + buffer.putOctet(body->type()); + buffer.putShort(channel); + buffer.putLong(body->size()); + body->encode(buffer); + buffer.putOctet(0xCE); +} + +uint32_t AMQFrame::size() const{ + assert(body.get()); + return 1/*type*/ + 2/*channel*/ + 4/*body size*/ + body->size() + + 1/*0xCE*/; +} + +bool AMQFrame::decode(Buffer& buffer) +{ + if(buffer.available() < 7) + return false; + buffer.record(); + uint32_t frameSize = decodeHead(buffer); + if(buffer.available() < frameSize + 1){ + buffer.restore(); + return false; + } + decodeBody(buffer, frameSize); + uint8_t end = buffer.getOctet(); + if(end != 0xCE) THROW_QPID_ERROR(FRAMING_ERROR, "Frame end not found"); + return true; +} + +uint32_t AMQFrame::decodeHead(Buffer& buffer){ + type = buffer.getOctet(); + channel = buffer.getShort(); + return buffer.getLong(); +} + +void AMQFrame::decodeBody(Buffer& buffer, uint32_t size) +{ + switch(type) + { + case METHOD_BODY: + body = AMQMethodBody::create(versionMap, version, buffer); + break; + case REQUEST_BODY: + body = AMQRequestBody::create(versionMap, version, buffer); + break; + case RESPONSE_BODY: + body = AMQResponseBody::create(versionMap, version, buffer); + break; + case HEADER_BODY: + body = AMQBody::shared_ptr(new AMQHeaderBody()); + break; + case CONTENT_BODY: + body = AMQBody::shared_ptr(new AMQContentBody()); + break; + case HEARTBEAT_BODY: + body = AMQBody::shared_ptr(new AMQHeartbeatBody()); + break; + default: + THROW_QPID_ERROR( + FRAMING_ERROR, + boost::format("Unknown frame type %d") % type); + } + body->decode(buffer, size); +} + +std::ostream& operator<<(std::ostream& out, const AMQFrame& t) +{ + out << "Frame[channel=" << t.channel << "; "; + if (t.body.get() == 0) + out << "empty"; + else + out << *t.body; + out << "]"; + return out; +} + + +}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/AMQFrame.h b/qpid/cpp/lib/common/framing/AMQFrame.h new file mode 100644 index 0000000000..0c18e0c2a5 --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQFrame.h @@ -0,0 +1,78 @@ +#ifndef _AMQFrame_ +#define _AMQFrame_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <boost/cast.hpp> + +#include <amqp_types.h> +#include <AMQBody.h> +#include <AMQDataBlock.h> +#include <AMQMethodBody.h> +#include <AMQHeaderBody.h> +#include <AMQContentBody.h> +#include <AMQHeartbeatBody.h> +#include <AMQP_MethodVersionMap.h> +#include <AMQP_HighestVersion.h> +#include <Buffer.h> + +namespace qpid { +namespace framing { + + +class AMQFrame : public AMQDataBlock +{ + public: + AMQFrame(ProtocolVersion _version = highestProtocolVersion); + AMQFrame(ProtocolVersion _version, uint16_t channel, AMQBody* body); + AMQFrame(ProtocolVersion _version, uint16_t channel, const AMQBody::shared_ptr& body); + virtual ~AMQFrame(); + virtual void encode(Buffer& buffer); + virtual bool decode(Buffer& buffer); + virtual uint32_t size() const; + uint16_t getChannel(); + AMQBody::shared_ptr getBody(); + + /** Convenience template to cast the body to an expected type */ + template <class T> boost::shared_ptr<T> castBody() { + assert(dynamic_cast<T*>(getBody().get())); + boost::static_pointer_cast<T>(getBody()); + } + + uint32_t decodeHead(Buffer& buffer); + void decodeBody(Buffer& buffer, uint32_t size); + + private: + static AMQP_MethodVersionMap versionMap; + ProtocolVersion version; + + uint16_t channel; + uint8_t type; + AMQBody::shared_ptr body; + + + friend std::ostream& operator<<(std::ostream& out, const AMQFrame& body); +}; + +}} // namespace qpid::framing + + +#endif diff --git a/qpid/cpp/lib/common/framing/AMQHeaderBody.cpp b/qpid/cpp/lib/common/framing/AMQHeaderBody.cpp new file mode 100644 index 0000000000..3ddae4eebf --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQHeaderBody.cpp @@ -0,0 +1,75 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <AMQHeaderBody.h> +#include <QpidError.h> +#include <BasicHeaderProperties.h> + +qpid::framing::AMQHeaderBody::AMQHeaderBody(int classId) : weight(0), contentSize(0){ + createProperties(classId); +} + +qpid::framing::AMQHeaderBody::AMQHeaderBody() : properties(0), weight(0), contentSize(0){ +} + +qpid::framing::AMQHeaderBody::~AMQHeaderBody(){ + delete properties; +} + +uint32_t qpid::framing::AMQHeaderBody::size() const{ + return 12 + properties->size(); +} + +void qpid::framing::AMQHeaderBody::encode(Buffer& buffer) const { + buffer.putShort(properties->classId()); + buffer.putShort(weight); + buffer.putLongLong(contentSize); + properties->encode(buffer); +} + +void qpid::framing::AMQHeaderBody::decode(Buffer& buffer, uint32_t bufSize){ + uint16_t classId = buffer.getShort(); + weight = buffer.getShort(); + contentSize = buffer.getLongLong(); + createProperties(classId); + properties->decode(buffer, bufSize - 12); +} + +void qpid::framing::AMQHeaderBody::createProperties(int classId){ + switch(classId){ + case BASIC: + properties = new qpid::framing::BasicHeaderProperties(); + break; + default: + THROW_QPID_ERROR(FRAMING_ERROR, "Unknown header class"); + } +} + +void qpid::framing::AMQHeaderBody::print(std::ostream& out) const +{ + out << "header (" << size() << " bytes)" << " content_size=" << getContentSize(); + const BasicHeaderProperties* props = + dynamic_cast<const BasicHeaderProperties*>(getProperties()); + if (props) { + out << ", message_id=" << props->getMessageId(); + out << ", delivery_mode=" << (int) props->getDeliveryMode(); + out << ", headers=" << const_cast<BasicHeaderProperties*>(props)->getHeaders(); + } +} diff --git a/qpid/cpp/lib/common/framing/AMQHeaderBody.h b/qpid/cpp/lib/common/framing/AMQHeaderBody.h new file mode 100644 index 0000000000..d57f93aacd --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQHeaderBody.h @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <amqp_types.h> +#include <AMQBody.h> +#include <Buffer.h> +#include <HeaderProperties.h> + +#ifndef _AMQHeaderBody_ +#define _AMQHeaderBody_ + +namespace qpid { +namespace framing { + +class AMQHeaderBody : public AMQBody +{ + HeaderProperties* properties; + uint16_t weight; + uint64_t contentSize; + + void createProperties(int classId); +public: + typedef boost::shared_ptr<AMQHeaderBody> shared_ptr; + + AMQHeaderBody(int classId); + AMQHeaderBody(); + inline uint8_t type() const { return HEADER_BODY; } + HeaderProperties* getProperties(){ return properties; } + const HeaderProperties* getProperties() const { return properties; } + inline uint64_t getContentSize() const { return contentSize; } + inline void setContentSize(uint64_t _size) { contentSize = _size; } + virtual ~AMQHeaderBody(); + virtual uint32_t size() const; + virtual void encode(Buffer& buffer) const; + virtual void decode(Buffer& buffer, uint32_t size); + virtual void print(std::ostream& out) const; +}; + +} +} + + +#endif diff --git a/qpid/cpp/lib/common/framing/AMQHeartbeatBody.cpp b/qpid/cpp/lib/common/framing/AMQHeartbeatBody.cpp new file mode 100644 index 0000000000..63f83a3d29 --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQHeartbeatBody.cpp @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include <AMQHeartbeatBody.h> +#include <iostream> + +qpid::framing::AMQHeartbeatBody::~AMQHeartbeatBody() {} + +void qpid::framing::AMQHeartbeatBody::print(std::ostream& out) const { + out << "heartbeat"; +} diff --git a/qpid/cpp/lib/common/framing/AMQHeartbeatBody.h b/qpid/cpp/lib/common/framing/AMQHeartbeatBody.h new file mode 100644 index 0000000000..a3e9d823f1 --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQHeartbeatBody.h @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <amqp_types.h> +#include <AMQBody.h> +#include <Buffer.h> + +#ifndef _AMQHeartbeatBody_ +#define _AMQHeartbeatBody_ + +namespace qpid { +namespace framing { + +class AMQHeartbeatBody : public AMQBody +{ +public: + typedef boost::shared_ptr<AMQHeartbeatBody> shared_ptr; + + virtual ~AMQHeartbeatBody(); + inline uint32_t size() const { return 0; } + inline uint8_t type() const { return HEARTBEAT_BODY; } + inline void encode(Buffer& ) const {} + inline void decode(Buffer& , uint32_t /*size*/) {} + virtual void print(std::ostream& out) const; +}; + +} +} + +#endif diff --git a/qpid/cpp/lib/common/framing/AMQMethodBody.cpp b/qpid/cpp/lib/common/framing/AMQMethodBody.cpp new file mode 100644 index 0000000000..23502068f5 --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQMethodBody.cpp @@ -0,0 +1,59 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <AMQFrame.h> +#include <AMQMethodBody.h> +#include <QpidError.h> +#include "AMQP_MethodVersionMap.h" + +namespace qpid { +namespace framing { + +void AMQMethodBody::encodeId(Buffer& buffer) const{ + buffer.putShort(amqpClassId()); + buffer.putShort(amqpMethodId()); +} + +void AMQMethodBody::invoke(AMQP_ServerOperations&, const MethodContext&){ + assert(0); + THROW_QPID_ERROR(PROTOCOL_ERROR, "Method not supported by AMQP Server."); +} + +AMQMethodBody::shared_ptr AMQMethodBody::create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer) +{ + ClassMethodId id; + id.decode(buffer); + return AMQMethodBody::shared_ptr( + versionMap.createMethodBody( + id.classId, id.methodId, version.getMajor(), version.getMinor())); +} + +void AMQMethodBody::ClassMethodId::decode(Buffer& buffer) { + classId = buffer.getShort(); + methodId = buffer.getShort(); +} + +void AMQMethodBody::decode(Buffer& buffer, uint32_t /*size*/) { + decodeContent(buffer); +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/AMQMethodBody.h b/qpid/cpp/lib/common/framing/AMQMethodBody.h new file mode 100644 index 0000000000..c2b00c2169 --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQMethodBody.h @@ -0,0 +1,84 @@ +#ifndef _AMQMethodBody_ +#define _AMQMethodBody_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <iostream> +#include <amqp_types.h> +#include <AMQBody.h> +#include <Buffer.h> +#include <AMQP_ServerOperations.h> +#include <MethodContext.h> + +namespace qpid { +namespace framing { + +class AMQP_MethodVersionMap; + +class AMQMethodBody : public AMQBody +{ + public: + typedef boost::shared_ptr<AMQMethodBody> shared_ptr; + + static shared_ptr create( + AMQP_MethodVersionMap& map, ProtocolVersion version, Buffer& buf); + + ProtocolVersion version; + uint8_t type() const { return METHOD_BODY; } + AMQMethodBody(uint8_t major, uint8_t minor) : version(major, minor) {} + AMQMethodBody(ProtocolVersion ver) : version(ver) {} + virtual ~AMQMethodBody() {} + void decode(Buffer&, uint32_t); + + virtual MethodId amqpMethodId() const = 0; + virtual ClassId amqpClassId() const = 0; + + virtual void invoke(AMQP_ServerOperations&, const MethodContext&); + + template <class T> bool isA() { + return amqpClassId()==T::CLASS_ID && amqpMethodId()==T::METHOD_ID; + } + + /** Return request ID or response correlationID */ + virtual RequestId getRequestId() const { return 0; } + + virtual bool isRequest() const { return false; } + virtual bool isResponse() const { return false; } + + protected: + static uint32_t baseSize() { return 4; } + + struct ClassMethodId { + uint16_t classId; + uint16_t methodId; + void decode(Buffer& b); + }; + + void encodeId(Buffer& buffer) const; + virtual void encodeContent(Buffer& buffer) const = 0; + virtual void decodeContent(Buffer& buffer) = 0; +}; + + +}} // namespace qpid::framing + + +#endif diff --git a/qpid/cpp/lib/common/framing/AMQRequestBody.cpp b/qpid/cpp/lib/common/framing/AMQRequestBody.cpp new file mode 100644 index 0000000000..54e1c11863 --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQRequestBody.cpp @@ -0,0 +1,66 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "AMQRequestBody.h" +#include "AMQP_MethodVersionMap.h" + +namespace qpid { +namespace framing { + +void AMQRequestBody::Data::encode(Buffer& buffer) const { + buffer.putLongLong(requestId); + buffer.putLongLong(responseMark); + buffer.putLong(0); // Reserved long in spec. +} + +void AMQRequestBody::Data::decode(Buffer& buffer) { + requestId = buffer.getLongLong(); + responseMark = buffer.getLongLong(); + buffer.getLong(); // Ignore reserved long. +} + +void AMQRequestBody::encode(Buffer& buffer) const { + data.encode(buffer); + encodeId(buffer); + encodeContent(buffer); +} + +AMQRequestBody::shared_ptr +AMQRequestBody::create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer) +{ + ClassMethodId id; + Data data; + data.decode(buffer); + id.decode(buffer); + AMQRequestBody* body = dynamic_cast<AMQRequestBody*>( + versionMap.createMethodBody( + id.classId, id.methodId, version.getMajor(), version.getMinor())); + assert(body); + body->data = data; + return AMQRequestBody::shared_ptr(body); +} + +void AMQRequestBody::printPrefix(std::ostream& out) const { + out << "request(id=" << data.requestId << ",mark=" + << data.responseMark << "): "; +} + +}} // namespace qpid::framing + diff --git a/qpid/cpp/lib/common/framing/AMQRequestBody.h b/qpid/cpp/lib/common/framing/AMQRequestBody.h new file mode 100644 index 0000000000..e184fff1d6 --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQRequestBody.h @@ -0,0 +1,78 @@ +#ifndef _framing_AMQRequestBody_h +#define _framing_AMQRequestBody_h + +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "AMQMethodBody.h" + +namespace qpid { +namespace framing { + +/** + * Body of a request method frame. + */ +class AMQRequestBody : public AMQMethodBody +{ + public: + typedef boost::shared_ptr<AMQRequestBody> shared_ptr; + + struct Data { + Data(RequestId id=0, ResponseId mark=0) + : requestId(id), responseMark(mark) {} + void encode(Buffer&) const; + void decode(Buffer&); + + RequestId requestId; + ResponseId responseMark; + }; + + static Data& getData(const AMQBody::shared_ptr& body) { + return boost::dynamic_pointer_cast<AMQRequestBody>(body)->getData(); + } + + static shared_ptr create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer); + + AMQRequestBody(ProtocolVersion v, RequestId id=0, ResponseId mark=0) + : AMQMethodBody(v), data(id, mark) {} + + uint8_t type() const { return REQUEST_BODY; } + void encode(Buffer& buffer) const; + + Data& getData() { return data; } + RequestId getRequestId() const { return data.requestId; } + ResponseId getResponseMark() const { return data.responseMark; } + void setRequestId(RequestId id) { data.requestId=id; } + void setResponseMark(ResponseId mark) { data.responseMark=mark; } + + bool isRequest()const { return true; } + protected: + static const uint32_t baseSize() { return AMQMethodBody::baseSize()+20; } + void printPrefix(std::ostream& out) const; + + private: + Data data; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_AMQRequestBody_h*/ diff --git a/qpid/cpp/lib/common/framing/AMQResponseBody.cpp b/qpid/cpp/lib/common/framing/AMQResponseBody.cpp new file mode 100644 index 0000000000..7da71a5d25 --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQResponseBody.cpp @@ -0,0 +1,65 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "AMQFrame.h" +#include "AMQResponseBody.h" +#include "AMQP_MethodVersionMap.h" + +namespace qpid { +namespace framing { + +void AMQResponseBody::Data::encode(Buffer& buffer) const { + buffer.putLongLong(responseId); + buffer.putLongLong(requestId); + buffer.putLong(batchOffset); +} + +void AMQResponseBody::Data::decode(Buffer& buffer) { + responseId = buffer.getLongLong(); + requestId = buffer.getLongLong(); + batchOffset = buffer.getLong(); +} + +void AMQResponseBody::encode(Buffer& buffer) const { + data.encode(buffer); + encodeId(buffer); + encodeContent(buffer); +} + +AMQResponseBody::shared_ptr AMQResponseBody::create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer) +{ + ClassMethodId id; + Data data; + data.decode(buffer); + id.decode(buffer); + AMQResponseBody* body = dynamic_cast<AMQResponseBody*>( + versionMap.createMethodBody( + id.classId, id.methodId, version.getMajor(), version.getMinor())); + assert(body); + body->data = data; + return AMQResponseBody::shared_ptr(body); +} + +void AMQResponseBody::printPrefix(std::ostream& out) const { + out << "response(id=" << data.responseId << ",request=" << data.requestId + << ",batch=" << data.batchOffset << "): "; +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/AMQResponseBody.h b/qpid/cpp/lib/common/framing/AMQResponseBody.h new file mode 100644 index 0000000000..fa381baddd --- /dev/null +++ b/qpid/cpp/lib/common/framing/AMQResponseBody.h @@ -0,0 +1,85 @@ +#ifndef _framing_AMQResponseBody_h +#define _framing_AMQResponseBody_h + +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "AMQMethodBody.h" + +namespace qpid { +namespace framing { + +class AMQP_MethodVersionMap; + +/** + * Body of a response method frame. + */ +class AMQResponseBody : public AMQMethodBody +{ + + public: + typedef boost::shared_ptr<AMQResponseBody> shared_ptr; + + struct Data { + Data(ResponseId id=0, RequestId req=0, BatchOffset off=0) + : responseId(id), requestId(req), batchOffset(off) {} + void encode(Buffer&) const; + void decode(Buffer&); + + uint64_t responseId; + uint64_t requestId; + uint32_t batchOffset; + }; + + static Data& getData(const AMQBody::shared_ptr& body) { + return boost::dynamic_pointer_cast<AMQResponseBody>(body)->getData(); + } + + static shared_ptr create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer); + + AMQResponseBody( + ProtocolVersion v, ResponseId id=0, RequestId req=0, BatchOffset off=0) + : AMQMethodBody(v), data(id, req, off) {} + + uint8_t type() const { return RESPONSE_BODY; } + void encode(Buffer& buffer) const; + + Data& getData() { return data; } + ResponseId getResponseId() const { return data.responseId; } + RequestId getRequestId() const { return data.requestId; } + BatchOffset getBatchOffset() const { return data.batchOffset; } + void setResponseId(ResponseId id) { data.responseId = id; } + void setRequestId(RequestId id) { data.requestId = id; } + void setBatchOffset(BatchOffset id) { data.batchOffset = id; } + + bool isResponse() const { return true; } + protected: + static const uint32_t baseSize() { return AMQMethodBody::baseSize()+20; } + void printPrefix(std::ostream& out) const; + + private: + Data data; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_AMQResponseBody_h*/ diff --git a/qpid/cpp/lib/common/framing/BasicHeaderProperties.cpp b/qpid/cpp/lib/common/framing/BasicHeaderProperties.cpp new file mode 100644 index 0000000000..930ec9f4dd --- /dev/null +++ b/qpid/cpp/lib/common/framing/BasicHeaderProperties.cpp @@ -0,0 +1,103 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <BasicHeaderProperties.h> + +//TODO: This could be easily generated from the spec + +qpid::framing::BasicHeaderProperties::BasicHeaderProperties() : deliveryMode(0), priority(0), timestamp(0){} +qpid::framing::BasicHeaderProperties::~BasicHeaderProperties(){} + +uint32_t qpid::framing::BasicHeaderProperties::size() const{ + uint32_t bytes = 2;//flags + if(contentType.length() > 0) bytes += contentType.length() + 1; + if(contentEncoding.length() > 0) bytes += contentEncoding.length() + 1; + if(headers.count() > 0) bytes += headers.size(); + if(deliveryMode != 0) bytes += 1; + if(priority != 0) bytes += 1; + if(correlationId.length() > 0) bytes += correlationId.length() + 1; + if(replyTo.length() > 0) bytes += replyTo.length() + 1; + if(expiration.length() > 0) bytes += expiration.length() + 1; + if(messageId.length() > 0) bytes += messageId.length() + 1; + if(timestamp != 0) bytes += 8; + if(type.length() > 0) bytes += type.length() + 1; + if(userId.length() > 0) bytes += userId.length() + 1; + if(appId.length() > 0) bytes += appId.length() + 1; + if(clusterId.length() > 0) bytes += clusterId.length() + 1; + + return bytes; +} + +void qpid::framing::BasicHeaderProperties::encode(qpid::framing::Buffer& buffer) const{ + uint16_t flags = getFlags(); + buffer.putShort(flags); + + if(contentType.length() > 0) buffer.putShortString(contentType); + if(contentEncoding.length() > 0) buffer.putShortString(contentEncoding); + if(headers.count() > 0) buffer.putFieldTable(headers); + if(deliveryMode != 0) buffer.putOctet(deliveryMode); + if(priority != 0) buffer.putOctet(priority); + if(correlationId.length() > 0) buffer.putShortString(correlationId); + if(replyTo.length() > 0) buffer.putShortString(replyTo); + if(expiration.length() > 0) buffer.putShortString(expiration); + if(messageId.length() > 0) buffer.putShortString(messageId); + if(timestamp != 0) buffer.putLongLong(timestamp);; + if(type.length() > 0) buffer.putShortString(type); + if(userId.length() > 0) buffer.putShortString(userId); + if(appId.length() > 0) buffer.putShortString(appId); + if(clusterId.length() > 0) buffer.putShortString(clusterId); +} + +void qpid::framing::BasicHeaderProperties::decode(qpid::framing::Buffer& buffer, uint32_t /*size*/){ + uint16_t flags = buffer.getShort(); + if(flags & (1 << 15)) buffer.getShortString(contentType); + if(flags & (1 << 14)) buffer.getShortString(contentEncoding); + if(flags & (1 << 13)) buffer.getFieldTable(headers); + if(flags & (1 << 12)) deliveryMode = buffer.getOctet(); + if(flags & (1 << 11)) priority = buffer.getOctet(); + if(flags & (1 << 10)) buffer.getShortString(correlationId); + if(flags & (1 << 9)) buffer.getShortString(replyTo); + if(flags & (1 << 8)) buffer.getShortString(expiration); + if(flags & (1 << 7)) buffer.getShortString(messageId); + if(flags & (1 << 6)) timestamp = buffer.getLongLong(); + if(flags & (1 << 5)) buffer.getShortString(type); + if(flags & (1 << 4)) buffer.getShortString(userId); + if(flags & (1 << 3)) buffer.getShortString(appId); + if(flags & (1 << 2)) buffer.getShortString(clusterId); +} + +uint16_t qpid::framing::BasicHeaderProperties::getFlags() const{ + uint16_t flags(0); + if(contentType.length() > 0) flags |= (1 << 15); + if(contentEncoding.length() > 0) flags |= (1 << 14); + if(headers.count() > 0) flags |= (1 << 13); + if(deliveryMode != 0) flags |= (1 << 12); + if(priority != 0) flags |= (1 << 11); + if(correlationId.length() > 0) flags |= (1 << 10); + if(replyTo.length() > 0) flags |= (1 << 9); + if(expiration.length() > 0) flags |= (1 << 8); + if(messageId.length() > 0) flags |= (1 << 7); + if(timestamp != 0) flags |= (1 << 6); + if(type.length() > 0) flags |= (1 << 5); + if(userId.length() > 0) flags |= (1 << 4); + if(appId.length() > 0) flags |= (1 << 3); + if(clusterId.length() > 0) flags |= (1 << 2); + return flags; +} diff --git a/qpid/cpp/lib/common/framing/BasicHeaderProperties.h b/qpid/cpp/lib/common/framing/BasicHeaderProperties.h new file mode 100644 index 0000000000..1f3fd31250 --- /dev/null +++ b/qpid/cpp/lib/common/framing/BasicHeaderProperties.h @@ -0,0 +1,97 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <amqp_types.h> +#include <Buffer.h> +#include <FieldTable.h> +#include <HeaderProperties.h> + +#ifndef _BasicHeaderProperties_ +#define _BasicHeaderProperties_ + +namespace qpid { +namespace framing { + enum delivery_mode {TRANSIENT = 1, PERSISTENT = 2}; + + //TODO: This could be easily generated from the spec + class BasicHeaderProperties : public HeaderProperties + { + string contentType; + string contentEncoding; + FieldTable headers; + uint8_t deliveryMode; + uint8_t priority; + string correlationId; + string replyTo; + string expiration; + string messageId; + uint64_t timestamp; + string type; + string userId; + string appId; + string clusterId; + + uint16_t getFlags() const; + + public: + BasicHeaderProperties(); + virtual ~BasicHeaderProperties(); + virtual uint32_t size() const; + virtual void encode(Buffer& buffer) const; + virtual void decode(Buffer& buffer, uint32_t size); + + inline virtual uint8_t classId() { return BASIC; } + + inline const string& getContentType() const { return contentType; } + inline const string& getContentEncoding() const { return contentEncoding; } + inline FieldTable& getHeaders() { return headers; } + inline uint8_t getDeliveryMode() const { return deliveryMode; } + inline uint8_t getPriority() const { return priority; } + inline const string& getCorrelationId() const {return correlationId; } + inline const string& getReplyTo() const { return replyTo; } + inline const string& getExpiration() const { return expiration; } + inline const string& getMessageId() const {return messageId; } + inline uint64_t getTimestamp() const { return timestamp; } + inline const string& getType() const { return type; } + inline const string& getUserId() const { return userId; } + inline const string& getAppId() const { return appId; } + inline const string& getClusterId() const { return clusterId; } + + void inline setContentType(const string& _type){ contentType = _type; } + void inline setContentEncoding(const string& encoding){ contentEncoding = encoding; } + void inline setHeaders(const FieldTable& _headers){ headers = _headers; } + void inline setDeliveryMode(uint8_t mode){ deliveryMode = mode; } + void inline setPriority(uint8_t _priority){ priority = _priority; } + void inline setCorrelationId(const string& _correlationId){ correlationId = _correlationId; } + void inline setReplyTo(const string& _replyTo){ replyTo = _replyTo;} + void inline setExpiration(const string& _expiration){ expiration = _expiration; } + void inline setMessageId(const string& _messageId){ messageId = _messageId; } + void inline setTimestamp(uint64_t _timestamp){ timestamp = _timestamp; } + void inline setType(const string& _type){ type = _type; } + void inline setUserId(const string& _userId){ userId = _userId; } + void inline setAppId(const string& _appId){appId = _appId; } + void inline setClusterId(const string& _clusterId){ clusterId = _clusterId; } + }; + +} +} + + +#endif diff --git a/qpid/cpp/lib/common/framing/BodyHandler.cpp b/qpid/cpp/lib/common/framing/BodyHandler.cpp new file mode 100644 index 0000000000..5dd0c0c23d --- /dev/null +++ b/qpid/cpp/lib/common/framing/BodyHandler.cpp @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "QpidError.h" +#include "BodyHandler.h" +#include <AMQRequestBody.h> +#include <AMQResponseBody.h> +#include <AMQMethodBody.h> +#include <AMQHeaderBody.h> +#include <AMQContentBody.h> +#include <AMQHeartbeatBody.h> + +using namespace qpid::framing; +using namespace boost; + +BodyHandler::~BodyHandler() {} + +void BodyHandler::handleBody(shared_ptr<AMQBody> body) { + switch(body->type()) + { + case REQUEST_BODY: + handleRequest(shared_polymorphic_cast<AMQRequestBody>(body)); + break; + case RESPONSE_BODY: + handleResponse(shared_polymorphic_cast<AMQResponseBody>(body)); + break; + case METHOD_BODY: + handleMethod(shared_polymorphic_cast<AMQMethodBody>(body)); + break; + case HEADER_BODY: + handleHeader(shared_polymorphic_cast<AMQHeaderBody>(body)); + break; + case CONTENT_BODY: + handleContent(shared_polymorphic_cast<AMQContentBody>(body)); + break; + case HEARTBEAT_BODY: + handleHeartbeat(shared_polymorphic_cast<AMQHeartbeatBody>(body)); + break; + default: + QPID_ERROR(PROTOCOL_ERROR, "Unknown frame type "+body->type()); + } +} + diff --git a/qpid/cpp/lib/common/framing/BodyHandler.h b/qpid/cpp/lib/common/framing/BodyHandler.h new file mode 100644 index 0000000000..cb3f0997b0 --- /dev/null +++ b/qpid/cpp/lib/common/framing/BodyHandler.h @@ -0,0 +1,61 @@ +#ifndef _BodyHandler_ +#define _BodyHandler_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include <boost/shared_ptr.hpp> + +#include "Requester.h" +#include "Responder.h" + +namespace qpid { +namespace framing { + +class AMQRequestBody; +class AMQResponseBody; +class AMQMethodBody; +class AMQHeaderBody; +class AMQContentBody; +class AMQHeartbeatBody; + +/** + * Interface to handle incoming frame bodies. + * Derived classes provide logic for each frame type. + */ +class BodyHandler { + public: + virtual ~BodyHandler(); + virtual void handleBody(boost::shared_ptr<AMQBody> body); + + protected: + virtual void handleRequest(boost::shared_ptr<AMQRequestBody>) = 0; + virtual void handleResponse(boost::shared_ptr<AMQResponseBody>) = 0; + virtual void handleMethod(boost::shared_ptr<AMQMethodBody>) = 0; + virtual void handleHeader(boost::shared_ptr<AMQHeaderBody>) = 0; + virtual void handleContent(boost::shared_ptr<AMQContentBody>) = 0; + virtual void handleHeartbeat(boost::shared_ptr<AMQHeartbeatBody>) = 0; +}; + +}} + + +#endif diff --git a/qpid/cpp/lib/common/framing/Buffer.cpp b/qpid/cpp/lib/common/framing/Buffer.cpp new file mode 100644 index 0000000000..52c9a42d55 --- /dev/null +++ b/qpid/cpp/lib/common/framing/Buffer.cpp @@ -0,0 +1,183 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <Buffer.h> +#include <FramingContent.h> +#include <FieldTable.h> + +qpid::framing::Buffer::Buffer(uint32_t _size) : size(_size), owner(true), position(0), limit(_size){ + data = new char[size]; +} + +qpid::framing::Buffer::Buffer(char* _data, uint32_t _size) : size(_size), owner(false), data(_data), position(0), limit(_size){ +} + +qpid::framing::Buffer::~Buffer(){ + if(owner) delete[] data; +} + +void qpid::framing::Buffer::flip(){ + limit = position; + position = 0; +} + +void qpid::framing::Buffer::clear(){ + limit = size; + position = 0; +} + +void qpid::framing::Buffer::compact(){ + uint32_t p = limit - position; + //copy p chars from position to 0 + memmove(data, data + position, p); + limit = size; + position = p; +} + +void qpid::framing::Buffer::record(){ + r_position = position; + r_limit = limit; +} + +void qpid::framing::Buffer::restore(){ + position = r_position; + limit = r_limit; +} + +uint32_t qpid::framing::Buffer::available(){ + return limit - position; +} + +char* qpid::framing::Buffer::start(){ + return data + position; +} + +void qpid::framing::Buffer::move(uint32_t bytes){ + position += bytes; +} + +void qpid::framing::Buffer::putOctet(uint8_t i){ + data[position++] = i; +} + +void qpid::framing::Buffer::putShort(uint16_t i){ + uint16_t b = i; + data[position++] = (uint8_t) (0xFF & (b >> 8)); + data[position++] = (uint8_t) (0xFF & b); +} + +void qpid::framing::Buffer::putLong(uint32_t i){ + uint32_t b = i; + data[position++] = (uint8_t) (0xFF & (b >> 24)); + data[position++] = (uint8_t) (0xFF & (b >> 16)); + data[position++] = (uint8_t) (0xFF & (b >> 8)); + data[position++] = (uint8_t) (0xFF & b); +} + +void qpid::framing::Buffer::putLongLong(uint64_t i){ + uint32_t hi = i >> 32; + uint32_t lo = i; + putLong(hi); + putLong(lo); +} + +uint8_t qpid::framing::Buffer::getOctet(){ + return (uint8_t) data[position++]; +} + +uint16_t qpid::framing::Buffer::getShort(){ + uint16_t hi = (unsigned char) data[position++]; + hi = hi << 8; + hi |= (unsigned char) data[position++]; + return hi; +} + +uint32_t qpid::framing::Buffer::getLong(){ + uint32_t a = (unsigned char) data[position++]; + uint32_t b = (unsigned char) data[position++]; + uint32_t c = (unsigned char) data[position++]; + uint32_t d = (unsigned char) data[position++]; + a = a << 24; + a |= b << 16; + a |= c << 8; + a |= d; + return a; +} + +uint64_t qpid::framing::Buffer::getLongLong(){ + uint64_t hi = getLong(); + uint64_t lo = getLong(); + hi = hi << 32; + return hi | lo; +} + + +void qpid::framing::Buffer::putShortString(const string& s){ + uint8_t len = s.length(); + putOctet(len); + s.copy(data + position, len); + position += len; +} + +void qpid::framing::Buffer::putLongString(const string& s){ + uint32_t len = s.length(); + putLong(len); + s.copy(data + position, len); + position += len; +} + +void qpid::framing::Buffer::getShortString(string& s){ + uint8_t len = getOctet(); + s.assign(data + position, len); + position += len; +} + +void qpid::framing::Buffer::getLongString(string& s){ + uint32_t len = getLong(); + s.assign(data + position, len); + position += len; +} + +void qpid::framing::Buffer::putFieldTable(const FieldTable& t){ + t.encode(*this); +} + +void qpid::framing::Buffer::getFieldTable(FieldTable& t){ + t.decode(*this); +} + +void qpid::framing::Buffer::putContent(const Content& c){ + c.encode(*this); +} + +void qpid::framing::Buffer::getContent(Content& c){ + c.decode(*this); +} + +void qpid::framing::Buffer::putRawData(const string& s){ + uint32_t len = s.length(); + s.copy(data + position, len); + position += len; +} + +void qpid::framing::Buffer::getRawData(string& s, uint32_t len){ + s.assign(data + position, len); + position += len; +} diff --git a/qpid/cpp/lib/common/framing/Buffer.h b/qpid/cpp/lib/common/framing/Buffer.h new file mode 100644 index 0000000000..63a15c7c3d --- /dev/null +++ b/qpid/cpp/lib/common/framing/Buffer.h @@ -0,0 +1,86 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <amqp_types.h> + +#ifndef _Buffer_ +#define _Buffer_ + +namespace qpid { +namespace framing { + +class Content; +class FieldTable; + +class Buffer +{ + const uint32_t size; + const bool owner;//indicates whether the data is owned by this instance + char* data; + uint32_t position; + uint32_t limit; + uint32_t r_position; + uint32_t r_limit; + +public: + + Buffer(uint32_t size); + Buffer(char* data, uint32_t size); + ~Buffer(); + + void flip(); + void clear(); + void compact(); + void record(); + void restore(); + uint32_t available(); + char* start(); + void move(uint32_t bytes); + + void putOctet(uint8_t i); + void putShort(uint16_t i); + void putLong(uint32_t i); + void putLongLong(uint64_t i); + + uint8_t getOctet(); + uint16_t getShort(); + uint32_t getLong(); + uint64_t getLongLong(); + + void putShortString(const string& s); + void putLongString(const string& s); + void getShortString(string& s); + void getLongString(string& s); + + void putFieldTable(const FieldTable& t); + void getFieldTable(FieldTable& t); + + void putContent(const Content& c); + void getContent(Content& c); + + void putRawData(const string& s); + void getRawData(string& s, uint32_t size); + +}; + +}} // namespace qpid::framing + + +#endif diff --git a/qpid/cpp/lib/common/framing/ChannelAdapter.cpp b/qpid/cpp/lib/common/framing/ChannelAdapter.cpp new file mode 100644 index 0000000000..8a1ff39ee5 --- /dev/null +++ b/qpid/cpp/lib/common/framing/ChannelAdapter.cpp @@ -0,0 +1,99 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include <boost/format.hpp> + +#include "ChannelAdapter.h" +#include "AMQFrame.h" +#include "Exception.h" + +using boost::format; + +namespace qpid { +namespace framing { + +void ChannelAdapter::init( + ChannelId i, OutputHandler& o, ProtocolVersion v) +{ + assertChannelNotOpen(); + id = i; + out = &o; + version = v; +} + +RequestId ChannelAdapter::send(AMQBody::shared_ptr body) { + RequestId result = 0; + assertChannelOpen(); + switch (body->type()) { + case REQUEST_BODY: { + AMQRequestBody::shared_ptr request = + boost::shared_polymorphic_downcast<AMQRequestBody>(body); + requester.sending(request->getData()); + result = request->getData().requestId; + break; + } + case RESPONSE_BODY: { + AMQResponseBody::shared_ptr response = + boost::shared_polymorphic_downcast<AMQResponseBody>(body); + responder.sending(response->getData()); + break; + } + } + out->send(new AMQFrame(getVersion(), getId(), body)); + return result; +} + +void ChannelAdapter::handleRequest(AMQRequestBody::shared_ptr request) { + assertMethodOk(*request); + AMQRequestBody::Data& requestData = request->getData(); + responder.received(requestData); + handleMethodInContext(request, MethodContext(this, request)); +} + +void ChannelAdapter::handleResponse(AMQResponseBody::shared_ptr response) { + assertMethodOk(*response); + // TODO aconway 2007-01-30: Consider a response handled on receipt. + // Review - any cases where this is not the case? + AMQResponseBody::Data& responseData = response->getData(); + requester.processed(responseData); + handleMethod(response); +} + +void ChannelAdapter::handleMethod(AMQMethodBody::shared_ptr method) { + assertMethodOk(*method); + handleMethodInContext(method, MethodContext(this, method)); +} + +void ChannelAdapter::assertMethodOk(AMQMethodBody& method) const { + if (getId() != 0 && method.amqpClassId() == ConnectionOpenBody::CLASS_ID) + throw ConnectionException( + 504, format("Connection method on non-0 channel %d.")%getId()); +} + +void ChannelAdapter::assertChannelOpen() const { + if (getId() != 0 && !isOpen()) + throw ConnectionException( + 504, format("Channel %d is not open.")%getId()); +} + +void ChannelAdapter::assertChannelNotOpen() const { + if (getId() != 0 && isOpen()) + throw ConnectionException( + 504, format("Channel %d is already open.") % getId()); +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/ChannelAdapter.h b/qpid/cpp/lib/common/framing/ChannelAdapter.h new file mode 100644 index 0000000000..f6e3986eed --- /dev/null +++ b/qpid/cpp/lib/common/framing/ChannelAdapter.h @@ -0,0 +1,105 @@ +#ifndef _ChannelAdapter_ +#define _ChannelAdapter_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include <boost/shared_ptr.hpp> + +#include "BodyHandler.h" +#include "Requester.h" +#include "Responder.h" +#include "framing/amqp_types.h" + +namespace qpid { +namespace framing { + +class MethodContext; + +// FIXME aconway 2007-02-20: Rename as ChannelBase or just Channel. + +/** + * Base class for client and broker channels. + * + * - receives frame bodies from the network. + * - Updates request/response data. + * - Dispatches requests with a MethodContext for responses. + * + * send() + * - Updates request/resposne ID data. + * - Forwards frame to the peer. + * + * Thread safety: OBJECT UNSAFE. Instances must not be called + * concurrently. AMQP defines channels to be serialized. + */ +class ChannelAdapter : public BodyHandler { + public: + /** + *@param output Processed frames are forwarded to this handler. + */ + ChannelAdapter(ChannelId id_=0, OutputHandler* out_=0, + ProtocolVersion ver=ProtocolVersion()) + : id(id_), out(out_), version(ver) {} + + /** Initialize the channel adapter. */ + void init(ChannelId, OutputHandler&, ProtocolVersion); + + ChannelId getId() const { return id; } + ProtocolVersion getVersion() const { return version; } + + /** + * Wrap body in a frame and send the frame. + * Takes ownership of body. + */ + RequestId send(AMQBody::shared_ptr body); + RequestId send(AMQBody* body) { return send(AMQBody::shared_ptr(body)); } + + void handleMethod(boost::shared_ptr<qpid::framing::AMQMethodBody>); + void handleRequest(boost::shared_ptr<qpid::framing::AMQRequestBody>); + void handleResponse(boost::shared_ptr<qpid::framing::AMQResponseBody>); + + virtual bool isOpen() const = 0; + + protected: + void assertMethodOk(AMQMethodBody& method) const; + void assertChannelOpen() const; + void assertChannelNotOpen() const; + + virtual void handleMethodInContext( + boost::shared_ptr<qpid::framing::AMQMethodBody> method, + const MethodContext& context) = 0; + + RequestId getFirstAckRequest() { return requester.getFirstAckRequest(); } + RequestId getLastAckRequest() { return requester.getLastAckRequest(); } + RequestId getNextSendRequestId() { return requester.getNextId(); } + + private: + ChannelId id; + OutputHandler* out; + ProtocolVersion version; + Requester requester; + Responder responder; +}; + +}} + + +#endif diff --git a/qpid/cpp/lib/common/framing/FieldTable.cpp b/qpid/cpp/lib/common/framing/FieldTable.cpp new file mode 100644 index 0000000000..5bbc4651d3 --- /dev/null +++ b/qpid/cpp/lib/common/framing/FieldTable.cpp @@ -0,0 +1,150 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <FieldTable.h> +#include <QpidError.h> +#include <Buffer.h> +#include <Value.h> +#include <assert.h> + +namespace qpid { +namespace framing { + +FieldTable::~FieldTable() {} + +uint32_t FieldTable::size() const { + uint32_t len(4); + for(ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) { + // 2 = shortstr_len_byyte + type_char_byte + len += 2 + (i->first).size() + (i->second)->size(); + } + return len; +} + +int FieldTable::count() const { + return values.size(); +} + +namespace +{ +std::ostream& operator<<(std::ostream& out, const FieldTable::ValueMap::value_type& i) { + return out << i.first << ":" << *i.second; +} +} + +std::ostream& operator<<(std::ostream& out, const FieldTable& t) { + out << "{"; + FieldTable::ValueMap::const_iterator i = t.getMap().begin(); + if (i != t.getMap().end()) out << *i++; + while (i != t.getMap().end()) + { + out << "," << *i++; + } + return out << "}"; +} + +void FieldTable::setString(const std::string& name, const std::string& value){ + values[name] = ValuePtr(new StringValue(value)); +} + +void FieldTable::setInt(const std::string& name, int value){ + values[name] = ValuePtr(new IntegerValue(value)); +} + +void FieldTable::setTimestamp(const std::string& name, uint64_t value){ + values[name] = ValuePtr(new TimeValue(value)); +} + +void FieldTable::setTable(const std::string& name, const FieldTable& value){ + values[name] = ValuePtr(new FieldTableValue(value)); +} + +namespace { +template <class T> T default_value() { return T(); } +template <> int default_value<int>() { return 0; } +template <> uint64_t default_value<uint64_t>() { return 0; } +} + +template <class T> +T FieldTable::getValue(const std::string& name) const +{ + ValueMap::const_iterator i = values.find(name); + if (i == values.end()) return default_value<T>(); + const ValueOps<T> *vt = dynamic_cast<const ValueOps<T>*>(i->second.get()); + return vt->getValue(); +} + +std::string FieldTable::getString(const std::string& name) const { + return getValue<std::string>(name); +} + +int FieldTable::getInt(const std::string& name) const { + return getValue<int>(name); +} + +uint64_t FieldTable::getTimestamp(const std::string& name) const { + return getValue<uint64_t>(name); +} + +void FieldTable::getTable(const std::string& name, FieldTable& value) const { + value = getValue<FieldTable>(name); +} + +void FieldTable::encode(Buffer& buffer) const{ + buffer.putLong(size() - 4); + for (ValueMap::const_iterator i = values.begin(); i!=values.end(); ++i) { + buffer.putShortString(i->first); + buffer.putOctet(i->second->getType()); + i->second->encode(buffer); + } +} + +void FieldTable::decode(Buffer& buffer){ + uint32_t len = buffer.getLong(); + uint32_t available = buffer.available(); + if (available < len) + THROW_QPID_ERROR(FRAMING_ERROR, "Not enough data for field table."); + uint32_t leftover = available - len; + while(buffer.available() > leftover){ + std::string name; + buffer.getShortString(name); + std::auto_ptr<Value> value(Value::decode_value(buffer)); + values[name] = ValuePtr(value.release()); + } +} + + +bool FieldTable::operator==(const FieldTable& x) const { + if (values.size() != x.values.size()) return false; + for (ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) { + ValueMap::const_iterator j = x.values.find(i->first); + if (j == x.values.end()) return false; + if (*(i->second) != *(j->second)) return false; + } + return true; +} + +void FieldTable::erase(const std::string& name) +{ + values.erase(values.find(name)); +} + +} +} diff --git a/qpid/cpp/lib/common/framing/FieldTable.h b/qpid/cpp/lib/common/framing/FieldTable.h new file mode 100644 index 0000000000..e25a7d3f8c --- /dev/null +++ b/qpid/cpp/lib/common/framing/FieldTable.h @@ -0,0 +1,90 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <iostream> +#include <vector> +#include <boost/shared_ptr.hpp> +#include <map> +#include <amqp_types.h> + +#ifndef _FieldTable_ +#define _FieldTable_ + +namespace qpid { + /** + * The framing namespace contains classes that are used to create, + * send and receive the basic packets from which AMQP is built. + */ +namespace framing { + +class Value; +class Buffer; + +/** + * A set of name-value pairs. (See the AMQP spec for more details on + * AMQP field tables). + * + * \ingroup clientapi + */ +class FieldTable +{ + public: + typedef boost::shared_ptr<Value> ValuePtr; + typedef std::map<std::string, ValuePtr> ValueMap; + + ~FieldTable(); + uint32_t size() const; + int count() const; + void setString(const std::string& name, const std::string& value); + void setInt(const std::string& name, int value); + void setTimestamp(const std::string& name, uint64_t value); + void setTable(const std::string& name, const FieldTable& value); + //void setDecimal(string& name, xxx& value); + std::string getString(const std::string& name) const; + int getInt(const std::string& name) const; + uint64_t getTimestamp(const std::string& name) const; + void getTable(const std::string& name, FieldTable& value) const; + //void getDecimal(string& name, xxx& value); + void erase(const std::string& name); + + void encode(Buffer& buffer) const; + void decode(Buffer& buffer); + + bool operator==(const FieldTable& other) const; + + // TODO aconway 2006-09-26: Yeuch! Rework FieldTable to have + // a map-like interface. + const ValueMap& getMap() const { return values; } + ValueMap& getMap() { return values; } + + private: + friend std::ostream& operator<<(std::ostream& out, const FieldTable& body); + ValueMap values; + template<class T> T getValue(const std::string& name) const; +}; + +class FieldNotFoundException{}; +class UnknownFieldName : public FieldNotFoundException{}; +class IncorrectFieldType : public FieldNotFoundException{}; +} +} + + +#endif diff --git a/qpid/cpp/lib/common/framing/FramingContent.cpp b/qpid/cpp/lib/common/framing/FramingContent.cpp new file mode 100644 index 0000000000..24efa38dcb --- /dev/null +++ b/qpid/cpp/lib/common/framing/FramingContent.cpp @@ -0,0 +1,75 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <assert.h> + +#include "Buffer.h" +#include "FramingContent.h" +#include <QpidError.h> +#include <sstream> + +namespace qpid { +namespace framing { + +Content::Content() : discriminator(0) {} + +Content::Content(uint8_t _discriminator, const string& _value): discriminator(_discriminator), value(_value) { + validate(); +} + +void Content::validate() { + if (discriminator == REFERENCE) { + if(value.empty()) { + THROW_QPID_ERROR(FRAMING_ERROR, "Reference cannot be empty"); + } + }else if (discriminator != INLINE) { + std::stringstream out; + out << "Invalid discriminator: " << (int) discriminator; + THROW_QPID_ERROR(FRAMING_ERROR, out.str()); + } +} + +Content::~Content() {} + +void Content::encode(Buffer& buffer) const { + buffer.putOctet(discriminator); + buffer.putLongString(value); +} + +void Content::decode(Buffer& buffer) { + discriminator = buffer.getOctet(); + buffer.getLongString(value); + validate(); +} + +size_t Content::size() const { + return 1/*discriminator*/ + 4/*for recording size of long string*/ + value.size(); +} + +std::ostream& operator<<(std::ostream& out, const Content& content) { + if (content.discriminator == REFERENCE) { + out << "{REF:" << content.value << "}"; + } else if (content.discriminator == INLINE) { + out << "{INLINE:" << content.value.size() << " bytes}"; + } + return out; +} + +}} // namespace framing::qpid diff --git a/qpid/cpp/lib/common/framing/FramingContent.h b/qpid/cpp/lib/common/framing/FramingContent.h new file mode 100644 index 0000000000..696bcc7c1a --- /dev/null +++ b/qpid/cpp/lib/common/framing/FramingContent.h @@ -0,0 +1,40 @@ +#ifndef _framing_FramingContent_h +#define _framing_FramingContent_h + +#include <ostream> + +namespace qpid { +namespace framing { + +enum discriminator_types { INLINE = 0, REFERENCE = 1 }; + +/** + * A representation of the AMQP 'content' data type (used for message + * bodies) which can hold inline data or a reference. + */ +class Content +{ + uint8_t discriminator; + string value; + + void validate(); + + public: + Content(); + Content(uint8_t _discriminator, const string& _value); + ~Content(); + + void encode(Buffer& buffer) const; + void decode(Buffer& buffer); + size_t size() const; + bool isInline() const { return discriminator == INLINE; } + bool isReference() const { return discriminator == REFERENCE; } + const string& getValue() const { return value; } + + friend std::ostream& operator<<(std::ostream&, const Content&); +}; + +}} // namespace qpid::framing + + +#endif /*!_framing_FramingContent_h*/ diff --git a/qpid/cpp/lib/common/framing/HeaderProperties.h b/qpid/cpp/lib/common/framing/HeaderProperties.h new file mode 100644 index 0000000000..1ec4840309 --- /dev/null +++ b/qpid/cpp/lib/common/framing/HeaderProperties.h @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <amqp_types.h> +#include <Buffer.h> + +#ifndef _HeaderProperties_ +#define _HeaderProperties_ + +namespace qpid { +namespace framing { + + enum header_classes{BASIC = 60}; + + class HeaderProperties + { + + public: + inline virtual ~HeaderProperties(){} + virtual uint8_t classId() = 0; + virtual uint32_t size() const = 0; + virtual void encode(Buffer& buffer) const = 0; + virtual void decode(Buffer& buffer, uint32_t size) = 0; + }; +} +} + + +#endif diff --git a/qpid/cpp/lib/common/framing/InitiationHandler.cpp b/qpid/cpp/lib/common/framing/InitiationHandler.cpp new file mode 100644 index 0000000000..dd92c9859b --- /dev/null +++ b/qpid/cpp/lib/common/framing/InitiationHandler.cpp @@ -0,0 +1,24 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include <InitiationHandler.h> + +qpid::framing::InitiationHandler::~InitiationHandler() {} diff --git a/qpid/cpp/lib/common/framing/InitiationHandler.h b/qpid/cpp/lib/common/framing/InitiationHandler.h new file mode 100644 index 0000000000..d94fc58d2c --- /dev/null +++ b/qpid/cpp/lib/common/framing/InitiationHandler.h @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <string> + +#ifndef _InitiationHandler_ +#define _InitiationHandler_ + +#include <ProtocolInitiation.h> + +namespace qpid { +namespace framing { + + class InitiationHandler{ + public: + virtual ~InitiationHandler(); + virtual void initiated(ProtocolInitiation* header) = 0; + }; + +} +} + + +#endif diff --git a/qpid/cpp/lib/common/framing/InputHandler.h b/qpid/cpp/lib/common/framing/InputHandler.h new file mode 100644 index 0000000000..4e2d4bcc9b --- /dev/null +++ b/qpid/cpp/lib/common/framing/InputHandler.h @@ -0,0 +1,39 @@ +#ifndef _InputHandler_ +#define _InputHandler_ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include <AMQFrame.h> +#include <boost/noncopyable.hpp> + +namespace qpid { +namespace framing { + +class InputHandler : private boost::noncopyable { + public: + virtual ~InputHandler() {} + virtual void received(AMQFrame* frame) = 0; +}; + +}} + + +#endif diff --git a/qpid/cpp/lib/common/framing/MethodContext.cpp b/qpid/cpp/lib/common/framing/MethodContext.cpp new file mode 100644 index 0000000000..73af73f8e5 --- /dev/null +++ b/qpid/cpp/lib/common/framing/MethodContext.cpp @@ -0,0 +1,31 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "MethodContext.h" +#include "amqp_types.h" +#include "AMQRequestBody.h" + +namespace qpid { +namespace framing { + +RequestId MethodContext::getRequestId() const { + return boost::shared_polymorphic_downcast<AMQRequestBody>(methodBody) + ->getRequestId(); +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/MethodContext.h b/qpid/cpp/lib/common/framing/MethodContext.h new file mode 100644 index 0000000000..3493924bf6 --- /dev/null +++ b/qpid/cpp/lib/common/framing/MethodContext.h @@ -0,0 +1,80 @@ +#ifndef _framing_MethodContext_h +#define _framing_MethodContext_h + +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <boost/shared_ptr.hpp> + +#include "OutputHandler.h" +#include "ProtocolVersion.h" + +namespace qpid { +namespace framing { + +class BodyHandler; +class AMQMethodBody; +class ChannelAdapter; + +/** + * Invocation context for an AMQP method. + * + * It provides the method being processed and the channel on which + * it arrived. + * + * All Handler functions take a MethodContext as the last parameter. + */ +struct MethodContext +{ + typedef boost::shared_ptr<AMQMethodBody> BodyPtr; + + MethodContext(ChannelAdapter* ch=0, BodyPtr method=BodyPtr()) + : channel(ch), methodBody(method) {} + + /** + * Channel on which the method being processed arrived. + * 0 if the method was constructed by the caller + * rather than received from a channel. + */ + ChannelAdapter* channel; + + /** + * Body of the method being processed. + * It's useful for passing around instead of unpacking all its parameters. + * It's also provides the request ID when constructing a response. + */ + BodyPtr methodBody; + + /** + * Return methodBody's request ID. + * It is an error to call this if methodBody is not a request. + */ + RequestId getRequestId() const; +}; + +// FIXME aconway 2007-02-01: Method context only required on Handler +// functions, not on Proxy functions. If we add set/getChannel(ChannelAdapter*) +// on AMQBody and set it during decodeing then we could get rid of the context. + + + +}} // namespace qpid::framing + + + +#endif /*!_framing_MethodContext_h*/ diff --git a/qpid/cpp/lib/common/framing/OutputHandler.h b/qpid/cpp/lib/common/framing/OutputHandler.h new file mode 100644 index 0000000000..9ffd4227d8 --- /dev/null +++ b/qpid/cpp/lib/common/framing/OutputHandler.h @@ -0,0 +1,39 @@ +#ifndef _OutputHandler_ +#define _OutputHandler_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <boost/noncopyable.hpp> + +namespace qpid { +namespace framing { +class AMQFrame; + +class OutputHandler : private boost::noncopyable { + public: + virtual ~OutputHandler() {} + virtual void send(AMQFrame* frame) = 0; +}; + +}} + + +#endif diff --git a/qpid/cpp/lib/common/framing/ProtocolInitiation.cpp b/qpid/cpp/lib/common/framing/ProtocolInitiation.cpp new file mode 100644 index 0000000000..de53488f7b --- /dev/null +++ b/qpid/cpp/lib/common/framing/ProtocolInitiation.cpp @@ -0,0 +1,63 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <ProtocolInitiation.h> + +namespace qpid { +namespace framing { + +ProtocolInitiation::ProtocolInitiation(){} + +ProtocolInitiation::ProtocolInitiation(uint8_t _major, uint8_t _minor) : version(_major, _minor) {} + +ProtocolInitiation::ProtocolInitiation(ProtocolVersion p) : version(p) {} + +ProtocolInitiation::~ProtocolInitiation(){} + +void ProtocolInitiation::encode(Buffer& buffer){ + buffer.putOctet('A'); + buffer.putOctet('M'); + buffer.putOctet('Q'); + buffer.putOctet('P'); + buffer.putOctet(1);//class + buffer.putOctet(1);//instance + buffer.putOctet(version.getMajor()); + buffer.putOctet(version.getMinor()); +} + +bool ProtocolInitiation::decode(Buffer& buffer){ + if(buffer.available() >= 8){ + buffer.getOctet();//A + buffer.getOctet();//M + buffer.getOctet();//Q + buffer.getOctet();//P + buffer.getOctet();//class + buffer.getOctet();//instance + version.setMajor(buffer.getOctet()); + version.setMinor(buffer.getOctet()); + return true; + }else{ + return false; + } +} + +//TODO: this should prbably be generated from the spec at some point to keep the version numbers up to date + +}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/ProtocolInitiation.h b/qpid/cpp/lib/common/framing/ProtocolInitiation.h new file mode 100644 index 0000000000..ed7b59e94e --- /dev/null +++ b/qpid/cpp/lib/common/framing/ProtocolInitiation.h @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <amqp_types.h> +#include <Buffer.h> +#include <AMQDataBlock.h> +#include <ProtocolVersion.h> + +#ifndef _ProtocolInitiation_ +#define _ProtocolInitiation_ + +namespace qpid { +namespace framing { + +class ProtocolInitiation : public AMQDataBlock +{ +private: + ProtocolVersion version; + +public: + ProtocolInitiation(); + ProtocolInitiation(uint8_t major, uint8_t minor); + ProtocolInitiation(ProtocolVersion p); + virtual ~ProtocolInitiation(); + virtual void encode(Buffer& buffer); + virtual bool decode(Buffer& buffer); + inline virtual uint32_t size() const { return 8; } + inline uint8_t getMajor() const { return version.getMajor(); } + inline uint8_t getMinor() const { return version.getMinor(); } + inline ProtocolVersion getVersion() const { return version; } +}; + +} +} + + +#endif diff --git a/qpid/cpp/lib/common/framing/ProtocolVersion.cpp b/qpid/cpp/lib/common/framing/ProtocolVersion.cpp new file mode 100644 index 0000000000..fd4b1a645f --- /dev/null +++ b/qpid/cpp/lib/common/framing/ProtocolVersion.cpp @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <ProtocolVersion.h> +#include <sstream> + +using namespace qpid::framing; + +const std::string ProtocolVersion::toString() const +{ + std::stringstream ss; + ss << major_ << "-" << minor_; + return ss.str(); +} + +ProtocolVersion& ProtocolVersion::operator=(ProtocolVersion p) +{ + major_ = p.major_; + minor_ = p.minor_; + return *this; +} + +bool ProtocolVersion::operator==(ProtocolVersion p) const +{ + return major_ == p.major_ && minor_ == p.minor_; +} + diff --git a/qpid/cpp/lib/common/framing/ProtocolVersion.h b/qpid/cpp/lib/common/framing/ProtocolVersion.h new file mode 100644 index 0000000000..5e1429c1ea --- /dev/null +++ b/qpid/cpp/lib/common/framing/ProtocolVersion.h @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _ProtocolVersion_ +#define _ProtocolVersion_ + +#include <amqp_types.h> + +namespace qpid +{ +namespace framing +{ + +class ProtocolVersion +{ +private: + uint8_t major_; + uint8_t minor_; + +public: + ProtocolVersion(uint8_t _major=0, uint8_t _minor=0) + : major_(_major), minor_(_minor) {} + + uint8_t getMajor() const { return major_; } + void setMajor(uint8_t major) { major_ = major; } + uint8_t getMinor() const { return minor_; } + void setMinor(uint8_t minor) { minor_ = minor; } + const std::string toString() const; + + ProtocolVersion& operator=(ProtocolVersion p); + + bool operator==(ProtocolVersion p) const; + bool operator!=(ProtocolVersion p) const { return ! (*this == p); } +}; + +} // namespace framing +} // namespace qpid + + +#endif // ifndef _ProtocolVersion_ diff --git a/qpid/cpp/lib/common/framing/ProtocolVersionException.cpp b/qpid/cpp/lib/common/framing/ProtocolVersionException.cpp new file mode 100644 index 0000000000..9088422f6f --- /dev/null +++ b/qpid/cpp/lib/common/framing/ProtocolVersionException.cpp @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <boost/format.hpp> +#include <ProtocolVersionException.h> + + +using namespace qpid::framing; + +void ProtocolVersionException::init(const std::string& msg) +{ + whatStr = boost::str( + boost::format("ProtocolVersionException: %s found: %s") + % versionFound.toString() % msg); +} + diff --git a/qpid/cpp/lib/common/framing/ProtocolVersionException.h b/qpid/cpp/lib/common/framing/ProtocolVersionException.h new file mode 100644 index 0000000000..8e2de8b843 --- /dev/null +++ b/qpid/cpp/lib/common/framing/ProtocolVersionException.h @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#ifndef _ProtocolVersionException_ +#define _ProtocolVersionException_ + +#include <Exception.h> +#include <ProtocolVersion.h> +#include <string> +#include <vector> + +namespace qpid { +namespace framing { + +class ProtocolVersionException : public qpid::Exception +{ +protected: + ProtocolVersion versionFound; + +public: + ~ProtocolVersionException() throw() {} + + template <class T> + ProtocolVersionException( + ProtocolVersion ver, const T& msg) throw () : versionFound(ver) + { init(boost::lexical_cast<std::string>(msg)); } + + template <class T> + ProtocolVersionException(const T& msg) throw () + { init(boost::lexical_cast<std::string>(msg)); } + + private: + void init(const std::string& msg); +}; + +}} // namespace qpid::framing + +#endif //ifndef _ProtocolVersionException_ diff --git a/qpid/cpp/lib/common/framing/Proxy.cpp b/qpid/cpp/lib/common/framing/Proxy.cpp new file mode 100644 index 0000000000..0b2a882a49 --- /dev/null +++ b/qpid/cpp/lib/common/framing/Proxy.cpp @@ -0,0 +1,32 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "Proxy.h" +#include "ChannelAdapter.h" +#include "ProtocolVersion.h" + +namespace qpid { +namespace framing { + +Proxy::~Proxy() {} + +ProtocolVersion Proxy::getProtocolVersion() const { + return channel.getVersion(); +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/Proxy.h b/qpid/cpp/lib/common/framing/Proxy.h new file mode 100644 index 0000000000..8ed46ed748 --- /dev/null +++ b/qpid/cpp/lib/common/framing/Proxy.h @@ -0,0 +1,51 @@ +#ifndef _framing_Proxy_h +#define _framing_Proxy_h + +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "ProtocolVersion.h" + +namespace qpid { +namespace framing { + +class ChannelAdapter; +class FieldTable; +class Content; + +/** + * Base class for proxies. + */ +class Proxy +{ + + public: + Proxy(ChannelAdapter& ch) : channel(ch) {} + virtual ~Proxy(); + + ProtocolVersion getProtocolVersion() const; + + protected: + ChannelAdapter& channel; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_Proxy_h*/ diff --git a/qpid/cpp/lib/common/framing/Requester.cpp b/qpid/cpp/lib/common/framing/Requester.cpp new file mode 100644 index 0000000000..9ee809e2ee --- /dev/null +++ b/qpid/cpp/lib/common/framing/Requester.cpp @@ -0,0 +1,40 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <boost/format.hpp> + +#include "Requester.h" +#include "QpidError.h" + +namespace qpid { +namespace framing { + +Requester::Requester() : lastId(0), responseMark(0) {} + +void Requester::sending(AMQRequestBody::Data& request) { + request.requestId = ++lastId; + request.responseMark = responseMark; +} + +void Requester::processed(const AMQResponseBody::Data& response) { + responseMark = response.responseId; + firstAckRequest = response.requestId; + lastAckRequest = firstAckRequest + response.batchOffset; +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/Requester.h b/qpid/cpp/lib/common/framing/Requester.h new file mode 100644 index 0000000000..dcc4460041 --- /dev/null +++ b/qpid/cpp/lib/common/framing/Requester.h @@ -0,0 +1,67 @@ +#ifndef _framing_Requester_h +#define _framing_Requester_h + +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <set> +#include "AMQRequestBody.h" +#include "AMQResponseBody.h" + +namespace qpid { +namespace framing { + +class AMQRequestBody; +class AMQResponseBody; + +/** + * Manage request IDs and the response mark for locally initiated requests. + * + * THREAD UNSAFE: This class is called as frames are sent or received + * sequentially on a connection, so it does not need to be thread safe. + */ +class Requester +{ + public: + Requester(); + + /** Called before sending a request to set request data. */ + void sending(AMQRequestBody::Data&); + + /** Called after processing a response. */ + void processed(const AMQResponseBody::Data&); + + /** Get the next request id to be used. */ + RequestId getNextId() { return lastId + 1; } + /** Get the first request acked by this response */ + RequestId getFirstAckRequest() { return firstAckRequest; } + /** Get the last request acked by this response */ + RequestId getLastAckRequest() { return lastAckRequest; } + + private: + RequestId lastId; + ResponseId responseMark; + ResponseId firstAckRequest; + ResponseId lastAckRequest; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_Requester_h*/ diff --git a/qpid/cpp/lib/common/framing/Responder.cpp b/qpid/cpp/lib/common/framing/Responder.cpp new file mode 100644 index 0000000000..c8c5ce8dcc --- /dev/null +++ b/qpid/cpp/lib/common/framing/Responder.cpp @@ -0,0 +1,43 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include <boost/format.hpp> + +#include "Responder.h" +#include "QpidError.h" + +namespace qpid { +namespace framing { + +Responder::Responder() : lastId(0), responseMark(0) {} + +void Responder::received(const AMQRequestBody::Data& request) { + if (request.responseMark < responseMark || request.responseMark > lastId) + THROW_QPID_ERROR( + PROTOCOL_ERROR, boost::format("Invalid response mark %d.") + %request.responseMark); + responseMark = request.responseMark; +} + +void Responder::sending(AMQResponseBody::Data& response) { + response.responseId = ++lastId; + assert(response.requestId); // Should be already set. + response.batchOffset = 0; +} + +}} // namespace qpid::framing + diff --git a/qpid/cpp/lib/common/framing/Responder.h b/qpid/cpp/lib/common/framing/Responder.h new file mode 100644 index 0000000000..0e1785256b --- /dev/null +++ b/qpid/cpp/lib/common/framing/Responder.h @@ -0,0 +1,61 @@ +#ifndef _framing_Responder_h +#define _framing_Responder_h + +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "AMQRequestBody.h" +#include "AMQResponseBody.h" + +namespace qpid { +namespace framing { + +/** + * Manage response ids and response mark remotely initianted requests. + * + * THREAD UNSAFE: This class is called as frames are sent or received + * sequentially on a connection, so it does not need to be thread safe. + */ +class Responder +{ + public: + Responder(); + + /** Called after receiving a request. */ + void received(const AMQRequestBody::Data& request); + + /** Called before sending a response to set respose data. */ + void sending(AMQResponseBody::Data& response); + + /** Get the ID of the highest response acknowledged by the peer. */ + ResponseId getResponseMark() { return responseMark; } + + // TODO aconway 2007-01-14: Batching support - store unsent + // Response for equality comparison with subsequent responses. + // + + private: + ResponseId lastId; + ResponseId responseMark; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_Responder_h*/ diff --git a/qpid/cpp/lib/common/framing/Value.cpp b/qpid/cpp/lib/common/framing/Value.cpp new file mode 100644 index 0000000000..03e005e384 --- /dev/null +++ b/qpid/cpp/lib/common/framing/Value.cpp @@ -0,0 +1,122 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <Value.h> +#include <Buffer.h> +#include <FieldTable.h> +#include <QpidError.h> +#include <sstream> + +namespace qpid { +namespace framing { + +Value::~Value() {} + +void StringValue::encode(Buffer& buffer){ + buffer.putLongString(value); +} +void StringValue::decode(Buffer& buffer){ + buffer.getLongString(value); +} + +void IntegerValue::encode(Buffer& buffer){ + buffer.putLong((uint32_t) value); +} +void IntegerValue::decode(Buffer& buffer){ + value = buffer.getLong(); +} + +void TimeValue::encode(Buffer& buffer){ + buffer.putLongLong(value); +} +void TimeValue::decode(Buffer& buffer){ + value = buffer.getLongLong(); +} + +void DecimalValue::encode(Buffer& buffer){ + buffer.putOctet(value.decimals); + buffer.putLong(value.value); +} +void DecimalValue::decode(Buffer& buffer){ + value = Decimal(buffer.getLong(), buffer.getOctet()); +} + +void FieldTableValue::encode(Buffer& buffer){ + buffer.putFieldTable(value); +} +void FieldTableValue::decode(Buffer& buffer){ + buffer.getFieldTable(value); +} + +std::auto_ptr<Value> Value::decode_value(Buffer& buffer) +{ + std::auto_ptr<Value> value; + uint8_t type = buffer.getOctet(); + switch(type){ + case 'S': + value.reset(new StringValue()); + break; + case 'I': + value.reset(new IntegerValue()); + break; + case 'D': + value.reset(new DecimalValue()); + break; + case 'T': + value.reset(new TimeValue()); + break; + case 'F': + value.reset(new FieldTableValue()); + break; + + //non-standard types, introduced in java client for JMS compliance + case 'x': + value.reset(new BinaryValue()); + break; + default: + std::stringstream out; + out << "Unknown field table value type: " << type; + THROW_QPID_ERROR(FRAMING_ERROR, out.str()); + } + value->decode(buffer); + return value; +} + +EmptyValue::~EmptyValue() {} + +void EmptyValue::print(std::ostream& out) const +{ + out << "<empty field value>"; +} + +std::ostream& operator<<(std::ostream& out, const Value& v) { + v.print(out); + return out; +} + +std::ostream& operator<<(std::ostream& out, const Decimal& d) +{ + return out << "Decimal(" << d.value << "," << d.decimals << ")"; +} + +}} + + + diff --git a/qpid/cpp/lib/common/framing/Value.h b/qpid/cpp/lib/common/framing/Value.h new file mode 100644 index 0000000000..8752b02f40 --- /dev/null +++ b/qpid/cpp/lib/common/framing/Value.h @@ -0,0 +1,171 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <iostream> +#include <vector> +#include <amqp_types.h> +#include <FieldTable.h> + +#ifndef _Value_ +#define _Value_ + +namespace qpid { +namespace framing { + +class Buffer; + +/** + * Represents a decimal value. + * No arithmetic functionality for now, we only care about encoding/decoding. + */ +struct Decimal { + uint32_t value; + uint8_t decimals; + + Decimal(uint32_t value_=0, uint8_t decimals_=0) : value(value_), decimals(decimals_) {} + bool operator==(const Decimal& d) const { + return decimals == d.decimals && value == d.value; + } + bool operator!=(const Decimal& d) const { return !(*this == d); } +}; + +std::ostream& operator<<(std::ostream& out, const Decimal& d); + +/** + * Polymorpic base class for values. + */ +class Value { + public: + virtual ~Value(); + virtual uint32_t size() const = 0; + virtual char getType() const = 0; + virtual void encode(Buffer& buffer) = 0; + virtual void decode(Buffer& buffer) = 0; + virtual bool operator==(const Value&) const = 0; + bool operator!=(const Value& v) const { return !(*this == v); } + virtual void print(std::ostream& out) const = 0; + + /** Create a new value by decoding from the buffer */ + static std::auto_ptr<Value> decode_value(Buffer& buffer); +}; + +std::ostream& operator<<(std::ostream& out, const Value& d); + + +/** + * Template for common operations on Value sub-classes. + */ +template <class T> +class ValueOps : public Value +{ + protected: + T value; + public: + ValueOps() {} + ValueOps(const T& v) : value(v) {} + const T& getValue() const { return value; } + T& getValue() { return value; } + + virtual bool operator==(const Value& v) const { + const ValueOps<T>* vo = dynamic_cast<const ValueOps<T>*>(&v); + if (vo == 0) return false; + else return value == vo->value; + } + + void print(std::ostream& out) const { out << value; } +}; + + +class StringValue : public ValueOps<std::string> { + public: + StringValue(const std::string& v) : ValueOps<std::string>(v) {} + StringValue() {} + virtual uint32_t size() const { return 4 + value.length(); } + virtual char getType() const { return 'S'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + +class IntegerValue : public ValueOps<int> { + public: + IntegerValue(int v) : ValueOps<int>(v) {} + IntegerValue(){} + virtual uint32_t size() const { return 4; } + virtual char getType() const { return 'I'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + +class TimeValue : public ValueOps<uint64_t> { + public: + TimeValue(uint64_t v) : ValueOps<uint64_t>(v){} + TimeValue(){} + virtual uint32_t size() const { return 8; } + virtual char getType() const { return 'T'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + +class DecimalValue : public ValueOps<Decimal> { + public: + DecimalValue(const Decimal& d) : ValueOps<Decimal>(d) {} + DecimalValue(uint32_t value_=0, uint8_t decimals_=0) : + ValueOps<Decimal>(Decimal(value_, decimals_)){} + virtual uint32_t size() const { return 5; } + virtual char getType() const { return 'D'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + + +class FieldTableValue : public ValueOps<FieldTable> { + public: + FieldTableValue(const FieldTable& v) : ValueOps<FieldTable>(v){} + FieldTableValue(){} + virtual uint32_t size() const { return 4 + value.size(); } + virtual char getType() const { return 'F'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + +class EmptyValue : public Value { + public: + ~EmptyValue(); + virtual uint32_t size() const { return 0; } + virtual char getType() const { return 0; } + virtual void encode(Buffer& ) {} + virtual void decode(Buffer& ) {} + virtual bool operator==(const Value& v) const { + return dynamic_cast<const EmptyValue*>(&v); + } + virtual void print(std::ostream& out) const; +}; + +//non-standard types, introduced in java client for JMS compliance +class BinaryValue : public StringValue { + public: + BinaryValue(const std::string& v) : StringValue(v) {} + BinaryValue() {} + virtual char getType() const { return 'x'; } +}; + +}} // qpid::framing + +#endif diff --git a/qpid/cpp/lib/common/framing/amqp_framing.h b/qpid/cpp/lib/common/framing/amqp_framing.h new file mode 100644 index 0000000000..62f87352f8 --- /dev/null +++ b/qpid/cpp/lib/common/framing/amqp_framing.h @@ -0,0 +1,36 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <amqp_types.h> +#include <AMQFrame.h> +#include <AMQBody.h> +#include <BodyHandler.h> +#include <AMQMethodBody.h> +#include <AMQHeaderBody.h> +#include <AMQContentBody.h> +#include <AMQHeartbeatBody.h> +#include <AMQP_MethodVersionMap.h> +#include <InputHandler.h> +#include <OutputHandler.h> +#include <InitiationHandler.h> +#include <ProtocolInitiation.h> +#include <BasicHeaderProperties.h> +#include <ProtocolVersion.h> +#include <ProtocolVersionException.h> diff --git a/qpid/cpp/lib/common/framing/amqp_types.h b/qpid/cpp/lib/common/framing/amqp_types.h new file mode 100644 index 0000000000..49963bd570 --- /dev/null +++ b/qpid/cpp/lib/common/framing/amqp_types.h @@ -0,0 +1,57 @@ +#ifndef AMQP_TYPES_H +#define AMQP_TYPES_H +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** \file + * Type definitions and forward declarations of all types used to + * in AMQP messages. + */ + +#include <string> +#ifdef _WINDOWS +#include "windows.h" +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; +#endif +#ifndef _WINDOWS +#include "stdint.h" +#endif + +namespace qpid { +namespace framing { + +using std::string; +typedef uint16_t ChannelId; +typedef uint64_t RequestId; +typedef uint64_t ResponseId; +typedef uint32_t BatchOffset; +typedef uint16_t ClassId; +typedef uint16_t MethodId; +typedef uint16_t ReplyCode; + +// Types represented by classes. +class Content; +class FieldTable; +}} // namespace qpid::framing +#endif diff --git a/qpid/cpp/lib/common/framing/amqp_types_full.h b/qpid/cpp/lib/common/framing/amqp_types_full.h new file mode 100644 index 0000000000..6a24a99d38 --- /dev/null +++ b/qpid/cpp/lib/common/framing/amqp_types_full.h @@ -0,0 +1,36 @@ +#ifndef _framing_amqp_types_decl_h +#define _framing_amqp_types_decl_h + +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** \file + * Type definitions and full declarations of all types used to + * in AMQP messages. + * + * Its better to include amqp_types.h in another header instead of this file + * unless the header actually needs the full declarations. Including + * full declarations when forward declarations would do increases compile + * times. + */ + +#include "amqp_types.h" +#include "FramingContent.h" +#include "FieldTable.h" + +#endif /*!_framing_amqp_types_decl_h*/ |