You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rh...@apache.org on 2012/07/27 14:53:09 UTC

svn commit: r1366372 - in /qpid/proton/trunk: ./ examples/ruby/ proton-c/bindings/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/

Author: rhs
Date: Fri Jul 27 12:53:08 2012
New Revision: 1366372

URL: http://svn.apache.org/viewvc?rev=1366372&view=rev
Log:
patch from dpierce with ruby bindings and examples

Added:
    qpid/proton/trunk/examples/ruby/
    qpid/proton/trunk/examples/ruby/EXAMPLES
    qpid/proton/trunk/examples/ruby/fetch.rb
    qpid/proton/trunk/examples/ruby/mailserver.rb
    qpid/proton/trunk/examples/ruby/post.rb
    qpid/proton/trunk/examples/ruby/recv.rb
    qpid/proton/trunk/examples/ruby/send.rb
    qpid/proton/trunk/proton-c/bindings/ruby/
    qpid/proton/trunk/proton-c/bindings/ruby/CMakeLists.txt
    qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
Modified:
    qpid/proton/trunk/config.sh
    qpid/proton/trunk/proton-c/bindings/CMakeLists.txt
    qpid/proton/trunk/proton-c/bindings/php/CMakeLists.txt
    qpid/proton/trunk/proton-c/bindings/python/CMakeLists.txt

Modified: qpid/proton/trunk/config.sh
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/config.sh?rev=1366372&r1=1366371&r2=1366372&view=diff
==============================================================================
--- qpid/proton/trunk/config.sh (original)
+++ qpid/proton/trunk/config.sh Fri Jul 27 12:53:08 2012
@@ -22,13 +22,22 @@ export PROTON_HOME=$(dirname $(readlink 
 
 if [ -z "$CPROTON_BUILD" ]; then
     if [ -d $PROTON_HOME/proton-c/build ]; then
-        export PYTHON_BINDINGS=$PROTON_HOME/proton-c/build/bindings/python
+        PROTON_BINDINGS=$PROTON_HOME/proton-c/build/bindings
     else
-        export PYTHON_BINDINGS=$PROTON_HOME/proton-c/bindings/python
+        PROTON_BINDINGS=$PROTON_HOME/proton-c/bindings
     fi
 else
-    export PYTHON_BINDINGS=$CPROTON_BUILD/bindings/python
+    PROTON_BINDINGS=$CPROTON_BUILD/bindings
 fi
 
+# Python & Jython
+export PYTHON_BINDINGS=$PROTON_BINDINGS/python
 export PYTHONPATH=$PROTON_HOME/tests:$PROTON_HOME/proton-c:$PYTHON_BINDINGS
 export JYTHONPATH=$PROTON_HOME/tests:$PROTON_HOME/proton-j:$PROTON_HOME/proton-j/dist/lib/qpidproton.jar
+
+# PHP
+export PHP_BINDINGS=$PROTON_BINDINGS/php
+
+# Ruby
+export RUBY_BINDINGS=$PROTON_BINDINGS/ruby
+export RUBYLIB=$RUBY_BINDINGS

Added: qpid/proton/trunk/examples/ruby/EXAMPLES
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/examples/ruby/EXAMPLES?rev=1366372&view=auto
==============================================================================
--- qpid/proton/trunk/examples/ruby/EXAMPLES (added)
+++ qpid/proton/trunk/examples/ruby/EXAMPLES Fri Jul 27 12:53:08 2012
@@ -0,0 +1,10 @@
+EXAMPLES:
+
+ * send.rb, recv.rb:
+   Demonstrates the use of the messenger APIs for sending and receiving
+   messages from point to point.
+
+ * server.rb, post.rb, fetch.rb:
+   Demonstrates setting up a mail exchange via the server app and then posting
+   and fetching messages to specific mailboxes via post and fetch,
+   respectively.

Added: qpid/proton/trunk/examples/ruby/fetch.rb
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/examples/ruby/fetch.rb?rev=1366372&view=auto
==============================================================================
--- qpid/proton/trunk/examples/ruby/fetch.rb (added)
+++ qpid/proton/trunk/examples/ruby/fetch.rb Fri Jul 27 12:53:08 2012
@@ -0,0 +1,204 @@
+#!/usr/bin/env ruby
+#
+# 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.
+
+require 'cproton'
+require 'optparse'
+
+$options = {
+  :hostname => "0.0.0.0",
+  :port => "5672",
+  :count => 1,
+  :verbose => false
+}
+messages = []
+
+OptionParser.new do |opts|
+  opts.banner = "Usage: #{File.basename $0} [options] <mailbox>"
+
+  opts.on("-s", "--server <address>", String, :REQUIRED,
+          "Address of the server") do |server|
+  end
+
+  opts.on("-p", "--port <port>", Integer, :REQUIRED,
+          "Port on the server") do |port|
+    $options[:port] = port
+  end
+
+  opts.on("-c", "--count <#>", Integer, :REQUIRED,
+          "Number of messages to read from the mailbox") do |count|
+    $options[:count] = count
+  end
+
+  opts.on("-v", "--verbose", :NONE,
+          "Turn on extra trace messages.") do |verbose|
+    $options[:verbose] = true
+  end
+
+  begin
+    ARGV << "-h" if ARGV.empty?
+    opts.parse!
+  rescue OptionParser::ParseError => error
+    STDERR.puts error.message, "\n", opts
+    exit 1
+  end
+
+  $options[:mailbox] = ARGV.first unless ARGV.empty?
+
+  abort("No mailbox specified.") if $options[:mailbox].nil?
+
+end
+
+def log(text, return_code = 0)
+  STDOUT.puts "#{Time.new}: #{text}" if $options[:verbose] || return_code.nonzero?
+
+  # if we were given a non-zero code, then exit
+  exit return_code unless return_code.zero?
+end
+
+class FetchClient
+  attr_reader :sasl
+  attr_reader :link
+  attr_reader :conn
+
+  def initialize(hostname, port, mailbox)
+    @hostname = hostname
+    @port = port
+    @mailbox = mailbox
+  end
+
+  def setup
+    # setup a driver connection to the server
+    log "Connecting to server host = #{@hostname}:#{@port}"
+    @driver = Cproton::pn_driver
+    @cxtr = Cproton::pn_connector(@driver, @hostname, @port, nil)
+
+    # configure SASL
+    @sasl = Cproton::pn_connector_sasl @cxtr
+    Cproton::pn_sasl_mechanisms @sasl, "ANONYMOUS"
+    Cproton::pn_sasl_client @sasl
+
+    # inform the engine about the connection, and link the driver to it.
+    @conn = Cproton::pn_connection
+    Cproton::pn_connector_set_connection @cxtr, @conn
+
+    # create a session and link for receiving from the mailbox
+    log "Fetching from the mailbox = #{@mailbox}"
+    @ssn = Cproton::pn_session @conn
+    @link = Cproton::pn_receiver @ssn, "receiver"
+    Cproton::pn_set_source @link, @mailbox
+
+    # now open all the engine endpoints
+    Cproton::pn_connection_open @conn
+    Cproton::pn_session_open @ssn
+    Cproton::pn_link_open @link
+  end
+
+  def wait
+    log "Waiting for events..."
+    Cproton::pn_connector_process @cxtr
+    Cproton::pn_driver_wait @driver, -1
+    Cproton::pn_connector_process @cxtr
+    log "...waiting done!"
+  end
+
+  def settle
+    # locally settle any remotely settled deliveries
+    d = Cproton::pn_unsettled_head @link
+    while d && !Cproton::pn_readable(d)
+      # delivery that has not yet been read
+      _next = Cproton::pn_unsettled_next d
+      Cproton::pn_settle(d) if Cproton::pn_remote_settled(d)
+      d = _next
+    end
+  end
+
+end
+
+if __FILE__ == $PROGRAM_NAME
+  receiver = FetchClient.new($options[:hostname],
+                             $options[:port],
+                             $options[:mailbox])
+
+  receiver.setup
+
+  # wait until we authenticate with the server
+  while ![Cproton::PN_SASL_PASS, Cproton::PN_SASL_FAIL].include? Cproton::pn_sasl_state(receiver.sasl)
+    receiver.wait
+  end
+
+  if Cproton::pn_sasl_state(receiver.sasl) == Cproton::PN_SASL_FAIL
+    log "ERROR: Authentication failure", -1
+  end
+
+  # wait until the server has opened the connection
+  while ((Cproton::pn_link_state(receiver.link) & Cproton::PN_REMOTE_ACTIVE) != Cproton::PN_REMOTE_ACTIVE)
+    receiver.wait
+  end
+
+  # check if the server recognizes the mailbox, fail if it does not
+  if Cproton::pn_remote_source(receiver.link) != $options[:mailbox]
+    log "ERROR: mailbox #{$options[:mailbox]} does not exist!", -2
+  end
+
+  # Allow the server to send the expected number of messages to the receiver
+  # by setting the credit to the expected count
+  Cproton::pn_flow(receiver.link, $options[:count])
+
+  # main loop: continue fetching messages until all the expected number of
+  # messages have been retrieved
+
+  while Cproton::pn_credit(receiver.link) > 0
+    # wait for some messages to arrive
+    receiver.wait if Cproton::pn_queued(receiver.link).zero?
+
+    # read all queued deliveries
+    while Cproton::pn_queued(receiver.link) > 0
+      delivery = Cproton::pn_current(receiver.link)
+
+      # read all bytes of message
+      (rc, msg) = Cproton::pn_recv(receiver.link, Cproton::pn_pending(delivery))
+      log "Received count/status=#{rc}"
+
+      log("ERROR: Receive failed (#{rc}), exiting...", -3) if rc < 0
+
+      puts "#{msg}"
+
+      # let the server know we accept the message
+      Cproton::pn_disposition(delivery, Cproton::PN_ACCEPTED)
+
+      # go to the next deliverable
+      Cproton::pn_advance(receiver.link)
+    end
+
+    receiver.settle
+  end
+
+  # block until any leftover deliveries are settled
+  while Cproton::pn_unsettled(receiver.link) > 0
+    receiver.wait
+    receiver.settle
+  end
+
+  # we're done,c lose and wait for the remote to close also
+  Cproton::pn_connection_close(receiver.conn)
+  while ((Cproton::pn_connection_state(receiver.conn) & Cproton::PN_REMOTE_CLOSED) != Cproton::PN_REMOTE_CLOSED)
+    receiver.wait
+  end
+
+end

Added: qpid/proton/trunk/examples/ruby/mailserver.rb
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/examples/ruby/mailserver.rb?rev=1366372&view=auto
==============================================================================
--- qpid/proton/trunk/examples/ruby/mailserver.rb (added)
+++ qpid/proton/trunk/examples/ruby/mailserver.rb Fri Jul 27 12:53:08 2012
@@ -0,0 +1,322 @@
+#!/usr/bin/env ruby
+#
+# 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.
+#
+
+require 'cproton'
+require 'optparse'
+
+FAILED         = 0
+CONNECTION_UP  = 1
+AUTHENTICATING = 2
+
+$options  = {
+  :verbose => false,
+  :hostname => "0.0.0.0",
+  :port => "5672"
+}
+
+OptionParser.new do |opts|
+  opts.banner = "Usage: mailserver [options] <server-address> [<server-port>]"
+
+  opts.on("-v", "--verbose", :NONE,
+          "Print status messages to stdout") do |f|
+    $options[:verbose] = true
+  end
+
+  opts.parse!
+
+  $options[:hostname] = ARGV[0] if ARGV.length > 0
+  $options[:port] = ARGV[1] if ARGV.length > 1
+end
+
+def log(text)
+  STDOUT.puts "#{Time.new}: #{text}" if $options[:verbose]
+end
+
+class MailServer
+  def initialize(hostname, port, verbose)
+    @hostname = hostname
+    @port = port
+    @verbose = verbose
+    @counter = 0
+    @mailboxes = {}
+
+    @driver = nil
+  end
+
+  def setup
+    @driver = Cproton::pn_driver
+    @listener = Cproton::pn_listener @driver, @hostname, @port, nil
+    raise "Error: could not listen on #{@hostname}:#{@port}" if @listener.nil?
+  end
+
+  def wait
+    log "Driver sleep."
+    Cproton::pn_driver_wait @driver, -1
+    log "Driver wakeup."
+  end
+
+  def accept_connection_requests
+    l = Cproton::pn_driver_listener @driver
+
+    while !l.nil?
+      log "Accepting connection."
+      cxtr = Cproton::pn_listener_accept l
+      Cproton::pn_connector_set_context cxtr, AUTHENTICATING
+      l = Cproton::pn_driver_listener @driver
+    end
+  end
+
+  def process_connections
+    cxtr = Cproton::pn_driver_connector @driver
+
+    while cxtr
+      log "Process connector"
+
+      Cproton::pn_connector_process cxtr
+
+      state = Cproton::pn_connector_context cxtr
+      case state
+      when AUTHENTICATING
+        log "Authenticating..."
+        self.authenticate_connector cxtr
+
+      when CONNECTION_UP
+        log "Connection established..."
+        self.service_connector cxtr
+
+      else
+        raise "Unknown connection state #{state}"
+      end
+
+      Cproton::pn_connector_process cxtr
+
+      if Cproton::pn_connector_closed cxtr
+        log "Closing connector."
+        Cproton::pn_connector_free cxtr
+      end
+
+      cxtr = Cproton::pn_driver_connector @driver
+
+    end
+  end
+
+  def authenticate_connector(cxtr)
+    log "Authenticating..."
+
+    sasl = Cproton::pn_connector_sasl cxtr
+    state = Cproton::pn_sasl_state sasl
+    while [Cproton::PN_SASL_CONF, Cproton::PN_SASL_STEP].include? state
+
+      case state
+      when Cproton::PN_SASL_CONF
+        log "Authenticating-CONF..."
+        Cproton::pn_sasl_mechanisms sasl, "ANONYMOUS"
+        Cproton::pn_sasl_server sasl
+
+      when Cproton::PN_SASL_STEP
+        log "Authenticating-STEP..."
+        mech = Cproton::pn_sasl_remote_mechanisms sasl
+        if mech == "ANONYMOUS"
+          Cproton::pn_sasl_done sasl, Cproton::PN_SASL_OK
+        else
+          Cproton::pn_sasl_done sasl, Cproton::PN_SASL_AUTH
+        end
+      end
+
+      state = Cproton::pn_sasl_state sasl
+
+    end
+
+    case state
+    when Cproton::PN_SASL_PASS
+      Cproton::pn_connector_set_connection cxtr, Cproton::pn_connection
+      Cproton::pn_connector_set_context cxtr, CONNECTION_UP
+      log "Authentication-PASSED"
+
+    when Cproton::PN_SASL_FAIL
+      Cproton::pn_connector_set_context cxtr, FAILED
+      log "Authentication-FAILED"
+
+    else
+      log "Authentication-PENDING"
+    end
+
+  end
+
+  def service_connector(cxtr)
+    log "I/O processing starting."
+
+    conn = Cproton::pn_connector_connection cxtr
+    if ((Cproton::pn_connection_state(conn) & Cproton::PN_LOCAL_UNINIT) == Cproton::PN_LOCAL_UNINIT)
+      log "Connection opened."
+      Cproton::pn_connection_open(conn)
+    end
+
+    ssn = Cproton::pn_session_head conn, Cproton::PN_LOCAL_UNINIT
+    while ssn
+      Cproton::pn_session_open ssn
+      log "Session opened."
+      ssn = Cproton::pn_session_next ssn, Cproton::PN_LOCAL_UNINIT
+    end
+
+    link = Cproton::pn_link_head conn, Cproton::PN_LOCAL_UNINIT
+    while link
+      setup_link link
+      link = Cproton::pn_link_next link, Cproton::PN_LOCAL_UNINIT
+    end
+
+    delivery = Cproton::pn_work_head conn
+    while delivery
+      log "Process delivery #{Cproton::pn_delivery_tag delivery}"
+      if Cproton::pn_readable delivery
+        process_receive delivery
+      elsif Cproton::pn_writable delivery
+        send_message delivery
+      end
+
+      if Cproton::pn_updated delivery
+        log "Remote disposition for #{Cproton::pn_delivery_tag delivery}: #{Cproton::pn_remote_disposition delivery}"
+        Cproton::pn_settle(delivery) if Cproton::pn_remote_disposition delivery
+      end
+
+      delivery = Cproton::pn_work_next delivery
+    end
+
+    link = Cproton::pn_link_head conn, Cproton::PN_LOCAL_ACTIVE | Cproton::PN_REMOTE_CLOSED
+    while link
+      Cproton::pn_link_close link
+      log "Link closed."
+      link = Cproton::pn_link_next link, Cproton::PN_LOCAL_ACTIVE | Cproton::PN_REMOTE_CLOSED
+    end
+
+    ssn = Cproton::pn_session_head conn, Cproton::PN_LOCAL_ACTIVE | Cproton::PN_REMOTE_CLOSED
+    while ssn
+      Cproton::pn_session_close ssn
+      log "Session closed."
+      ssn = Cproton::pn_session_next ssn, Cproton::PN_LOCAL_ACTIVE | Cproton::PN_REMOTE_CLOSED
+    end
+
+    if Cproton::pn_connection_state(conn) == (Cproton::PN_LOCAL_ACTIVE | Cproton::PN_REMOTE_CLOSED)
+      log "Connection closed."
+      Cproton::pn_connection_close conn
+    end
+
+  end
+
+  def process_receive(delivery)
+    link = Cproton::pn_link delivery
+    mbox = Cproton::pn_remote_target link
+    (rc, msg) = Cproton::pn_recv link, 1024
+
+    log "Message received #{rc}"
+
+    while rc >= 0
+      unless @mailboxes.include? mbox
+        log "Error: cannot send to mailbox #{mbox} - dropping message."
+      else
+        @mailboxes[mbox] << msg
+        log "Mailbox #{mbox} contains: #{@mailboxes[mbox].size}"
+      end
+
+      (rc, msg) = Cproton::pn_recv link, 1024
+    end
+
+    log "Messages accepted."
+
+    Cproton::pn_disposition delivery, Cproton::PN_ACCEPTED
+    Cproton::pn_settle delivery
+    Cproton::pn_advance link
+
+    Cproton::pn_flow(link, 1) if Cproton::pn_credit(link).zero?
+  end
+
+  def send_message(delivery)
+    link = Cproton::pn_link delivery
+    mbox = Cproton::pn_remote_source link
+    log "Request for Mailbox=#{mbox}"
+
+    if @mailboxes.include?(mbox) && !@mailboxes[mbox].empty?
+      msg = @mailboxes[mbox].first
+      @mailboxes[mbox].delete_at 0
+      log "Fetching message #{msg}"
+    else
+      log "Warning: mailbox #{mbox} is empty, sending empty message"
+      msg = ""
+    end
+
+    sent = Cproton::pn_send link, msg
+    log "Message sent: #{sent}"
+
+    if Cproton::pn_advance link
+      Cproton::pn_delivery link, "server-delivery-#{@counter}"
+      @counter += 1
+    end
+  end
+
+  def setup_link(link)
+    r_tgt = Cproton::pn_remote_target link
+    r_src = Cproton::pn_remote_source link
+
+    if Cproton::pn_is_sender link
+      log "Opening link to read from mailbox: #{r_src}"
+
+      unless @mailboxes.include? r_src
+        log "Error: mailbox #{r_src} does not exist!"
+        r_src = nil
+      end
+    else
+      log "Opening link to write to mailbox: #{r_tgt}"
+
+      @mailboxes[r_tgt] = [] unless @mailboxes.include? r_tgt
+    end
+
+    Cproton::pn_set_target link, r_tgt
+    Cproton::pn_set_source link, r_src
+
+    if Cproton::pn_is_sender link
+      Cproton::pn_delivery link, "server-delivery-#{@counter}"
+      @counter += 1
+    else
+      Cproton::pn_flow link, 1
+    end
+
+    Cproton::pn_link_open link
+
+  end
+
+end
+
+#------------------
+# Begin entry point
+#------------------
+
+if __FILE__ == $PROGRAM_NAME
+  server = MailServer.new($options[:hostname],
+                          $options[:port],
+                          $options[:verbose])
+
+  server.setup
+  loop do
+    server.wait
+    server.accept_connection_requests
+    server.process_connections
+  end
+end
+

Added: qpid/proton/trunk/examples/ruby/post.rb
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/examples/ruby/post.rb?rev=1366372&view=auto
==============================================================================
--- qpid/proton/trunk/examples/ruby/post.rb (added)
+++ qpid/proton/trunk/examples/ruby/post.rb Fri Jul 27 12:53:08 2012
@@ -0,0 +1,191 @@
+#!/usr/bin/env ruby
+#
+# 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.
+#
+
+require 'cproton'
+require 'optparse'
+
+
+$options  = {
+  :verbose => false,
+  :hostname => "0.0.0.0",
+  :port => "5672"
+}
+
+
+OptionParser.new do |opts|
+  opts.banner = "Usage: mailserver [options] <server-address> [<server-port>] <message-string> [<message-string> ...]"
+
+  opts.on("-s", "--server", String, :REQUIRED,
+          "The server hostname (def. #{$options[:hostname]})") do |hostname|
+    $options[:hostname] = hostname
+  end
+
+  opts.on("-p", "--port", String, :REQUIRED,
+          "The server port (def. #{$options[:port]})") do |port|
+    $options[:post] = port
+  end
+
+  opts.on("-m", "--mailbox", String, :REQUIRED,
+          "Name of the mailbox on the server") do |mailbox|
+    $options[:mailbox] = mailbox
+  end
+
+  opts.on("-v", "--verbose", :NONE,
+             "Enable verbose output (def. #{$options[:verbose]})") do
+    $options[:verbose] = true
+  end
+
+  begin
+    ARGV << "-h" if ARGV.empty?
+    opts.parse!(ARGV)
+  rescue OptionParser::ParseError => error
+    STDERR.puts error.message, "\n", opts
+    exit 1
+  end
+
+  $options[:messages] = ARGV
+
+  abort "No mailbox specified." if $options[:mailbox].nil?
+  abort "No messages specified." if $options[:messages].empty?
+
+end
+
+def log(text)
+  printf "#{Time.new}: #{text}\n" if $options[:verbose]
+end
+
+
+class PostClient
+
+  attr_reader :sasl
+  attr_reader :link
+  attr_reader :conn
+
+  def initialize(hostname, port, mailbox, verbose)
+    @hostname = hostname
+    @port = port
+    @mailbox = mailbox
+    @verbose = verbose
+  end
+
+  def setup
+    log "Connection to server host = #{@hostname}:#{@port}"
+    @driver = Cproton::pn_driver
+    @cxtr = Cproton::pn_connector(@driver, @hostname, @port, nil)
+
+    # configure SASL
+    @sasl = Cproton::pn_connector_sasl @cxtr
+    Cproton::pn_sasl_mechanisms @sasl, "ANONYMOUS"
+    Cproton::pn_sasl_client @sasl
+
+    # inform the engine about the connection, and link the driver to it.
+    @conn = Cproton::pn_connection
+    Cproton::pn_connector_set_connection @cxtr, @conn
+
+    # create a session and link for receiving from the mailbox
+    log "Posting to mailbox = #{@mailbox}"
+    @ssn = Cproton::pn_session @conn
+    @link = Cproton::pn_sender @ssn, "sender"
+    Cproton::pn_set_target @link, @mailbox
+
+    # now open all the engien end points
+    Cproton::pn_connection_open @conn
+    Cproton::pn_session_open @ssn
+    Cproton::pn_link_open @link
+  end
+
+  def wait
+    log "Waiting for events..."
+    Cproton::pn_connector_process @cxtr
+    Cproton::pn_driver_wait @driver, -1
+    Cproton::pn_connector_process @cxtr
+    log "..waiting done!"
+  end
+
+  def settle
+    d = Cproton::pn_unsettled_head @link
+    while d
+      _next = Cproton::pn_unsettled_next d
+      disp = Cproton::pn_remote_disposition d
+
+      if disp.nonzero? && disp != Cproton::PN_ACCEPTED
+        log "Warning: message was not accepted by the remote!"
+      end
+
+      if disp || Cproton::pn_remote_settled(disp)
+        Cproton::pn_settle(d)
+      end
+
+      d = _next
+    end
+  end
+
+end
+
+
+if __FILE__ == $PROGRAM_NAME
+  sender = PostClient.new($options[:hostname],
+                          $options[:port],
+                          $options[:mailbox],
+                          $options[:verbose])
+  sender.setup
+
+  sender.wait while ![Cproton::PN_SASL_PASS, Cproton::PN_SASL_FAIL].include? Cproton::pn_sasl_state(sender.sasl)
+
+  abort "Error: Authentication failure" if Cproton::pn_sasl_state(sender.sasl) == Cproton::PN_SASL_FAIL
+
+  while !$options[:messages].empty? do
+
+    while Cproton::pn_credit(sender.link).zero?
+      log "Waiting for credit"
+      sender.wait
+    end
+
+    while Cproton::pn_credit(sender.link) > 0
+      msg = $options[:messages].first
+      $options[:messages].delete_at 0
+      log "Sending #{msg}"
+      d = Cproton::pn_delivery sender.link, "post-deliver-#{$options[:messages].length}"
+      rc = Cproton::pn_send(sender.link, msg)
+
+      abort "Error: sending message: #{msg}" if rc < 0
+
+      fail unless rc == msg.length
+
+      Cproton::pn_advance sender.link
+    end
+
+    sender.settle
+  end
+
+  while Cproton::pn_unsettled(sender.link) > 0
+    log "Settling things with the server..."
+    sender.wait
+    sender.settle
+    log "Finished settling."
+  end
+
+  Cproton::pn_connection_close sender.conn
+  while ((Cproton::pn_connection_state(sender.conn) & Cproton::PN_REMOTE_CLOSED) != Cproton::PN_REMOTE_CLOSED)
+    log "Waiting for things to become closed..."
+    sender.wait
+  end
+
+end

Added: qpid/proton/trunk/examples/ruby/recv.rb
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/examples/ruby/recv.rb?rev=1366372&view=auto
==============================================================================
--- qpid/proton/trunk/examples/ruby/recv.rb (added)
+++ qpid/proton/trunk/examples/ruby/recv.rb Fri Jul 27 12:53:08 2012
@@ -0,0 +1,70 @@
+#!/usr/bin/env ruby
+#
+# 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.
+
+require 'cproton'
+require 'optparse'
+
+addresses = []
+
+OptionParser.new do |opts|
+  opts.banner = "Usage: recv.rb <addr1> ... <addrn>"
+  opts.parse!
+
+  addresses = ARGV
+end
+
+addresses = ["//~0.0.0.0"] if addresses.empty?
+
+mng = Cproton::pn_messenger nil
+
+if Cproton::pn_messenger_start(mng).nonzero?
+  puts "ERROR: #{Cproton::pn_messenger_error mng}"
+end
+
+addresses.each do |address|
+  if Cproton::pn_messenger_subscribe(mng, address).nonzero?
+    puts "ERROR: #{Cproton::pn_messenger_error(mng)}"
+    exit
+  end
+end
+
+msg = Cproton::pn_message
+
+loop do
+  if Cproton::pn_messenger_recv(mng, 10).nonzero?
+    puts "ERROR: #{Cproton::pn_messenger_error mng}"
+    exit
+  end
+
+  while Cproton::pn_messenger_incoming(mng).nonzero?
+    if Cproton::pn_messenger_get(mng, msg).nonzero?
+      puts "ERROR: #{Cproton::pn_messenger_error mng}"
+      exit
+    else
+      (cd, body) = Cproton::pn_message_save(msg, 1024)
+      puts "Address: #{Cproton::pn_message_get_address msg}"
+      subject = Cproton::pn_message_get_subject(msg) || "(no subject)"
+      puts "Subject: #{subject}"
+      puts "Content: #{body}"
+    end
+  end
+end
+
+Cproton::pn_messenger_stop mng
+Cproton::pn_messenger_free mng

Added: qpid/proton/trunk/examples/ruby/send.rb
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/examples/ruby/send.rb?rev=1366372&view=auto
==============================================================================
--- qpid/proton/trunk/examples/ruby/send.rb (added)
+++ qpid/proton/trunk/examples/ruby/send.rb Fri Jul 27 12:53:08 2012
@@ -0,0 +1,65 @@
+#!/usr/bin/env ruby
+#
+# 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.
+
+require 'cproton'
+require 'optparse'
+
+options = {}
+messages = []
+
+OptionParser.new do |opts|
+  opts.banner = "Usage: send.rb [options] <msg1> ... <msgn>"
+  opts.on("-a", "--address [addr]", "The receiver's address (def. //0.0.0.0)") do |f|
+    options[:address] = f
+  end
+
+  opts.parse!
+
+  messages = ARGV
+end
+
+options[:address] = "//0.0.0.0" unless options[:address]
+messages << "Hello world!" if messages.empty?
+
+mng = Cproton::pn_messenger nil
+
+Cproton::pn_messenger_start mng
+
+msg = Cproton::pn_message
+
+messages.each do |message|
+  Cproton::pn_message_set_address msg, options[:address]
+#  Cproton::pn_message_set_subject msg, "Message sent on #{Time.new}"
+  Cproton::pn_message_load msg, message
+
+  if Cproton::pn_messenger_put(mng, msg).nonzero?
+    puts "ERROR: #{Cproton::pn_messenger_error mng}"
+    exit
+  end
+end
+
+if Cproton::pn_messenger_send(mng).nonzero?
+  puts "ERROR: #{Cproton::pn_messenger_error mng}"
+  exit
+else
+  puts "SENT: " + messages.join(",")
+end
+
+Cproton::pn_messenger_stop mng
+Cproton::pn_messenger_free mng

Modified: qpid/proton/trunk/proton-c/bindings/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/CMakeLists.txt?rev=1366372&r1=1366371&r2=1366372&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/CMakeLists.txt (original)
+++ qpid/proton/trunk/proton-c/bindings/CMakeLists.txt Fri Jul 27 12:53:08 2012
@@ -22,14 +22,21 @@ include(UseSWIG)
 set (BINDING_DEPS qpid-proton qpid-proton-posix ${LINK_DEPS})
 
 # Build wrapper for Python:
-# @todo: conditionalize on whether python is available!
-add_subdirectory(python)
+find_package (PythonLibs)
+if (PYTHONLIBS_FOUND)
+  add_subdirectory(python)
+endif (PYTHONLIBS_FOUND)
+
+# Build wrapper for Ruby:
+include(FindRuby)
+if (RUBY_FOUND)
+  add_subdirectory(ruby)
+endif (RUBY_FOUND)
 
 # Build wrapper for PHP
 # For now, assume PHP support if the 'php-config' tool is present.
 # @todo: allow user to specify which php-config if multiple PHP sources installed!
-
-FIND_PROGRAM(PHP_CONFIG_EXE php-config)
-IF(PHP_CONFIG_EXE)
+find_program(PHP_CONFIG_EXE php-config)
+if (PHP_CONFIG_EXE)
   add_subdirectory(php)
-ENDIF(PHP_CONFIG_EXE)
+endif (PHP_CONFIG_EXE)

Modified: qpid/proton/trunk/proton-c/bindings/php/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/CMakeLists.txt?rev=1366372&r1=1366371&r2=1366372&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/php/CMakeLists.txt (original)
+++ qpid/proton/trunk/proton-c/bindings/php/CMakeLists.txt Fri Jul 27 12:53:08 2012
@@ -24,17 +24,17 @@
 # Uses the php-config command line tool from PHP to extract the location of the PHP header
 # files
 
-EXECUTE_PROCESS(COMMAND ${PHP_CONFIG_EXE} --includes
+execute_process(COMMAND ${PHP_CONFIG_EXE} --includes
                 OUTPUT_VARIABLE PHP_INCLUDES
                 RESULT_VARIABLE retval
                 ERROR_VARIABLE  errmsg
                 OUTPUT_STRIP_TRAILING_WHITESPACE)
-IF (NOT ${retval} EQUAL 0)
-   MESSAGE(SEND_ERROR "Command \"${PHP_CONFIG_EXE} --include\" failed with output:\n${errmsg}")
-ELSE()
-   #MESSAGE(STATUS "PHP_INCLUDES=[${PHP_INCLUDES}]")
-   set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/php.i PROPERTIES SWIG_FLAGS "-I${PROJECT_SOURCE_DIR}/include")
-   swig_add_module(cproton php ${CMAKE_CURRENT_SOURCE_DIR}/php.i)
-   set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "${PHP_INCLUDES}")
-   swig_link_libraries(cproton ${BINDING_DEPS})
-ENDIF()
+if (NOT ${retval} EQUAL 0)
+  message(SEND_ERROR "Command \"${PHP_CONFIG_EXE} --include\" failed with output:\n${errmsg}")
+else ()
+  #message(STATUS "PHP_INCLUDES=[${PHP_INCLUDES}]")
+  set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/php.i PROPERTIES SWIG_FLAGS "-I${PROJECT_SOURCE_DIR}/include")
+  swig_add_module(cproton php ${CMAKE_CURRENT_SOURCE_DIR}/php.i)
+  set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "${PHP_INCLUDES}")
+  swig_link_libraries(cproton ${BINDING_DEPS})
+endif ()

Modified: qpid/proton/trunk/proton-c/bindings/python/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/CMakeLists.txt?rev=1366372&r1=1366371&r2=1366372&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/CMakeLists.txt (original)
+++ qpid/proton/trunk/proton-c/bindings/python/CMakeLists.txt Fri Jul 27 12:53:08 2012
@@ -1,5 +1,3 @@
-find_package (PythonLibs)
-
 set(CMAKE_SWIG_FLAGS "-threads")
 
 swig_add_module(cproton python python.i)

Added: qpid/proton/trunk/proton-c/bindings/ruby/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/CMakeLists.txt?rev=1366372&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/CMakeLists.txt (added)
+++ qpid/proton/trunk/proton-c/bindings/ruby/CMakeLists.txt Fri Jul 27 12:53:08 2012
@@ -0,0 +1,26 @@
+#
+# 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_directories (${RUBY_INCLUDE_PATH})
+swig_add_module(cproton-ruby ruby ruby.i)
+swig_link_libraries(cproton-ruby ${BINDING_DEPS} ${RUBY_LIBRARY})
+set_target_properties(cproton-ruby PROPERTIES PREFIX "")
+add_custom_command(TARGET cproton-ruby
+                   POST_BUILD
+                   COMMAND cmake -E rename cproton-ruby.so cproton.so)

Added: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1366372&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (added)
+++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Jul 27 12:53:08 2012
@@ -0,0 +1,157 @@
+%module cproton
+
+%{
+#include <proton/engine.h>
+#include <proton/message.h>
+#include <proton/sasl.h>
+#include <proton/driver.h>
+#include <proton/messenger.h>
+%}
+
+typedef unsigned int size_t;
+typedef signed int ssize_t;
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+typedef unsigned long int uint64_t;
+typedef int int32_t;
+
+%include <cstring.i>
+
+%cstring_output_withsize(char *OUTPUT, size_t *OUTPUT_SIZE)
+%cstring_output_allocate_size(char **ALLOC_OUTPUT, size_t *ALLOC_SIZE, free(*$1));
+
+%{
+#if !defined(RSTRING_LEN)
+#  define RSTRING_LEN(x) (RSTRING(X)->len)
+#  define RSTRING_PTR(x) (RSTRING(x)->ptr)
+#endif
+%}
+
+%typemap(in) pn_bytes_t {
+  if ($input == Qnil) {
+    $1.start = NULL;
+    $1.size = 0;
+  } else {
+    $1.start = RSTRING_PTR($input);
+    if (!$1.start) {
+      return NULL;
+    }
+    $1.size = RSTRING_LEN($input);
+  }
+}
+
+%typemap(out) pn_bytes_t {
+  $result = rb_str_new($1.start, $1.size);
+}
+
+%typemap (in) void *
+{
+  $1 = (void *) $input;
+}
+
+%typemap (out) void *
+{
+  $result = (VALUE) $1;
+}
+
+int pn_message_load(pn_message_t *msg, char *STRING, size_t LENGTH);
+%ignore pn_message_load;
+
+int pn_message_load_data(pn_message_t *msg, char *STRING, size_t LENGTH);
+%ignore pn_message_load_data;
+
+int pn_message_load_text(pn_message_t *msg, char *STRING, size_t LENGTH);
+%ignore pn_message_load_text;
+
+int pn_message_load_amqp(pn_message_t *msg, char *STRING, size_t LENGTH);
+%ignore pn_message_load_amqp;
+
+int pn_message_load_json(pn_message_t *msg, char *STRING, size_t LENGTH);
+%ignore pn_message_load_json;
+
+int pn_message_encode(pn_message_t *msg, char *OUTPUT, size_t *OUTPUT_SIZE);
+%ignore pn_message_encode;
+
+int pn_message_save(pn_message_t *msg, char *OUTPUT, size_t *OUTPUT_SIZE);
+%ignore pn_message_save;
+
+int pn_message_save_data(pn_message_t *msg, char *OUTPUT, size_t *OUTPUT_SIZE);
+%ignore pn_message_save_data;
+
+int pn_message_save_text(pn_message_t *msg, char *OUTPUT, size_t *OUTPUT_SIZE);
+%ignore pn_message_save_text;
+
+int pn_message_save_amqp(pn_message_t *msg, char *OUTPUT, size_t *OUTPUT_SIZE);
+%ignore pn_message_save_amqp;
+
+int pn_message_save_json(pn_message_t *msg, char *OUTPUT, size_t *OUTPUT_SIZE);
+%ignore pn_message_save_json;
+
+ssize_t pn_send(pn_link_t *transport, char *STRING, size_t LENGTH);
+%ignore pn_send;
+
+%rename(pn_recv) wrap_pn_recv;
+%inline %{
+  int wrap_pn_recv(pn_link_t *link, char *OUTPUT, size_t *OUTPUT_SIZE) {
+    ssize_t sz = pn_recv(link, OUTPUT, *OUTPUT_SIZE);
+    if (sz >= 0) {
+      *OUTPUT_SIZE = sz;
+    } else {
+      *OUTPUT_SIZE = 0;
+    }
+    return sz;
+  }
+%}
+%ignore pn_recv;
+
+ssize_t pn_input(pn_transport_t *transport, char *STRING, size_t LENGTH);
+%ignore pn_input;
+
+%rename(pn_output) wrap_pn_output;
+%inline %{
+  int wrap_pn_output(pn_transport_t *transport, char *OUTPUT, size_t *OUTPUT_SIZE) {
+    ssize_t sz = pn_output(transport, OUTPUT, *OUTPUT_SIZE);
+    if (sz >= 0) {
+      *OUTPUT_SIZE = sz;
+    } else {
+      *OUTPUT_SIZE = 0;
+    }
+    return sz;
+  }
+%}
+%ignore pn_output;
+
+%rename(pn_delivery) wrap_pn_delivery;
+%inline %{
+  pn_delivery_t *wrap_pn_delivery(pn_link_t *link, char *STRING, size_t LENGTH) {
+    return pn_delivery(link, pn_dtag(STRING, LENGTH));
+  }
+%}
+%ignore pn_delivery;
+
+%rename(pn_delivery_tag) wrap_pn_delivery_tag;
+%inline %{
+  void wrap_pn_delivery_tag(pn_delivery_t *delivery, char **ALLOC_OUTPUT, size_t *ALLOC_SIZE) {
+    pn_delivery_tag_t tag = pn_delivery_tag(delivery);
+    *ALLOC_OUTPUT = malloc(tag.size);
+    *ALLOC_SIZE = tag.size;
+    memcpy(*ALLOC_OUTPUT, tag.bytes, tag.size);
+  }
+%}
+%ignore pn_delivery_tag;
+
+%rename(pn_message_data) wrap_pn_message_data;
+%inline %{
+  int wrap_pn_message_data(char *STRING, size_t LENGTH, char *OUTPUT, size_t *OUTPUT_SIZE) {
+    ssize_t sz = pn_message_data(OUTPUT, *OUTPUT_SIZE, STRING, LENGTH);
+    if (sz >= 0) {
+      *OUTPUT_SIZE = sz;
+    } else {
+      *OUTPUT_SIZE = 0;
+    }
+    return sz;
+  }
+%}
+%ignore pn_message_data;
+
+%include "../cproton.i"



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org