diff options
Diffstat (limited to 'ACE/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp')
-rw-r--r-- | ACE/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp | 239 |
1 files changed, 239 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..1bc9f4a208b --- /dev/null +++ b/ACE/protocols/ace/HTBP/HTBP_Inside_Squid_Filter.cpp @@ -0,0 +1,239 @@ +// 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) + { + if (ACE::debug()) + ACE_ERROR ((LM_ERROR, + ACE_TEXT("HTBP::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("HTBP::Inside_Squid_Filter::") + ACE_TEXT("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 (ACE_OS::strtol(tpos,0,10)); + start = nl+1; + } + + ch->leftovers().rd_ptr(header_end); + if (this->http_code() != 200) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT("HTBP::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("HTBP::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("HTBP::Inside_Squid_Filter::") + ACE_TEXT("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 (ACE_OS::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 |