summaryrefslogtreecommitdiff
path: root/ACE/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp')
-rw-r--r--ACE/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp236
1 files changed, 236 insertions, 0 deletions
diff --git a/ACE/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp b/ACE/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp
new file mode 100644
index 00000000000..acb019ce2bb
--- /dev/null
+++ b/ACE/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp
@@ -0,0 +1,236 @@
+// 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$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+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++;
+
+ // This test was originally get_host_name() == -1, but this is
+ // problematic if the address doesn't resolve to a name. I think
+ // that it should be configurable, or maybe the hostname needs to
+ // be carried independent of the address to work with hosts that may
+ // have dynamic IP addresses. For now that isn't a problem.
+ if (session->peer_addr().get_host_addr(remote_host,
+ sizeof remote_host) == 0)
+ 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;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL