diff options
author | Aidan Skinner <aidan@apache.org> | 2008-04-15 12:14:00 +0000 |
---|---|---|
committer | Aidan Skinner <aidan@apache.org> | 2008-04-15 12:14:00 +0000 |
commit | eaec25d7ebc6f54d336b4a60318d20bf48a302de (patch) | |
tree | d7759823a6ba0858034539a0bda3813fdabe2d09 | |
parent | 0e22f5b286209658a88d9c3e731cdf491139c659 (diff) | |
download | qpid-python-eaec25d7ebc6f54d336b4a60318d20bf48a302de.tar.gz |
Merged revisions 647798-648216 via svnmerge from
https://svn.apache.org/repos/asf/incubator/qpid/trunk
........
r647800 | gsim | 2008-04-14 14:57:36 +0100 (Mon, 14 Apr 2008) | 3 lines
QPID-648: keep the sasl_conn member in the handler to avoid the need for friend declaration
........
r647887 | rhs | 2008-04-14 17:33:40 +0100 (Mon, 14 Apr 2008) | 1 line
fixed encode/decode of structs in command/control arguments to include the type code when specified
........
r647903 | gsim | 2008-04-14 17:56:35 +0100 (Mon, 14 Apr 2008) | 4 lines
Use the errata file for final 0-10 that has a type code for xids without which dtx.recover can't work.
Return the indoubt xids as an array of struct32s each of which contains an encoded xid.
........
r647937 | aconway | 2008-04-14 20:14:10 +0100 (Mon, 14 Apr 2008) | 7 lines
https://bugzilla.redhat.com/show_bug.cgi?id=441080 from Ville Skytt?\195?\164 (ville.skytta@iki.fi)
qpidc's build does not use $RPM_OPT_FLAGS so it misses some compiler security
features, and strips installed executables thus preventing rpmbuild from doing
its job and creating a useful debuginfo package. Candidate fix for both
attached, build tested only.
........
r647940 | gsim | 2008-04-14 20:19:27 +0100 (Mon, 14 Apr 2008) | 3 lines
QPID-648: more flexible sasl implementation (patch provided by mfarrellee@redhat.com)
........
r647990 | gsim | 2008-04-14 21:34:30 +0100 (Mon, 14 Apr 2008) | 3 lines
Fix to struct32 encoding
........
r647999 | gsim | 2008-04-14 22:11:25 +0100 (Mon, 14 Apr 2008) | 4 lines
* Fix interpretation of accept-mode, 0 == EXPLICIT
* Ensure accepts are taken into account in command sequence
........
r648013 | nsantos | 2008-04-14 22:42:21 +0100 (Mon, 14 Apr 2008) | 1 line
fix home dir permissions
........
r648095 | aconway | 2008-04-15 02:58:05 +0100 (Tue, 15 Apr 2008) | 2 lines
Struct32 encoding
........
r648194 | gsim | 2008-04-15 10:40:28 +0100 (Tue, 15 Apr 2008) | 3 lines
Remove deleted file from distribution list.
........
r648196 | gsim | 2008-04-15 10:41:48 +0100 (Tue, 15 Apr 2008) | 2 lines
QPID-648: Get list of supported mechanisms from sasl lib. (Patch from mfarrellee@redhat.com)
........
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/thegreatmerge@648218 13f79535-47bb-0310-9956-ffa450edef68
37 files changed, 466 insertions, 202 deletions
diff --git a/qpid/cpp/qpidc.spec.in b/qpid/cpp/qpidc.spec.in index 2819f02c45..6320bf16b0 100644 --- a/qpid/cpp/qpidc.spec.in +++ b/qpid/cpp/qpidc.spec.in @@ -5,7 +5,7 @@ Name: @PACKAGE@ Version: @VERSION@ -Release: 25%{?dist} +Release: 28%{?dist} Summary: Libraries for Qpid C++ client applications Group: System Environment/Libraries License: Apache Software License @@ -80,14 +80,15 @@ exit 0 %setup -q %build -%configure --disable-static --without-cpg CXXFLAGS="-g -O3 -DNDEBUG" +CXXFLAGS="%{optflags} -DNDEBUG -O3" \ +%configure --disable-static --without-cpg make %{?_smp_mflags} # Remove this generated perl file, we don't need it and it upsets rpmlint. rm docs/api/html/installdox %install rm -rf %{buildroot} -make install-strip DESTDIR=%{buildroot} +make install DESTDIR=%{buildroot} install -Dp -m0755 etc/qpidd %{buildroot}%{_initrddir}/qpidd install -d -m0755 %{buildroot}%{_localstatedir}/lib/qpidd rm -f %{buildroot}%_libdir/*.a @@ -130,7 +131,7 @@ make check %_libdir/libqpidcluster.so.0.1.0 %_sbindir/%{qpidd} %{_initrddir}/%{qpidd} -%_localstatedir/lib/qpidd +%attr(755, qpidd, qpidd) %_localstatedir/lib/qpidd %doc %_mandir/man1/%{qpidd}.* %files -n %{qpidd}-devel @@ -164,6 +165,10 @@ fi /sbin/ldconfig %changelog +* Mon Apr 14 2008 Nuno Santos <nsantos@redhat.com> - 0.2-28 + - Fix home dir permissions + - Bumped for Fedora 9 + * Mon Mar 31 2008 Nuno Santos <nsantos@redhat.com> - 0.2-25 - Create user qpidd, start qpidd service as qpidd diff --git a/qpid/cpp/rubygen/0-10/specification.rb b/qpid/cpp/rubygen/0-10/specification.rb index 7e73d1c91e..25618116cb 100755 --- a/qpid/cpp/rubygen/0-10/specification.rb +++ b/qpid/cpp/rubygen/0-10/specification.rb @@ -2,6 +2,13 @@ $: << ".." # Include .. in load path require 'cppgen' + +class UnknownStructSub + def visitable?() true end + def fqclassname() "UnknownStruct" end +end + + class Specification < CppGen def initialize(outdir, amqp) super(outdir, amqp) @@ -27,17 +34,6 @@ class Specification < CppGen end end - # class constants - - def class_h(c) - genl "const uint8_t CODE=#{c.code};" - genl "extern const char* NAME;" - end - - def class_cpp(c) - genl "const char* NAME=\"#{c.fqname}\";" - end - def visitable?(x) x.code and x.size=="4" end # Used by structs, commands and controls. @@ -120,7 +116,7 @@ class Specification < CppGen def action_cpp(a) action_struct_cpp(a) { scope("void #{a.classname}::Handler::#{a.funcname}(", ")") { - genl a.unused_parameters.join(",\n") + genl a.unused_parameters.join(",\n") } scope { genl "assert(0);" @@ -146,20 +142,44 @@ class Specification < CppGen # segment-type and track are are built in domain_h d unless ["track","segment-type"].include?(d.name) } - # Domains/structs that must be generated early because they are used by - # other definitions: - @amqp.classes.select{ |c| pregenerate_class?(c) }.each { |c| - namespace(c.nsname) { - c.collect_all(AmqpDomain).each { |d| domain_h d if pregenerate? d } - c.collect_all(AmqpStruct).each { |s| genl "class #{s.classname};" if pregenerate? s } + each_class_ns { |c| + genl "const uint8_t CODE=#{c.code};" # class code + genl "extern const char* NAME;" + c.each_descendant { |x| + case x + when AmqpDomain then domain_h x + when AmqpStruct then genl "class #{x.classname};" + when AmqpAction then genl "class #{x.classname};" + end } } - # Now dependent domains/structs and actions + } + } + end + + # Generate struct definitions into a separate header file so the + # can be included by Struct32.h without circularity. + def gen_structs() + h_file("#{@dir}/structs") { + include "#{@dir}/specification_fwd" + include "#{@dir}/Map.h" + include "#{@dir}/Array.h" + include "#{@dir}/complex_types.h" + include "#{@dir}/UnknownStruct.h" + include "#{@dir}/Packer.h" + namespace(@ns) { each_class_ns { |c| - class_h c - c.collect_all(AmqpDomain).each { |d| domain_h d unless pregenerate? d} - c.collect_all(AmqpStruct).each { |s| genl "class #{s.classname};" unless pregenerate? s } - c.collect_all(AmqpAction).each { |a| genl "class #{a.classname};" unless pregenerate? a } + c.collect_all(AmqpStruct).each { |s| struct_h s } + } + } + } + + cpp_file("#{@dir}/structs") { + include "#{@dir}/structs" + include "#{@dir}/Struct32" + namespace(@ns) { + each_class_ns { |c| + c.collect_all(AmqpStruct).each { |s| struct_cpp(s) } } } } @@ -168,23 +188,19 @@ class Specification < CppGen # Generate the specification files def gen_specification() h_file("#{@dir}/specification") { - include "#{@dir}/specification_fwd" - include "#{@dir}/all_built_in_types" + include "#{@dir}/specification_fwd.h" + include "#{@dir}/Map.h" + include "#{@dir}/Array.h" + include "#{@dir}/UnknownType.h" + include "#{@dir}/complex_types.h" + include "#{@dir}/Struct32" include "#{@dir}/Packer.h" include "<iosfwd>" - namespace(@ns) { - # Structs that must be generated early because - # they are used by other definitions: - each_class_ns { |c| - c.collect_all(AmqpStruct).each { |s| struct_h s if pregenerate? s } - } - # Now dependent domains/structs and actions + namespace(@ns) { each_class_ns { |c| - c.collect_all(AmqpStruct).each { |s| struct_h s unless pregenerate? s} c.collect_all(AmqpAction).each { |a| action_h a } } - } - } + }} cpp_file("#{@dir}/specification") { include "#{@dir}/specification" @@ -193,14 +209,13 @@ class Specification < CppGen ["Command","Control", "Struct"].each { |x| include "#{@dir}/Apply#{x}" } namespace(@ns) { each_class_ns { |c| - class_cpp c + genl "const char* NAME=\"#{c.fqname}\";" c.actions.each { |a| action_cpp a} - c.collect_all(AmqpStruct).each { |s| struct_cpp(s) } } } } end - + def gen_proxy() h_file("#{@dir}/ProxyTemplate.h") { include "#{@dir}/specification" @@ -247,10 +262,14 @@ class Specification < CppGen genl "virtual void visit(#{const}#{s.fqclassname}& x) { this->invoke(x); }" }} end - + def gen_visitor(base, subs) + if base=="Struct" + subs << UnknownStructSub.new + end + h_file("#{@dir}/#{base}Visitor.h") { - include "#{@dir}/specification" + include base=="Struct" ? "#{@dir}/structs" : "#{@dir}/specification" namespace("#{@ns}") { visitor_interface_h(base, subs, false) visitor_interface_h(base, subs, true) @@ -265,12 +284,13 @@ class Specification < CppGen } } end - + def gen_holder(base, subs) - name=base.caps+"Holder" + name= (base=="Struct") ? "Struct32" : base+"Holder" h_file("#{@dir}/#{name}") { include "#{@dir}/Apply#{base}" include "#{@dir}/Holder" + include base=="Struct" ? "#{@dir}/structs" : "#{@dir}/specification" namespace(@ns){ namespace("#{base.downcase}_max") { gen "template <class M, class X> " @@ -284,7 +304,7 @@ class Specification < CppGen } genl "static const int MAX=#{last}::max;" } - holder_base="amqp_0_10::Holder<#{base}Holder, #{base}, #{base.downcase}_max::MAX>" + holder_base="amqp_0_10::Holder<#{name}, #{base}, #{base.downcase}_max::MAX>" struct("#{name}", "public #{holder_base}") { genl "#{name}() {}" genl "template <class T> explicit #{name}(const T& t) : #{holder_base}(t) {}" @@ -308,8 +328,16 @@ class Specification < CppGen subs.each { |s| genl "case 0x#{s.full_code.to_s(16)}: *this=in_place<#{s.fqclassname}>(); break;" } - genl "default: throw CommandInvalidException(QPID_MSG(\"Invalid class-#{base.downcase} key \" << std::hex << key));" - }} + genl "default: " + indent { + if (base=="Struct") + genl "*this=in_place<UnknownStruct>(classCode, code);" + else + genl "throw CommandInvalidException(QPID_MSG(\"Invalid class-#{base.downcase} key \" << std::hex << key));" + end + } + } + } genl genl "std::ostream& operator<<(std::ostream& o, const #{name}& h) { return h.get() ? (o << *h.get()) : (o << \"<empty #{name}>\"); }" } @@ -325,9 +353,10 @@ class Specification < CppGen gen_specification_fwd gen_specification gen_proxy + gen_structs gen_visitable("Command", @amqp.collect_all(AmqpCommand)) gen_visitable("Control", @amqp.collect_all(AmqpControl)) - gen_visitable("Struct", @amqp.collect_all(AmqpStruct).select { |s| s.code}) + gen_visitable("Struct", @amqp.collect_all(AmqpStruct).select { |s| s.code}) end end diff --git a/qpid/cpp/src/Makefile.am b/qpid/cpp/src/Makefile.am index a31dbdfa9d..4a43a9cc55 100644 --- a/qpid/cpp/src/Makefile.am +++ b/qpid/cpp/src/Makefile.am @@ -104,7 +104,6 @@ libqpidcommon_la_SOURCES = \ $(rgen_common_cpp) \ $(platform_src) \ qpid/amqp_0_10/apply.h \ - qpid/amqp_0_10/all_built_in_types.h \ qpid/amqp_0_10/built_in_types.h \ qpid/amqp_0_10/complex_types.h \ qpid/amqp_0_10/complex_types.cpp \ @@ -112,6 +111,7 @@ libqpidcommon_la_SOURCES = \ qpid/amqp_0_10/Array.cpp \ qpid/amqp_0_10/Body.h \ qpid/amqp_0_10/Header.h \ + qpid/amqp_0_10/Header.cpp \ qpid/amqp_0_10/FrameHeader.h \ qpid/amqp_0_10/FrameHeader.cpp \ qpid/amqp_0_10/Holder.h \ @@ -125,6 +125,8 @@ libqpidcommon_la_SOURCES = \ qpid/amqp_0_10/Unit.cpp \ qpid/amqp_0_10/UnknownType.h \ qpid/amqp_0_10/UnknownType.cpp \ + qpid/amqp_0_10/UnknownStruct.h \ + qpid/amqp_0_10/UnknownStruct.cpp \ qpid/Serializer.h \ qpid/framing/AccumulatedAck.cpp \ qpid/framing/AMQBody.cpp \ diff --git a/qpid/cpp/src/qpid/Serializer.h b/qpid/cpp/src/qpid/Serializer.h index fc53097207..a8ded9f5e0 100644 --- a/qpid/cpp/src/qpid/Serializer.h +++ b/qpid/cpp/src/qpid/Serializer.h @@ -105,7 +105,7 @@ template <class Derived> class Serializer { /** Get the max number of bytes that can be processed under the * current limit. */ - size_t getLimit() const { + size_t bytesRemaining() const { return limit - bytes; } /** Set absolute limit. */ diff --git a/qpid/cpp/src/qpid/amqp_0_10/Frame.cpp b/qpid/cpp/src/qpid/amqp_0_10/Header.cpp index 1140b6058d..669c960e7f 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/Frame.cpp +++ b/qpid/cpp/src/qpid/amqp_0_10/Header.cpp @@ -18,11 +18,17 @@ * under the License. * */ -#include "Frame.h" +#include "Header.h" namespace qpid { namespace amqp_0_10 { -bool Frame::match(const Frame& x) { +std::ostream& operator<<(std::ostream& o, const Header& h) { + o << "Header["; + std::ostream_iterator<Struct32> i(o, " "); + std::copy(h.begin(), h.end(), i); + o << "]"; + return o; } + }} // namespace qpid::amqp_0_10 diff --git a/qpid/cpp/src/qpid/amqp_0_10/Header.h b/qpid/cpp/src/qpid/amqp_0_10/Header.h index 44edcb9f3d..b3498a1c8c 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/Header.h +++ b/qpid/cpp/src/qpid/amqp_0_10/Header.h @@ -21,21 +21,32 @@ * under the License. * */ +#include "qpid/amqp_0_10/built_in_types.h" +#include "qpid/amqp_0_10/Struct32.h" +#include <vector> #include <ostream> namespace qpid { namespace amqp_0_10 { -// FIXME aconway 2008-03-27: TODO -class Header -{ +class Header : public std::vector<Struct32> { public: - template <class S> void serialize(S&) {} - private: + Header() {} + + template <class S> void serialize(S& s) { s.split(*this); } + template <class S> void encode(S& s) const { s(this->begin(), this->end()); } + template <class S> void decode(S& s); }; -// FIXME aconway 2008-03-28: TODO -inline std::ostream& operator<<(std::ostream& o, const Header&) { return o; } +template <class S> void Header::decode(S& s) { + this->clear(); + while (s.bytesRemaining() > 0) { + this->push_back(Struct32()); + s(this->back()); + } +} + +std::ostream& operator<<(std::ostream& o, const Header&); }} // namespace qpid::amqp_0_10 diff --git a/qpid/cpp/src/qpid/amqp_0_10/Holder.h b/qpid/cpp/src/qpid/amqp_0_10/Holder.h index 1664afcc8f..3c734d967f 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/Holder.h +++ b/qpid/cpp/src/qpid/amqp_0_10/Holder.h @@ -73,6 +73,14 @@ class Holder : public framing::Blob<Size, BaseHeld> { apply(s, *this->get()); } + template <class T> T* getIf() { + return (getClassCode()==T::CLASS_CODE && getCode()==T::CODE) ? static_cast<T*>(this->get()) : 0; + } + + template <class T> const T* getIf() const { + return (getClassCode()==T::CLASS_CODE && getCode()==T::CODE) ? static_cast<T*>(this->get()) : 0; + } + private: struct Assign : public ApplyFunctor<void> { Holder& holder; diff --git a/qpid/cpp/src/qpid/amqp_0_10/Map.cpp b/qpid/cpp/src/qpid/amqp_0_10/Map.cpp index 2d32466c3f..b517b8baba 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/Map.cpp +++ b/qpid/cpp/src/qpid/amqp_0_10/Map.cpp @@ -18,7 +18,9 @@ * under the License. * */ -#include "all_built_in_types.h" +#include "Map.h" +#include "qpid/amqp_0_10/Struct32.h" +#include "qpid/amqp_0_10/Array.h" #include <ostream> namespace qpid { diff --git a/qpid/cpp/src/qpid/amqp_0_10/Map.h b/qpid/cpp/src/qpid/amqp_0_10/Map.h index d63eb0cc4e..c0dcf73930 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/Map.h +++ b/qpid/cpp/src/qpid/amqp_0_10/Map.h @@ -171,7 +171,7 @@ template <class S> void Map::decode(S& s) { typename S::ScopedLimit l(s, decodedSize); // Make sure we don't overrun. // FIXME aconway 2008-04-03: replace preview with 0-10: // for ( ; count > 0; --count) { - while (s.getLimit() > 0) { + while (s.bytesRemaining() > 0) { key_type k; MapValue v; s(k)(v); insert(value_type(k,v)); diff --git a/qpid/cpp/src/qpid/amqp_0_10/Unit.cpp b/qpid/cpp/src/qpid/amqp_0_10/Unit.cpp index 1fa6b2e085..75ea1c1b30 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/Unit.cpp +++ b/qpid/cpp/src/qpid/amqp_0_10/Unit.cpp @@ -27,9 +27,10 @@ namespace amqp_0_10 { void Unit::updateVariant() { switch (header.getType()) { case CONTROL: variant=ControlHolder(); break; - case COMMAND: variant=CommandHolder(); - case HEADER: variant=Header(); - case BODY: variant=Body(header.getDataSize()); + case COMMAND: variant=CommandHolder(); break; + case HEADER: variant=Header(); break; + case BODY: variant=Body(header.getDataSize()); break; + default: assert(0); // FIXME aconway 2008-04-14: exception? } } diff --git a/qpid/cpp/src/qpid/amqp_0_10/all_built_in_types.h b/qpid/cpp/src/qpid/amqp_0_10/UnknownStruct.cpp index 1568465004..023e9d08b4 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/all_built_in_types.h +++ b/qpid/cpp/src/qpid/amqp_0_10/UnknownStruct.cpp @@ -1,6 +1,3 @@ -#ifndef QPID_AMQP_0_10_ALL_BUILT_IN_TYPES_H -#define QPID_AMQP_0_10_ALL_BUILT_IN_TYPES_H - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -22,10 +19,16 @@ * */ -#include "built_in_types.h" -#include "Map.h" -#include "Array.h" -#include "UnknownType.h" -#include "complex_types.h" +#include "qpid/amqp_0_10/StructVisitor.h" +#include "qpid/amqp_0_10/UnknownStruct.h" + +namespace qpid { +namespace amqp_0_10 { + +void UnknownStruct::accept(Visitor& v) { v.visit(*this); } +void UnknownStruct::accept(ConstVisitor& v) const { v.visit(*this); } +std::ostream& operator<<(std::ostream& o, const UnknownStruct& u) { + return o << "UnknownStruct[class=" << u.classCode << " code=" << u.code << "]"; +} -#endif /*!QPID_AMQP_0_10_ALL_BUILT_IN_TYPES_H*/ +}} // namespace qpid::amqp_0_10 diff --git a/qpid/cpp/src/qpid/amqp_0_10/UnknownStruct.h b/qpid/cpp/src/qpid/amqp_0_10/UnknownStruct.h new file mode 100644 index 0000000000..d4fc77159b --- /dev/null +++ b/qpid/cpp/src/qpid/amqp_0_10/UnknownStruct.h @@ -0,0 +1,43 @@ +#ifndef QPID_AMQP_0_10_UNKNOWNSTRUCT_H +#define QPID_AMQP_0_10_UNKNOWNSTRUCT_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. + * + */ +#include "qpid/amqp_0_10/complex_types.h" + +namespace qpid { +namespace amqp_0_10 { + +struct UnknownStruct : public Struct, public Vbin32 { + static const uint8_t SIZE=4; + static const uint8_t PACK=2; + + UnknownStruct(uint8_t cc=0, uint8_t c=0) : classCode(cc), code(c) {} + void accept(Visitor&); + void accept(ConstVisitor&) const; + uint8_t classCode, code; +}; + +std::ostream& operator<<(std::ostream&, const UnknownStruct&); + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_UNKNOWNSTRUCT_H*/ diff --git a/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h b/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h index dccb6a4785..f2ada40bba 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h +++ b/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h @@ -137,6 +137,7 @@ typedef SerializableString<Uint8, Uint32> Vbin32; // Forward declare class types. class Map; +class Struct32; class UnknownType; template <class T> struct ArrayDomain; typedef ArrayDomain<UnknownType> Array; @@ -145,13 +146,11 @@ typedef ArrayDomain<UnknownType> Array; struct ByteRanges { template <class S> void serialize(S&) {} }; struct SequenceSet { template <class S> void serialize(S&) {} }; struct List { template <class S> void serialize(S&) {} }; -struct Struct32 { template <class S> void serialize(S&) {} }; // FIXME aconway 2008-03-10: dummy ostream operators inline std::ostream& operator<<(std::ostream& o, const ByteRanges&) { return o; } inline std::ostream& operator<<(std::ostream& o, const SequenceSet&) { return o; } inline std::ostream& operator<<(std::ostream& o, const List&) { return o; } -inline std::ostream& operator<<(std::ostream& o, const Struct32&) { return o; } enum SegmentType { CONTROL, COMMAND, HEADER, BODY }; diff --git a/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp b/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp index 78ddfeb026..b2975f56d1 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp +++ b/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp @@ -19,6 +19,7 @@ * */ +#include "qpid/amqp_0_10/UnknownStruct.h" #include "qpid/amqp_0_10/ApplyCommand.h" #include "qpid/amqp_0_10/ApplyControl.h" #include "qpid/amqp_0_10/ApplyStruct.h" @@ -52,11 +53,21 @@ uint8_t Control::getClassCode() const { return apply(GetClassCode(), *this); } const char* Control::getName() const { return apply(GetName(), *this); } const char* Control::getClassName() const { return apply(GetClassName(), *this); } +// Special cases for UnknownStruct +struct GetStructCode : public GetCode { + using GetCode::operator(); + uint8_t operator()(const UnknownStruct& u) const { return u.code; } +}; + +struct GetStructClassCode : public GetClassCode { + using GetClassCode::operator(); + uint8_t operator()(const UnknownStruct& u) const { return u.classCode; } +}; -uint8_t Struct::getCode() const { return apply(GetCode(), *this); } +uint8_t Struct::getCode() const { return apply(GetStructCode(), *this); } +uint8_t Struct::getClassCode() const { return apply(GetStructClassCode(), *this); } uint8_t Struct::getPack() const { return apply(GetPack(), *this); } uint8_t Struct::getSize() const { return apply(GetSize(), *this); } -uint8_t Struct::getClassCode() const { return apply(GetClassCode(), *this); } struct PrintVisitor { typedef std::ostream& result_type; diff --git a/qpid/cpp/src/qpid/amqp_0_10/complex_types.h b/qpid/cpp/src/qpid/amqp_0_10/complex_types.h index 5d327cc46e..46d2fa9491 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/complex_types.h +++ b/qpid/cpp/src/qpid/amqp_0_10/complex_types.h @@ -93,9 +93,9 @@ std::ostream& operator<<(std::ostream&, const Control&); // Note: only coded structs inherit from Struct. struct StructVisitor; struct ConstStructVisitor; -struct StructHolder; +struct Struct32; struct Struct - : public Visitable<StructVisitor, ConstStructVisitor, StructHolder> + : public Visitable<StructVisitor, ConstStructVisitor, Struct32> { uint8_t getCode() const; uint8_t getPack() const; diff --git a/qpid/cpp/src/qpid/broker/Broker.h b/qpid/cpp/src/qpid/broker/Broker.h index 8d39c6005d..ea29348c16 100644 --- a/qpid/cpp/src/qpid/broker/Broker.h +++ b/qpid/cpp/src/qpid/broker/Broker.h @@ -22,8 +22,6 @@ * */ -#include "config.h" - #include "ConnectionFactory.h" #include "ConnectionToken.h" #include "DirectExchange.h" diff --git a/qpid/cpp/src/qpid/broker/MessageAdapter.cpp b/qpid/cpp/src/qpid/broker/MessageAdapter.cpp index ea2882b474..0e99d923d4 100644 --- a/qpid/cpp/src/qpid/broker/MessageAdapter.cpp +++ b/qpid/cpp/src/qpid/broker/MessageAdapter.cpp @@ -60,7 +60,7 @@ namespace broker{ bool TransferAdapter::requiresAccept(const framing::FrameSet& f) { const framing::Message010TransferBody* b = f.as<framing::Message010TransferBody>(); - return b && b->getAcceptMode(); + return b && b->getAcceptMode() == 0/*EXPLICIT == 0*/; } std::string PreviewAdapter::getExchange(const framing::FrameSet& f) diff --git a/qpid/cpp/src/qpid/broker/PreviewConnection.cpp b/qpid/cpp/src/qpid/broker/PreviewConnection.cpp index 6f411c99d6..ad4497b24e 100644 --- a/qpid/cpp/src/qpid/broker/PreviewConnection.cpp +++ b/qpid/cpp/src/qpid/broker/PreviewConnection.cpp @@ -18,9 +18,6 @@ * under the License. * */ - -#include "config.h" - #include "PreviewConnection.h" #include "SessionState.h" #include "BrokerAdapter.h" @@ -39,10 +36,6 @@ #include <iostream> #include <assert.h> -#if HAVE_SASL -#include <sasl/sasl.h> -#endif - using namespace boost; using namespace qpid::sys; using namespace qpid::framing; @@ -94,9 +87,6 @@ public: PreviewConnection::PreviewConnection(ConnectionOutputHandler* out_, Broker& broker_, const std::string& mgmtId_, bool isLink) : ConnectionState(out_, broker_), -#if HAVE_SASL - sasl_conn(NULL), -#endif adapter(*this, isLink), mgmtClosing(false), mgmtId(mgmtId_) @@ -119,12 +109,6 @@ PreviewConnection::PreviewConnection(ConnectionOutputHandler* out_, Broker& brok } PreviewConnection::~PreviewConnection () { -#if HAVE_LIBSASL2 - if (NULL != sasl_conn) { - sasl_dispose(&sasl_conn); - sasl_conn = NULL; - } -#endif } void PreviewConnection::received(framing::AMQFrame& frame){ diff --git a/qpid/cpp/src/qpid/broker/PreviewConnection.h b/qpid/cpp/src/qpid/broker/PreviewConnection.h index c9e8b115d3..7a8404bf77 100644 --- a/qpid/cpp/src/qpid/broker/PreviewConnection.h +++ b/qpid/cpp/src/qpid/broker/PreviewConnection.h @@ -21,8 +21,6 @@ #ifndef _PreviewConnection_ #define _PreviewConnection_ -#include "config.h" - #include <memory> #include <sstream> #include <vector> @@ -49,19 +47,11 @@ #include <boost/ptr_container/ptr_map.hpp> -#if HAVE_SASL -#include <sasl/sasl.h> -#endif - namespace qpid { namespace broker { class PreviewConnection : public sys::ConnectionInputHandler, public ConnectionState { -#if HAVE_SASL - friend class PreviewConnectionHandler; -#endif - public: PreviewConnection(sys::ConnectionOutputHandler* out, Broker& broker, const std::string& mgmtId, bool isLink = false); ~PreviewConnection (); @@ -86,11 +76,6 @@ class PreviewConnection : public sys::ConnectionInputHandler, public ConnectionS management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args); - protected: -#if HAVE_SASL - sasl_conn_t *sasl_conn; -#endif - private: typedef boost::ptr_map<framing::ChannelId, PreviewSessionHandler> ChannelMap; typedef std::vector<Queue::shared_ptr>::iterator queue_iterator; diff --git a/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp b/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp index 5c5f2f263e..3477b59cb5 100644 --- a/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp +++ b/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp @@ -69,84 +69,187 @@ void PreviewConnectionHandler::handle(framing::AMQFrame& frame) PreviewConnectionHandler::PreviewConnectionHandler(PreviewConnection& connection, bool isClient) : handler(new Handler(connection)) { FieldTable properties; - string mechanisms(PLAIN); + string mechanisms; string locales(en_US); if (isClient) { handler->serverMode = false; }else { +#if HAVE_SASL + if (connection.getBroker().getOptions().auth) { + const char *list; + unsigned int list_len; + int count; + int code = sasl_listmech(handler->sasl_conn, NULL, + "", " ", "", + &list, &list_len, + &count); + + if (SASL_OK != code) { + QPID_LOG(info, "SASL: Mechanism listing failed: " + << sasl_errdetail(handler->sasl_conn)); + + // TODO: Change this to an exception signaling + // server error, when one is available + throw CommandInvalidException("Mechanism listing failed"); + } else { + // TODO: For 0-10 the mechanisms must be returned + // in a list instead of space separated + mechanisms = list; + } + } else { +#endif + // TODO: It would be more proper for this to be ANONYMOUS + mechanisms = PLAIN; +#if HAVE_SASL + } +#endif + + QPID_LOG(info, "SASL: Sending mechanism list: " << mechanisms); + handler->serverMode = true; handler->client.start(99, 0, properties, mechanisms, locales); } } -PreviewConnectionHandler::Handler:: Handler(PreviewConnection& c) : client(c.getOutput()), server(c.getOutput()), - connection(c), serverMode(false) {} +PreviewConnectionHandler::Handler::Handler(PreviewConnection& c) : +#if HAVE_SASL + sasl_conn(NULL), +#endif + client(c.getOutput()), server(c.getOutput()), + connection(c), serverMode(false) +{ +#if HAVE_SASL + if (connection.getBroker().getOptions().auth) { + int code = sasl_server_new(BROKER_SASL_NAME, + NULL, NULL, NULL, NULL, NULL, 0, + &sasl_conn); -void PreviewConnectionHandler::Handler::startOk(const framing::FieldTable& /*clientProperties*/, - const string& mechanism, - const string& response, const string& /*locale*/) + if (SASL_OK != code) { + QPID_LOG(info, "SASL: Connection creation failed: " + << sasl_errdetail(sasl_conn)); + + // TODO: Change this to an exception signaling + // server error, when one is available + throw CommandInvalidException("Unable to perform authentication"); + } + } +#endif +} + +PreviewConnectionHandler::Handler::~Handler() { - //TODO: handle SASL mechanisms more cleverly - if (mechanism == PLAIN) { - QPID_LOG(info, "SASL Plain: Attempting authentication"); - if (response.size() > 0 && response[0] == (char) 0) { - string temp = response.substr(1); - string::size_type i = temp.find((char)0); - string uid = temp.substr(0, i); - string pwd = temp.substr(i + 1); +#if HAVE_SASL + if (NULL != sasl_conn) { + sasl_dispose(&sasl_conn); + sasl_conn = NULL; + } +#endif +} #if HAVE_SASL - if (connection.getBroker().getOptions().auth) { - int code = sasl_server_new(BROKER_SASL_NAME, - NULL, NULL, NULL, NULL, NULL, 0, - &connection.sasl_conn); - - if (SASL_OK != code) { - QPID_LOG(info, "SASL Plain: Connection creation failed: " - << sasl_errdetail(connection.sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw CommandInvalidException("Unable to perform authentication"); - } - - code = sasl_checkpass(connection.sasl_conn, - uid.c_str(), uid.length(), - pwd.c_str(), pwd.length()); - if (SASL_OK == code) { - QPID_LOG(info, "SASL Plain: Authentication accepted for " << uid); - } else { - // See man sasl_errors(3) or sasl/sasl.h for possible errors - QPID_LOG(info, "SASL Plain: Authentication rejected for " - << uid << ": " - << sasl_errdetail(connection.sasl_conn)); - - // TODO: Change this to an exception signaling - // authentication failure, when one is available - throw ConnectionForcedException("Authentication failed"); - } - } else { +void PreviewConnectionHandler::Handler::processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len) +{ + if (SASL_OK == code) { + const void *uid; + + code = sasl_getprop(sasl_conn, + SASL_USERNAME, + &uid); + if (SASL_OK != code) { + QPID_LOG(info, "SASL: Authentication succeeded, username unavailable"); + // TODO: Change this to an exception signaling + // authentication failure, when one is available + throw ConnectionForcedException("Authenticated username unavailable"); + } + + QPID_LOG(info, "SASL: Authentication succeeded for: " << (char *)uid); + + connection.setUserId((char *)uid); + + client.tune(framing::CHANNEL_MAX, + connection.getFrameMax(), + connection.getHeartbeat()); + } else if (SASL_CONTINUE == code) { + string challenge_str(challenge, challenge_len); + + QPID_LOG(debug, "SASL: sending challenge to client"); + + client.secure(challenge_str); + } else { + QPID_LOG(info, "SASL: Authentication failed: " + << sasl_errdetail(sasl_conn)); + + // TODO: Change to more specific exceptions, when they are + // available + switch (code) { + case SASL_NOMECH: + throw ConnectionForcedException("Unsupported mechanism"); + break; + case SASL_TRYAGAIN: + throw ConnectionForcedException("Transient failure, try again"); + break; + default: + throw ConnectionForcedException("Authentication failed"); + break; + } + } +} #endif - QPID_LOG(warning, - "SASL Plain Warning: No Authentication Performed for " - << uid); + +void PreviewConnectionHandler::Handler::startOk(const framing::FieldTable& /*clientProperties*/, #if HAVE_SASL - } + const string& mechanism, + const string& response, +#else + const string& /*mechanism*/, + const string& /*response*/, #endif + const string& /*locale*/) +{ +#if HAVE_SASL + if (connection.getBroker().getOptions().auth) { + const char *challenge; + unsigned int challenge_len; - connection.setUserId(uid); - } + QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism); + int code = sasl_server_start(sasl_conn, + mechanism.c_str(), + response.c_str(), response.length(), + &challenge, &challenge_len); + + processAuthenticationStep(code, challenge, challenge_len); } else { - // The 0-10 spec states that if the client requests a - // mechanism not proposed by the server the server MUST - // close the connection. Assumption here is if we proposed - // a mechanism we'd have a case for it above. - throw NotImplementedException("Unsupported authentication mechanism"); - } - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), connection.getHeartbeat()); +#endif + QPID_LOG(warning, "SASL: No Authentication Performed"); + + // TODO: Figure out what should actually be set in this case + connection.setUserId("anonymous"); + + client.tune(framing::CHANNEL_MAX, + connection.getFrameMax(), + connection.getHeartbeat()); +#if HAVE_SASL + } +#endif } -void PreviewConnectionHandler::Handler::secureOk(const string& /*response*/){} +void PreviewConnectionHandler::Handler::secureOk(const string& +#if HAVE_SASL + response +#endif + ) { +#if HAVE_SASL + int code; + const char *challenge; + unsigned int challenge_len; + + code = sasl_server_step(sasl_conn, + response.c_str(), response.length(), + &challenge, &challenge_len); + + processAuthenticationStep(code, challenge, challenge_len); +#endif +} void PreviewConnectionHandler::Handler::tuneOk(uint16_t /*channelmax*/, uint32_t framemax, uint16_t heartbeat) diff --git a/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h b/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h index 7c3636373a..b71068d81d 100644 --- a/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h +++ b/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h @@ -21,6 +21,8 @@ #ifndef _PreviewConnectionAdapter_ #define _PreviewConnectionAdapter_ +#include "config.h" + #include <memory> #include "qpid/framing/amqp_types.h" #include "qpid/framing/AMQFrame.h" @@ -33,6 +35,10 @@ #include "qpid/framing/ProtocolVersion.h" #include "qpid/Exception.h" +#if HAVE_SASL +#include <sasl/sasl.h> +#endif + namespace qpid { namespace broker { @@ -44,12 +50,16 @@ class PreviewConnectionHandler : public framing::FrameHandler struct Handler : public framing::AMQP_ServerOperations::ConnectionHandler, public framing::AMQP_ClientOperations::ConnectionHandler { +#if HAVE_SASL + sasl_conn_t *sasl_conn; +#endif framing::AMQP_ClientProxy::Connection client; framing::AMQP_ServerProxy::Connection server; PreviewConnection& connection; bool serverMode; Handler(PreviewConnection& connection); + ~Handler(); void startOk(const qpid::framing::FieldTable& clientProperties, const std::string& mechanism, const std::string& response, const std::string& locale); @@ -77,6 +87,12 @@ class PreviewConnectionHandler : public framing::FrameHandler void openOk(const std::string& knownHosts); void redirect(const std::string& host, const std::string& knownHosts); + private: +#if HAVE_SASL + void processAuthenticationStep(int code, + const char *challenge, + unsigned int challenge_len); +#endif }; std::auto_ptr<Handler> handler; public: diff --git a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp b/qpid/cpp/src/qpid/broker/SessionAdapter.cpp index 8093c7c174..b7985e9ed8 100644 --- a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp +++ b/qpid/cpp/src/qpid/broker/SessionAdapter.cpp @@ -452,12 +452,11 @@ void SessionAdapter::TxHandlerImpl::rollback() std::string SessionAdapter::DtxHandlerImpl::convert(const framing::Xid010& xid) { - std::stringstream out; - out << xid.getFormat() << xid.getGlobalId() << xid.getBranchId(); - return out.str(); + std::string encoded; + encode(xid, encoded); + return encoded; } - void SessionAdapter::DtxHandlerImpl::select() { state.selectDtx(); @@ -543,13 +542,14 @@ Dtx010RecoverResult SessionAdapter::DtxHandlerImpl::recover() { std::set<std::string> xids; getBroker().getStore().collectPreparedXids(xids); - - //TODO: remove the need to copy from one container type to another - std::vector<std::string> data; + /* + * create array of long structs + */ + Array indoubt(0xAB); for (std::set<std::string>::iterator i = xids.begin(); i != xids.end(); i++) { - data.push_back(*i); + boost::shared_ptr<FieldValue> xid(new Struct32Value(*i)); + indoubt.add(xid); } - Array indoubt(data); return Dtx010RecoverResult(indoubt); } diff --git a/qpid/cpp/src/qpid/broker/SessionAdapter.h b/qpid/cpp/src/qpid/broker/SessionAdapter.h index a77f1b5d77..0cbbd13777 100644 --- a/qpid/cpp/src/qpid/broker/SessionAdapter.h +++ b/qpid/cpp/src/qpid/broker/SessionAdapter.h @@ -27,6 +27,7 @@ #include "qpid/framing/AMQP_ServerOperations.h" #include "qpid/framing/reply_exceptions.h" #include "qpid/framing/SequenceSet.h" +#include "qpid/framing/StructHelper.h" #include <vector> #include <boost/function.hpp> @@ -222,7 +223,7 @@ class Queue; void rollback(); }; - class DtxHandlerImpl : public Dtx010Handler, public HandlerHelper + class DtxHandlerImpl : public Dtx010Handler, public HandlerHelper, private framing::StructHelper { std::string convert(const framing::Xid010& xid); diff --git a/qpid/cpp/src/qpid/broker/SessionState.cpp b/qpid/cpp/src/qpid/broker/SessionState.cpp index d719bbe145..64d62934b9 100644 --- a/qpid/cpp/src/qpid/broker/SessionState.cpp +++ b/qpid/cpp/src/qpid/broker/SessionState.cpp @@ -230,6 +230,7 @@ void SessionState::enqueued(boost::intrusive_ptr<Message> msg) { completed.add(msg->getCommandId()); if (msg->requiresAccept()) { + nextOut++;//accept is a command, so the counter must be incremented getProxy().getMessage010().accept(SequenceSet(msg->getCommandId())); } } diff --git a/qpid/cpp/src/qpid/framing/FieldValue.cpp b/qpid/cpp/src/qpid/framing/FieldValue.cpp index cbda061209..8171a94ef2 100644 --- a/qpid/cpp/src/qpid/framing/FieldValue.cpp +++ b/qpid/cpp/src/qpid/framing/FieldValue.cpp @@ -119,6 +119,14 @@ Str16Value::Str16Value(const std::string& v) : reinterpret_cast<const uint8_t*>(v.data()+v.size()))) {} +Struct32Value::Struct32Value(const std::string& v) : + FieldValue( + 0xAB, + new VariableWidthValue<4>( + reinterpret_cast<const uint8_t*>(v.data()), + reinterpret_cast<const uint8_t*>(v.data()+v.size()))) +{} + IntegerValue::IntegerValue(int v) : FieldValue(0x21, new FixedWidthValue<4>(v)) { diff --git a/qpid/cpp/src/qpid/framing/FieldValue.h b/qpid/cpp/src/qpid/framing/FieldValue.h index 272670d102..d7efc4d22d 100644 --- a/qpid/cpp/src/qpid/framing/FieldValue.h +++ b/qpid/cpp/src/qpid/framing/FieldValue.h @@ -212,6 +212,12 @@ class Str16Value : public FieldValue { Str16Value(const std::string& v); }; +class Struct32Value : public FieldValue { + public: + Struct32Value(const std::string& v); +}; + + /* * Basic integer value encodes as signed 32 bit */ diff --git a/qpid/cpp/src/qpid/framing/StructHelper.h b/qpid/cpp/src/qpid/framing/StructHelper.h index ad6ba89906..e3dce4f5ec 100644 --- a/qpid/cpp/src/qpid/framing/StructHelper.h +++ b/qpid/cpp/src/qpid/framing/StructHelper.h @@ -34,7 +34,7 @@ class StructHelper public: template <class T> void encode(const T t, std::string& data) { - uint32_t size = t.size() + 2/*type*/; + uint32_t size = t.bodySize() + 2/*type*/; data.resize(size); Buffer wbuffer(const_cast<char*>(data.data()), size); wbuffer.putShort(T::TYPE); diff --git a/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp b/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp index 153557c5e5..5c784912b3 100644 --- a/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp +++ b/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp @@ -246,13 +246,19 @@ void AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) { if (protocolInit.decode(in)) { decoded = in.getPosition(); QPID_LOG(debug, "RECV [" << identifier << "] INIT(" << protocolInit << ")"); - codec = factory->create(protocolInit.getVersion(), *this, identifier); - if (!codec) { - //TODO: may still want to revise this... - //send valid version header & close connection. - write(framing::ProtocolInitiation(framing::highestProtocolVersion)); + try { + codec = factory->create(protocolInit.getVersion(), *this, identifier); + if (!codec) { + //TODO: may still want to revise this... + //send valid version header & close connection. + write(framing::ProtocolInitiation(framing::highestProtocolVersion)); + readError = true; + aio->queueWriteClose(); + } + } catch (const std::exception& e) { + QPID_LOG(error, e.what()); readError = true; - aio->queueWriteClose(); + aio->queueWriteClose(); } } } diff --git a/qpid/cpp/src/tests/amqp_0_10/Map.cpp b/qpid/cpp/src/tests/amqp_0_10/Map.cpp index dcba6e38c2..dcec1f49f7 100644 --- a/qpid/cpp/src/tests/amqp_0_10/Map.cpp +++ b/qpid/cpp/src/tests/amqp_0_10/Map.cpp @@ -19,8 +19,10 @@ * */ #include "unit_test.h" -#include "qpid/amqp_0_10/all_built_in_types.h" -//FIXME aconway 2008-04-08: #include "qpid/amqp_0_10/allSegmentTypes.h" +#include "qpid/amqp_0_10/Map.h" +#include "qpid/amqp_0_10/Array.h" +#include "qpid/amqp_0_10/Struct32.h" +#include "qpid/amqp_0_10/UnknownType.h" #include "qpid/amqp_0_10/Codec.h" #include <iostream> diff --git a/qpid/cpp/src/tests/amqp_0_10/serialize.cpp b/qpid/cpp/src/tests/amqp_0_10/serialize.cpp index 8928a9fbc9..f38de33bcc 100644 --- a/qpid/cpp/src/tests/amqp_0_10/serialize.cpp +++ b/qpid/cpp/src/tests/amqp_0_10/serialize.cpp @@ -30,7 +30,7 @@ #include "qpid/amqp_0_10/Codec.h" #include "qpid/amqp_0_10/specification.h" #include "qpid/amqp_0_10/ControlHolder.h" -#include "qpid/amqp_0_10/StructHolder.h" +#include "qpid/amqp_0_10/Struct32.h" #include "qpid/amqp_0_10/FrameHeader.h" #include "qpid/amqp_0_10/Map.h" #include "qpid/amqp_0_10/Unit.h" @@ -213,6 +213,22 @@ BOOST_AUTO_TEST_CASE(testControlEncodeDecode) { BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u); } +BOOST_AUTO_TEST_CASE(testStruct32) { + message::DeliveryProperties dp; + dp.priority=message::MEDIUM; + dp.routingKey="foo"; + Struct32 s(dp); + string data; + Codec::encode(back_inserter(data))(s); + BOOST_CHECK_EQUAL(data.size(), Codec::size(s)); + Struct32 s2; + Codec::decode(data.begin())(s2); + message::DeliveryProperties* dp2 = s2.getIf<message::DeliveryProperties>(); + BOOST_REQUIRE(dp2); + BOOST_CHECK_EQUAL(dp2->priority, message::MEDIUM); + BOOST_CHECK_EQUAL(dp2->routingKey, "foo"); +} + struct DummyPacked { static const uint8_t PACK=1; boost::optional<char> i, j; @@ -319,10 +335,10 @@ BOOST_AUTO_TEST_CASE(testStruct) { BOOST_CHECK_EQUAL(encodedBits, packBits(dp)); data.clear(); - Struct::Holder h(dp); + Struct32 h(dp); Codec::encode(back_inserter(data))(h); - Struct::Holder h2; + Struct32 h2; Codec::decode(data.begin())(h2); BOOST_CHECK_EQUAL(h2.getClassCode(), Uint8(message::DeliveryProperties::CLASS_CODE)); BOOST_CHECK_EQUAL(h2.getCode(), Uint8(message::DeliveryProperties::CODE)); diff --git a/qpid/cpp/src/tests/python_tests b/qpid/cpp/src/tests/python_tests index f35cb16480..4360992a2e 100755 --- a/qpid/cpp/src/tests/python_tests +++ b/qpid/cpp/src/tests/python_tests @@ -12,7 +12,7 @@ run() { if test -d ../../../python ; then cd ../../../python - run 0-10 cpp_failing_0-10.txt + run 0-10-errata cpp_failing_0-10.txt test -z "$QPID_NO_PREVIEW" && run ../specs/amqp.0-10-preview.xml cpp_failing_0-10_preview.txt else echo Warning: python tests not found. diff --git a/qpid/cpp/xml/extra.xml b/qpid/cpp/xml/extra.xml index 3e2f84e7bd..f91f737c94 100644 --- a/qpid/cpp/xml/extra.xml +++ b/qpid/cpp/xml/extra.xml @@ -34,7 +34,7 @@ </domain> <domain name="xid010"> - <struct size="short" pack="short"> + <struct size="long" pack="short" type="1540"> <field name="format" domain="long" /> <field name="global-id" domain="shortstr" /> <field name="branch-id" domain="shortstr" /> diff --git a/qpid/python/qpid/codec010.py b/qpid/python/qpid/codec010.py index 0e4244fb75..f82a7a49dc 100644 --- a/qpid/python/qpid/codec010.py +++ b/qpid/python/qpid/codec010.py @@ -195,21 +195,21 @@ class Codec(Packer): def read_control(self): cntrl = self.spec.controls[self.read_uint16()] - return cntrl.decode(self) + return Struct(cntrl, **cntrl.decode_fields(self)) def write_control(self, ctrl): type = ctrl._type self.write_uint16(type.code) - type.encode(self, ctrl) + type.encode_fields(self, ctrl) def read_command(self): type = self.spec.commands[self.read_uint16()] hdr = self.spec["session.header"].decode(self) - cmd = type.decode(self) + cmd = Struct(type, **type.decode_fields(self)) return hdr, cmd def write_command(self, hdr, cmd): self.write_uint16(cmd._type.code) hdr._type.encode(self, hdr) - cmd._type.encode(self, cmd) + cmd._type.encode_fields(self, cmd) def read_size(self, width): if width > 0: diff --git a/qpid/python/qpid/session.py b/qpid/python/qpid/session.py index bbe2b326d6..427a403b90 100644 --- a/qpid/python/qpid/session.py +++ b/qpid/python/qpid/session.py @@ -281,6 +281,9 @@ class Delegate: def __init__(self, session): self.session = session + #XXX: do something with incoming accepts + def message_accept(self, ma): None + def execution_result(self, er): future = self.session.results.pop(er.command_id) future.set(er.value) diff --git a/qpid/python/qpid/spec010.py b/qpid/python/qpid/spec010.py index 4eb03008d0..03f60edc4e 100644 --- a/qpid/python/qpid/spec010.py +++ b/qpid/python/qpid/spec010.py @@ -192,6 +192,9 @@ class Composite(Type, Coded): def decode(self, codec): codec.read_size(self.size) + if self.code is not None: + code = codec.read_uint16() + assert self.code == code return datatypes.Struct(self, **self.decode_fields(codec)) def decode_fields(self, codec): @@ -211,6 +214,8 @@ class Composite(Type, Coded): def encode(self, codec, value): sc = StringCodec(self.spec) + if self.code is not None: + sc.write_uint16(self.code) self.encode_fields(sc, value) codec.write_size(self.size, len(sc.encoded)) codec.write(sc.encoded) diff --git a/qpid/python/qpid/testlib.py b/qpid/python/qpid/testlib.py index 931face3a4..a0018c671f 100644 --- a/qpid/python/qpid/testlib.py +++ b/qpid/python/qpid/testlib.py @@ -132,6 +132,8 @@ Options: # Abbreviations for default settings. if (self.specfile == "0-10"): self.spec = load(self.get_spec_file("amqp.0-10.xml")) + elif (self.specfile == "0-10-errata"): + self.spec = load(self.get_spec_file("amqp.0-10-qpid-errata.xml")) else: if (self.specfile == "0-8"): self.specfile = self.get_spec_file("amqp.0-8.xml") diff --git a/qpid/python/tests/spec010.py b/qpid/python/tests/spec010.py index 4161dc060f..ff29bd8cea 100644 --- a/qpid/python/tests/spec010.py +++ b/qpid/python/tests/spec010.py @@ -26,7 +26,7 @@ from qpid.datatypes import Struct class SpecTest(TestCase): def setUp(self): - self.spec = load(testrunner.get_spec_file("amqp.0-10.xml")) + self.spec = load(testrunner.get_spec_file("amqp.0-10-qpid-errata.xml")) def testSessionHeader(self): hdr = self.spec["session.header"] @@ -62,3 +62,11 @@ class SpecTest(TestCase): dec = self.encdec(self.spec["message.subscribe"], cmd) assert cmd.exclusive == dec.exclusive assert cmd.destination == dec.destination + + def testXid(self): + xid = self.spec["dtx.xid"] + sc = StringCodec(self.spec) + st = Struct(xid, format=0, global_id="gid", branch_id="bid") + xid.encode(sc, st) + assert sc.encoded == '\x00\x00\x00\x10\x06\x04\x07\x00\x00\x00\x00\x00\x03gid\x03bid' + assert xid.decode(sc).__dict__ == st.__dict__ |