summaryrefslogtreecommitdiffstats
path: root/src/uscxml/server
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-11-16 16:45:34 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-11-16 16:45:34 (GMT)
commita5b2c2081329958710a59107854349f5b6a14bcb (patch)
treecd4724968c4eb865db853450ebab19094ca6d6dc /src/uscxml/server
parent22ddb37efb48c484e022fef5516491ad69608397 (diff)
downloaduscxml-a5b2c2081329958710a59107854349f5b6a14bcb.zip
uscxml-a5b2c2081329958710a59107854349f5b6a14bcb.tar.gz
uscxml-a5b2c2081329958710a59107854349f5b6a14bcb.tar.bz2
Builds on windows again
Diffstat (limited to 'src/uscxml/server')
-rw-r--r--src/uscxml/server/HTTPServer.cpp252
-rw-r--r--src/uscxml/server/HTTPServer.h16
-rw-r--r--src/uscxml/server/InterpreterServlet.cpp54
-rw-r--r--src/uscxml/server/InterpreterServlet.h16
4 files changed, 171 insertions, 167 deletions
diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp
index 04a831e..2258ab0 100644
--- a/src/uscxml/server/HTTPServer.cpp
+++ b/src/uscxml/server/HTTPServer.cpp
@@ -76,7 +76,7 @@ HTTPServer::HTTPServer(unsigned short port, unsigned short wsPort, SSLConfig* ss
_thread = NULL;
_httpHandle = NULL;
_wsHandle = NULL;
-
+
determineAddress();
unsigned int allowedMethods =
@@ -91,12 +91,12 @@ HTTPServer::HTTPServer(unsigned short port, unsigned short wsPort, SSLConfig* ss
EVHTTP_REQ_PATCH;
evhttp_set_allowed_methods(_http, allowedMethods); // allow all methods
-
+
if (_port > 0)
_httpHandle = evhttp_bind_socket_with_handle(_http, INADDR_ANY, _port);
if (_httpHandle)
LOG(INFO) << "HTTP server listening on tcp/" << _port;
-
+
_wsPort = wsPort;
if (_wsPort > 0)
_wsHandle = evws_bind_socket(_evws, _wsPort);
@@ -186,42 +186,42 @@ void HTTPServer::wsRecvReqCallback(struct evws_connection *conn, struct evws_fra
wsFrame.evwsConn = conn;
struct evws_header *header;
- TAILQ_FOREACH(header, &conn->headers, next) {
+ for (header = conn->headers.tqh_first; header; header = header->next.tqe_next) {
wsFrame.data.compound["header"].compound[header->key] = Data(header->value, Data::VERBATIM);
}
switch (frame->opcode) {
- case EVWS_CONTINUATION_FRAME:
- wsFrame.data.compound["type"] = Data("continuation", Data::VERBATIM);
- wsFrame.data.compound["content"] = Data(std::string(frame->data, frame->size), Data::VERBATIM);
- break;
- case EVWS_TEXT_FRAME:
- wsFrame.data.compound["type"] = Data("text", Data::VERBATIM);
- wsFrame.data.compound["content"] = Data(std::string(frame->data, frame->size), Data::VERBATIM);
- break;
- case EVWS_BINARY_FRAME:
- wsFrame.data.compound["type"] = Data("binary", Data::VERBATIM);
- wsFrame.data.compound["content"] = Data(frame->data, frame->size, "application/octet-stream");
- break;
- case EVWS_CONNECTION_CLOSE:
- wsFrame.data.compound["type"] = Data("close", Data::VERBATIM);
- break;
- case EVWS_PING:
- wsFrame.data.compound["type"] = Data("ping", Data::VERBATIM);
- break;
- case EVWS_PONG:
- wsFrame.data.compound["type"] = Data("ping", Data::VERBATIM);
- break;
+ case EVWS_CONTINUATION_FRAME:
+ wsFrame.data.compound["type"] = Data("continuation", Data::VERBATIM);
+ wsFrame.data.compound["content"] = Data(std::string(frame->data, frame->size), Data::VERBATIM);
+ break;
+ case EVWS_TEXT_FRAME:
+ wsFrame.data.compound["type"] = Data("text", Data::VERBATIM);
+ wsFrame.data.compound["content"] = Data(std::string(frame->data, frame->size), Data::VERBATIM);
+ break;
+ case EVWS_BINARY_FRAME:
+ wsFrame.data.compound["type"] = Data("binary", Data::VERBATIM);
+ wsFrame.data.compound["content"] = Data(frame->data, frame->size, "application/octet-stream");
+ break;
+ case EVWS_CONNECTION_CLOSE:
+ wsFrame.data.compound["type"] = Data("close", Data::VERBATIM);
+ break;
+ case EVWS_PING:
+ wsFrame.data.compound["type"] = Data("ping", Data::VERBATIM);
+ break;
+ case EVWS_PONG:
+ wsFrame.data.compound["type"] = Data("ping", Data::VERBATIM);
+ break;
}
wsFrame.data.compound["uri"] = Data(HTTPServer::getBaseURL(WebSockets) + conn->uri, Data::VERBATIM);
wsFrame.data.compound["path"] = Data(conn->uri, Data::VERBATIM);
-
+
// try with the handler registered for path first
bool answered = false;
if (callbackData != NULL)
answered = ((WebSocketServlet*)callbackData)->wsRecvRequest(conn, wsFrame);
-
+
if (!answered)
HTTPServer::getInstance()->processByMatchingServlet(conn, wsFrame);
@@ -246,7 +246,7 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD
}
}
#endif
-
+
evhttp_request_own(req);
Request request;
request.evhttpReq = req;
@@ -393,7 +393,7 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD
}
}
}
-
+
request.raw = raw.str();
// try with the handler registered for path first
@@ -439,22 +439,22 @@ void HTTPServer::processByMatchingServlet(const Request& request) {
void HTTPServer::processByMatchingServlet(evws_connection* conn, const WSFrame& frame) {
tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
-
+
ws_servlet_iter_t servletIter = _wsServlets.begin();
-
+
std::string actualPath = frame.data.compound.at("path").atom;
std::map<std::string, WebSocketServlet*, comp_strsize_less> matches;
-
+
while(servletIter != _wsServlets.end()) {
// is the servlet path a prefix of the actual path?
std::string servletPath = "/" + servletIter->first;
if (iequals(actualPath.substr(0, servletPath.length()), servletPath) && // servlet path is a prefix
- iequals(actualPath.substr(servletPath.length(), 1), "/")) { // and next character is a '/'
+ iequals(actualPath.substr(servletPath.length(), 1), "/")) { // and next character is a '/'
matches.insert(std::make_pair(servletPath, servletIter->second));
}
servletIter++;
}
-
+
// process by best matching servlet until someone feels responsible
std::map<std::string, WebSocketServlet*, comp_strsize_less>::iterator matchesIter = matches.begin();
while(matchesIter != matches.end()) {
@@ -544,7 +544,7 @@ bool HTTPServer::registerServlet(const std::string& path, HTTPServlet* servlet)
bool HTTPServer::registerServlet(const std::string& path, WebSocketServlet* servlet) {
HTTPServer* INSTANCE = getInstance();
tthread::lock_guard<tthread::recursive_mutex> lock(INSTANCE->_mutex);
-
+
// remove trailing and leading slash
std::string actualPath = path;
if (boost::ends_with(actualPath, "/"))
@@ -552,7 +552,7 @@ bool HTTPServer::registerServlet(const std::string& path, WebSocketServlet* serv
if (boost::starts_with(actualPath, "/"))
actualPath = actualPath.substr(1);
std::string suffixedPath = actualPath;
-
+
// if this servlet allows to adapt the path, do so
int i = 2;
while(INSTANCE->_wsServlets.find(suffixedPath) != INSTANCE->_wsServlets.end()) {
@@ -562,15 +562,15 @@ bool HTTPServer::registerServlet(const std::string& path, WebSocketServlet* serv
ss << actualPath << i++;
suffixedPath = ss.str();
}
-
+
std::stringstream servletURL;
servletURL << "ws://" << INSTANCE->_address << ":" << INSTANCE->_wsPort << "/" << suffixedPath;
servlet->setURL(servletURL.str());
-
+
INSTANCE->_wsServlets[suffixedPath] = servlet;
-
+
// LOG(INFO) << "HTTP Servlet listening at: " << servletURL.str() << std::endl;
-
+
// register callback
evws_set_cb(INSTANCE->_evws, ("/" + suffixedPath).c_str(), HTTPServer::wsRecvReqCallback, NULL, servlet);
@@ -582,15 +582,19 @@ std::string HTTPServer::getBaseURL(ServerType type) {
std::stringstream servletURL;
switch (type) {
- case HTTP:
- servletURL << "http://" << INSTANCE->_address << ":" << INSTANCE->_port;
- break;
- case HTTPS:
- servletURL << "https://" << INSTANCE->_address << ":" << INSTANCE->_sslPort;
- break;
- case WebSockets:
- servletURL << "ws://" << INSTANCE->_address << ":" << INSTANCE->_wsPort;
- break;
+ case HTTP:
+ servletURL << "http://" << INSTANCE->_address << ":" << INSTANCE->_port;
+ break;
+#if (defined EVENT_SSL_FOUND && defined OPENSSL_FOUND && defined OPENSSL_HAS_ELIPTIC_CURVES)
+ case HTTPS:
+ servletURL << "https://" << INSTANCE->_address << ":" << INSTANCE->_sslPort;
+ break;
+#endif
+ case WebSockets:
+ servletURL << "ws://" << INSTANCE->_address << ":" << INSTANCE->_wsPort;
+ break;
+ default:
+ break;
}
return servletURL.str();
}
@@ -628,84 +632,84 @@ void HTTPServer::determineAddress() {
_address = std::string(hostname);
}
-
+
#if (defined EVENT_SSL_FOUND && defined OPENSSL_FOUND && defined OPENSSL_HAS_ELIPTIC_CURVES)
- // see https://github.com/ppelleti/https-example/blob/master/https-server.c
- struct bufferevent* HTTPServer::sslBufferEventCallback(struct event_base *base, void *arg) {
- struct bufferevent* r;
- SSL_CTX *ctx = (SSL_CTX *) arg;
- r = bufferevent_openssl_socket_new (base,
- -1,
- SSL_new (ctx),
- BUFFEREVENT_SSL_ACCEPTING,
- BEV_OPT_CLOSE_ON_FREE);
- return r;
+// see https://github.com/ppelleti/https-example/blob/master/https-server.c
+struct bufferevent* HTTPServer::sslBufferEventCallback(struct event_base *base, void *arg) {
+ struct bufferevent* r;
+ SSL_CTX *ctx = (SSL_CTX *) arg;
+ r = bufferevent_openssl_socket_new (base,
+ -1,
+ SSL_new (ctx),
+ BUFFEREVENT_SSL_ACCEPTING,
+ BEV_OPT_CLOSE_ON_FREE);
+ return r;
+}
+
+
+void HTTPServer::sslGeneralBufferEventCallback (struct evhttp_request *req, void *arg) {
+ struct evbuffer *evb = NULL;
+ const char *uri = evhttp_request_get_uri (req);
+ struct evhttp_uri *decoded = NULL;
+
+ /* We only handle POST requests. */
+ if (evhttp_request_get_command (req) != EVHTTP_REQ_POST) {
+ evhttp_send_reply (req, 200, "OK", NULL);
+ return;
}
-
-
- void HTTPServer::sslGeneralBufferEventCallback (struct evhttp_request *req, void *arg) {
- struct evbuffer *evb = NULL;
- const char *uri = evhttp_request_get_uri (req);
- struct evhttp_uri *decoded = NULL;
-
- /* We only handle POST requests. */
- if (evhttp_request_get_command (req) != EVHTTP_REQ_POST) {
- evhttp_send_reply (req, 200, "OK", NULL);
- return;
- }
-
- printf ("Got a POST request for <%s>\n", uri);
-
- /* Decode the URI */
- decoded = evhttp_uri_parse (uri);
- if (! decoded) {
- printf ("It's not a good URI. Sending BADREQUEST\n");
- evhttp_send_error (req, HTTP_BADREQUEST, 0);
- return;
- }
-
- /* Decode the payload */
- struct evkeyvalq kv;
- memset (&kv, 0, sizeof (kv));
- struct evbuffer *buf = evhttp_request_get_input_buffer (req);
- evbuffer_add (buf, "", 1); /* NUL-terminate the buffer */
- char *payload = (char *) evbuffer_pullup (buf, -1);
- if (0 != evhttp_parse_query_str (payload, &kv)) {
- printf ("Malformed payload. Sending BADREQUEST\n");
- evhttp_send_error (req, HTTP_BADREQUEST, 0);
- return;
- }
-
- /* Determine peer */
- char *peer_addr;
- ev_uint16_t peer_port;
- struct evhttp_connection *con = evhttp_request_get_connection (req);
- evhttp_connection_get_peer (con, &peer_addr, &peer_port);
-
- /* Extract passcode */
- const char *passcode = evhttp_find_header (&kv, "passcode");
- char response[256];
- evutil_snprintf (response, sizeof (response),
- "Hi %s! I %s your passcode.\n", peer_addr,
- (0 == strcmp (passcode, "R23")
- ? "liked"
- : "didn't like"));
- evhttp_clear_headers (&kv); /* to free memory held by kv */
-
- /* This holds the content we're sending. */
- evb = evbuffer_new ();
-
- evhttp_add_header (evhttp_request_get_output_headers (req),
- "Content-Type", "application/x-yaml");
- evbuffer_add (evb, response, strlen (response));
-
- evhttp_send_reply (req, 200, "OK", evb);
-
- if (decoded)
- evhttp_uri_free (decoded);
- if (evb)
- evbuffer_free (evb);
+
+ printf ("Got a POST request for <%s>\n", uri);
+
+ /* Decode the URI */
+ decoded = evhttp_uri_parse (uri);
+ if (! decoded) {
+ printf ("It's not a good URI. Sending BADREQUEST\n");
+ evhttp_send_error (req, HTTP_BADREQUEST, 0);
+ return;
}
+
+ /* Decode the payload */
+ struct evkeyvalq kv;
+ memset (&kv, 0, sizeof (kv));
+ struct evbuffer *buf = evhttp_request_get_input_buffer (req);
+ evbuffer_add (buf, "", 1); /* NUL-terminate the buffer */
+ char *payload = (char *) evbuffer_pullup (buf, -1);
+ if (0 != evhttp_parse_query_str (payload, &kv)) {
+ printf ("Malformed payload. Sending BADREQUEST\n");
+ evhttp_send_error (req, HTTP_BADREQUEST, 0);
+ return;
+ }
+
+ /* Determine peer */
+ char *peer_addr;
+ ev_uint16_t peer_port;
+ struct evhttp_connection *con = evhttp_request_get_connection (req);
+ evhttp_connection_get_peer (con, &peer_addr, &peer_port);
+
+ /* Extract passcode */
+ const char *passcode = evhttp_find_header (&kv, "passcode");
+ char response[256];
+ evutil_snprintf (response, sizeof (response),
+ "Hi %s! I %s your passcode.\n", peer_addr,
+ (0 == strcmp (passcode, "R23")
+ ? "liked"
+ : "didn't like"));
+ evhttp_clear_headers (&kv); /* to free memory held by kv */
+
+ /* This holds the content we're sending. */
+ evb = evbuffer_new ();
+
+ evhttp_add_header (evhttp_request_get_output_headers (req),
+ "Content-Type", "application/x-yaml");
+ evbuffer_add (evb, response, strlen (response));
+
+ evhttp_send_reply (req, 200, "OK", evb);
+
+ if (decoded)
+ evhttp_uri_free (decoded);
+ if (evb)
+ evbuffer_free (evb);
+}
#endif
} \ No newline at end of file
diff --git a/src/uscxml/server/HTTPServer.h b/src/uscxml/server/HTTPServer.h
index 6f3c792..7083a3c 100644
--- a/src/uscxml/server/HTTPServer.h
+++ b/src/uscxml/server/HTTPServer.h
@@ -40,7 +40,7 @@ namespace uscxml {
class HTTPServlet;
class WebSocketServlet;
-
+
class USCXML_API HTTPServer {
public:
class Request : public Event {
@@ -60,7 +60,7 @@ public:
std::string content;
struct evws_connection* evwsConn;
};
-
+
class SSLConfig {
public:
SSLConfig() : port(8443) {}
@@ -85,11 +85,11 @@ public:
};
enum ServerType {
- HTTPS,
- HTTP,
- WebSockets
+ HTTPS,
+ HTTP,
+ WebSockets
};
-
+
static HTTPServer* getInstance(unsigned short port, unsigned short wsPort, SSLConfig* sslConf = NULL);
static HTTPServer* getInstance() {
return getInstance(0, 0, NULL);
@@ -140,10 +140,10 @@ private:
struct event_base* _base;
struct evhttp* _http;
struct evws* _evws;
-
+
struct evhttp_bound_socket* _httpHandle;
evutil_socket_t _wsHandle;
-
+
unsigned short _port;
unsigned short _wsPort;
std::string _address;
diff --git a/src/uscxml/server/InterpreterServlet.cpp b/src/uscxml/server/InterpreterServlet.cpp
index 8218669..01c8f07 100644
--- a/src/uscxml/server/InterpreterServlet.cpp
+++ b/src/uscxml/server/InterpreterServlet.cpp
@@ -85,11 +85,11 @@ void InterpreterHTTPServlet::send(const SendRequest& req) {
LOG(ERROR) << "send not supported by http iorprocessor, use the fetch element";
}
-
-
+
+
InterpreterWebSocketServlet::InterpreterWebSocketServlet(InterpreterImpl* interpreter) {
_interpreter = interpreter;
-
+
std::stringstream path;
path << _interpreter->getName();
int i = 2;
@@ -109,16 +109,16 @@ boost::shared_ptr<IOProcessorImpl> InterpreterWebSocketServlet::create(Interpret
bool InterpreterWebSocketServlet::wsRecvRequest(struct evws_connection *conn, const HTTPServer::WSFrame& frame) {
tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
-
+
// evhttp_request_own(req.curlReq);
-
+
_requests[toStr((uintptr_t)conn)] = conn;
-
+
Event event = frame;
-
+
event.name = "ws." + event.data.compound["type"].atom;
event.origin = toStr((uintptr_t)conn);
-
+
if (event.data.compound["type"].atom.compare("text") == 0 && event.data.compound["content"]) {
if (event.data.compound["content"].compound.size() > 0) {
std::map<std::string, Data>::iterator compoundIter = event.data.compound["content"].compound.begin();
@@ -131,7 +131,7 @@ bool InterpreterWebSocketServlet::wsRecvRequest(struct evws_connection *conn, co
}
}
}
-
+
_interpreter->receive(event);
return true;
}
@@ -155,23 +155,23 @@ void InterpreterWebSocketServlet::send(const SendRequest& req) {
if (false) {
} else if (req.data.binary) {
evws_send_data(_requests[req.target],
- EVWS_BINARY_FRAME,
- req.data.binary->data,
- req.data.binary->size);
+ EVWS_BINARY_FRAME,
+ req.data.binary->data,
+ req.data.binary->size);
} else if (req.data.node) {
std::stringstream ssXML;
ssXML << req.data.node;
std::string data = ssXML.str();
evws_send_data(_requests[req.target],
- EVWS_TEXT_FRAME,
- data.c_str(),
- data.length());
+ EVWS_TEXT_FRAME,
+ data.c_str(),
+ data.length());
} else if (req.data) {
std::string data = Data::toJSON(req.data);
evws_send_data(_requests[req.target],
- EVWS_TEXT_FRAME,
- data.c_str(),
- data.length());
+ EVWS_TEXT_FRAME,
+ data.c_str(),
+ data.length());
} else {
LOG(WARNING) << "Not sure what to make off content given to send on websocket!";
}
@@ -180,23 +180,23 @@ void InterpreterWebSocketServlet::send(const SendRequest& req) {
if (false) {
} else if (req.data.binary) {
evws_broadcast(getWSBase(), req.target.c_str(),
- EVWS_BINARY_FRAME,
- req.data.binary->data,
- req.data.binary->size);
+ EVWS_BINARY_FRAME,
+ req.data.binary->data,
+ req.data.binary->size);
} else if (req.data.node) {
std::stringstream ssXML;
ssXML << req.data.node;
std::string data = ssXML.str();
evws_broadcast(getWSBase(), req.target.c_str(),
- EVWS_TEXT_FRAME,
- data.c_str(),
- data.length());
+ EVWS_TEXT_FRAME,
+ data.c_str(),
+ data.length());
} else if (req.data) {
std::string data = Data::toJSON(req.data);
evws_broadcast(getWSBase(), req.target.c_str(),
- EVWS_TEXT_FRAME,
- data.c_str(),
- data.length());
+ EVWS_TEXT_FRAME,
+ data.c_str(),
+ data.length());
} else {
LOG(WARNING) << "Not sure what to make off content given to broadcast on websocket!";
}
diff --git a/src/uscxml/server/InterpreterServlet.h b/src/uscxml/server/InterpreterServlet.h
index 46cc737..0315598 100644
--- a/src/uscxml/server/InterpreterServlet.h
+++ b/src/uscxml/server/InterpreterServlet.h
@@ -83,21 +83,21 @@ public:
InterpreterWebSocketServlet() {};
InterpreterWebSocketServlet(InterpreterImpl* interpreter);
virtual ~InterpreterWebSocketServlet() {}
-
+
virtual boost::shared_ptr<IOProcessorImpl> create(InterpreterImpl* interpreter);
-
+
virtual std::set<std::string> getNames() {
std::set<std::string> names;
names.insert("websocket");
names.insert("http://www.w3.org/TR/scxml/#WebSocketEventProcessor");
return names;
}
-
+
Data getDataModelVariables();
virtual void send(const SendRequest& req);
-
+
virtual bool wsRecvRequest(struct evws_connection *conn, const HTTPServer::WSFrame& frame);
-
+
std::string getPath() {
return _path;
}
@@ -117,15 +117,15 @@ public:
tthread::recursive_mutex& getMutex() {
return _mutex;
}
-
+
protected:
InterpreterImpl* _interpreter;
-
+
tthread::recursive_mutex _mutex;
std::map<std::string, struct evws_connection*> _requests;
std::string _path;
std::string _url;
-
+
};
}