summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan Skinner <aidan@apache.org>2008-04-15 12:14:00 +0000
committerAidan Skinner <aidan@apache.org>2008-04-15 12:14:00 +0000
commiteaec25d7ebc6f54d336b4a60318d20bf48a302de (patch)
treed7759823a6ba0858034539a0bda3813fdabe2d09
parent0e22f5b286209658a88d9c3e731cdf491139c659 (diff)
downloadqpid-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
-rw-r--r--qpid/cpp/qpidc.spec.in13
-rwxr-xr-xqpid/cpp/rubygen/0-10/specification.rb121
-rw-r--r--qpid/cpp/src/Makefile.am4
-rw-r--r--qpid/cpp/src/qpid/Serializer.h2
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/Header.cpp (renamed from qpid/cpp/src/qpid/amqp_0_10/Frame.cpp)10
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/Header.h25
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/Holder.h8
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/Map.cpp4
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/Map.h2
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/Unit.cpp7
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/UnknownStruct.cpp (renamed from qpid/cpp/src/qpid/amqp_0_10/all_built_in_types.h)21
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/UnknownStruct.h43
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/built_in_types.h3
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp15
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/complex_types.h4
-rw-r--r--qpid/cpp/src/qpid/broker/Broker.h2
-rw-r--r--qpid/cpp/src/qpid/broker/MessageAdapter.cpp2
-rw-r--r--qpid/cpp/src/qpid/broker/PreviewConnection.cpp16
-rw-r--r--qpid/cpp/src/qpid/broker/PreviewConnection.h15
-rw-r--r--qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp219
-rw-r--r--qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h16
-rw-r--r--qpid/cpp/src/qpid/broker/SessionAdapter.cpp18
-rw-r--r--qpid/cpp/src/qpid/broker/SessionAdapter.h3
-rw-r--r--qpid/cpp/src/qpid/broker/SessionState.cpp1
-rw-r--r--qpid/cpp/src/qpid/framing/FieldValue.cpp8
-rw-r--r--qpid/cpp/src/qpid/framing/FieldValue.h6
-rw-r--r--qpid/cpp/src/qpid/framing/StructHelper.h2
-rw-r--r--qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp18
-rw-r--r--qpid/cpp/src/tests/amqp_0_10/Map.cpp6
-rw-r--r--qpid/cpp/src/tests/amqp_0_10/serialize.cpp22
-rwxr-xr-xqpid/cpp/src/tests/python_tests2
-rw-r--r--qpid/cpp/xml/extra.xml2
-rw-r--r--qpid/python/qpid/codec010.py8
-rw-r--r--qpid/python/qpid/session.py3
-rw-r--r--qpid/python/qpid/spec010.py5
-rw-r--r--qpid/python/qpid/testlib.py2
-rw-r--r--qpid/python/tests/spec010.py10
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__