summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorPhil Mesnier <mesnier_p@ociweb.com>2004-11-05 04:29:02 +0000
committerPhil Mesnier <mesnier_p@ociweb.com>2004-11-05 04:29:02 +0000
commit2cf7df592ed63aea6d00d49d0ee54b7293caf49f (patch)
treeb6af3fc856b24ad1964ae6f33982a9bf97d2da50 /protocols
parent5fbd7766eaa709261927d7e059fa5348b39b2057 (diff)
downloadATCD-2cf7df592ed63aea6d00d49d0ee54b7293caf49f.tar.gz
ChangeLog tag: Thu Nov 4 22:08:40 2004 Phil Mesnier <mesnier_p@ociweb.com>
Diffstat (limited to 'protocols')
-rw-r--r--protocols/ace/HTBP/HTBP.mpc7
-rw-r--r--protocols/ace/HTBP/HTBP_Addr.cpp89
-rw-r--r--protocols/ace/HTBP/HTBP_Addr.h87
-rw-r--r--protocols/ace/HTBP/HTBP_Channel.cpp532
-rw-r--r--protocols/ace/HTBP/HTBP_Channel.h277
-rw-r--r--protocols/ace/HTBP/HTBP_Channel.inl122
-rw-r--r--protocols/ace/HTBP/HTBP_Environment.cpp197
-rw-r--r--protocols/ace/HTBP/HTBP_Environment.h107
-rw-r--r--protocols/ace/HTBP/HTBP_Export.h53
-rw-r--r--protocols/ace/HTBP/HTBP_Filter.cpp56
-rw-r--r--protocols/ace/HTBP/HTBP_Filter.h100
-rw-r--r--protocols/ace/HTBP/HTBP_Filter.inl60
-rw-r--r--protocols/ace/HTBP/HTBP_Filter_Factory.cpp57
-rw-r--r--protocols/ace/HTBP/HTBP_Filter_Factory.h66
-rw-r--r--protocols/ace/HTBP/HTBP_ID_Requestor.cpp135
-rw-r--r--protocols/ace/HTBP/HTBP_ID_Requestor.h58
-rw-r--r--protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp227
-rw-r--r--protocols/ace/HTBP/HTBP_Inside_Squid_Filter.h87
-rw-r--r--protocols/ace/HTBP/HTBP_Inside_Squid_Filter.inl9
-rw-r--r--protocols/ace/HTBP/HTBP_Macros.h10
-rw-r--r--protocols/ace/HTBP/HTBP_Notifier.cpp87
-rw-r--r--protocols/ace/HTBP/HTBP_Notifier.h54
-rw-r--r--protocols/ace/HTBP/HTBP_Notifier.inl4
-rw-r--r--protocols/ace/HTBP/HTBP_Outside_Squid_Filter.cpp192
-rw-r--r--protocols/ace/HTBP/HTBP_Outside_Squid_Filter.h82
-rw-r--r--protocols/ace/HTBP/HTBP_Outside_Squid_Filter.inl9
-rw-r--r--protocols/ace/HTBP/HTBP_Session.cpp301
-rw-r--r--protocols/ace/HTBP/HTBP_Session.h193
-rw-r--r--protocols/ace/HTBP/HTBP_Session.inl109
-rw-r--r--protocols/ace/HTBP/HTBP_Stream.cpp330
-rw-r--r--protocols/ace/HTBP/HTBP_Stream.h291
-rw-r--r--protocols/ace/HTBP/HTBP_Stream.inl4
-rw-r--r--protocols/ace/HTBP/HTID_Generator.cgi78
-rw-r--r--protocols/ace/HTBP/README186
34 files changed, 4256 insertions, 0 deletions
diff --git a/protocols/ace/HTBP/HTBP.mpc b/protocols/ace/HTBP/HTBP.mpc
new file mode 100644
index 00000000000..21c99d9a407
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project(HTBP) : acelib, core {
+ sharedname = ACE_HTBP
+ dynamicflags = HTBP_BUILD_DLL
+}
diff --git a/protocols/ace/HTBP/HTBP_Addr.cpp b/protocols/ace/HTBP/HTBP_Addr.cpp
new file mode 100644
index 00000000000..0ea811bb108
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Addr.cpp
@@ -0,0 +1,89 @@
+// $Id$
+
+#include "HTBP_Addr.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (HTBP,
+ ACE_HTBP_Addr,
+ "$Id$")
+
+ // Constructor
+ ACE::HTBP::Addr::Addr ()
+{
+}
+
+// Creates a ACE_INET_Addr from a PORT_NUMBER and the remote
+// HOST_NAME.
+
+ACE::HTBP::Addr::Addr (u_short port_number,
+ const char host_name[],
+ int address_family)
+ : ACE_INET_Addr (port_number, host_name, address_family),
+ htid_ ()
+{
+}
+
+ACE::HTBP::Addr::Addr (const char *htid)
+ : htid_(htid)
+{
+}
+
+ACE::HTBP::Addr::Addr (const ACE::HTBP::Addr &other)
+ : ACE_INET_Addr (other),
+ htid_(other.htid_)
+{
+
+}
+
+// Destructor
+ACE::HTBP::Addr::~Addr ()
+{
+}
+
+int
+ACE::HTBP::Addr::set (u_short port,
+ const char host[],
+ const char *htid)
+{
+ if (htid != 0 && ACE_OS::strlen (htid) != 0)
+ return this->set_htid (htid);
+ return this->ACE_INET_Addr::set(port,host);
+}
+
+int
+ACE::HTBP::Addr::set_htid (const char *htid)
+{
+ this->htid_ = htid;
+ this->set_port_number (0);
+ return 0;
+}
+
+const char *
+ACE::HTBP::Addr::get_htid (void) const
+{
+ return this->htid_.c_str();
+}
+
+int
+ACE::HTBP::Addr::addr_to_string (ACE_TCHAR buffer[],
+ size_t size,
+ int ipaddr_format) const
+{
+ if (this->htid_.length() == 0)
+ return this->ACE_INET_Addr::addr_to_string(buffer,size,ipaddr_format);
+ if (size < htid_.length())
+ return -1;
+ ACE_OS::strncpy (buffer,
+ ACE_TEXT_CHAR_TO_TCHAR(htid_.c_str()),
+ size);
+ return 0;
+}
+
+int
+ACE::HTBP::Addr::string_to_addr (const char address[])
+{
+ // if (ACE_OS::strchr (address,':'))
+ return this->ACE_INET_Addr::string_to_addr(address);
+ // this->htid_ = address;
+ // return 0;
+}
diff --git a/protocols/ace/HTBP/HTBP_Addr.h b/protocols/ace/HTBP/HTBP_Addr.h
new file mode 100644
index 00000000000..3cbbaa397f7
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Addr.h
@@ -0,0 +1,87 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file HTBP_Addr.h
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier
+ */
+//=============================================================================
+
+#ifndef ACE_HTBP_ADDR_H
+#define ACE_HTBP_ADDR_H
+#include /**/ "ace/pre.h"
+
+#include "HTBP_Export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/INET_Addr.h"
+#include "ace/Synch.h"
+#include "ace/SString.h"
+
+namespace ACE
+{
+ namespace HTBP
+ {
+
+ /**
+ * @class Addr
+ *
+ * @brief Defines the member functions of the pure virtual class
+ * Addr
+ *
+ * This class derives from ACE_INET_Addr. It is the base class for
+ * the Inside, Proxy and Outside classes
+ */
+ class HTBP_Export Addr : public ACE_INET_Addr
+ {
+ public:
+ /// Constructor
+ Addr ();
+
+ Addr (const Addr &other);
+
+ /// Create an Addr suitable for use on the inside of a firewall this
+ /// take a string used to populate the htid_ member. With this address,
+ /// the IP addr form is ignored.
+ Addr (const char *htid);
+
+ /// Initialize an Addr for the outside of a firewall. In this form,
+ /// the htid_ is an empty string and the arguments are passed to the
+ /// base address type.
+ Addr (u_short port_number,
+ const char host_name[],
+ int address_family = AF_UNSPEC);
+
+ /// Destructor
+ virtual ~Addr ();
+
+ int set (u_short port,
+ const char host [],
+ const char *htid);
+
+ /// Methods to help convert the OutSide_Addr to a String
+ /// and vice versa
+ int addr_to_string (ACE_TCHAR buffer[],
+ size_t size,
+ int ipaddr_format = 1) const;
+ int string_to_addr (const char address[]);
+
+ int set_htid(const char *htid);
+ const char *get_htid (void) const;
+
+ private:
+ /// HTID - web-obtained unique-identifier
+ ACE_CString htid_;
+ };
+
+ }
+}
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_ADDR_H */
diff --git a/protocols/ace/HTBP/HTBP_Channel.cpp b/protocols/ace/HTBP/HTBP_Channel.cpp
new file mode 100644
index 00000000000..ee00eb90efc
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Channel.cpp
@@ -0,0 +1,532 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Channel.cpp
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier, Priyanka Gontla
+ */
+//=============================================================================
+#include "HTBP_Channel.h"
+
+#if !defined (__ACE_INLINE__)
+#include "HTBP_Channel.inl"
+#endif
+
+#include "HTBP_Session.h"
+#include "HTBP_Filter_Factory.h"
+
+#include "ace/Message_Block.h"
+
+
+// Initialization and termination methods.
+/// Constructor.
+ACE::HTBP::Channel::Channel (ACE::HTBP::Session *s)
+ : filter_ (0),
+ session_ (s),
+ ace_stream_ (),
+ notifier_ (0),
+ leftovers_ (1000),
+ data_len_ (0),
+ data_consumed_ (0),
+ state_ (Init),
+ error_buffer_ (0)
+{
+ ACE_NEW (this->notifier_,ACE::HTBP::Notifier(this));
+ this->filter_ = get_filter ();
+ this->request_count_ = ACE_static_cast (unsigned long,ACE_OS::time());
+}
+
+/// Constructor, takes ownership of the supplied stream
+ACE::HTBP::Channel::Channel (ACE_SOCK_Stream &s)
+ : filter_ (0),
+ session_ (0),
+ ace_stream_ (s.get_handle()),
+ notifier_ (0),
+ leftovers_ (1000),
+ data_len_ (0),
+ data_consumed_ (0),
+ state_ (Init),
+ error_buffer_ (0)
+
+{
+ filter_ = get_filter ();
+ this->request_count_ = ACE_static_cast (unsigned long,ACE_OS::time());
+}
+
+ACE::HTBP::Channel::Channel (ACE_HANDLE h)
+ : filter_ (0),
+ session_ (0),
+ ace_stream_ (h),
+ notifier_ (0),
+ leftovers_ (1000),
+ data_len_ (0),
+ data_consumed_ (0),
+ state_ (Init),
+ error_buffer_ (0)
+{
+ filter_ = get_filter ();
+ this->request_count_ = ACE_static_cast (unsigned long,ACE_OS::time());
+}
+
+/// Destructor.
+ACE::HTBP::Channel::~Channel (void)
+{
+ delete this->filter_;
+ delete this->notifier_;
+}
+
+ /// Dump the state of an object.
+void
+ACE::HTBP::Channel::dump (void) const
+{
+}
+
+unsigned long
+ACE::HTBP::Channel::request_count (void)
+{
+ return this->request_count_++;
+}
+
+void
+ACE::HTBP::Channel::register_notifier (ACE_Reactor *r)
+{
+ if (r == 0)
+ return;
+ if (this->notifier_ == 0)
+ {
+ ACE_NEW (this->notifier_,ACE::HTBP::Notifier(this));
+ }
+ else
+ {
+ if (notifier_->get_handle() == ACE_INVALID_HANDLE)
+ {
+ delete this->notifier_;
+ ACE_NEW (this->notifier_,ACE::HTBP::Notifier(this));
+ }
+ }
+
+ r->register_handler(notifier_,ACE_Event_Handler::READ_MASK);
+}
+
+ACE::HTBP::Notifier *
+ACE::HTBP::Channel::notifier (void)
+{
+ return this->notifier_;
+}
+
+ACE_HANDLE
+ACE::HTBP::Channel::get_handle (void) const
+{
+ return this->ace_stream_.get_handle ();
+}
+
+void
+ACE::HTBP::Channel::data_consumed (size_t n)
+{
+ this->data_consumed_ += n;
+ if (this->data_consumed_ == this->data_len_)
+ {
+ this->filter_->recv_data_trailer(this);
+ this->filter_->send_ack(this);
+ }
+}
+
+int
+ACE::HTBP::Channel::load_buffer (void)
+{
+ this->leftovers_.crunch();
+ if (this->state() == Detached ||
+ this->state() == Ack_Sent)
+ {
+ this->data_len_ = 0;
+ this->data_consumed_ = 0;
+ }
+
+ ssize_t nread = 0;
+ errno = 0;
+#if 0
+ if (this->session_ &&
+ (this->session_->sock_flags() & ACE_NONBLOCK == ACE_NONBLOCK))
+#endif
+ {
+ nread =
+ ACE::handle_read_ready (this->ace_stream().get_handle(),
+ &ACE_Time_Value::zero);
+ if (nread == -1 && errno == ETIME)
+ errno = EWOULDBLOCK;
+ }
+ if (nread != -1)
+ nread = this->ace_stream().recv (this->leftovers_.wr_ptr(),
+ this->leftovers_.space());
+ if (nread < 1)
+ {
+ if (nread == 0 || (errno != EWOULDBLOCK && errno != EAGAIN))
+ {
+ this->state_ = Closed;
+#if 0
+ ACE_ERROR ((LM_ERROR,
+ "load_buffer[%d] %p\n",
+ this->ace_stream_.get_handle(),"recv"));
+#endif
+ }
+ return nread;
+ }
+ this->leftovers_.wr_ptr(nread);
+ *this->leftovers_.wr_ptr() = '\0';
+#if 0
+ ACE_DEBUG ((LM_DEBUG,"load_buffer[%d] received %d \n",
+ this->ace_stream_.get_handle(),leftovers_.length()));
+ ACE_HEX_DUMP ((LM_DEBUG,leftovers_.rd_ptr(),leftovers_.length()));
+#endif
+ return nread;
+}
+
+int
+ACE::HTBP::Channel::flush_buffer (void)
+{
+ if (this->session_)
+ return this->session_->flush_outbound_queue();
+ return 0;
+}
+
+int
+ACE::HTBP::Channel::send_ack (void)
+{
+ return this->filter_->send_ack(this);
+}
+
+int
+ACE::HTBP::Channel::recv_ack (void)
+{
+ if (load_buffer() == -1)
+ return -1;
+ return this->filter_->recv_ack(this);
+}
+
+void
+ACE::HTBP::Channel::state (ACE::HTBP::Channel::State s)
+{
+ if (s == Detached)
+ {
+ this->session_->detach(this);
+ this->session_ = 0;
+ }
+ this->state_ = s;
+}
+
+int
+ACE::HTBP::Channel::consume_error (void)
+{
+ if (error_buffer_ == 0)
+ {
+ ACE_NEW_RETURN (error_buffer_,
+ ACE_Message_Block (this->data_len_ + 1),
+ 0);
+ }
+
+ ssize_t result = 0;
+ size_t n = error_buffer_->size();
+ char *buf = error_buffer_->wr_ptr();
+
+ if (this->leftovers_.length() > 0)
+ {
+ result = ACE_MIN (n,this->leftovers_.length());
+ ACE_OS::memcpy (buf,this->leftovers_.rd_ptr(), result);
+ this->leftovers_.rd_ptr(result);
+ buf += result;
+ }
+
+ if (result < (ssize_t)n &&
+ result < (ssize_t)data_len_)
+ {
+ n -= result;
+ result += this->ace_stream_.recv(buf, n);
+ }
+ if (result > 0)
+ {
+ this->error_buffer_->wr_ptr(result);
+ this->data_consumed_ += result;
+ if (this->data_consumed_ == this->data_len_)
+ {
+ *this->error_buffer_->wr_ptr() = '\0';
+ ACE_DEBUG ((LM_DEBUG,"Received entire error buffer: \n%s\n",
+ this->error_buffer_->rd_ptr()));
+ delete error_buffer_;
+ error_buffer_ = 0;
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+// = I/O functions.
+
+/// The ACE::HTBP::Channel is a sibling of the ACE_SOCK_IO class, rather than a
+/// decendant. This is due to the requirement to wrap all messages with
+/// an HTTP request or reply wrapper, and to send application data in only
+/// one direction on one stream.
+
+int
+ACE::HTBP::Channel::pre_recv(void)
+{
+ if (this->state_ == Init ||
+ this->state_ == Detached ||
+ this->state_ == Header_Pending ||
+ this->state_ == Ack_Sent)
+ {
+ if (this->load_buffer() == -1 && this->leftovers_.length() == 0)
+ {
+ if (errno != EWOULDBLOCK)
+ this->state_ = Closed;
+ ACE_DEBUG ((LM_DEBUG,"pre_recv returning -1, state = %d\n",state_));
+ return -1;
+ }
+ if (this->filter_->recv_data_header(this) == -1)
+ ACE_DEBUG ((LM_DEBUG,"recv_data_header failed, %p\n","pre_recv"));
+ }
+ switch (this->state_)
+ {
+ case Data_Queued:
+ case Ack_Sent:
+ case Ready:
+ return 0;
+ case Header_Pending:
+ errno = EWOULDBLOCK;
+ return -1;
+ default:
+ ACE_DEBUG ((LM_DEBUG,"channel[%d] state = %d, %p\n",
+ this->get_handle(),
+ this->state_,"pre_recv"));
+ }
+ return -1;
+}
+
+/// Recv an <n> byte buffer from the connected socket.
+ssize_t
+ACE::HTBP::Channel::recv (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ ssize_t result = 0;
+ if (this->pre_recv() == -1 && this->leftovers_.length() == 0)
+ return -1;
+
+ if (this->leftovers_.length() > 0)
+ {
+ result = ACE_MIN (n,this->leftovers_.length());
+ ACE_OS::memcpy (buf,this->leftovers_.rd_ptr(), result);
+ this->leftovers_.rd_ptr(result);
+ buf = (char *)buf + result;
+ }
+
+ if (result < (ssize_t)n &&
+ result < (ssize_t)data_len_)
+ {
+ n -= result;
+ result += this->ace_stream_.recv(buf, n, flags, timeout);
+ }
+ if (result > 0)
+ data_consumed((size_t)result);
+ return result;
+}
+
+ /// Recv an <n> byte buffer from the connected socket.
+ssize_t
+ACE::HTBP::Channel::recv (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout)
+{
+ ssize_t result = 0;
+ if (this->pre_recv() == -1)
+ return -1;
+
+ result = 0;
+ if (this->leftovers_.length() > 0)
+ {
+ result = ACE_MIN (n,this->leftovers_.length());
+ ACE_OS::memcpy (buf,this->leftovers_.rd_ptr(), result);
+ this->leftovers_.rd_ptr(result);
+ buf = (char *)buf + result;
+ }
+
+ if ((size_t)result < n && (size_t)result < this->data_len())
+ {
+ n -= result;
+ result += this->ace_stream_.recv(buf, n, timeout);
+ }
+
+ if (result > 0)
+ this->data_consumed((size_t)result);
+ return result;
+}
+
+ /// Recv an <iovec> of size <n> from the connected socket.
+ssize_t
+ACE::HTBP::Channel::recvv (iovec iov[],
+ int iovcnt,
+ const ACE_Time_Value *timeout)
+{
+ ssize_t result = 0;
+ if (this->pre_recv() == -1)
+ return -1;
+
+ if (this->leftovers_.length())
+ {
+ int ndx = 0;
+ iovec *iov2 = new iovec[iovcnt];
+ for (int i = 0; i < iovcnt; i++)
+ {
+ size_t n = ACE_MIN ((size_t) iov[i].iov_len ,
+ (size_t) this->leftovers_.length());
+ if (n > 0)
+ {
+ ACE_OS::memcpy (iov[i].iov_base,this->leftovers_.rd_ptr(), n);
+ this->leftovers_.rd_ptr(n);
+ result += n;
+ }
+ if (n < (size_t) iov[i].iov_len)
+ {
+ iov2[ndx].iov_len = iov[i].iov_len - n;
+ iov2[ndx].iov_base = (char *)iov[i].iov_base + n;
+ ndx++;
+ }
+ }
+ if (ndx > 0)
+ result += this->ace_stream_.recvv(iov2,ndx,timeout);
+ delete [] iov2;
+ }
+ else
+ result = this->ace_stream_.recvv(iov,iovcnt,timeout);
+
+ if (result > 0)
+ this->data_consumed((size_t)result);
+ return result;
+}
+
+ssize_t
+ACE::HTBP::Channel::recvv (iovec *io_vec,
+ const ACE_Time_Value *timeout)
+{
+ ssize_t result = 0;
+ if (this->pre_recv() == -1)
+ return -1;
+
+ ACE_DEBUG ((LM_DEBUG,"recvv, leftover len = %d\n",
+ this->leftovers_.length()));
+ if (this->leftovers_.length())
+ {
+ io_vec->iov_base = 0;
+ io_vec->iov_len = 0;
+ ACE_NEW_RETURN (io_vec->iov_base,
+ char[this->leftovers_.length()],-1);
+ io_vec->iov_len = this->leftovers_.length();
+ ACE_OS::memcpy (io_vec->iov_base,
+ this->leftovers_.rd_ptr(),
+ io_vec->iov_len);
+ result = io_vec->iov_len;
+ this->leftovers_.length(0);
+ }
+ else
+ result = this->ace_stream_.recvv(io_vec,timeout);
+
+ if (result > 0)
+ this->data_consumed((size_t)result);
+ return result;
+}
+
+ssize_t
+ACE::HTBP::Channel::send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ ssize_t result = 0;
+ if (this->filter_->send_data_header(n,this) == -1)
+ return -1;
+ result = this->ace_stream_.send(buf,n,flags,timeout);
+ if (result == -1)
+ return -1;
+ if (this->filter_->send_data_trailer(this) == -1)
+ return -1;
+ return result;
+}
+
+ssize_t
+ACE::HTBP::Channel::send (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout)
+{
+ ssize_t result = 0;
+ if (this->filter_ == 0)
+ ACE_ERROR_RETURN ((LM_DEBUG, "ACE::HTBP::Channel::send: filter is null\n"),-1);
+ if (this->filter_->send_data_header(n,this) == -1)
+ return -1;
+ result = this->ace_stream_.send (buf,n,timeout);
+ if (result == -1)
+ return -1;
+ if (this->filter_->send_data_trailer(this) == -1)
+ return -1;
+ return result;
+}
+
+ssize_t
+ACE::HTBP::Channel::sendv (const iovec iov[],
+ int iovcnt,
+ const ACE_Time_Value *timeout)
+{
+ if (this->ace_stream_.get_handle() == ACE_INVALID_HANDLE)
+ this->session_->inbound();
+
+ ssize_t result = 0;
+ size_t n = 0;
+ for (int i = 0; i < iovcnt; n += iov[i++].iov_len);
+
+ if (this->filter_->send_data_header(n,this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,"sendv, %p\n","send_data_header"),-1);
+
+ result = this->ace_stream_.sendv (iov,iovcnt,timeout);
+
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,"sendv, %p\n","ace_stream_.sendv"),-1);
+
+ if (this->filter_->send_data_trailer(this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,"sendv, %p\n","send_data_trailer\n"),-1);
+
+ return result;
+}
+
+int
+ACE::HTBP::Channel::enable (int value) const
+{
+ this->ace_stream_.enable(value);
+
+ return 0; //this->ace_stream_.enable(value);
+}
+
+int
+ACE::HTBP::Channel::disable (int value) const
+{
+ this->ace_stream_.disable(value);
+
+ return 0;//this->ace_stream_.disable(value);
+}
+
+ACE::HTBP::Filter *
+ACE::HTBP::Channel::get_filter ()
+{
+ ACE::HTBP::Filter_Factory *factory = 0;
+
+ // @todo Should I be throwing an exception here if
+ // memory is not allocated right ?
+ ACE_NEW_RETURN (factory,
+ ACE::HTBP::Filter_Factory,
+ 0);
+ int inside = (this->session_ != 0);
+ return factory->get_filter (inside);
+}
diff --git a/protocols/ace/HTBP/HTBP_Channel.h b/protocols/ace/HTBP/HTBP_Channel.h
new file mode 100644
index 00000000000..3109ed656eb
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Channel.h
@@ -0,0 +1,277 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Channel.h
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier, Priyanka Gontla
+ */
+//=============================================================================
+
+#ifndef ACE_HTBP_CHANNEL_H
+#define ACE_HTBP_CHANNEL_H
+#include /**/ "ace/pre.h"
+
+#include "ace/SOCK_Stream.h"
+#include "ace/Message_Block.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "HTBP_Export.h"
+#include "HTBP_Addr.h"
+#include "HTBP_Filter.h"
+#include "HTBP_Notifier.h"
+
+
+namespace ACE
+{
+ namespace HTBP
+ {
+ // Forward declarations.
+ class Session;
+
+ /**
+ * @class ACE::HTBP::Channel
+ *
+ * @brief Defines the methods in the <Ht_Channel> abstraction.
+ *
+ * This adds additional wrapper methods atop the <IO>
+ * class.
+ *
+ * <buf> is the buffer to write from or receive into.
+ * <len> is the number of bytes to transfer.
+ * The <timeout> parameter in the following methods indicates how
+ * long to blocking trying to transfer data. If <timeout> == 0,
+ * then the call behaves as a normal send/recv call, i.e., for
+ * blocking sockets, the call will block until action is possible;
+ * for non-blocking sockets, EWOULDBLOCK will be returned if no
+ * action is immediately possible.
+ * If <timeout> != 0, the call will wait for data to arrive no longer
+ * than the relative time specified in *<timeout>.
+ * The "_n()" I/O methods keep looping until all the data has been
+ * transferred. These methods also work for sockets in non-blocking
+ * mode i.e., they keep looping on EWOULDBLOCK. <timeout> is used
+ * to make sure we keep making progress, i.e., the same timeout
+ * value is used for every I/O operation in the loop and the timeout
+ * is not counted down.
+ * The return values for the "*_n()" methods match the return values
+ * from the non "_n()" methods and are specified as follows:
+ * - On complete transfer, the number of bytes transferred is returned.
+ * - On timeout, -1 is returned, errno == ETIME.
+ * - On error, -1 is returned, errno is set to appropriate error.
+ * - On EOF, 0 is returned, errno is irrelevant.
+ *
+ * On partial transfers, i.e., if any data is transferred before
+ * timeout/error/EOF, <bytes_transferred> will contain the number of
+ * bytes transferred.
+ * Methods with <iovec> parameter are I/O vector variants of the I/O
+ * operations.
+ * Methods with the extra <flags> argument will always result in
+ * <send> getting called. Methods without the extra <flags> argument
+ * will result in <send> getting called on Win32 platforms, and
+ * <write> getting called on non-Win32 platforms.
+ */
+ class HTBP_Export Channel
+ {
+ public:
+ friend class Notifier;
+ // Initialization and termination methods.
+ /// Constructor.
+ Channel (Session *s = 0);
+
+ Channel (ACE_SOCK_Stream &s);
+ Channel (ACE_HANDLE h);
+
+ /// Destructor.
+ ~Channel (void);
+
+ enum State {
+ Init,
+ Ready,
+ Data_Queued,
+ Ack_Sent,
+ Header_Sent,
+ Closed,
+ Send_Ack,
+ Detached,
+ Wait_For_Ack,
+ Header_Pending
+ };
+
+ // = I/O functions.
+
+ /// The Channel is a sibling of the ACE_SOCK_IO class, rather than a
+ /// decendant. This is due to the requirement to wrap all messages with
+ /// an HTTP request or reply wrapper, and to send application data in only
+ /// one direction on one stream.
+
+ /// Recv an <n> byte buffer from the connected socket.
+ ssize_t recv (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0);
+
+ /// Recv an <n> byte buffer from the connected socket.
+ ssize_t recv (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0);
+
+ /// Recv an <iovec> of size <n> from the connected socket.
+ ssize_t recvv (iovec iov[],
+ int n,
+ const ACE_Time_Value *timeout = 0);
+
+ /// Same as above. Deprecated.
+ ssize_t recv (iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout = 0);
+
+ /**
+ * Allows a client to read from a socket without having to provide a
+ * buffer to read. This method determines how much data is in the
+ * socket, allocates a buffer of this size, reads in the data, and
+ * returns the number of bytes read. The caller is responsible for
+ * deleting the member in the <iov_base> field of <io_vec> using
+ * delete [] io_vec->iov_base.
+ */
+ ssize_t recvv (iovec *io_vec,
+ const ACE_Time_Value *timeout = 0);
+
+ /// Send an <n> byte buffer to the connected socket.
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0);
+
+ /// Send an <n> byte buffer to the connected socket.
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0);
+
+ /// Send an <iovec> of size <n> to the connected socket.
+ ssize_t sendv (const iovec iov[],
+ int n,
+ const ACE_Time_Value *timeout = 0);
+
+ // = Selectively close endpoints.
+ /// Close down the reader.
+ int close_reader (void);
+
+ /// Close down the writer.
+ int close_writer (void);
+
+ /**
+ * Close down the socket (we need this to make things work correctly
+ * on Win32, which requires use to do a <close_writer> before doing
+ * the close to avoid losing data).
+ */
+ int close (void);
+
+ // = Meta-type info
+ typedef ACE_INET_Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ public:
+ Session *session (void) const;
+ void session (Session *);
+
+ Notifier *notifier (void);
+
+ void register_notifier (ACE_Reactor *r);
+
+ ACE_HANDLE get_handle (void) const;
+
+ const ACE_SOCK_Stream &ace_stream (void) const;
+ ACE_SOCK_Stream &ace_stream (void);
+
+ ///@notes Added the following methods to continue with
+ /// current compilation of HTIOP. Might not be needed in
+ /// future. - Priyanka
+ /// {@
+ void set_handle (ACE_HANDLE h);
+
+ /**
+ * Enable asynchronous I/O (ACE_SIGIO), urgent data (ACE_SIGURG),
+ * non-blocking I/O (ACE_NONBLOCK), or close-on-exec (ACE_CLOEXEC),
+ * which is passed as the <value>.
+ */
+ int enable (int value) const;
+
+ /**
+ * Disable asynchronous I/O (ACE_SIGIO), urgent data (ACE_SIGURG),
+ * non-blocking I/O (ACE_NONBLOCK), or close-on-exec (ACE_CLOEXEC),
+ * which is passed as the <value>.
+ */
+ int disable (int value) const;
+ //@}
+
+ // buffer related methods.
+ ACE_Message_Block &leftovers (void);
+ size_t data_len (void) const;
+ void data_len (size_t n);
+ size_t data_consumed (void) const;
+ void data_consumed (size_t n);
+ int load_buffer (void);
+ int flush_buffer (void);
+ int recv_ack (void);
+ int send_ack (void);
+ unsigned long request_count();
+ Filter *filter (void) const;
+ void filter (Filter *);
+ State state (void) const;
+ void state (Channel::State s);
+ int pre_recv(void);
+ int consume_error (void);
+
+ private:
+
+ /// Get the filter from the Filter_Factory
+ Filter * get_filter ();
+
+ /// The filter_ is a pluggable component used to manage the
+ /// wrapping of data in a way suitable for the proxy to
+ /// manage. The actual filter instance is owned by the
+ /// session. Different filters may be required depending on
+ /// which side of the proxy we are on, and the direction of data
+ /// flow.
+ Filter *filter_;
+
+ /// The session_ is a reference to the persistent session this
+ /// stream is associated with. On the inside, sessions are
+ /// created by the Connector, which then create streams on
+ /// demand.
+ Session *session_;
+
+ /// Since this stream implements its own send and recv methods,
+ /// the filter cannot simply call the send and recv methods of
+ /// this class. Therefore an ACE_SOCK_Stream wrapper around the
+ /// same socket instance is necessary to avoid recursion.
+ ACE_SOCK_Stream ace_stream_;
+
+ Notifier *notifier_;
+
+ ACE_Message_Block leftovers_;
+ size_t data_len_;
+ size_t data_consumed_;
+ State state_;
+ ACE_Message_Block *error_buffer_;
+ unsigned long request_count_;
+ };
+ }
+}
+
+#if defined (__ACE_INLINE__)
+#include "HTBP_Channel.inl"
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_CHANNEL_H */
diff --git a/protocols/ace/HTBP/HTBP_Channel.inl b/protocols/ace/HTBP/HTBP_Channel.inl
new file mode 100644
index 00000000000..70fc4834842
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Channel.inl
@@ -0,0 +1,122 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ACE::HTBP::Channel.i
+
+
+ACE_INLINE
+ACE::HTBP::Session *
+ACE::HTBP::Channel::session (void) const
+{
+ return this->session_;
+}
+
+// session assignment only occurs when the stream is transferred to another
+// session. Do *not* delete the old session object.
+ACE_INLINE
+void
+ACE::HTBP::Channel::session (ACE::HTBP::Session *s)
+{
+ this->session_ = s;
+}
+
+// I'm not sure of the proper use case for getting the filter reference. The
+// problem is that the filter is not reference counted, so the returned value
+// should not be stored.
+ACE_INLINE
+ACE::HTBP::Filter *
+ACE::HTBP::Channel::filter (void) const
+{
+ return this->filter_;
+}
+
+// Filters are owned by the channel. If a new filter is applied, the old one
+// must be deleted.
+ACE_INLINE
+void
+ACE::HTBP::Channel::filter (ACE::HTBP::Filter *f)
+{
+ if (this->filter_)
+ delete this->filter_;
+ this->filter_ = f;
+}
+
+ACE_INLINE
+int
+ACE::HTBP::Channel::close_reader (void)
+{
+ return this->ace_stream_.close_reader();
+}
+
+ACE_INLINE
+int
+ACE::HTBP::Channel::close_writer (void)
+{
+ return this->ace_stream_.close_writer();
+}
+
+ACE_INLINE
+int
+ACE::HTBP::Channel::close (void)
+{
+ return this->ace_stream_.close();
+}
+
+ACE_INLINE
+ACE::HTBP::Channel::State
+ACE::HTBP::Channel::state (void) const
+{
+ return this->state_;
+}
+
+ACE_INLINE
+ACE_Message_Block &
+ACE::HTBP::Channel::leftovers (void)
+{
+ return this->leftovers_;
+}
+
+ACE_INLINE
+size_t
+ACE::HTBP::Channel::data_len(void) const
+{
+ return this->data_len_;
+}
+
+ACE_INLINE
+void
+ACE::HTBP::Channel::data_len(size_t n)
+{
+ this->data_len_ = n;
+}
+
+ACE_INLINE
+size_t
+ACE::HTBP::Channel::data_consumed(void) const
+{
+ return this->data_consumed_;
+}
+
+
+ACE_INLINE
+const ACE_SOCK_Stream&
+ACE::HTBP::Channel::ace_stream (void) const
+{
+ return this->ace_stream_;
+}
+
+ACE_INLINE
+ACE_SOCK_Stream&
+ACE::HTBP::Channel::ace_stream (void)
+{
+ return this->ace_stream_;
+}
+
+ACE_INLINE
+void
+ACE::HTBP::Channel::set_handle (ACE_HANDLE h)
+{
+ if (h == 0)
+ return;
+ this->ace_stream_.set_handle (h);
+}
diff --git a/protocols/ace/HTBP/HTBP_Environment.cpp b/protocols/ace/HTBP/HTBP_Environment.cpp
new file mode 100644
index 00000000000..60d3b017f17
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Environment.cpp
@@ -0,0 +1,197 @@
+// $Id$
+
+#include "HTBP_Environment.h"
+
+ACE_RCSID (HTBP,
+ ACE_HTBP_Environment,
+ "$Id$")
+
+ACE::HTBP::Environment::Environment (ACE_Configuration *config,
+ int using_registry,
+ const ACE_TCHAR *persistent_file)
+ : config_ (config),
+ imp_exp_ (0),
+ own_config_ (config != 0)
+{
+ initialize (using_registry,
+ persistent_file);
+}
+
+ACE::HTBP::Environment::~Environment ()
+{
+ if (!own_config_)
+ this->clear();
+ else
+ delete this->config_;
+
+ delete this->imp_exp_;
+}
+
+void
+ACE::HTBP::Environment::clear ()
+{
+ if (this->config_)
+ this->config_->remove_section (config_->root_section (),
+ ACE_TEXT("htbp"),
+ 1);
+}
+
+int
+ACE::HTBP::Environment::initialize (int use_registry,
+ const ACE_TCHAR *persistent_file)
+{
+ if (this->config_ == 0)
+ {
+ int result = -1;
+ if (use_registry)
+ result = this->open_registry_config();
+ if (result == -1)
+ result = this->open_persistent_config (persistent_file);
+ if (result != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("ACE::HTBP::Environment::initialize (): ")
+ ACE_TEXT("Open Config failed")),
+ -1);
+ }
+ }
+
+
+ ACE_NEW_RETURN (this->imp_exp_,
+ ACE_Ini_ImpExp (*this->config_),
+ -1);
+
+ if (this->config_->open_section (config_->root_section (),
+ ACE_TEXT("htbp"), 1,
+ this->htbp_key_) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("ACE::HTBP::Environment::initialize (). ")
+ ACE_TEXT("Open HTBP Section failed")),
+ -1);
+ return 0;
+}
+
+int
+ACE::HTBP::Environment::open_registry_config ()
+{
+#if defined (ACE_WIN32)
+ HKEY root =
+ ACE_Configuration_Win32Registry::resolve_key
+ (HKEY_LOCAL_MACHINE,ACE_TEXT("Software\\HTBP\\Environment"));
+
+ ACE_NEW_RETURN (this->config_,
+ ACE_Configuration_Win32Registry (root),
+ -1);
+ return 0;
+#else
+ errno = ENOTSUP;
+ return -1;
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE::HTBP::Environment::open_persistent_config (const ACE_TCHAR *persistent_file)
+{
+ ACE_Configuration_Heap *heap;
+ ACE_NEW_RETURN (heap,
+ ACE_Configuration_Heap,
+ -1);
+ // do this before trying to open so it isn't leaked if the open fails.
+ this->config_ = heap;
+ if (persistent_file == 0)
+ heap->open();
+ else
+ if (heap->open (persistent_file) != 0)
+ ACE_ERROR_RETURN (( LM_ERROR,
+ ACE_TEXT ("ACE::HTBP::Environment::open_config: %p\n"),
+ persistent_file),
+ -1 );
+ return 0;
+}
+
+int
+ACE::HTBP::Environment::get_htid_url (ACE_TString &htid_url) const
+{
+ return this->config_->get_string_value (this->htbp_key_,
+ ACE_TEXT("htid_url"),
+ htid_url);
+}
+
+int
+ACE::HTBP::Environment::set_htid_url (const ACE_TCHAR *htid_generator_url)
+{
+ return this->config_->set_string_value (this->htbp_key_,
+ ACE_TEXT("htid_url"),
+ htid_generator_url);
+}
+
+
+int
+ACE::HTBP::Environment::get_htid_via_proxy (int &via_proxy) const
+{
+ return this->config_->get_integer_value (this->htbp_key_,
+ ACE_TEXT("htid_via_proxy"),
+ (u_int &)via_proxy);
+}
+
+int
+ACE::HTBP::Environment::set_htid_via_proxy (int via_proxy)
+{
+ return this->config_->set_integer_value (this->htbp_key_,
+ ACE_TEXT("htid_via_proxy"),
+ (u_int)via_proxy);
+}
+
+int
+ACE::HTBP::Environment::get_proxy_host (ACE_TString &proxy_host) const
+{
+ return this->config_->get_string_value (this->htbp_key_,
+ ACE_TEXT("proxy_host"),
+ proxy_host);
+}
+
+int
+ACE::HTBP::Environment::set_proxy_host (const ACE_TCHAR *proxy_host)
+{
+ return this->config_->set_string_value (this->htbp_key_,
+ ACE_TEXT("proxy_host"),
+ proxy_host);
+}
+
+int
+ACE::HTBP::Environment::get_proxy_port (unsigned int &proxy_port) const
+{
+ int result = this->config_->get_integer_value (this->htbp_key_,
+ ACE_TEXT("proxy_port"),
+ proxy_port);
+ if (result != 0)
+ {
+ ACE_TString port_str;
+ result = this->config_->get_string_value (this->htbp_key_,
+ ACE_TEXT("proxy_port"),
+ port_str);
+ if (result == 0)
+ proxy_port = ACE_OS::strtol(port_str.c_str(),0,10);
+ }
+ return result;
+}
+
+int
+ACE::HTBP::Environment::set_proxy_port (unsigned int proxy_port)
+{
+ return this->config_->set_integer_value (this->htbp_key_,
+ ACE_TEXT("proxy_port"),
+ proxy_port);
+}
+
+int
+ACE::HTBP::Environment::import_config (const ACE_TCHAR *filename)
+{
+ return this->imp_exp_->import_config (filename);
+}
+
+int
+ACE::HTBP::Environment::export_config (const ACE_TCHAR *filename)
+{
+ return this->imp_exp_->export_config (filename);
+}
diff --git a/protocols/ace/HTBP/HTBP_Environment.h b/protocols/ace/HTBP/HTBP_Environment.h
new file mode 100644
index 00000000000..2f4cc90a5ac
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Environment.h
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+// $Id$
+
+#ifndef ACE_HTBP_ENVIRONMENT_H
+#define ACE_HTBP_ENVIRONMENT_H
+#include /**/ "ace/pre.h"
+
+#include "HTBP_Export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Configuration.h"
+#include "ace/Configuration_Import_Export.h"
+#include "ace/Singleton.h"
+
+
+namespace ACE
+{
+ namespace HTBP
+ {
+
+ /**
+ * @class Environment
+ *
+ * @brief
+ *
+ * This class manages the storage of configuration data, either in a
+ * flat file for Unix systems, or in the Windows registry
+ */
+ class HTBP_Export Environment
+ {
+ public:
+
+ /// Constructor
+ Environment (ACE_Configuration *config = 0,
+ int using_registry = 0,
+ const ACE_TCHAR *persistent_file = 0);
+
+ /// Destructor
+ ~Environment ();
+
+ /// removes all htbp related values from the configuration
+ void clear (void);
+
+ /// Accessors to HTID URL
+ /// Returns 0 on success
+ /// {@
+ int get_htid_url (ACE_TString &htid_url) const;
+ int set_htid_url (const ACE_TCHAR *htid_generator_url);
+ /// @}
+
+ /// Accessors to HTID via proxy - If value is true, HTID request goes
+ /// through configured proxy otherwise it uses a direct connection.
+ /// Returns 0 on success
+ /// {@
+ int get_htid_via_proxy (int &htid_via_proxy) const;
+ int set_htid_via_proxy (int htid_via_proxy);
+ /// @}
+
+ /// Accessors to Proxy Address
+ /// Returns 0 on success
+ /// {@
+ int get_proxy_host (ACE_TString &proxy_host) const;
+ int set_proxy_host (const ACE_TCHAR *proxy_host);
+ /// @}
+
+ /// Returns 0 on success
+ /// {@
+ int get_proxy_port (unsigned int &proxy_port) const;
+ int set_proxy_port (unsigned int proxy_port);
+ /// @}
+
+ /// Import the configuration from the filename
+ int import_config (const ACE_TCHAR *filename);
+
+ /// Export the configuration to the filename
+ int export_config (const ACE_TCHAR *filename);
+
+ private:
+ /// Open config, set sections etc
+ int initialize (int use_registry,
+ const ACE_TCHAR *persistent_file);
+
+ /// Open an ACE_Configuration of the appropriate type.
+ int open_registry_config ();
+ int open_persistent_config (const ACE_TCHAR *persistent_file);
+
+ /// Our Proxy and HTID generator URL database
+ ACE_Configuration *config_;
+
+ /// Flat section of HTBP related items
+ ACE_Configuration_Section_Key htbp_key_;
+
+ /// the wrapper used to import or export initialization values
+ ACE_Ini_ImpExp *imp_exp_;
+
+ /// We created the config instance, so we must clean it up
+ int own_config_;
+
+ };
+ }
+}
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_ENVIRONMENT_H */
diff --git a/protocols/ace/HTBP/HTBP_Export.h b/protocols/ace/HTBP/HTBP_Export.h
new file mode 100644
index 00000000000..19ce8a89547
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Export.h
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl -d -s HTBP
+// ------------------------------
+#ifndef HTBP_EXPORT_H
+#define HTBP_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (HTBP_HAS_DLL)
+# define HTBP_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && HTBP_HAS_DLL */
+
+#if !defined (HTBP_HAS_DLL)
+# define HTBP_HAS_DLL 1
+#endif /* ! HTBP_HAS_DLL */
+
+#if defined (HTBP_HAS_DLL) && (HTBP_HAS_DLL == 1)
+# if defined (HTBP_BUILD_DLL)
+# define HTBP_Export ACE_Proper_Export_Flag
+# define HTBP_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define HTBP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* HTBP_BUILD_DLL */
+# define HTBP_Export ACE_Proper_Import_Flag
+# define HTBP_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define HTBP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* HTBP_BUILD_DLL */
+#else /* HTBP_HAS_DLL == 1 */
+# define HTBP_Export
+# define HTBP_SINGLETON_DECLARATION(T)
+# define HTBP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* HTBP_HAS_DLL == 1 */
+
+// Set HTBP_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (HTBP_NTRACE)
+# if (ACE_NTRACE == 1)
+# define HTBP_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define HTBP_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !HTBP_NTRACE */
+
+#if (HTBP_NTRACE == 1)
+# define HTBP_TRACE(X)
+#else /* (HTBP_NTRACE == 1) */
+# define HTBP_TRACE(X) ACE_TRACE_IMPL(X)
+#endif /* (HTBP_NTRACE == 1) */
+
+#endif /* HTBP_EXPORT_H */
+
+// End of auto generated file.
diff --git a/protocols/ace/HTBP/HTBP_Filter.cpp b/protocols/ace/HTBP/HTBP_Filter.cpp
new file mode 100644
index 00000000000..0e239e0b419
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Filter.cpp
@@ -0,0 +1,56 @@
+// ACE_HTBP_Filter.cpp
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+#include <sstream>
+
+#include "HTBP_Session.h"
+#include "HTBP_Filter.h"
+
+#if !defined (__ACE_INLINE__)
+#include "HTBP_Filter.inl"
+#endif
+
+ACE_RCSID(HTBP,ACE_HTBP_Filter,"$ID: $")
+
+ACE::HTBP::Filter::Filter (void)
+ :http_code_ (0)
+{
+}
+
+ACE::HTBP::Filter::~Filter (void)
+{
+}
+
+char *
+ACE::HTBP::Filter::header_complete (ACE::HTBP::Channel *ch)
+{
+ if (ch->leftovers().length() == 0)
+ {
+ return 0;
+ }
+ if (ch->leftovers().space() > 0)
+ *ch->leftovers().wr_ptr() = '\0';
+ char *start = ch->leftovers().rd_ptr();
+ char *nl = ACE_OS::strchr (start,'\n');
+ if (this->http_code_ == 0)
+ {
+ char *code = ACE_OS::strstr (start,"HTTP/1.");
+ if (code && code < nl)
+ {
+ code += 9; // skip past "HTTP/1.1 "
+ this->http_code_ = strtol(code,0,10);
+ }
+ }
+
+ while (nl)
+ {
+ if ((nl == start) ||
+ (nl == start +1 && *start == '\r'))
+ return nl + 1;
+ start = nl + 1;
+ nl = ACE_OS::strchr (start,'\n');
+ }
+ return 0;
+}
diff --git a/protocols/ace/HTBP/HTBP_Filter.h b/protocols/ace/HTBP/HTBP_Filter.h
new file mode 100644
index 00000000000..9548f377d1b
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Filter.h
@@ -0,0 +1,100 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Filter.h
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier
+ */
+//=============================================================================
+
+#ifndef ACE_HTBP_FILTER_H
+#define ACE_HTBP_FILTER_H
+#include /**/ "ace/pre.h"
+
+#include "ace/OS.h"
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "HTBP_Export.h"
+
+namespace ACE
+{
+ namespace HTBP
+ {
+
+ // Forward declarations.
+ class Channel;
+
+ /**
+ * @class ACE_HTBP_Filter
+ *
+ * @brief Defines the methods in the <ACE_HTBP_Filter> abstraction.
+ *
+ * A filter is responsible for wrapping / unwrapping messages
+ * depending on direction of flow on each stream. There will be 4
+ * filters participating in a session, inside-send, inside-recv,
+ * outside-send, ouside-recv. It is anticipated that specialized
+ * filters will be implemented that tune the filter behavior based
+ * on proxy particulars. That, or there will be a matrix
+ * configuration parameters that may be tweeked to match the
+ * configuration. It remains to be seen which is easier to
+ * manage.
+ */
+ class HTBP_Export Filter
+ {
+ public:
+ Filter (void);
+
+ virtual ~Filter (void);
+
+ /// Inside and outside Send filters need to supply a data header that
+ /// sets the stage before sending the data body, and then (maybe) send a
+ /// data trailer that closes the message. The data header may be formatted
+ /// differently on the first message, to send optional context information.
+ virtual ssize_t send_data_header (ssize_t data_len, Channel *ch);
+ virtual ssize_t send_data_trailer (Channel *ch);
+
+ /// Upon receiving data, the Channel is obliged to send an ack. This is
+ /// either an empty document if this is the in-to-out stream, or a new
+ /// long-duration document request if this is the out-to-in stream.
+ virtual int send_ack (Channel *ch);
+ virtual int recv_ack (Channel *ch);
+
+ /// receiving data must compliment sending. In the case of an in-to-out
+ /// stream. It is possible that the stream identity is not known until the
+ /// first request is received. In this case the filter will have to look
+ /// lookup the received session ID and either create a new instance or
+ /// reassign itself to an existing sesion. In that case, the associated
+ /// stream will have to be reassigned as well.
+ ///
+ virtual ssize_t recv_data_header (Channel *ch);
+ virtual ssize_t recv_data_trailer(Channel *ch);
+
+ /// reset the http_code_ in anticipation of a new message.
+ void reset_http_code (void);
+
+ /// get the value of the most recent http result code
+ int http_code (void);
+
+ protected:
+ char *header_complete (Channel *ch);
+
+ private:
+ /// Store the most recent HTTP result code. Typically it will be 200,
+ /// but it could be a 4xx or 5xx code if the proxy reports an error.
+ int http_code_;
+
+ };
+ }
+}
+
+#if defined (__ACE_INLINE__)
+#include "HTBP_Filter.inl"
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_FILTER_H */
diff --git a/protocols/ace/HTBP/HTBP_Filter.inl b/protocols/ace/HTBP/HTBP_Filter.inl
new file mode 100644
index 00000000000..224b7e02699
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Filter.inl
@@ -0,0 +1,60 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ACE_HTBP_Filter.i
+
+ACE_INLINE
+ssize_t
+ACE::HTBP::Filter::send_data_header (ssize_t, ACE::HTBP::Channel * )
+{
+ return 0;
+}
+
+ACE_INLINE
+ssize_t
+ACE::HTBP::Filter::send_data_trailer (ACE::HTBP::Channel *)
+{
+ return 0;
+}
+
+ACE_INLINE
+int
+ACE::HTBP::Filter::send_ack (ACE::HTBP::Channel *)
+{
+ return 0;
+}
+
+ACE_INLINE
+int
+ACE::HTBP::Filter::recv_ack (ACE::HTBP::Channel *)
+{
+ return 0;
+}
+
+ACE_INLINE
+ssize_t
+ACE::HTBP::Filter::recv_data_header (ACE::HTBP::Channel *)
+{
+ return 0;
+}
+
+ACE_INLINE
+ssize_t
+ACE::HTBP::Filter::recv_data_trailer(ACE::HTBP::Channel *)
+{
+ return 0;
+}
+
+ACE_INLINE
+void
+ACE::HTBP::Filter::reset_http_code (void)
+{
+ this->http_code_ = 0;
+}
+
+ACE_INLINE
+int
+ACE::HTBP::Filter::http_code (void)
+{
+ return this->http_code_;
+}
diff --git a/protocols/ace/HTBP/HTBP_Filter_Factory.cpp b/protocols/ace/HTBP/HTBP_Filter_Factory.cpp
new file mode 100644
index 00000000000..8c42584d143
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Filter_Factory.cpp
@@ -0,0 +1,57 @@
+// $Id$
+
+#include "HTBP_Filter_Factory.h"
+#include "HTBP_Inside_Squid_Filter.h"
+#include "HTBP_Outside_Squid_Filter.h"
+
+#include "HTBP_Stream.h"
+#include "ace/Service_Object.h"
+#include "ace/Dynamic_Service.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID (ACE_HTBP_Filter_Factory, HTBP, "$Id$")
+
+ACE::HTBP::Filter_Factory::Filter_Factory ()
+{
+}
+
+ACE::HTBP::Filter_Factory::~Filter_Factory ()
+{
+}
+
+ACE::HTBP::Filter *
+ACE::HTBP::Filter_Factory::get_filter (int inside)
+{
+ ACE::HTBP::Filter *filter = 0;
+ if (inside)
+ ACE_NEW_RETURN (filter,
+ ACE::HTBP::Inside_Squid_Filter (),0);
+ else
+ ACE_NEW_RETURN (filter,
+ ACE::HTBP::Outside_Squid_Filter (),0);
+ return filter;
+}
+
+int
+ACE::HTBP::Filter_Factory::init (int /* argc */,
+ ACE_TCHAR * /* argv */ [])
+{
+ return 0;
+}
+
+ACE_STATIC_SVC_DEFINE (ACE_HTBP_Filter_Factory,
+ ACE_TEXT ("Filter_Factory"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (ACE_HTBP_Filter_Factory),
+ ACE_Service_Type::DELETE_THIS |
+ ACE_Service_Type::DELETE_OBJ,
+ 0)
+
+ACE_FACTORY_NAMESPACE_DEFINE (HTBP, ACE_HTBP_Filter_Factory,
+ ACE::HTBP::Filter_Factory)
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Dynamic_Service<ACE::HTBP::Filter_Factory>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Dynamic_Service<ACE::HTBP::Filter_Factory>
+#endif
diff --git a/protocols/ace/HTBP/HTBP_Filter_Factory.h b/protocols/ace/HTBP/HTBP_Filter_Factory.h
new file mode 100644
index 00000000000..84f32000664
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Filter_Factory.h
@@ -0,0 +1,66 @@
+// -*- C++ -*-
+// $Id$
+
+//=============================================================================
+/**
+ * @file HTBP_Filter_Factory.h
+ *
+ * $Id$
+ *
+ * @author Priyanka Gontla
+ */
+//=============================================================================
+
+#ifndef ACE_HTBP_FILTER_FACTORY
+#define ACE_HTBP_FILTER_FACTORY
+#include /**/ "ace/pre.h"
+
+#include "HTBP_Export.h"
+#include "HTBP_Filter.h"
+#include "ace/Service_Config.h"
+#include "ace/Service_Object.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+namespace ACE
+{
+ namespace HTBP
+ {
+ class Stream;
+
+ /**
+ * @class Filter_Factory
+ *
+ * @brief Factory to get the Filters
+ *
+ * The Filter Factory is to be used for getting filters based on the
+ * mode requested. This class is a ACE_Service_Object and should be
+ * loadable with the help of the service configurator framework.
+ */
+ class HTBP_Export Filter_Factory : public ACE_Service_Object
+ {
+ public:
+
+ /// Constructor
+ Filter_Factory ();
+
+ ~Filter_Factory ();
+
+ /// Initialization hook.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+ //
+ Filter *get_filter (int inside);
+ };
+ }
+}
+
+ACE_STATIC_SVC_DECLARE_EXPORT (HTBP, ACE_HTBP_Filter_Factory)
+ACE_FACTORY_DECLARE (HTBP, ACE_HTBP_Filter_Factory)
+
+
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_FILTER_FACTORY */
diff --git a/protocols/ace/HTBP/HTBP_ID_Requestor.cpp b/protocols/ace/HTBP/HTBP_ID_Requestor.cpp
new file mode 100644
index 00000000000..3c4b72e38fb
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_ID_Requestor.cpp
@@ -0,0 +1,135 @@
+// $Id$
+
+#include "HTBP_ID_Requestor.h"
+#include "HTBP_Environment.h"
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/UUID.h"
+
+ACE_RCSID(HTBP,
+ ACE_HTBP_ID_Requestor,
+ "$Id$")
+
+ACE_TString ACE::HTBP::ID_Requestor::htid_;
+ACE_SYNCH_MUTEX ACE::HTBP::ID_Requestor::htid_lock_;
+
+ACE::HTBP::ID_Requestor::ID_Requestor (ACE::HTBP::Environment *env)
+ : port_ (0),
+ host_ (),
+ url_()
+{
+ if (env)
+ {
+ env->get_htid_url(url_);
+ int via_proxy = 0;
+ env->get_htid_via_proxy (via_proxy);
+ if (via_proxy && env->get_proxy_host (host_) == 0)
+ env->get_proxy_port (port_);
+ }
+}
+
+int
+ACE::HTBP::ID_Requestor::connect_to_server (ACE_SOCK_Stream *cli_stream)
+{
+ if (port_ == 0 || host_.length() == 0)
+ {
+ int host_start = url_.find (ACE_TEXT("http://")) + 7;
+ int port_sep = 0;
+ int sep = 0;
+ if (host_start == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("ACE::HTBP::ID_Requestor::")
+ ACE_TEXT("connect_to_server: ")
+ ACE_TEXT("invalid URL: \"%s\"\n"),
+ url_.c_str()),
+ -1);
+ port_sep = url_.find (ACE_TEXT(":"),(size_t)host_start);
+ sep = url_.find (ACE_TEXT("/"),(size_t)host_start);
+ if (sep == -1 || sep == host_start +1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("ACE::HTBP::ID_Requestor::")
+ ACE_TEXT("connect_to_server: ")
+ ACE_TEXT("invalid URL: \"%s\"\n"),
+ url_.c_str()),
+ -1);
+ if (port_sep == -1)
+ {
+ port_sep = sep;
+ port_ = 80; // should be a default?
+ }
+ host_ = url_.substr(host_start,port_sep - host_start);
+ }
+
+ ACE_INET_Addr remote_addr (port_, host_.c_str());
+ ACE_SOCK_Connector con;
+ if (con.connect (*cli_stream,
+ remote_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("ACE::HTBP::ID_Requestor::connect_to_server: ")
+ ACE_TEXT("%p\n"),
+ ACE_TEXT("socket connect")),
+ -1);
+ return 0;
+}
+
+int
+ACE::HTBP::ID_Requestor::send_request (ACE_SOCK_Stream *cli_stream)
+{
+ char *buffer;
+ ACE_NEW_RETURN (buffer, char[this->url_.length()+16],-1);
+ ACE_OS::sprintf (buffer,"GET %s HTTP/1.0\n\n",
+ ACE_TEXT_ALWAYS_CHAR(url_.c_str()));
+ int result = cli_stream->send_n (buffer,ACE_OS::strlen(buffer));
+ delete [] buffer;
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("ACE::HTBP::ID_Requestor::send_request %p\n"),
+ ACE_TEXT("socket send")), -1);
+ return 0;
+}
+
+ACE_TCHAR *
+ACE::HTBP::ID_Requestor::get_HTID ()
+{
+ if (ACE::HTBP::ID_Requestor::htid_.length() != 0)
+ return ACE::HTBP::ID_Requestor::htid_.rep();
+
+ ACE_Guard<ACE_SYNCH_MUTEX> guard (ACE::HTBP::ID_Requestor::htid_lock_);
+
+ if (ACE::HTBP::ID_Requestor::htid_.length() != 0)
+ return ACE::HTBP::ID_Requestor::htid_.rep();
+
+ ACE_SOCK_Stream cli_stream;
+ ACE_TCHAR * htid = 0;
+
+ if (this->url_.length() == 0 ||
+ this->connect_to_server (&cli_stream) == -1 ||
+ this->send_request (&cli_stream) == -1)
+ {
+ ACE_Utils::UUID_Generator gen;
+ ACE_Utils::UUID *uuid = gen.generateUUID ();
+ const ACE_CString *uuidstr = uuid->to_string();
+ ACE::HTBP::ID_Requestor::htid_ = ACE_TEXT_CHAR_TO_TCHAR (uuidstr->c_str());
+ delete uuid;
+ return ACE::HTBP::ID_Requestor::htid_.rep();
+ }
+ iovec recv_buf;
+ ssize_t result = cli_stream.recvv (&recv_buf);
+ cli_stream.close();
+
+ if (result > 0)
+ {
+ ACE_CString answer ((char *)recv_buf.iov_base,recv_buf.iov_len);
+ ssize_t start = answer.rfind (ACE_TEXT('\n'));
+ if (start == ACE_CString::npos)
+ start = 0;
+ else
+ start++;
+ ACE::HTBP::ID_Requestor::htid_ = ACE_TEXT_CHAR_TO_TCHAR(answer.substr (start).c_str());
+ htid = ACE::HTBP::ID_Requestor::htid_.rep();
+ }
+ return htid;
+}
diff --git a/protocols/ace/HTBP/HTBP_ID_Requestor.h b/protocols/ace/HTBP/HTBP_ID_Requestor.h
new file mode 100644
index 00000000000..e6cdd87fb1d
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_ID_Requestor.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+// $Id$
+
+#ifndef HTID_REQUESTOR_H
+#define HTID_REQUESTOR_H
+#include /**/ "ace/pre.h"
+
+#include "HTBP_Export.h"
+#include "ace/SString.h"
+#include "ace/Synch.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Forward declarations
+class ACE_SOCK_Stream;
+
+namespace ACE
+{
+ namespace HTBP
+ {
+ // Forward declarations
+ class Environment;
+
+ /**
+ * ACE_HTBP_ID_Requestor
+ *
+ * @brief This singleton class is to be used to get a HTID
+ */
+ class HTBP_Export ID_Requestor
+ {
+ public:
+ /// Constructor.
+ ID_Requestor (Environment * = 0);
+
+ /// Accessor to HTID
+ ACE_TCHAR *get_HTID ();
+
+ private:
+ /// Connects to the remote host
+ int connect_to_server (ACE_SOCK_Stream *cli_stream);
+
+ /// Send HTTP GET request to the server.
+ int send_request (ACE_SOCK_Stream *cli_stream);
+
+ unsigned port_;
+ ACE_TString host_;
+ ACE_TString url_;
+
+ static ACE_TString htid_;
+ static ACE_SYNCH_MUTEX htid_lock_;
+ };
+
+ }
+}
+#include /**/ "ace/post.h"
+#endif /* HTID_REQUESTOR_H */
diff --git a/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp b/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp
new file mode 100644
index 00000000000..b936cd8e580
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp
@@ -0,0 +1,227 @@
+// ACE_HTBP_Filter.cpp
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+//#include <sstream>
+
+#include "HTBP_Session.h"
+#include "HTBP_Inside_Squid_Filter.h"
+
+#if !defined (__ACE_INLINE__)
+#include "HTBP_Inside_Squid_Filter.inl"
+#endif
+
+ACE_RCSID(HTBP,ACE_HTBP_Inside_Squid_Filter,"$ID:$")
+
+ssize_t
+ACE::HTBP::Inside_Squid_Filter::send_data_trailer (ACE::HTBP::Channel *ch)
+{
+ ch->state(ACE::HTBP::Channel::Wait_For_Ack);
+ return 0;
+}
+
+int
+ACE::HTBP::Inside_Squid_Filter::make_request_header (ACE::HTBP::Channel *ch,
+ const char *cmd,
+ char *buffer,
+ size_t buffer_size)
+{
+ // the string is formatted as:
+ // command http://host:port/htid/sessionId/request<requestId>.html HTTP/1.1\n
+ // host:port is the remote host and port from the channel,
+ // htid is the local endpoint identifier
+ // sessionId is the discreet session counter between these peers
+ // requestId is the discreet request sent for this session.
+
+ ACE::HTBP::Session *session = ch->session();
+
+ const char * format = "%shttp://%s:%d/%s/%d/request%d.html HTTP/1.1\n";
+ char remote_host[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
+ unsigned remote_port = session->peer_addr().get_port_number();
+ const char *local_htid = session->local_addr().get_htid();
+
+ ACE_UINT32 tempId = session->session_id().id_;
+ size_t sid_size = 1;
+ size_t rid_size = 1;
+ while (tempId /= 10) sid_size++;
+ tempId = ch->request_count();
+ while (tempId /= 10) rid_size++;
+
+ if (session->peer_addr().get_host_name(remote_host,
+ sizeof remote_host) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("HTBP::Inside_Squid_Filter:could not get ")
+ ACE_TEXT("peer_addr hostname\n")),
+ -1);
+
+
+ size_t size =
+ ACE_OS::strlen(format)
+ - 12 // subtract out the size of the format specifiers
+ + ACE_OS::strlen (cmd)
+ + ACE_OS::strlen (remote_host)
+ + 5 // maximum size for a the remote port number
+ + ACE_OS::strlen (local_htid)
+ + sid_size // size of session id
+ + rid_size; // size of request id
+
+ if (size > buffer_size)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("HTBP::Inside_Squid_Filter: insufficient ")
+ ACE_TEXT("buffer space for request header, need %d ")
+ ACE_TEXT("got %d\n"),
+ size, buffer_size),
+ -1);
+
+ ACE_OS::sprintf (buffer,format,
+ cmd,remote_host,remote_port,
+ local_htid, session->session_id().id_,
+ ch->request_count());
+
+ return ACE_OS::strlen(buffer);
+}
+
+ssize_t
+ACE::HTBP::Inside_Squid_Filter::send_data_header (ssize_t data_len,
+ ACE::HTBP::Channel *ch)
+{
+ char *buffer = new char[BUFSIZ];
+ ssize_t result = -1;
+ if (this->make_request_header (ch,"POST ",buffer,BUFSIZ) != -1)
+ {
+ ACE_CString header (buffer);
+ header += "Content-Type: application/octet-stream\nContent-Length: ";
+ char datalenstr[20];
+ ACE_OS::itoa (data_len,datalenstr,10);
+ header += datalenstr;
+ header += "\n\n";
+ result = ch->ace_stream().send(header.c_str(),header.length());
+ }
+ ch->state(result == -1 ? ACE::HTBP::Channel::Closed :
+ ACE::HTBP::Channel::Header_Sent);
+ this->reset_http_code();
+ return 1;
+}
+
+ssize_t
+ACE::HTBP::Inside_Squid_Filter::recv_data_header (ACE::HTBP::Channel *ch)
+{
+ if (this->http_code() != 200 && this->http_code() != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("Inside_Squid_Filter::recv_data_header, ")
+ ACE_TEXT("non-OK result code %d recvd\n"),
+ this->http_code()));
+
+ errno = ch->consume_error () ? EINVAL : EWOULDBLOCK;
+ return 0;
+ }
+ char *header_end = this->header_complete(ch);
+ if (header_end == 0)
+ {
+ if (ch->state() != ACE::HTBP::Channel::Closed)
+ {
+ ch->state (ACE::HTBP::Channel::Header_Pending);
+ errno = EWOULDBLOCK;
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("Inside_Squid_Filter::recv_data_header, ")
+ ACE_TEXT("header not complete\n")),
+ 0);
+ }
+ char *start = ch->leftovers().rd_ptr();
+ ACE_CString token = "Content-Length: ";
+ char *tpos = ACE_OS::strstr(start,token.c_str());
+ char *nl = ACE_OS::strchr (start,'\n');
+ if (tpos != 0)
+ {
+ tpos += token.length();
+ *nl = 0;
+ ch->data_len (strtol(tpos,0,10));
+ start = nl+1;
+ }
+
+ ch->leftovers().rd_ptr(header_end);
+ if (this->http_code() != 200)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("Inside_Squid_Filter::recv_data_header, ")
+ ACE_TEXT("non-OK result code %d recvd\n"),
+ this->http_code()));
+
+ errno = ch->consume_error () ? EINVAL : EWOULDBLOCK;
+ return 0;
+ }
+
+ ch->state(ACE::HTBP::Channel::Data_Queued);
+ return 1;
+}
+
+ssize_t
+ACE::HTBP::Inside_Squid_Filter::recv_data_trailer (ACE::HTBP::Channel *ch)
+{
+ ch->state(ACE::HTBP::Channel::Send_Ack);
+ return 0;
+}
+
+int
+ACE::HTBP::Inside_Squid_Filter::send_ack (ACE::HTBP::Channel *ch)
+{
+ char *buffer = new char[BUFSIZ];
+ ssize_t result = -1;
+ if (ch->state() == ACE::HTBP::Channel::Ack_Sent)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("Inside Filter::send_ack: ")
+ ACE_TEXT("state is already ACK_SENT\n")),
+ 1);
+ }
+ if (this->make_request_header (ch,"GET ",buffer,BUFSIZ) != -1)
+ {
+ ACE_CString header (buffer);
+ header += "\n";
+ result = ch->ace_stream().send(header.c_str(),header.length());
+ }
+ ch->state(result == -1 ?
+ ACE::HTBP::Channel::Closed : ACE::HTBP::Channel::Ack_Sent);
+ this->reset_http_code();
+ return 1;
+}
+
+int
+ACE::HTBP::Inside_Squid_Filter::recv_ack (ACE::HTBP::Channel *ch)
+{
+
+ char *header_end = this->header_complete(ch);
+ if (header_end == 0)
+ {
+ if (ch->state() != ACE::HTBP::Channel::Closed)
+ errno = EWOULDBLOCK;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT("Inside_Squid_Filter::recv_data_header, ")
+ ACE_TEXT("header not complete\n")),0);
+ }
+ if (this->http_code() == 200)
+ {
+ ch->leftovers().length(0);
+ ch->state(ACE::HTBP::Channel::Ready);
+ return 1;
+ }
+
+ char *start = ch->leftovers().rd_ptr();
+ ACE_CString token = "Content-Length: ";
+ char *tpos = ACE_OS::strstr(start,token.c_str());
+ char *nl = ACE_OS::strchr (start,'\n');
+ if (tpos != 0)
+ {
+ tpos += token.length();
+ *nl = 0;
+ ch->data_len (strtol(tpos,0,10));
+ start = nl+1;
+ }
+
+ ch->leftovers().rd_ptr(header_end);
+ errno = ch->consume_error () ? EINVAL : EWOULDBLOCK;
+ return 0;
+}
diff --git a/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.h b/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.h
new file mode 100644
index 00000000000..142607aa49f
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.h
@@ -0,0 +1,87 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Inside_Squid_Filter.h
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier
+ */
+//=============================================================================
+
+#ifndef ACE_HTBP_INSIDE_SQUID_FILTER_H
+#define ACE_HTBP_INSIDE_SQUID_FILTER_H
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "HTBP_Export.h"
+#include "HTBP_Filter.h"
+
+namespace ACE
+{
+ namespace HTBP
+ {
+
+ /**
+ * @class Inside_Squid_Filter
+ *
+ * @brief Defines the methods in the <Filter> abstraction.
+ *
+ * A filter is responsible for wrapping / unwrapping messages
+ * depending on direction of flow on each stream. There will be 4
+ * filters participating in a session, inside-send, inside-recv,
+ * outside-send, ouside-recv. It is anticipated that specialized
+ * filters will be implemented that tune the filter behavior based
+ * on proxy particulars. That, or there will be a matrix
+ * configuration parameters that may be tweeked to match the
+ * configuration. It remains to be seen which is easier to
+ * manage.
+ */
+ class HTBP_Export Inside_Squid_Filter : public Filter
+ {
+ public:
+ /// Destructor.
+ virtual ~Inside_Squid_Filter (void);
+
+ /// Inside and outside Send filters need to supply a data header
+ /// that sets the stage before sending the data body, and then
+ /// (maybe) send a data trailer that closes the message. The
+ /// data header may be formatted differently on the first
+ /// message, to send optional context information.
+ virtual ssize_t send_data_header (ssize_t data_len, Channel *);
+ virtual ssize_t send_data_trailer (Channel *);
+
+ /// Upon receiving data, the Channel is obliged to send an
+ /// ack. This is either an empty document if this is the
+ /// in-to-out stream, or a new long-duration document request if
+ /// this is the out-to-in stream.
+ virtual int send_ack (Channel *);
+ virtual int recv_ack (Channel *);
+
+ /// receiving data must compliment sending. In the case of an
+ /// in-to-out stream. It is possible that the stream identity is
+ /// not known until the first request is received. In this case
+ /// the filter will have to look lookup the received session ID
+ /// and either create a new instance or reassign itself to an
+ /// existing sesion. In that case, the associated stream will
+ /// have to be reassigned as well.
+ ///
+ virtual ssize_t recv_data_header (Channel *);
+ virtual ssize_t recv_data_trailer(Channel *);
+ private:
+ int make_request_header (Channel *, const char *, char *, size_t );
+
+ };
+ }
+}
+
+#if defined (__ACE_INLINE__)
+#include "HTBP_Inside_Squid_Filter.inl"
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_FILTER_H */
diff --git a/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.inl b/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.inl
new file mode 100644
index 00000000000..d9c4618537e
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.inl
@@ -0,0 +1,9 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ACE_HTBP_Inside_Squid_Filter.i
+
+ACE_INLINE
+ACE::HTBP::Inside_Squid_Filter::~Inside_Squid_Filter (void)
+{
+}
diff --git a/protocols/ace/HTBP/HTBP_Macros.h b/protocols/ace/HTBP/HTBP_Macros.h
new file mode 100644
index 00000000000..0cb1300cc1d
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Macros.h
@@ -0,0 +1,10 @@
+// $Id$
+
+#ifndef ACE_HTBP_MACROS_H
+#define ACE_HTBP_MACROS_H
+
+#if !defined (ACE_HTBP_ENVIRONMENT_CONFIG_FILE)
+#define ACE_HTBP_ENVIRONMENT_CONFIG_FILE "HT_Config.conf"
+#endif /* ACE_HTBP_ENVIRONMENT_CONFIG_FILE */
+
+#endif /* ACE_HTBP_MACROS_H */
diff --git a/protocols/ace/HTBP/HTBP_Notifier.cpp b/protocols/ace/HTBP/HTBP_Notifier.cpp
new file mode 100644
index 00000000000..fab0dbd44ba
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Notifier.cpp
@@ -0,0 +1,87 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Notifier.cpp
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier, Priyanka Gontla
+ */
+//=============================================================================
+#include "HTBP_Notifier.h"
+
+#if !defined (__ACE_INLINE__)
+#include "HTBP_Notifier.inl"
+#endif
+
+#include "HTBP_Channel.h"
+#include "HTBP_Session.h"
+#include "ace/Reactor.h"
+
+ACE::HTBP::Notifier::Notifier (ACE::HTBP::Channel *s)
+ : channel_(s)
+{
+}
+
+int
+ACE::HTBP::Notifier::handle_input(ACE_HANDLE )
+{
+ switch (this->channel_->state())
+ {
+ case ACE::HTBP::Channel::Detached:
+ this->channel_->pre_recv();
+ break;
+ case ACE::HTBP::Channel::Wait_For_Ack:
+ this->channel_->recv_ack();
+ break;
+ default:
+ this->channel_->load_buffer();
+ }
+
+ if (this->channel_->state() == ACE::HTBP::Channel::Closed)
+ {
+ this->unregister();
+ return 0;
+ }
+
+ if (this->channel_->session_)
+ {
+ if (this->channel_ == this->channel_->session_->inbound())
+ {
+ ACE_Event_Handler *h = this->channel_->session_->handler();
+ if (h && this->reactor())
+ this->reactor()->notify(h,
+ ACE_Event_Handler::READ_MASK);
+ else
+ ACE_DEBUG ((LM_DEBUG,"Notifier cannot notify, session has no handler (%x), or reactor (%x)\n",h,this->reactor()));
+ }
+ else
+ this->channel_->flush_buffer();
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,"Notifier has no session to notify!\n"));
+ return 0;
+}
+
+int
+ACE::HTBP::Notifier::handle_output (ACE_HANDLE )
+{
+ return -1;
+
+}
+
+void
+ACE::HTBP::Notifier::unregister (void)
+{
+ if (this->reactor())
+ this->reactor()->remove_handler(this,
+ ACE_Event_Handler::READ_MASK |
+ ACE_Event_Handler::DONT_CALL);
+}
+
+ACE_HANDLE
+ACE::HTBP::Notifier::get_handle(void) const
+{
+ return this->channel_->ace_stream().get_handle();
+}
diff --git a/protocols/ace/HTBP/HTBP_Notifier.h b/protocols/ace/HTBP/HTBP_Notifier.h
new file mode 100644
index 00000000000..24ff34b0d5e
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Notifier.h
@@ -0,0 +1,54 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Notifier.h
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier, Priyanka Gontla
+ */
+//=============================================================================
+
+#ifndef ACE_HTBP_NOTIFIER_H
+#define ACE_HTBP_NOTIFIER_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Event_Handler.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "HTBP_Export.h"
+
+namespace ACE
+{
+ namespace HTBP
+ {
+ // Forward declarations.
+ class Channel;
+
+ class HTBP_Export Notifier : public ACE_Event_Handler
+ {
+ public:
+ Notifier (Channel *ch);
+ int handle_input(ACE_HANDLE );
+ int handle_output(ACE_HANDLE );
+
+ void unregister (void);
+
+ ACE_HANDLE get_handle (void) const;
+
+ private:
+ Channel *channel_;
+ };
+ }
+}
+
+#if defined (__ACE_INLINE__)
+#include "HTBP_Notifier.inl"
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_NOTIFIER_H */
diff --git a/protocols/ace/HTBP/HTBP_Notifier.inl b/protocols/ace/HTBP/HTBP_Notifier.inl
new file mode 100644
index 00000000000..fec4c7f49c9
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Notifier.inl
@@ -0,0 +1,4 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ACE_HTBP_Notifier.i
diff --git a/protocols/ace/HTBP/HTBP_Outside_Squid_Filter.cpp b/protocols/ace/HTBP/HTBP_Outside_Squid_Filter.cpp
new file mode 100644
index 00000000000..3c035b8dcde
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Outside_Squid_Filter.cpp
@@ -0,0 +1,192 @@
+// ACE_HTBP_Outside_Squid_Filter.cpp
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+#include "HTBP_Session.h"
+#include "HTBP_Outside_Squid_Filter.h"
+
+#if !defined (__ACE_INLINE__)
+#include "HTBP_Outside_Squid_Filter.inl"
+#endif
+
+ACE_RCSID(HTBP,
+ ACE_HTBP_Outside_Squid_Filter,
+ "$Id$")
+
+ssize_t
+ACE::HTBP::Outside_Squid_Filter::recv_data_header (ACE::HTBP::Channel *ch)
+{
+ // on the outside of the firewall, this method must do the details
+ // necessary to call replace_session or whatever to migrate the sock
+ // stream to the appropriate ACE::HTBP::Channel, then to finally
+ // assign the right filter to that stream. That filter will an
+ // ACE::HTBP::Outside_[Send|Recv]_Filter.
+
+ // in the case of an ACE::HTBP::Outside_Recv_Filter, the assigned
+ // filter must be a null filter first, with a replacement.
+
+ // recv header details
+ char *header_end = this->header_complete(ch);
+ if (header_end == 0)
+ {
+ if (ch->state() != ACE::HTBP::Channel::Closed)
+ {
+ ch->state(ACE::HTBP::Channel::Header_Pending);
+ errno = EWOULDBLOCK;
+ }
+ return 0;
+ }
+
+ char *start = ch->leftovers().rd_ptr();
+
+ int is_inbound = 0;
+ ACE_CString token ("POST ");
+ if (ACE_OS::strncmp (start,token.c_str(),token.length()) == 0)
+ is_inbound = 1;
+ else
+ {
+ token = "GET ";
+ if (ACE_OS::strncmp (start,
+ token.c_str(),
+ token.length()) != 0)
+ {
+ ch->leftovers().length(0);
+ errno = EINVAL;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE::HTBP::Outside_Squid_Filter::recv_data_header "
+ "bad request header\n"),0);
+ }
+ }
+ start += token.length();
+ // "http://" is stripped by squid, leaving only "/"
+ start += (ACE_OS::strncmp (start,"http://",7) == 0) ? 7 : 1;
+
+ // set up the actual session and stream
+ ACE::HTBP::Session_Id_t session_id;
+ char * slash = ACE_OS::strchr(start,'/');
+ char * nl = ACE_OS::strchr (start,'\n');
+ if (slash == 0)
+ {
+ ch->leftovers().length(0);
+ errno = EINVAL;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE::HTBP::Outside_Squid_Filter::recv_data_header "
+ "missing sender key\n"),0);
+ }
+ *slash = 0;
+ session_id.local_.string_to_addr (start);
+ start = slash+1;
+
+ slash = ACE_OS::strchr(start,'/');
+ if (slash == 0)
+ {
+ ch->leftovers().length(0);
+ errno = EINVAL;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE::HTBP::Outside_Squid_Filter::recv_data_header "
+ "missing sender key\n"),0);
+ }
+ *slash = 0;
+ session_id.peer_.string_to_addr (start);
+ start = slash + 1;
+
+ slash = ACE_OS::strchr(start,' ');
+ if (slash == 0)
+ {
+ ch->leftovers().length (0);
+ errno = EINVAL;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE::HTBP::Outside_Squid_Filter::recv_data_header "
+ "missing sender key"),0);
+ }
+ *slash = 0;
+ session_id.id_ = strtol(start,0,10);
+ start = slash + 1;
+
+ if (is_inbound)
+ {
+ token = "Content-Length: ";
+ char *tpos = ACE_OS::strstr(start,token.c_str());
+ if (tpos != 0)
+ {
+ nl = ACE_OS::strchr(tpos,'\n');
+ tpos += token.length();
+ *nl = 0;
+ ch->data_len(strtol(tpos,0,10));
+ start = nl+1;
+ }
+ }
+ ch->leftovers().rd_ptr(header_end);
+
+ ACE::HTBP::Session *session = 0;
+ if (ACE::HTBP::Session::find_session (session_id, session) == -1)
+ {
+ ACE_NEW_RETURN (session, ACE::HTBP::Session (session_id), 0);
+ if (ACE::HTBP::Session::add_session (session) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE::HTBP::Outside_Squid_Filter::"
+ "recv_data_header %p",
+ "add_session"),0);
+ }
+ ch->session(session);
+
+ if (is_inbound)
+ {
+ ch->state(ACE::HTBP::Channel::Data_Queued);
+ session->inbound (ch);
+ }
+ else
+ {
+ ch->state(ACE::HTBP::Channel::Ready);
+ session->outbound (ch);
+ }
+ return 1;
+}
+
+ssize_t
+ACE::HTBP::Outside_Squid_Filter::recv_data_trailer (ACE::HTBP::Channel *ch)
+{
+ ch->state(ACE::HTBP::Channel::Send_Ack);
+ return 1;
+}
+
+int
+ACE::HTBP::Outside_Squid_Filter::send_ack (ACE::HTBP::Channel *ch)
+{
+ this->send_data_header (0,ch);
+ if (ch->state() == ACE::HTBP::Channel::Header_Sent)
+ ch->state(ACE::HTBP::Channel::Detached);
+ return 1;
+}
+
+ssize_t
+ACE::HTBP::Outside_Squid_Filter::send_data_header (ssize_t data_len,
+ ACE::HTBP::Channel *ch)
+{
+ ACE_CString header ("HTTP/1.1 200 OK\n"
+ "Content-Type: application/octet-stream\n"
+ "Content-Length: ");
+ char datalenstr[20];
+ ACE_OS::itoa (data_len,datalenstr,10);
+ header += datalenstr;
+ header += "\n\n";
+ ssize_t result = ch->ace_stream().send(header.c_str(),header.length());
+ ch->state(result == -1 ?
+ ACE::HTBP::Channel::Closed : ACE::HTBP::Channel::Header_Sent);
+ this->reset_http_code();
+ return 1;
+}
+
+ssize_t
+ACE::HTBP::Outside_Squid_Filter::send_data_trailer (ACE::HTBP::Channel *ch)
+{
+ ch->state(ACE::HTBP::Channel::Detached);
+ return 1;
+}
+
+int
+ACE::HTBP::Outside_Squid_Filter::recv_ack (ACE::HTBP::Channel *)
+{
+ return 1;
+}
diff --git a/protocols/ace/HTBP/HTBP_Outside_Squid_Filter.h b/protocols/ace/HTBP/HTBP_Outside_Squid_Filter.h
new file mode 100644
index 00000000000..5f0c820fccd
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Outside_Squid_Filter.h
@@ -0,0 +1,82 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Outside_Squid_Filter.h
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier
+ */
+//=============================================================================
+
+#ifndef ACE_HTBP_OUTSIDE_SQUID_FILTER_H
+#define ACE_HTBP_OUTSIDE_SQUID_FILTER_H
+#include /**/ "ace/pre.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "HTBP_Export.h"
+#include "HTBP_Filter.h"
+
+namespace ACE
+{
+ namespace HTBP
+ {
+ // Forward declarations
+ class Channel;
+
+ /**
+ * @class Outside_Squid_Filter
+ *
+ * @brief Defines the methods in the <Filter> abstraction.
+ *
+ * A filter is responsible for wrapping / unwrapping messages depending on
+ * direction of flow on each stream. There will be 4 filters participating in
+ * a session, outside-send, outside-recv, outside-send, ouside-recv. It is
+ * anticipated that specialized filters will be implemented that tune the
+ * filter behavior based on proxy particulars. That, or there will be a matrix
+ * configuration parameters that may be tweeked to match the configuration.
+ * It remains to be seen which is easier to manage.
+ */
+ class HTBP_Export Outside_Squid_Filter : public Filter
+ {
+ public:
+ /// Destructor.
+ virtual ~Outside_Squid_Filter (void);
+
+ /// Outside and outside Send filters need to supply a data header that
+ /// sets the stage before sending the data body, and then (maybe) send a
+ /// data trailer that closes the message. The data header may be formatted
+ /// differently on the first message, to send optional context information.
+ virtual ssize_t send_data_header (ssize_t data_len, Channel *);
+ virtual ssize_t send_data_trailer (Channel *);
+
+ /// Upon receiving data, the Channel is obliged to send an ack. This is
+ /// either an empty document if this is the in-to-out stream, or a new
+ /// long-duration document request if this is the out-to-in stream.
+ virtual int send_ack (Channel *);
+ virtual int recv_ack (Channel *);
+
+ /// receiving data must compliment sending. In the case of an in-to-out
+ /// stream. It is possible that the stream identity is not known until the
+ /// first request is received. In this case the filter will have to look
+ /// lookup the received session ID and either create a new instance or
+ /// reassign itself to an existing sesion. In that case, the associated
+ /// stream will have to be reassigned as well.
+ ///
+ virtual ssize_t recv_data_header (Channel *);
+ virtual ssize_t recv_data_trailer(Channel *);
+ };
+
+ }
+}
+
+#if defined (__ACE_INLINE__)
+#include "HTBP_Outside_Squid_Filter.inl"
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_OUTSIDE_FILTER_H */
diff --git a/protocols/ace/HTBP/HTBP_Outside_Squid_Filter.inl b/protocols/ace/HTBP/HTBP_Outside_Squid_Filter.inl
new file mode 100644
index 00000000000..351c6e53856
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Outside_Squid_Filter.inl
@@ -0,0 +1,9 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ACE_HTBP_Outside_Squid_Filter.i
+
+ACE_INLINE
+ACE::HTBP::Outside_Squid_Filter::~Outside_Squid_Filter (void)
+{
+}
diff --git a/protocols/ace/HTBP/HTBP_Session.cpp b/protocols/ace/HTBP/HTBP_Session.cpp
new file mode 100644
index 00000000000..3aed6b14324
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Session.cpp
@@ -0,0 +1,301 @@
+// SOCK_Stream.cpp
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+#include "HTBP_Session.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Event_Handler.h"
+#include "HTBP_Filter.h"
+#include "HTBP_ID_Requestor.h"
+
+#if !defined (__ACE_INLINE__)
+#include "HTBP_Session.inl"
+#endif
+
+ACE_RCSID(HTBP,ACE_HTBP_Session," $")
+
+ACE::HTBP::Session::Session_Map ACE::HTBP::Session::session_map_;
+ACE_UINT32 ACE::HTBP::Session::last_session_id_ = 0;
+ACE_SYNCH_MUTEX ACE::HTBP::Session::session_id_lock_;
+
+/// Static method definitions
+ACE_UINT32
+ACE::HTBP::Session::next_session_id ()
+{
+ ACE_Guard<ACE_SYNCH_MUTEX> g(ACE::HTBP::Session::session_id_lock_);
+ return ++last_session_id_;
+}
+
+int
+ACE::HTBP::Session::add_session (ACE::HTBP::Session *s)
+{
+ return session_map_.bind (s->session_id(),s);
+}
+
+int
+ACE::HTBP::Session::remove_session (ACE::HTBP::Session *s)
+{
+ if (session_map_.current_size() > 0)
+ return session_map_.unbind(s->session_id());
+ return 0;
+}
+
+int
+ACE::HTBP::Session::find_session (const ACE::HTBP::Session_Id_t &sid, ACE::HTBP::Session *&out)
+{
+ ACE::HTBP::Session::Map_Entry *e;
+ if (session_map_.find (sid,e) == -1)
+ {
+ out = 0;
+ return -1;
+ }
+ out = e->int_id_;
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+ACE::HTBP::Session::Session (void)
+ : proxy_addr_ (0),
+ destroy_proxy_addr_ (0),
+ inbound_ (0),
+ outbound_ (0),
+ closed_ (0),
+ handler_ (0),
+ reactor_(0),
+ stream_ (0),
+ sock_flags_(0)
+{
+ ACE::HTBP::ID_Requestor req;
+ ACE_TCHAR * htid = req.get_HTID();
+ session_id_.local_ = ACE_TEXT_ALWAYS_CHAR(htid);
+ delete[] htid;
+ session_id_.id_ = ACE::HTBP::Session::next_session_id();
+ ACE_NEW (inbound_, ACE::HTBP::Channel (this));
+ ACE_NEW (outbound_, ACE::HTBP::Channel (this));
+}
+
+ACE::HTBP::Session::Session (const ACE::HTBP::Addr &peer,
+ const ACE::HTBP::Addr &local,
+ ACE_UINT32 sid,
+ ACE_INET_Addr *proxy,
+ int take_proxy)
+ : proxy_addr_ (proxy),
+ destroy_proxy_addr_ (take_proxy),
+ inbound_ (0),
+ outbound_ (0),
+ closed_ (0),
+ handler_ (0),
+ reactor_(0),
+ stream_ (0),
+ sock_flags_(0)
+{
+ session_id_.peer_ = peer;
+ session_id_.local_ = local;
+ session_id_.id_ = (sid == 0) ?
+ ACE::HTBP::Session::next_session_id() : sid;
+
+ ACE_NEW (inbound_,ACE::HTBP::Channel (this));
+ ACE_NEW (outbound_,ACE::HTBP::Channel (this));
+}
+
+ACE::HTBP::Session::Session (const ACE::HTBP::Session_Id_t &id,
+ ACE_INET_Addr *proxy,
+ int take_proxy)
+ : proxy_addr_ (proxy),
+ destroy_proxy_addr_ (take_proxy),
+ session_id_(id),
+ inbound_ (0),
+ outbound_ (0),
+ closed_ (0),
+ handler_ (0),
+ reactor_ (0),
+ stream_ (0),
+ sock_flags_(0)
+{
+ ACE_NEW (inbound_, ACE::HTBP::Channel (this));
+ ACE_NEW (outbound_, ACE::HTBP::Channel (this));
+}
+
+ACE::HTBP::Session::Session (const ACE::HTBP::Session &other)
+{
+ this->operator=(other);
+}
+
+ACE::HTBP::Session&
+ACE::HTBP::Session::operator= (const ACE::HTBP::Session &)
+{
+ ACE_ASSERT (this == 0);
+ return *this;
+}
+
+ACE::HTBP::Session::~Session (void)
+{
+ if (destroy_proxy_addr_)
+ delete proxy_addr_;
+}
+
+int
+ACE::HTBP::Session::close (void)
+{
+ if (this->inbound_)
+ this->inbound_->close();
+ if (this->outbound_)
+ this->outbound_->close();
+ this->closed_= 1;
+ return ACE::HTBP::Session::remove_session (this);
+}
+
+
+ACE::HTBP::Channel *
+ACE::HTBP::Session::outbound (void) const
+{
+ if (!this->closed_ && this->proxy_addr_)
+ ACE_const_cast(ACE::HTBP::Session *,this)->reconnect();
+ if ( this->outbound_ == 0)
+ return 0;
+ ACE::HTBP::Channel::State s =this->outbound_->state();
+ return s == ACE::HTBP::Channel::Init || s == ACE::HTBP::Channel::Ready ? this->outbound_ : 0;
+}
+
+void
+ACE::HTBP::Session::reconnect_i (ACE::HTBP::Channel *s)
+{
+ ACE_SOCK_Connector conn;
+ char host[100];
+ this->proxy_addr_->get_host_name(host,100);
+ if (conn.connect (s->ace_stream(),*this->proxy_addr_) == -1)
+ {
+ ACE_TCHAR buffer[128];
+ this->proxy_addr_->addr_to_string(buffer,128, 0);
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT("ACE::HTBP::Session::reconnect failed to %s, %p\n"),
+ buffer, s == this->inbound_ ?
+ ACE_TEXT("inbound") : ACE_TEXT ("outbound")));
+ }
+ s->register_notifier(this->reactor_);
+ if (s == this->inbound_)
+ s->send_ack();
+}
+
+ACE_Event_Handler *
+ACE::HTBP::Session::handler (void)
+{
+ return this->handler_;
+}
+
+void
+ACE::HTBP::Session::handler (ACE_Event_Handler * h)
+{
+ this->handler_ = h;
+}
+
+void
+ACE::HTBP::Session::detach (ACE::HTBP::Channel *ch)
+{
+ if (this->inbound_ == ch)
+ this->inbound_ = 0;
+ else if (this->outbound_ == ch)
+ this->outbound_ = 0;
+ else
+ ACE_ERROR ((LM_ERROR, "ACE::HTBP::Session::detach called with unknown channel\n"));
+}
+
+void
+ACE::HTBP::Session::reactor (ACE_Reactor *r)
+{
+ this->reactor_ = r;
+ this->inbound_->register_notifier(r);
+ this->outbound_->register_notifier(r);
+}
+
+int
+ACE::HTBP::Session::enqueue (ACE_Message_Block *msg)
+{
+ this->outbound_queue_.enqueue_tail(msg);
+ return msg->length();
+}
+
+int
+ACE::HTBP::Session::flush_outbound_queue (void)
+{
+ int result = 0;
+ if (this->outbound_queue_.message_count() > 0)
+ {
+ ACE_Message_Block *msg = 0;
+ iovec *iov = 0;
+ ACE_NEW_RETURN (iov,
+ iovec[this->outbound_queue_.message_count()],
+ -1);
+ this->outbound_queue_.peek_dequeue_head (msg);
+ for (int i = 0; i < this->outbound_queue_.message_count(); i++)
+ {
+ iov[i].iov_base = msg->rd_ptr();
+ iov[i].iov_len = msg->length();
+ msg = msg->next();
+ }
+ result = this->outbound_->sendv (iov,this->outbound_queue_.message_count(),0);
+ delete [] iov;
+ while (this->outbound_queue_.dequeue_head(msg))
+ msg->release();
+ }
+ return result;
+}
+
+int
+ACE::HTBP::Session::close_inbound (void) const
+{
+ return this->inbound_ ? this->inbound_->close() : 0;
+}
+
+int
+ACE::HTBP::Session::close_outbound (void) const
+{
+ return this->outbound_ ? this->outbound_->close() : 0;
+}
+
+int
+ACE::HTBP::Session::enable (int flags)
+{
+ this->sock_flags_ |= flags;
+ int result = this->inbound_ ? this->inbound_->enable(flags) : 0;
+ result |= this->outbound_ ? this->outbound_->enable (flags) : 0;
+ return result;
+}
+
+int
+ACE::HTBP::Session::disable (int flags)
+{
+ this->sock_flags_ &= ~flags;
+ int result = this->inbound_ ? this->inbound_->disable(flags) : 0;
+ result |= this->outbound_ ? this->outbound_->disable (flags) : 0;
+ return result;
+}
+
+ACE::HTBP::Stream *
+ACE::HTBP::Session::stream (void)const
+{
+ return this->stream_;
+}
+
+void
+ACE::HTBP::Session::stream (ACE::HTBP::Stream *s)
+{
+ this->stream_ = s;
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Hash_Map_Manager_Ex<ACE::HTBP::Session_Id_t, ACE::HTBP::Session*, ACE_Hash<ACE::HTBP::Session_Id_t>,ACE_Equal_To<ACE::HTBP::Session_Id_t>,ACE_SYNCH_MUTEX>;
+template class ACE_Hash_Map_Manager<ACE::HTBP::Session_Id_t, ACE::HTBP::Session*, ACE_SYNCH_MUTEX>;
+template class ACE_Hash_Map_Entry<ACE::HTBP::Session_Id_t, ACE::HTBP::Session*>;
+template class ACE_Hash<ACE::HTBP::Session_Id_t>;
+template class ACE_Equal_To<ACE::HTBP::Session_Id_t>;
+
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Hash_Map_Manager_Ex<ACE::HTBP::Session_Id_t, ACE::HTBP::Session*, ACE_Hash<ACE::HTBP::Session_Id_t>,ACE_Equal_To<ACE::HTBP::Session_Id_t>,ACE_SYNCH_MUTEX>
+#pragma instantiate ACE_Hash_Map_Manager <ACE::HTBP::Session_Id_t, ACE::HTBP::Session*, ACE_SYNCH_MUTEX>
+#pragma instantiate ACE_Hash_Map_Entry <ACE::HTBP::Session_Id_t, ACE::HTBP::Session*>
+#pragma instantiate ACE_Hash<ACE::HTBP::Session_Id_t>;
+
+#pragma instantiate ACE_Equal_To<ACE::HTBP::Session_Id_t>
+#endif
diff --git a/protocols/ace/HTBP/HTBP_Session.h b/protocols/ace/HTBP/HTBP_Session.h
new file mode 100644
index 00000000000..9c162849215
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Session.h
@@ -0,0 +1,193 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Session.h
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier
+ */
+//=============================================================================
+
+#ifndef ACE_HTBP_SESSION_H
+#define ACE_HTBP_SESSION_H
+#include /**/ "ace/pre.h"
+
+#include "ace/SOCK_IO.h"
+#include "ace/Hash_Map_Manager.h"
+#include "ace/Synch.h"
+#include "ace/Message_Queue.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "HTBP_Addr.h"
+#include "HTBP_Export.h"
+#include "HTBP_Channel.h"
+
+#include "HTBP_Stream.h"
+
+// Forward declarations.
+class ACE_HTBP_Filter;
+class ACE_Event_Handler;
+
+namespace ACE
+{
+ namespace HTBP
+ {
+
+ class Session_Id_t
+ {
+ public:
+ ACE_UINT32 id_;
+ Addr local_;
+ Addr peer_;
+
+ u_long hash () const;
+ bool operator ==(const Session_Id_t &other) const;
+ };
+
+ /**
+ * @class Session
+ *
+ * @brief Defines the methods in the <Session> abstraction.
+ *
+ * A session is an entity that combines two Ht_Channels that connect directly
+ * to a proxy to manage communication with a remote peer. The Session may
+ * persist longer than either stream, assuming that the proxy is libel to
+ * close a connection at any time.
+ *
+ * This means that the session needs to be able to reconnect to the remote
+ * peer. This also means that the session needs to be aware of its location
+ * If it is outside the proxy and looses a stream, oh well. If it is inside,
+ * then the next time a stream is required, then it must reconnect before
+ * returning the stream.
+ *
+ * The session does not queue outbound messages. That is going to be the
+ * responsibility of the application, or a higher level protocol wrapper.
+ */
+ class HTBP_Export Session
+ {
+ public:
+ // Initialization and termination methods.
+ /// Constructor.
+ Session (void);
+
+ /// Constructor (sets the underlying session id with <sid>).
+ Session (const Addr& peer,
+ const Addr& local,
+ ACE_UINT32 sid = 0,
+ ACE_INET_Addr *proxy = 0,
+ int take_proxy = 0);
+ Session (const Session_Id_t &id,
+ ACE_INET_Addr *proxy = 0,
+ int take_proxy = 0);
+
+ Session (const Session &other);
+ Session& operator= (const Session &other);
+
+ /// Destructor.
+ ~Session (void);
+
+ /// The following methods are specific to the Session
+ static ACE_UINT32 next_session_id ();
+
+ static int add_session (Session *);
+ static int remove_session (Session *);
+ static int find_session (const Session_Id_t&,
+ Session *&out);
+
+ Stream *stream (void) const;
+ void stream (Stream *);
+
+ int enqueue (ACE_Message_Block *msg);
+ int flush_outbound_queue (void);
+
+ int close_inbound (void) const;
+ int close_outbound (void) const;
+
+ /// get references to the actual streams based on the direction
+ /// of data flow if this session is on the inside of the proxy
+ /// ie, has a non-null proxy addr, then the inbound stream is
+ /// the out_to_in stream, otherwise it is the in_to_out
+ /// stream. The outbound is the opposite of the inbound.
+ /// Whenever an application wishes to send data, whether that is
+ /// request or reply data, it uses the outbound stream, and it
+ /// should associate an event handler with the inbound stream
+ /// for receiving data.
+ Channel *inbound (void) const;
+ Channel *outbound (void) const;
+ void inbound (Channel *);
+ void outbound (Channel *);
+
+ int enable (int value);
+ int disable (int value);
+
+ const Session_Id_t& session_id(void) const;
+ void session_id (ACE_UINT32 );
+
+ const ACE_INET_Addr *proxy_addr (void) const;
+ void proxy_addr (ACE_INET_Addr *, int destroy = 0);
+
+ const Addr &peer_addr (void) const;
+ const Addr &local_addr (void) const;
+
+ void peer_addr (const Addr &);
+ void local_addr (const Addr &);
+
+ /// invoke close on both streams, then remove self from session map
+ int close (void);
+
+ ACE_Event_Handler *handler (void);
+ void handler (ACE_Event_Handler *);
+ void reactor (ACE_Reactor *);
+ void detach (Channel *);
+
+ int sock_flags(void) const;
+
+ private:
+ /// Connected Stream ensures that the particular stream is
+ /// connected to the proxy, if possible. The result is same as
+ /// the reference passed in, so that it may be used inline for
+ /// the inboundor outbound methods
+
+ void reconnect ();
+ void reconnect_i (Channel *);
+
+ typedef ACE_Hash_Map_Manager<Session_Id_t, Session*,
+ ACE_SYNCH_MUTEX> Session_Map;
+ typedef ACE_Hash_Map_Entry <Session_Id_t, Session*> Map_Entry;
+ static Session_Map session_map_;
+ static ACE_UINT32 last_session_id_;
+ static ACE_SYNCH_MUTEX session_id_lock_;
+
+ ACE_INET_Addr *proxy_addr_;
+ int destroy_proxy_addr_;
+
+ Session_Id_t session_id_;
+
+ Channel *inbound_;
+ Channel *outbound_;
+
+ Filter *inbound_filter_;
+ Filter *outbound_filter_;
+
+ int closed_;
+
+ ACE_Event_Handler *handler_;
+ ACE_Reactor *reactor_;
+
+ ACE_Message_Queue<ACE_SYNCH> outbound_queue_;
+ Stream * stream_;
+ int sock_flags_;
+ };
+ }
+}
+#if defined (__ACE_INLINE__)
+#include "HTBP_Session.inl"
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_SESSION_H */
diff --git a/protocols/ace/HTBP/HTBP_Session.inl b/protocols/ace/HTBP/HTBP_Session.inl
new file mode 100644
index 00000000000..fb5c337826c
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Session.inl
@@ -0,0 +1,109 @@
+/* -*- C++ -*- */
+// $Id$
+
+ACE_INLINE
+void
+ACE::HTBP::Session::reconnect ()
+{
+ if (!this->closed_ && this->proxy_addr_)
+ {
+ if (inbound_ &&
+ inbound_->ace_stream().get_handle() == ACE_INVALID_HANDLE)
+ reconnect_i (inbound_);
+ if (outbound_ &&
+ outbound_->ace_stream().get_handle() == ACE_INVALID_HANDLE)
+ reconnect_i (outbound_);
+ }
+}
+
+ACE_INLINE
+void
+ACE::HTBP::Session::inbound (ACE::HTBP::Channel *s)
+{
+ this->inbound_ = s;
+}
+
+
+ACE_INLINE
+void
+ACE::HTBP::Session::outbound (ACE::HTBP::Channel *s)
+{
+ this->outbound_ = s;
+}
+
+ACE_INLINE
+ACE::HTBP::Channel *
+ACE::HTBP::Session::inbound (void) const
+{
+ return this->inbound_;
+}
+
+ACE_INLINE
+const ACE::HTBP::Session_Id_t&
+ACE::HTBP::Session::session_id(void) const
+{
+ return this->session_id_;
+}
+
+// I'm wondering if this should be coupled with a map update...?
+ACE_INLINE
+void
+ACE::HTBP::Session::session_id (ACE_UINT32 id)
+{
+ this->session_id_.id_ = id;
+}
+
+ACE_INLINE
+const ACE_INET_Addr *
+ACE::HTBP::Session::proxy_addr (void) const
+{
+ return this->proxy_addr_;
+}
+
+ACE_INLINE
+const ACE::HTBP::Addr &
+ACE::HTBP::Session::peer_addr (void) const
+{
+ return this->session_id_.peer_;
+}
+
+ACE_INLINE
+const ACE::HTBP::Addr &
+ACE::HTBP::Session::local_addr (void) const
+{
+ return this->session_id_.local_;
+}
+
+ACE_INLINE
+void
+ACE::HTBP::Session::proxy_addr (ACE_INET_Addr *pa, int destroy)
+{
+ if (this->destroy_proxy_addr_)
+ delete this->proxy_addr_;
+ this->proxy_addr_ = pa;
+ this->destroy_proxy_addr_ = destroy;
+}
+
+ACE_INLINE
+int
+ACE::HTBP::Session::sock_flags (void) const
+{
+ return this->sock_flags_;
+}
+
+//---------------------------------------------------------------------------
+ACE_INLINE
+u_long
+ACE::HTBP::Session_Id_t::hash () const
+{
+ return id_; // + local.hash() + peer.hash();
+}
+
+ACE_INLINE
+bool
+ACE::HTBP::Session_Id_t::operator ==(const ACE::HTBP::Session_Id_t &other) const
+{
+ return ((this->id_ == other.id_) &&
+ (this->local_ == other.local_) &&
+ (this->peer_ == other.peer_));
+}
diff --git a/protocols/ace/HTBP/HTBP_Stream.cpp b/protocols/ace/HTBP/HTBP_Stream.cpp
new file mode 100644
index 00000000000..ffbbb3b9d82
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Stream.cpp
@@ -0,0 +1,330 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Stream.cpp
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier, Priyanka Gontla
+ */
+//=============================================================================
+#include "HTBP_Stream.h"
+
+#if !defined (__ACE_INLINE__)
+#include "HTBP_Stream.inl"
+#endif
+
+#include "HTBP_Session.h"
+#include "HTBP_Filter_Factory.h"
+
+#include "ace/Message_Block.h"
+
+
+// Initialization and termination methods.
+/// Constructor.
+ACE::HTBP::Stream::Stream (ACE::HTBP::Session *s)
+ : session_ (s)
+{
+ if (s == 0)
+ // create a temporary session to be replaced on first recv.
+ ACE_NEW (session_, ACE::HTBP::Session);
+ session_->stream (this);
+}
+
+/// Destructor.
+ACE::HTBP::Stream::~Stream (void)
+{
+}
+
+ /// Dump the state of an object.
+void
+ACE::HTBP::Stream::dump (void) const
+{
+}
+
+
+
+//---------------------------------------------------------------------------
+// = I/O functions.
+
+/// Recv an <n> byte buffer from the connected socket.
+ssize_t
+ACE::HTBP::Stream::recv (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ if (this->session_->inbound() == 0)
+ {
+ errno = EWOULDBLOCK;
+ ACE_ERROR_RETURN ((LM_ERROR,"recv(buf,n,flags) called, but no "
+ "inbound channel connected to stream\n"),-1);
+ }
+ return this->session_->inbound()->recv(buf,n,flags,timeout);
+}
+
+ /// Recv an <n> byte buffer from the connected socket.
+ssize_t
+ACE::HTBP::Stream::recv (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ if (this->session_->inbound() == 0)
+ {
+ errno = EWOULDBLOCK;
+ ACE_ERROR_RETURN ((LM_ERROR,"recv(buf,n) called, but no "
+ "inbound channel connected to stream\n"),-1);
+ }
+ return this->session_->inbound()->recv(buf,n,timeout);
+}
+
+ /// Recv an <iovec> of size <n> from the connected socket.
+ssize_t
+ACE::HTBP::Stream::recvv (iovec iov[],
+ int iovcnt,
+ const ACE_Time_Value *timeout) const
+{
+ if (this->session_->inbound() == 0)
+ {
+ errno = EWOULDBLOCK;
+ ACE_ERROR_RETURN ((LM_ERROR,"recv(iov,iovcnt) called, but no "
+ "inbound channel connected to stream\n"),-1);
+ }
+ return this->session_->inbound()->recvv(iov,iovcnt,timeout);
+}
+
+ssize_t
+ACE::HTBP::Stream::recvv (iovec *io_vec,
+ const ACE_Time_Value *timeout) const
+{
+ if (this->session_->inbound() == 0)
+ {
+ errno = EWOULDBLOCK;
+ ACE_ERROR_RETURN ((LM_ERROR,"recv(io_vec) called, but no "
+ "inbound channel connected to stream\n"),-1);
+ }
+ return this->session_->inbound()->recvv(io_vec,timeout);
+}
+
+ssize_t
+ACE::HTBP::Stream::recv (void *,
+ size_t,
+ ACE_OVERLAPPED *) const
+{
+ errno = ENOTSUP;
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE::HTBP::Stream: Asynch recv not supported\n"),-1);
+}
+
+ssize_t
+ACE::HTBP::Stream::send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ if (this->session_->outbound() == 0)
+ {
+ ACE_Message_Block *msg = 0;
+ ACE_NEW_RETURN (msg,ACE_Message_Block(n),-1);
+ msg->copy ((const char *)buf,n);
+ // probably ought to separately enqueue the flags and put the data buf
+ // in a continuation message
+ // Also, the timeout poses another interesting problem.
+ return this->session_->enqueue(msg);
+ }
+ return this->session_->outbound()->send(buf,n,flags,timeout);
+}
+
+ssize_t
+ACE::HTBP::Stream::send (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ if (this->session_->outbound() == 0)
+ {
+ ACE_Message_Block *msg = 0;
+ ACE_NEW_RETURN (msg,ACE_Message_Block(n),-1);
+ msg->copy ((const char *)buf,n);
+ return this->session_->enqueue(msg);
+ }
+ return this->session_->outbound()->send(buf,n,timeout);
+}
+
+ssize_t
+ACE::HTBP::Stream::sendv (const iovec iov[],
+ int iovcnt,
+ const ACE_Time_Value *timeout) const
+{
+ if (this->session_->outbound() == 0)
+ {
+ ACE_Message_Block *msg = 0;
+ size_t total = 0;
+ int i = 0;
+ for (; i < iovcnt; i++)
+ total += iov[i].iov_len;
+ ACE_NEW_RETURN (msg,ACE_Message_Block(total),-1);
+ for (i = 0; i < iovcnt; i++)
+ msg->copy ((const char *)iov[i].iov_base,iov[i].iov_len);
+ return this->session_->enqueue(msg);
+ }
+ return this->session_->outbound()->sendv(iov,iovcnt,timeout);
+}
+
+ssize_t
+ACE::HTBP::Stream::send (const void *,
+ size_t ,
+ ACE_OVERLAPPED *) const
+{
+ errno = ENOTSUP;
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE::HTBP::Stream: Asynch send not supported\n"),-1);
+}
+
+ssize_t
+ACE::HTBP::Stream::recv_n (void *,
+ size_t ,
+ int ,
+ const ACE_Time_Value *,
+ size_t *) const
+{
+ errno = ENOTSUP;
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE::HTBP::Stream: recv_n not supported\n"),-1);
+}
+
+ /// Try to recv exactly <len> bytes into <buf> from the connected socket.
+ssize_t
+ACE::HTBP::Stream::recv_n (void *,
+ size_t ,
+ const ACE_Time_Value *,
+ size_t *) const
+{
+ errno = ENOTSUP;
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE::HTBP::Stream: recv_n not supported\n"),-1);
+}
+
+ /// Receive an <iovec> of size <iovcnt> from the connected socket.
+ssize_t
+ACE::HTBP::Stream::recvv_n (iovec [],
+ int ,
+ const ACE_Time_Value *,
+ size_t *) const
+{
+ errno = ENOTSUP;
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE::HTBP::Stream: recvv_n not supported\n"),-1);
+}
+
+ /// Try to send exactly <len> bytes from <buf> to the connection socket.
+ssize_t
+ACE::HTBP::Stream::send_n (const void *,
+ size_t ,
+ int ,
+ const ACE_Time_Value *,
+ size_t *) const
+{
+ errno = ENOTSUP;
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE::HTBP::Stream: send_n not supported\n"),-1);
+}
+
+ /// Try to send exactly <len> bytes from <buf> to the connected socket.
+ssize_t
+ACE::HTBP::Stream::send_n (const void *,
+ size_t ,
+ const ACE_Time_Value *,
+ size_t *) const
+{
+ errno = ENOTSUP;
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE::HTBP::Stream: send_n not supported\n"),-1);
+}
+
+ /// Send all the <message_block>s chained through their <next> and
+ /// <cont> pointers. This call uses the underlying OS gather-write
+ /// operation to reduce the domain-crossing penalty.
+ssize_t
+ACE::HTBP::Stream::send_n (const ACE_Message_Block *,
+ const ACE_Time_Value *,
+ size_t *) const
+{
+ errno = ENOTSUP;
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE::HTBP::Stream: send_n not supported\n"),-1);
+}
+
+ /// Send an <iovec> of size <iovcnt> to the connected socket.
+ssize_t
+ACE::HTBP::Stream::sendv_n (const iovec [],
+ int,
+ const ACE_Time_Value *,
+ size_t *) const
+{
+ errno = ENOTSUP;
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE::HTBP::Stream: sendv_n not supported\n"),-1);
+}
+
+int
+ACE::HTBP::Stream::close_reader (void)
+{
+ return this->session_->close_inbound();
+}
+
+int
+ACE::HTBP::Stream::close_writer (void)
+{
+ return this->session_->close_outbound();
+}
+
+int
+ACE::HTBP::Stream::close (void)
+{
+ return this->session_->close();
+}
+
+int
+ACE::HTBP::Stream::enable (int value) const
+{
+ return this->session_->enable(value);
+}
+
+int
+ACE::HTBP::Stream::disable (int value) const
+{
+ return this->session_->disable(value);
+}
+
+int
+ACE::HTBP::Stream::get_local_addr (ACE::HTBP::Addr &local_addr) const
+{
+ local_addr = this->session_->local_addr ();
+ return 0;
+}
+
+int
+ACE::HTBP::Stream::get_remote_addr (ACE::HTBP::Addr &peer_addr) const
+{
+ peer_addr = this->session_->peer_addr();
+ return 0;
+}
+
+ACE::HTBP::Session *
+ACE::HTBP::Stream::session (void) const
+{
+ return this->session_;
+}
+
+void
+ACE::HTBP::Stream::session (ACE::HTBP::Session *s)
+{
+ delete this->session_;
+ this->session_ = s;
+ s->stream (this);
+}
+
+
+ACE_HANDLE
+ACE::HTBP::Stream::get_handle (void) const
+{
+ return ACE_INVALID_HANDLE;
+}
+
+void
+ACE::HTBP::Stream::set_handle (ACE_HANDLE )
+{
+ // no-op
+}
diff --git a/protocols/ace/HTBP/HTBP_Stream.h b/protocols/ace/HTBP/HTBP_Stream.h
new file mode 100644
index 00000000000..c627f5ef6a5
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Stream.h
@@ -0,0 +1,291 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file HTBP_Stream.h
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier, Priyanka Gontla
+ */
+//=============================================================================
+
+#ifndef ACE_HTBP_STREAM_H
+#define ACE_HTBP_STREAM_H
+#include /**/ "ace/pre.h"
+
+#include "ace/SOCK_Stream.h"
+#include "ace/Message_Block.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "HTBP_Export.h"
+#include "HTBP_Addr.h"
+#include "HTBP_Filter.h"
+#include "HTBP_Notifier.h"
+
+namespace ACE
+{
+ namespace HTBP
+ {
+ // Forward declarations.
+ class Session;
+
+ /**
+ * @class Stream
+ *
+ * @brief A stream facade for the HTTP Tunneling Bidirectional Protocol
+ *
+ * This adds provides the common interface for applications to do
+ * I/O that ultimately is wrapped in HTTP for tunneling through
+ * firewalls.
+ *
+ * This class is modelled after the ACE_SOCK_Stream class, and
+ * provides all of the I/O methods available in that class. Since
+ * this is a facade, it does not derive from ACE_SOCK_Stream. It
+ * also does not provide the same performance as ACE_SOCK_Stream,
+ * as some data may have to be stored by the HTBP classes prior to
+ * transmission.
+ *
+ * <buf> is the buffer to write from or receive into.
+ * <len> is the number of bytes to transfer.
+ * The <timeout> parameter in the following methods indicates how
+ * long to blocking trying to transfer data. If <timeout> == 0,
+ * then the call behaves as a normal send/recv call, i.e., for
+ * blocking sockets, the call will block until action is possible;
+ * for non-blocking sockets, EWOULDBLOCK will be returned if no
+ * action is immediately possible.
+ * If <timeout> != 0, the call will wait for data to arrive no longer
+ * than the relative time specified in *<timeout>.
+ * The "_n()" I/O methods keep looping until all the data has been
+ * transferred. These methods also work for sockets in non-blocking
+ * mode i.e., they keep looping on EWOULDBLOCK. <timeout> is used
+ * to make sure we keep making progress, i.e., the same timeout
+ * value is used for every I/O operation in the loop and the timeout
+ * is not counted down.
+ * The return values for the "*_n()" methods match the return values
+ * from the non "_n()" methods and are specified as follows:
+ * - On complete transfer, the number of bytes transferred is returned.
+ * - On timeout, -1 is returned, errno == ETIME.
+ * - On error, -1 is returned, errno is set to appropriate error.
+ * - On EOF, 0 is returned, errno is irrelevant.
+ *
+ * On partial transfers, i.e., if any data is transferred before
+ * timeout/error/EOF, <bytes_transferred> will contain the number of
+ * bytes transferred.
+ * Methods with <iovec> parameter are I/O vector variants of the I/O
+ * operations.
+ * Methods with the extra <flags> argument will always result in
+ * <send> getting called. Methods without the extra <flags> argument
+ * will result in <send> getting called on Win32 platforms, and
+ * <write> getting called on non-Win32 platforms.
+ */
+ class HTBP_Export Stream
+ {
+ public:
+ // Initialization and termination methods.
+ /// Constructor.
+ Stream (Session *s = 0);
+
+ /// Destructor.
+ ~Stream (void);
+
+ // = I/O functions.
+
+ /// The Stream is a sibling of the ACE_SOCK_IO class, rather
+ /// than a decendant. This is due to the requirement to wrap all
+ /// messages with an HTTP request or reply wrapper, and to send
+ /// application data in only one direction on one stream.
+
+ /// Recv an <n> byte buffer from the connected socket.
+ ssize_t recv (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Recv an <n> byte buffer from the connected socket.
+ ssize_t recv (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Recv an <iovec> of size <n> from the connected socket.
+ ssize_t recvv (iovec iov[],
+ int n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Same as above. Deprecated.
+ ssize_t recv (iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /**
+ * Allows a client to read from a socket without having to
+ * provide a buffer to read. This method determines how much
+ * data is in the socket, allocates a buffer of this size, reads
+ * in the data, and returns the number of bytes read. The
+ * caller is responsible for deleting the member in the
+ * <iov_base> field of <io_vec> using delete []
+ * io_vec->iov_base.
+ */
+ ssize_t recvv (iovec *io_vec,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Recv <n> bytes via Win32 <ReadFile> using overlapped I/O.
+ ssize_t recv (void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+ /// Send an <n> byte buffer to the connected socket.
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send an <n> byte buffer to the connected socket.
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send an <iovec> of size <n> to the connected socket.
+ ssize_t sendv (const iovec iov[],
+ int n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send <n> bytes via Win32 <WriteFile> using overlapped I/O.
+ ssize_t send (const void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+
+ /// Try to recv exactly <len> bytes into <buf> from the
+ /// connected socket.
+ ssize_t recv_n (void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Try to recv exactly <len> bytes into <buf> from the
+ /// connected socket.
+ ssize_t recv_n (void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Receive an <iovec> of size <iovcnt> from the connected
+ /// socket.
+ ssize_t recvv_n (iovec iov[],
+ int iovcnt,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Try to send exactly <len> bytes from <buf> to the connection
+ /// socket.
+ ssize_t send_n (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Try to send exactly <len> bytes from <buf> to the connected
+ /// socket.
+ ssize_t send_n (const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Send all the <message_block>s chained through their <next>
+ /// and <cont> pointers. This call uses the underlying OS
+ /// gather-write operation to reduce the domain-crossing
+ /// penalty.
+ ssize_t send_n (const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Send an <iovec> of size <iovcnt> to the connected socket.
+ ssize_t sendv_n (const iovec iov[],
+ int iovcnt,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ // = Selectively close endpoints. / Close down the reader.
+ int close_reader (void);
+
+ /// Close down the writer.
+ int close_writer (void);
+
+ /**
+ * Close down the socket (we need this to make things work correctly
+ * on Win32, which requires use to do a <close_writer> before doing
+ * the close to avoid losing data).
+ */
+ int close (void);
+
+ // = Meta-type info
+ typedef Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ public:
+ ///@notes Added the following methods to continue with
+ /// current compilation of HTIOP. Might not be needed in
+ /// future. - Priyanka
+ /// {@
+ void set_handle (ACE_HANDLE h);
+ ACE_HANDLE get_handle (void) const;
+
+ Session *session (void) const;
+ void session (Session *s);
+
+ /**
+ * Enable asynchronous I/O (ACE_SIGIO), urgent data (ACE_SIGURG),
+ * non-blocking I/O (ACE_NONBLOCK), or close-on-exec (ACE_CLOEXEC),
+ * which is passed as the <value>.
+ */
+ int enable (int value) const;
+
+ /**
+ * Disable asynchronous I/O (ACE_SIGIO), urgent data (ACE_SIGURG),
+ * non-blocking I/O (ACE_NONBLOCK), or close-on-exec (ACE_CLOEXEC),
+ * which is passed as the <value>.
+ */
+ int disable (int value) const;
+
+ /**
+ * Return the address of the remotely connected peer (if there is
+ * one), in the referenced <ACE_Addr>. Returns 0 if successful, else
+ * -1.
+ */
+ int get_remote_addr (Addr &) const;
+
+ /**
+ * Return the address of the remotely connected peer (if there is
+ * one), in the referenced <ACE_Addr>. Returns 0 if successful, else
+ * -1.
+ */
+ int get_local_addr (Addr &) const;
+
+ //@}
+
+ private:
+ /// The session_ is a reference to the persistent session this stream is
+ /// associated with. On the inside, sessions are created by the Connector,
+ /// which then create streams on demand.
+ Session *session_;
+
+ };
+ }
+}
+
+#if defined (__ACE_INLINE__)
+#include "HTBP_Stream.inl"
+#endif
+
+#include /**/ "ace/post.h"
+#endif /* ACE_HTBP_STREAM_H */
diff --git a/protocols/ace/HTBP/HTBP_Stream.inl b/protocols/ace/HTBP/HTBP_Stream.inl
new file mode 100644
index 00000000000..489ed1d91b5
--- /dev/null
+++ b/protocols/ace/HTBP/HTBP_Stream.inl
@@ -0,0 +1,4 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ACE_HTBP_Stream.i
diff --git a/protocols/ace/HTBP/HTID_Generator.cgi b/protocols/ace/HTBP/HTID_Generator.cgi
new file mode 100644
index 00000000000..0d57a552d6c
--- /dev/null
+++ b/protocols/ace/HTBP/HTID_Generator.cgi
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+
+# This is a sample script that may be used to create domain specific
+# unique ID's rather than using UUID. In a typical scenario, this HTID
+# generator would reside in the same domain as the target server, so
+# that it could be used by any clients of the server. While use of UUID
+# as a unique identifier is perfectly fine, use of a remote generator
+# gives additional benefits, such as the ability to collect metrics on
+# identity requestors.
+
+print "Content-type:text/html\n\n";
+
+$htid = $ENV{'REMOTE_ADDR'};
+
+open(IN,"counts.txt") or dienice("Can't open counts.txt for writing: $!");
+
+flock(IN,2); # lock the file
+seek(IN,0,0); # rewind it to the beginning
+
+$oldtimestamp = <IN>; # read only the first line.
+$save_time = $oldtimestamp;
+
+close(IN);
+
+
+$timestamp = time;
+
+if ($oldtimestamp == $timestamp)
+ {
+ open (IN2, "sec_id.txt") or
+ dienice ("Can't open sec_id.txt for writing: $!");
+
+ flock (IN2, 2);
+ seek (IN2, 0, 0);
+
+ $secondary_id = <IN2>;
+
+ # increment the secondary id
+ ++$secondary_id;
+
+
+ close (IN2);
+ }
+else {
+
+ $secondary_id = 0;
+}
+
+ open(OUT2,">sec_id.txt") or
+ dienice("Can't open outdata.txt for writing: $!");
+
+ flock(OUT2,2); # lock the file
+ seek(OUT2,0,0); # rewind it to the beginning
+
+ print OUT2 "$secondary_id";
+
+ close(OUT2);
+
+
+#save the timestamp for next time
+$oldtimestamp = $timestamp;
+
+
+open(OUT,">counts.txt") or dienice("Can't open outdata.txt for writing: $!");
+
+flock(OUT,2); # lock the file
+seek(OUT,0,0); # rewind it to the beginning
+print OUT "$oldtimestamp\n";
+close(OUT);
+
+
+$result_string = join (".$timestamp", $htid, ".$secondary_id");
+
+print <<EndOfHTML;
+
+$result_string
+
+EndOfHTML
diff --git a/protocols/ace/HTBP/README b/protocols/ace/HTBP/README
new file mode 100644
index 00000000000..577aaf15866
--- /dev/null
+++ b/protocols/ace/HTBP/README
@@ -0,0 +1,186 @@
+// $Id$
+
+This directory contains the HTTP Tunneling, Bidirectional, Protocol
+implementation. This is a new streaming abstraction layered over an
+HTTP document request/reply mechanism. It is designed to allow clients
+that are inside a of a corporate firewall to communicate with servers
+that are outside, hence HTTP Tunneling. Also, once a connection is
+established, the outside peer is able to send asynchronous messages to
+the inside peer, hence Bidirectional.
+
+HTBP provides Acceptor, Connector, and Stream classes that follow the
+interface defined for the ACE_Acceptor and ACE_Connector
+templates. This means that HTBP can be used right away with
+applications designed to use these templates.
+
+Bidirectionality is achieved in the context of the proxy's restriction
+by using two channels between the peers. One channel is defined for
+data flow from the inside to the outside, data flow from the outside
+in occurs on the other channel. In-to-out data is passed in the form
+of a PUT command with the data payload marshalled into an
+"application/gzip" buffer. On this channel, the outside peer always
+responds with a simple document which serves as an ack. On the
+out-to-in channel, the inside client must send a token request in the
+form of a GET command. This request goes unfulfilled until the outside
+peer has data to send, which it does by supplying an HTML document
+that again encapsulates the data so that it may pass through the proxy
+uncorrupted.
+
+The connections from the inside peer to the proxy, or from the proxy
+to the outside peer may be closed by the proxy at any time. The inside
+peer will automatically reconnect as needed when this happens. Since
+the outside peer cannot actively connect to the proxy, it will queue
+outbound messages as long as it can until a new out-to-in channel is
+made available, at which time it will flush its queue. The sense of
+channels may change over time, as the proxy may choose any local
+connection to the server to send any request (GET or POST).
+
+The outside peer is identified using an ordinary INET addr, however
+the inside peer uses a simple, transient unique ID to identify
+itself. Inside peers will never have any type of persistent identity.
+The unique ID used to identify the inside peer is usually a UUID value
+as composed by ACE_UUID_Generator. However, a domain based unique ID
+may also be obtainedusing HTBP::ID_Requestor::get_HTID(). If no domain
+based ID generator is configured, get_HTID() will return a UUID value.
+
+As there are a variety of HTTP proxies available, HTBP uses a
+pluggable filter class that defines the particular characteristics of
+a proxy and is responsible for marshalling and unmarshalling binary
+data. As of now there is a single filter available that works with a
+defaulted Squid proxy and may also be used as a null filter, directly
+connecting the inside and outside peers. This mode is useful for
+testing.
+
+CONFIGURING HTBP
+This is done through the ACE_Configuration framework. On windows
+platforms, the Windows Registry may be used, whereas on non-windows, a
+flat file is used to configure. Configuration data may also be
+persisted in a memory mapped file.
+
+The configuration map contains a single section, HTBP, that contains
+all the configurable parameters in name=value form. The following is
+an example of a configuration file:
+
+[htbp]
+proxy_host=<hostname> This is the hostname of the http
+ proxy through which all requests
+ will be sent.
+proxy_port=<port> This is the proxy's port.
+htid_url=<url> If a domain based unique id is
+ required, this is the URL of the
+ ID generator.
+htid_via_proxy=<1|0> If the htid_url must be reached
+ via the proxy, set this to 1.
+ Default is 0, meaning the ID
+ generator is directly accessible.
+
+COMPANION DIRECTORIES:
+$ACE_ROOT/tests/HTBP. These are the test drivers, which
+ also serve as example code.
+$TAO_ROOT/orbsvcs/orbsvcs/HTIOP This is a TAO pluggable protocol
+ based on HTBP.
+$TAO_ROOT/orbsvcs/tests/HTIOP The tests for HTIOP.
+
+
+BACKGROUND INFORMATION
+
+HT Addresses
+
+The class HT_Addr is a subclass of ACE_INET_Addr class. The interface
+for the HT_Addr is a common interface to be used with the inside and
+outside peers. The inside peer is identified by a HTID while the
+outside peer is identified with an ip address. Constructors are
+provided to initialize the inside and outside peers in addition to the
+default and copy constructors. addr_to_string and string_to_addr
+methods from the base class are overridden to help convert the HT_Addr
+to a string and vice versa. Finally, the class provides accessor
+methods for the default local address and the default proxy addresses.
+
+The local address is the address of the inside peer and is obtained
+using the singleton HTID_Requestor class. The HTID_Requestor class
+sends a request to the web server that is running at the htid_url to
+get the HTID unique to each inside peer.
+
+The proxy address is of ACE_INET_Addr type as it is no different to a
+regular server. It is obtained using the singleton HT_Environment
+class. The HT_Environment class helps read the HT configuration file
+and provides acccessors to the proxy address, port and the htid url.
+
+The code below illustrates the initialization of a local or inside,
+remote or outside and the proxy addresses using the classes
+aforementioned.
+
+ HT_Addr local(HTID_REQUESTOR::instance()->get_HTID());
+
+ char hostname [1000];
+ if (ACE_OS::hostname (hostname,
+ 1000) == -1)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Could not get the host name\n"));
+ return -1;
+ }
+
+ HT_Addr remote (8088, hostname);
+
+ char proxy_address [1000];
+ HT_ENVIRONMENT::instance ()->get_proxy_address (proxy_address);
+
+ unsigned int proxy_port;
+ HT_ENVIRONMENT::instance ()->get_proxy_port (proxy_port);
+
+ ACE_INET_Addr proxy(port, proxy_address);
+
+
+HT Streams
+
+The class HT_Stream is a sibling of the ACE_SOCK_IO class. It is used
+to send and receive messages between two peers identified by their HT
+addresses. It is made a sibling of the ACE_SOCK_IO class rather than
+a decendant. This is due to the requirement in the HTBP protocol to
+wrap all messages with an HTTP request or reply wrapper, and to send
+application data in only one direction on one stream.
+
+HT Sessions
+
+A session is an entity that combines two HT_Streams that connect
+directly to a proxy to manage communication with a remote peer. The
+session may persist longer than either stream, assuming that the proxy
+is libel to close a connection at any time. This means that the
+session needs to be able to reconnect to the remote peer. This also
+means that the session needs to be aware of its location. If it is
+outside the proxy and looses a stream, nothing can really be done. If
+it is inside, then the next time a stream is required, then it must
+reconnect before returning the stream. The session does not queue
+outbound messages. It will be the responsibility of the application or
+a higher level protocol wrapper.
+
+Each session is identified by a special type,
+HT_Session_Id_t. HT_Session_Id_t is a class with three members, the
+local address, the peer address and an id of type ACE_UINT32. A
+session map, ....
+
+Besides the default constructor and copy constructors, two other
+constructors are provided to initialize a session and are shown below.
+
+
+ /// Constructor (sets the underlying session id with <sid>).
+ HT_Session (const HT_Addr& peer,
+ const HT_Addr& local = HT_Addr::default_local(),
+ ACE_UINT32 sid = 0,
+ ACE_INET_Addr *proxy = 0,
+ int take_proxy = 0);
+
+ HT_Session (const HT_Session_Id_t &id,
+ ACE_INET_Addr *proxy = 0,
+ int take_proxy = 0);
+
+
+
+If a session id (sid) is not provided by the user, it is generated
+using the static method HT_Session::next_session_id().
+
+The following code illustrates the usage of HT_Stream and HT_Session
+classes.
+
+HT_Filters
+<TBD>