diff options
Diffstat (limited to 'ACE/apps/JAWS/clients/Caching/http_handler.cpp')
-rw-r--r-- | ACE/apps/JAWS/clients/Caching/http_handler.cpp | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/ACE/apps/JAWS/clients/Caching/http_handler.cpp b/ACE/apps/JAWS/clients/Caching/http_handler.cpp new file mode 100644 index 00000000000..bfeda511176 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/http_handler.cpp @@ -0,0 +1,238 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// apps/JAWS/clients/Caching +// +// = FILENAME +// http_handler.cpp +// +// = AUTHOR +// James Hu +// +// ============================================================================ + +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" +#include "ace/Filecache.h" +#include "http_handler.h" + +ACE_RCSID(Caching, http_handler, "$Id$") + +HTTP_Handler::HTTP_Handler (void) +{ +} + +HTTP_Handler::HTTP_Handler (const char * path) +{ + // How long is the request going to be? + this->request_[0] = '\0'; + this->request_size_ = + ACE_OS::strlen ("GET ") + + ACE_OS::strlen (path) + + ACE_OS::strlen (" HTTP/1.0\r\nAccept: HTTP/1.0\r\n\r\n"); + + // Make the request. + if ((u_int) this->request_size_ < sizeof (this->request_)) + ACE_OS::sprintf (this->request_, + "GET %s HTTP/1.0\r\nAccept: HTTP/1.0\r\n\r\n", + path); + + // Find the filename. + const char *last = ACE_OS::strrchr (path, '/'); + + if (last == 0) + last = path; + else if (last[1] == '\0') + last = "index.html"; + else + last = last+1; + + ACE_OS::sprintf (this->filename_, "%s", last); +} + +int +HTTP_Handler::open (void *) +{ + // If you want threads, use the activate stuff. +#if 0 + if (this->activate () != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, "HTTP_Handler::open, whups!\n"), -1); + } + + return 0; +#else + return this->svc (); +#endif /* 0 */ +} + +int +HTTP_Handler::svc (void) +{ + static char buf[BUFSIZ]; + int count = 0; + + ACE_DEBUG ((LM_DEBUG, "[%t] sending request --\n%s", this->request_)); + + this->peer ().send_n (this->request_, this->request_size_); + + // Read in characters until encounter \r\n\r\n + int done = 0; + char *contentlength; + + do + { + while (((count += this->peer ().recv_n (buf + count, 1)) > 0) + && ((u_int) count < sizeof (buf))) + { + buf[count] = '\0'; + + if (count < 2) + continue; + done = ACE_OS::strcmp (buf + count - 4, "\n\n") == 0; + + if (done) + break; + + if (count < 4) + continue; + + done = ACE_OS::strcmp (buf + count - 4, "\r\n\r\n") == 0; + + if (done) + break; + } + + if (!done) + { + char *last = ACE_OS::strrchr (buf, '\n'); + last[0] = '\0'; + + if ((contentlength = ACE_OS::strstr (buf, "\nContent-length:")) + || (contentlength = ACE_OS::strstr (buf, "\nContent-Length:"))) + done = 1; + else + { + last[0] = '\n'; + count = ACE_OS::strlen (last); + ACE_OS::memmove (buf, last, count + 1); + } + } + else + { + contentlength = ACE_OS::strstr (buf, "\nContent-length:"); + + if (!contentlength) + contentlength = + ACE_OS::strstr (buf, "\nContent-Length:"); + } + + } + while (!done); + + // ASSERT (contentlength != 0) + if (contentlength + && (::sscanf (contentlength, "\nContent-%*[lL]ength: %d ", + &this->response_size_) == 1)) + { + ACE_Filecache_Handle afh (ACE_TEXT_CHAR_TO_TCHAR (this->filename_), + this->response_size_); + + this->peer ().recv_n (afh.address (), this->response_size_); + + ACE_DEBUG ((LM_DEBUG, + " ``%s'' is now cached.\n", + this->filename_)); + } + else + { + // Maybe we should do something more clever here, such as extend + // ACE_Filecache_Handle to allow the creation of cache objects + // whose size is unknown? + + // Another possibility is to write the contents out to a file, + // and then cache it. + + // Perhaps make ACE_Filecache_Handle more savvy, and allow a + // constructor which accepts a PEER as a parameter. + ACE_DEBUG ((LM_DEBUG, + "HTTP_Handler, no content-length header!\n")); + } + + return 0; +} + +const char * +HTTP_Handler::filename (void) const +{ + return this->filename_; +} + +int +HTTP_Connector::connect (const char * url) +{ + char host[BUFSIZ]; + u_short port; + char path[BUFSIZ]; + + if (this->parseurl (url, host, &port, path) == -1) + { + ACE_DEBUG ((LM_DEBUG, + "HTTP_Connector, error parsing url: %s\n", + url)); + return -1; + } + + HTTP_Handler hh (path); + HTTP_Handler *hhptr = &hh; + + // First check the cache. + if (ACE_Filecache::instance ()->find (ACE_TEXT_CHAR_TO_TCHAR (hh.filename ())) == 0) + { + ACE_DEBUG ((LM_DEBUG, " ``%s'' is already cached.\n", + hh.filename ())); + return 0; + } + + return this->connector_.connect (hhptr, ACE_INET_Addr (port, host)); +} + +#define DEFAULT_SERVER_PORT 80 + +// extract the main components of a URL +int +HTTP_Connector::parseurl (const char *url, + char *host, + u_short *port, + char *path) +{ + int status = 0; + + // hackish, but useful + if (3 != ::sscanf (url, "http://%[^:/]:%hu%s", host, port, path)) + { + if (2 != ::sscanf (url, "http://%[^:/]:%hu", host, port)) + { + if (2 != ::sscanf (url, "http://%[^:/]%s", host, path)) + { + if (1 != ::sscanf (url, "http://%[^:/]", host)) + status = -1; + else + { + *port = DEFAULT_SERVER_PORT; + ACE_OS::strcpy (path, "/"); + } + } + else + *port = DEFAULT_SERVER_PORT; + } + else ACE_OS::strcpy (path, "/"); + } + + // 0 => success + // -1 => error + return status; +} + |