summaryrefslogtreecommitdiff
path: root/server/src/server.cc
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/server.cc')
-rw-r--r--server/src/server.cc200
1 files changed, 136 insertions, 64 deletions
diff --git a/server/src/server.cc b/server/src/server.cc
index 84c3463..4283a11 100644
--- a/server/src/server.cc
+++ b/server/src/server.cc
@@ -61,18 +61,18 @@ static std::string error_box(std::string message)
return errorbox;
}
-static std::string handleConnection(const char *buf, size_t size,
+static std::string handleConnection(const std::string &data,
Environment &env,
- char **sessionid,
- const char *sessioncommit)
+ std::string &sessionid,
+ bool sessioncommit)
{
std::string res;
Session *session = NULL;
- if(*sessionid == NULL) {
+ if(sessionid == "") {
session = env.sessions.newSession();
} else {
- session = env.sessions.session(*sessionid);
+ session = env.sessions.session(sessionid);
if(session == NULL) session = env.sessions.newSession();
}
@@ -81,51 +81,44 @@ static std::string handleConnection(const char *buf, size_t size,
return error_box(xml_encode("New session could not be created."));
}
- session->lock();
+ sessionid = session->id();
- if(asprintf(sessionid, "%s", session->id().c_str()) == -1) *sessionid = NULL;
+ {
+ SessionAutolock lock(*session);
- Transaction transaction;
- TransactionParser parser(&transaction);
+ if(data.length()) {
+ Transaction transaction;
+ TransactionParser parser(&transaction);
+
+ if(!parser.parse(data.c_str(), data.length())) {
+ PRACRO_ERR(server, "Failed to parse data!\n");
+ PRACRO_ERR(server, "DATA:[[%s]]\n", data.c_str());
+ res = error_box(xml_encode("XML Parse error."));
+ } else {
+ res = handleTransaction(transaction, env, *session);
+ }
+ }
- if(!parser.parse(buf, size)) {
- PRACRO_ERR(server, "Failed to parse data!\n");
- res = error_box(xml_encode("XML Parse error."));
- } else {
- res = handleTransaction(transaction, env, *session);
}
- session->unlock();
-
- if(sessioncommit != NULL) {
+ if(sessioncommit) {
session->commit();
env.sessions.deleteSession(session->id());
}
return res;
+}
- /*
- Transaction transaction;
- TransactionParser parser(&transaction);
-
- PRACRO_DEBUG(server, "Read %d bytes from network\n", size);
-
- std::string res;
- if(size) {
- if(parser.parse(buf, size)) {
- PRACRO_DEBUG(server, "Got complete XML document, %d bytes in current buffer.\n", size);
-
- res = handleTransaction(&transaction, pentominos_socket,
- *conn->db, session, macrolist, templatelist);
- } else {
- PRACRO_ERR(server, "Failed to parse data!\n");
- res = error_box(xml_encode("XML Parse error."));
- }
- }
- return res;
+struct condata {
+ std::map<std::string, std::string> headers;
+ std::string data;
+ size_t data_size;
+ std::string url;
+ std::string method;
+ std::string version;
+};
- */
-}
+//static std::map<struct MHD_Connection *, struct condata> condata;
static int handle_request_callback(void *cls,
struct MHD_Connection *con,
@@ -134,40 +127,116 @@ static int handle_request_callback(void *cls,
const char *version,
const char *data,
unsigned int *data_size,
- void **ptr)
+ void **con_cls)
{
- Environment *env = (Environment *)cls;
+ PRACRO_DEBUG(httpd, "handle_request_callback con:%p condata:%p\n",
+ con, *con_cls);
+
+ // Test for new connection
+ if(*con_cls == NULL) {
+ PRACRO_DEBUG(httpd,
+ "handle_request(url=\"%s\", method=\"%s\","
+ " version=\"%s\", data_size=\"%d\")\n",
+ url, method, version, *data_size);
+
+ struct condata *cd = new struct condata;
+ cd->url = url;
+ cd->method = method;
+ cd->version = version;
+ cd->data_size = 0;
+ cd->data = "";
+
+ const char *sid = MHD_lookup_connection_value(con, MHD_HEADER_KIND,
+ "SessionID");
+ if(sid) cd->headers["SessionID"] = sid;
+
+ const char *scm = MHD_lookup_connection_value(con, MHD_HEADER_KIND,
+ "SessionCommit");
+ if(scm) cd->headers["SessionCommit"] = scm;
+
+ const char *csz = MHD_lookup_connection_value(con, MHD_HEADER_KIND,
+ "Content-Length");
+ if(csz) {
+ cd->headers["Content-Length"] = csz;
+ cd->data_size = atol(csz);
+ PRACRO_DEBUG(httpd, "Content-Length: %s (%d)\n", csz, cd->data_size);
+ }
- PRACRO_DEBUG(httpd,
- "handle_request(url=\"%s\", method=\"%s\","
- " version=\"%s\", data_size=\"%d\")\n",
- url, method, version, *data_size);
+ *con_cls = cd;
+ }
- const char *sessionid =
- MHD_lookup_connection_value(con, MHD_HEADER_KIND, "SessionID");
- const char *sessioncommit =
- MHD_lookup_connection_value(con, MHD_HEADER_KIND, "SessionCommit");
+ struct condata *cd = (struct condata*)*con_cls;
+ cd->data.append(data, *data_size);
- std::string reply =
- handleConnection(data, *data_size, *env, (char**)&sessionid, sessioncommit);
-
- struct MHD_Response *rsp =
- MHD_create_response_from_data(reply.length(), (char*)reply.c_str(), MHD_NO, MHD_YES);
- MHD_add_response_header(rsp, MHD_HTTP_HEADER_CONTENT_TYPE, "text/plain; charset=UTF-8");
+ int ret = MHD_YES;
- if(*sessionid) {
- MHD_add_response_header(rsp, "SessionID", sessionid);
- free((char*)sessionid);
- }
+ PRACRO_DEBUG(httpd, "Waiting for %d bytes of data. Got %d (total %d)\n",
+ cd->data_size, *data_size, cd->data.length());
+
+ if(cd->data.length() >= cd->data_size) {
+
+ Environment *env = (Environment *)cls;
+
+ const char *sid = MHD_lookup_connection_value(con, MHD_HEADER_KIND,
+ "SessionID");
+ std::string sessionid;
+ if(sid) sessionid = sid;
+
+ const char *sessioncommit =
+ MHD_lookup_connection_value(con, MHD_HEADER_KIND, "SessionCommit");
+
+ PRACRO_DEBUG(httpd, "Starting to handle SessionID: %s%s\n",
+ sessionid.c_str(),
+ sessioncommit != NULL?" COMMIT":"");
+
+ PRACRO_DEBUG(httpd, "Data: [%s]\n", cd->data.c_str());
+
+ std::string reply =
+ handleConnection(cd->data, *env, sessionid, sessioncommit != NULL);
+
+ struct MHD_Response *rsp =
+ MHD_create_response_from_data(reply.length(), (char*)reply.c_str(),
+ MHD_NO, MHD_YES);
+ MHD_add_response_header(rsp, MHD_HTTP_HEADER_CONTENT_TYPE,
+ "text/plain; charset=UTF-8");
+
+ if(sessionid != "") {
+ MHD_add_response_header(rsp, "SessionID", sessionid.c_str());
+ }
+
+ ret = MHD_queue_response(con, MHD_HTTP_OK, rsp);
+ MHD_destroy_response(rsp);
+
+ PRACRO_DEBUG(httpd, "Finished handling SessionID: %s%s\n",
+ sessionid.c_str(),
+ sessioncommit != NULL?" COMMIT":"");
- int ret = MHD_queue_response(con, MHD_HTTP_OK, rsp);
- MHD_destroy_response(rsp);
+
+ delete cd;
+ *con_cls = NULL;
+
+ }
*data_size = 0;
return ret;
}
+void requestCompletedCallback(void *cls,
+ struct MHD_Connection *con,
+ void **con_cls,
+ enum MHD_RequestTerminationCode toe)
+{
+ PRACRO_DEBUG(httpd, "requestCompletedCallback %p\n", con);
+
+ // If connection was interrupted prematurely delete the content data here.
+ if(*con_cls) {
+ struct condata *cd = (struct condata*)*con_cls;
+ delete cd;
+ *con_cls = NULL;
+ }
+}
+
static void httpderr(void *arg, const char *fmt, va_list ap)
{
PRACRO_ERR_VA(server, fmt, ap);
@@ -181,7 +250,8 @@ void server()
bool forceshutdown = false;
port_t port = Conf::server_port;
- int flags = MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY; // | MHD_USE_PEDANTIC_CHECKS
+ int flags = MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY;
+ // | MHD_USE_PEDANTIC_CHECKS
#ifndef WITHOUT_SSL
if(Conf::use_ssl) flags |= MHD_USE_SSL;
#endif
@@ -193,7 +263,8 @@ void server()
struct MHD_Daemon *d;
d = MHD_start_daemon(flags, port, NULL, NULL,
handle_request_callback, &env,
- MHD_OPTION_NOTIFY_COMPLETED, NULL, NULL,
+ MHD_OPTION_NOTIFY_COMPLETED,
+ requestCompletedCallback, NULL,
MHD_OPTION_CONNECTION_LIMIT, Conf::connection_limit,
#ifndef WITHOUT_SSL
MHD_OPTION_HTTPS_MEM_KEY, Conf::ssl_key.c_str(),
@@ -246,10 +317,11 @@ char request[] =
int main()
{
Conf::xml_basedir = "../xml/";
- Conf::server_port = 32100; // Make sure wo don't interrupt an already running server.
+ // Make sure wo don't interrupt an already running server.
+ Conf::server_port = 32100;
Conf::database_backend = "testdb";
pid_t pid = fork();
-
+
switch(pid) {
case -1: // error
perror("fork() failed!\n");