summaryrefslogtreecommitdiff
path: root/src/Sockets/AjpBaseSocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Sockets/AjpBaseSocket.cpp')
-rw-r--r--src/Sockets/AjpBaseSocket.cpp258
1 files changed, 258 insertions, 0 deletions
diff --git a/src/Sockets/AjpBaseSocket.cpp b/src/Sockets/AjpBaseSocket.cpp
new file mode 100644
index 0000000..3b54dd0
--- /dev/null
+++ b/src/Sockets/AjpBaseSocket.cpp
@@ -0,0 +1,258 @@
+/**
+ ** \file AjpBaseSocket.cpp
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 Anders Hedstrom
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "AjpBaseSocket.h"
+#include "ajp13.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#ifdef _DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+
+// ---------------------------------------------------------------------------
+AjpBaseSocket::Initializer AjpBaseSocket::Init;
+
+
+// ---------------------------------------------------------------------------
+AjpBaseSocket::Initializer::Initializer()
+{
+
+ Header[HTTP_REQUEST_ACCEPT] = "accept";
+ Header[HTTP_REQUEST_ACCEPT_CHARSET] = "accept-charset";
+ Header[HTTP_REQUEST_ACCEPT_ENCODING] = "accept-encoding";
+ Header[HTTP_REQUEST_ACCEPT_LANGUAGE] = "accept-language";
+ Header[HTTP_REQUEST_AUTHORIZATION] = "authorization";
+ Header[HTTP_REQUEST_CONNECTION] = "connection";
+ Header[HTTP_REQUEST_CONTENT_TYPE] = "content-type";
+ Header[HTTP_REQUEST_CONTENT_LENGTH] = "content-length";
+ Header[HTTP_REQUEST_COOKIE] = "cookie";
+ Header[HTTP_REQUEST_COOKIE2] = "cookie2";
+ Header[HTTP_REQUEST_HOST] = "host";
+ Header[HTTP_REQUEST_PRAGMA] = "pragma";
+ Header[HTTP_REQUEST_REFERER] = "referer";
+ Header[HTTP_REQUEST_USER_AGENT] = "user-agent";
+
+ Method[HTTP_METHOD_OPTIONS] = "OPTIONS";
+ Method[HTTP_METHOD_GET] = "GET";
+ Method[HTTP_METHOD_HEAD] = "HEAD";
+ Method[HTTP_METHOD_POST] = "POST";
+ Method[HTTP_METHOD_PUT] = "PUT";
+ Method[HTTP_METHOD_DELETE] = "DELETE";
+ Method[HTTP_METHOD_TRACE] = "TRACE";
+ Method[HTTP_METHOD_PROPFIND] = "PROPFIND";
+ Method[HTTP_METHOD_PROPPATCH] = "PROPPATCH";
+ Method[HTTP_METHOD_MKCOL] = "MKCOL";
+ Method[HTTP_METHOD_COPY] = "COPY";
+ Method[HTTP_METHOD_MOVE] = "MOVE";
+ Method[HTTP_METHOD_LOCK] = "LOCK";
+ Method[HTTP_METHOD_UNLOCK] = "UNLOCK";
+ Method[HTTP_METHOD_ACL] = "ACL";
+ Method[HTTP_METHOD_REPORT] = "REPORT";
+ Method[HTTP_METHOD_VERSION_CONTROL] = "VERSION_CONTROL"; // with a dash "VERSION-CONTROL"
+ Method[HTTP_METHOD_CHECKIN] = "CHECKIN";
+ Method[HTTP_METHOD_CHECKOUT] = "CHECKOUT";
+ Method[HTTP_METHOD_UNCHECKOUT] = "UNCHECKOUT";
+ Method[HTTP_METHOD_SEARCH] = "SEARCH";
+ Method[HTTP_METHOD_MKWORKSPACE] = "MKWORKSPACE";
+ Method[HTTP_METHOD_UPDATE] = "UPDATE";
+ Method[HTTP_METHOD_LABEL] = "LABEL";
+ Method[HTTP_METHOD_MERGE] = "MERGE";
+ Method[HTTP_METHOD_BASELINE_CONTROL] = "BASELINE_CONTROL";
+ Method[HTTP_METHOD_MKACTIVITY] = "MKACTIVITY";
+
+ Attribute[ATTR_CONTEXT] = "context";
+ Attribute[ATTR_SERVLET_PATH] = "servlet_path";
+ Attribute[ATTR_REMOTE_USER] = "remote_user";
+ Attribute[ATTR_AUTH_TYPE] = "auth_type";
+ Attribute[ATTR_QUERY_STRING] = "query_string";
+ Attribute[ATTR_ROUTE] = "route";
+ Attribute[ATTR_SSL_CERT] = "ssl_cert";
+ Attribute[ATTR_SSL_CIPHER] = "ssl_cipher";
+ Attribute[ATTR_SSL_SESSION] = "ssl_session";
+ Attribute[ATTR_SSL_KEY_SIZE] = "ssl_key_size";
+ Attribute[ATTR_SECRET] = "secret";
+ Attribute[ATTR_STORED_METHOD] = "stored_method";
+
+ ResponseHeader["content-type"] = 0xa001;
+ ResponseHeader["content-language"] = 0xa002;
+ ResponseHeader["content-length"] = 0xa003;
+ ResponseHeader["date"] = 0xa004;
+ ResponseHeader["last-modified"] = 0xa005;
+ ResponseHeader["location"] = 0xa006;
+ ResponseHeader["set-cookie"] = 0xa007;
+ ResponseHeader["set-cookie2"] = 0xa008;
+ ResponseHeader["servlet-engine"] = 0xa009;
+ ResponseHeader["status"] = 0xa00a;
+ ResponseHeader["www-authenticate"] = 0xa00b;
+}
+
+
+// ---------------------------------------------------------------------------
+AjpBaseSocket::AjpBaseSocket(ISocketHandler& h) : TcpSocket(h)
+, m_state(0)
+, m_length(4)
+, m_ptr(0)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::OnRawData(const char *buf, size_t sz)
+{
+DEB(fprintf(stderr, "OnRawData: %d bytes\n", sz);)
+ size_t ptr = 0;
+ while (true)
+ {
+ size_t left = sz - ptr;
+DEB(fprintf(stderr, " left: %d bytes\n", left);
+fprintf(stderr, " state: %d\n", m_state);)
+ switch (m_state)
+ {
+ case 0:
+ {
+ size_t missing = m_length - m_ptr;
+ short len = (short)(missing < left ? missing : left);
+ memcpy(m_message + m_ptr, buf + ptr, len);
+ m_ptr += len;
+ ptr += len;
+ if (m_ptr < m_length)
+ {
+ return; // read more
+ }
+ int p = 0;
+ short id = get_integer(m_message, p);
+ short length = get_integer(m_message, p);
+ OnHeader(id, length);
+ m_state = 1;
+ m_length = length;
+ m_ptr = 0; // bytes in m_message
+ }
+ break;
+ case 1:
+ {
+ size_t missing = m_length - m_ptr;
+ short len = (short)(missing < left ? missing : left);
+ memcpy(m_message + m_ptr, buf + ptr, len);
+ m_ptr += len;
+ ptr += len;
+ if (m_ptr < m_length)
+ {
+ return; // read more
+ }
+ OnPacket(m_message, m_ptr);
+ m_state = 0;
+ m_length = 4;
+ m_ptr = 0;
+ }
+ break;
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+unsigned char AjpBaseSocket::get_byte(const char *buf, int& ptr)
+{
+ return (unsigned char)buf[ptr++];
+}
+
+
+// ---------------------------------------------------------------------------
+bool AjpBaseSocket::get_boolean(const char *buf, int& ptr)
+{
+ return ( (unsigned char)buf[ptr++] & 1) == 1 ? true : false;
+}
+
+
+// ---------------------------------------------------------------------------
+short AjpBaseSocket::get_integer(const char *buf, int& ptr)
+{
+ short n;
+ memcpy(&n, buf + ptr, 2);
+ ptr += 2;
+ return ntohs(n);
+}
+
+
+// ---------------------------------------------------------------------------
+std::string AjpBaseSocket::get_string(const char *buf, int& ptr)
+{
+ short len = get_integer(buf, ptr);
+ if (len != -1)
+ {
+ std::string tmp = buf + ptr;
+ ptr += len;
+ ptr++; // skip trailing 0x0
+ tmp.resize(len);
+ return tmp;
+ }
+ return "";
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::put_byte(char *buf, int& ptr, unsigned char zz)
+{
+ buf[ptr++] = zz;
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::put_boolean(char *buf, int& ptr, bool zz)
+{
+ buf[ptr++] = zz ? 1 : 0;
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::put_integer(char *buf, int& ptr, short zz)
+{
+ short tmp = htons(zz);
+ memcpy(buf + ptr, &tmp, 2);
+ ptr += 2;
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::put_string(char *buf, int& ptr, const std::string& zz)
+{
+ put_integer(buf, ptr, (short)zz.size() );
+ memcpy(buf + ptr, zz.c_str(), zz.size());
+ ptr += (int)zz.size();
+ put_byte(buf, ptr, 0);
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+