[xmppd-dev] commit r1544 - in branches/RELEASE-1_6_1: . jabberd
mail at jabberd.org
mail at jabberd.org
Mon Dec 8 17:16:50 CET 2008
Author: mawis
Date: Mon Dec 8 17:16:50 2008
New Revision: 1544
Log:
This implements a mini HTTP server on the ports where jabberd14 is listening for XML (e.g. the c2s, s2s and component ports).
The feature has been requested by Vahan Yerkanian to support Flash clients accessing his jabberd14 by delivering them crossdomain.xml files.
Modified:
branches/RELEASE-1_6_1/ChangeLog
branches/RELEASE-1_6_1/jabber.xml.dist.in
branches/RELEASE-1_6_1/jabberd/jabberd.h
branches/RELEASE-1_6_1/jabberd/mio.cc
branches/RELEASE-1_6_1/jabberd/mio_xml.cc
Modified: branches/RELEASE-1_6_1/ChangeLog
==============================================================================
--- branches/RELEASE-1_6_1/ChangeLog Tue Nov 25 23:55:44 2008 (r1543)
+++ branches/RELEASE-1_6_1/ChangeLog Mon Dec 8 17:16:50 2008 (r1544)
@@ -1,3 +1,9 @@
+2008-12-08 Matthias Wimmer <m at tthias.eu>
+
+ * jabberd/mio_xml.cc: implemented mini-HTTP-server in jabberd14
+ * jabberd/mio.cc: same
+ * jabberd/jabberd.h: same
+
2008-11-25 Matthias Wimmer <m at tthias.eu>
* jabberd/base/base_accept.cc: improvement in failure recovery for dynamic
Modified: branches/RELEASE-1_6_1/jabber.xml.dist.in
==============================================================================
--- branches/RELEASE-1_6_1/jabber.xml.dist.in Tue Nov 25 23:55:44 2008 (r1543)
+++ branches/RELEASE-1_6_1/jabber.xml.dist.in Mon Dec 8 17:16:50 2008 (r1544)
@@ -1073,12 +1073,28 @@
<bind>192.0.2.55</bind>
-->
- <!-- With this setting it is possible to configure jabberd to -->
- <!-- detect incoming HTTP requests. Jabberd14 will then bounce the -->
- <!-- user's agent to the configured URI. This might be especially -->
+ <!-- Jabberd14 has build-in minimal HTTP server support. If it -->
+ <!-- receives a HTTP GET request on one of its Jabber ports, it -->
+ <!-- will try to answer this request. This might be especially -->
<!-- useful, if you run your jabber server on port 80 and want to -->
<!-- bounce web requests to a different domain. -->
+ <!-- There are two configuration options available, that can be -->
+ <!-- used: -->
+ <!-- With the mini-webserver element, you can configure a -->
+ <!-- directory in your filesystem, that will be used to hold the -->
+ <!-- documents jabberd14 is returning for requests. For security -->
+ <!-- reasons only files directly in this directory will be served -->
+ <!-- back to the requestor. No sub-directories will be used. -->
+ <!-- (Symbolic links are followed.) -->
+ <!-- If jabberd14 could not find a matching document for the -->
+ <!-- request in you mini-webserver directory, it will consult the -->
+ <!-- content of the bounce element. This is then used as the -->
+ <!-- destination for bouncing the HTTP client to. -->
+ <!-- Important: Do not use jabberd14 to return big files on HTTP -->
+ <!-- requests. jabberd14 reads the complete file from disk to -->
+ <!-- build the response in memory. -->
<!--
+ <mini-webserver>@localstatedir@/lib/jabberd/mini-webserver</mini-webserver>
<bounce>http://www.example.com/</bounce>
-->
</io>
Modified: branches/RELEASE-1_6_1/jabberd/jabberd.h
==============================================================================
--- branches/RELEASE-1_6_1/jabberd/jabberd.h Tue Nov 25 23:55:44 2008 (r1543)
+++ branches/RELEASE-1_6_1/jabberd/jabberd.h Mon Dec 8 17:16:50 2008 (r1544)
@@ -412,7 +412,8 @@
int zzz_active; /**< if set to something else then 1, there has been sent a signal already, that is not yet processed */
struct karma *k; /**< default karma */
int rate_t, rate_p; /**< default rate, if any */
- char *bounce_uri; /**< where to bounce HTTP requests to */
+ char const* bounce_uri; /**< where to bounce HTTP requests to */
+ char const* webserver_path; /**< location where small HTTP requests are handled from */
} _ios,*ios;
/* MIO SOCKET HANDLERS */
@@ -501,7 +502,7 @@
void mio_close(mio m);
/* Writes an xmlnode to the socket */
-void mio_write(mio m, xmlnode stanza, char *buffer, int len);
+void mio_write(mio m, xmlnode stanza, char const* buffer, int len);
/* write the root element to a mio stream */
void mio_write_root(mio m, xmlnode root, int stream_type);
@@ -529,6 +530,9 @@
#define mio_ip(m) (m ? m->peer_ip : NULL)
#define mio_connect_errmsg(m) (m->connect_errmsg)
+// where to bounce a HTTP GET request to if not otherwise configured
+#define HTTP_BOUNCE_URI "http://jabberd.org/get-bounce"
+
/*-----------------
* Access controll
*-----------------*/
Modified: branches/RELEASE-1_6_1/jabberd/mio.cc
==============================================================================
--- branches/RELEASE-1_6_1/jabberd/mio.cc Tue Nov 25 23:55:44 2008 (r1543)
+++ branches/RELEASE-1_6_1/jabberd/mio.cc Mon Dec 8 17:16:50 2008 (r1544)
@@ -1117,8 +1117,9 @@
pth_yield(NULL);
}
- /* where to bounce HTTP requests to */
+ // HTTP configuration
mio__data->bounce_uri = pstrdup(mio__data->p, xmlnode_get_data(xmlnode_get_list_item(xmlnode_get_tags(io, "bounce", namespaces, temp_pool), 0)));
+ mio__data->webserver_path = pstrdup(mio__data->p, xmlnode_get_data(xmlnode_get_list_item(xmlnode_get_tags(io, "mini-webserver", namespaces, temp_pool), 0)));
if (karma != NULL) {
mio__data->k->val = j_atoi(xmlnode_get_data(xmlnode_get_list_item(xmlnode_get_tags(karma, "init", namespaces, temp_pool), 0)), KARMA_INIT);
@@ -1276,7 +1277,7 @@
* @param buffer pointer to a buffer of characters, that should be written to the connection
* @param len number of bytes contained in the buffer, that should be written (-1 to write a zero terminated string contained in the buffer)
*/
-void mio_write(mio m, xmlnode stanza, char *buffer, int len) {
+void mio_write(mio m, xmlnode stanza, char const* buffer, int len) {
mio_wbq newwbq;
pool p;
Modified: branches/RELEASE-1_6_1/jabberd/mio_xml.cc
==============================================================================
--- branches/RELEASE-1_6_1/jabberd/mio_xml.cc Tue Nov 25 23:55:44 2008 (r1543)
+++ branches/RELEASE-1_6_1/jabberd/mio_xml.cc Mon Dec 8 17:16:50 2008 (r1544)
@@ -39,6 +39,7 @@
*/
#include <jabberd.h>
+#include <fstream>
/* defined in mio.c */
extern ios mio__data;
@@ -321,22 +322,127 @@
/* init the parser if this is the first read call */
if (m->parser == NULL) {
_mio_xstream_init(m);
+
/* XXX pretty big hack here, if the initial read contained a nul, assume nul-packet-terminating format stream */
- if((nul = strchr(buf,'\0')) != NULL && (nul - buf) < bufsz)
- {
+ if((nul = strchr(buf,'\0')) != NULL && (nul - buf) < bufsz) {
m->type = type_NUL;
nul[-2] = ' '; /* assume it's .../>0 and make the stream open again */
}
- /* XXX another big hack/experiment, for bypassing dumb proxies */
- if(*buf == 'P')
+
+ // Check for HTTP requests, extract frist line for that reason
+ std::string buffer_data(buf, bufsz);
+ std::istringstream buffer_stream(buffer_data);
+ std::string first_line;
+ std::getline(buffer_stream, first_line);
+
+ // PUT/POST requests are a legacy hack to bypass some HTTP proxies
+ // Note: Most HTTP proxies do not forward these PUT/POST requests
+ // of Jabber. Using proxy CONNECT with a jabberd listening on port
+ // 443 seems to work better.
+ if (first_line.substr(0, 1) == "P") {
m->type = type_HTTP;
+ }
+
+ // GET requests: first check if we do serve our own file, else we might
+ // have been configured to forward the request to some URI.
+ if (first_line.substr(0, 4) == "GET ") {
+ // extract path and protocol
+ std::istringstream first_line_stream(first_line.substr(4));
+ std::string request_path;
+ std::string request_protocol;
+ first_line_stream >> request_path >> request_protocol;
+ log_debug2(ZONE, LOGT_IO, "handling HTTP-GET path=%s, protocol=%s", request_path.c_str(), request_protocol.c_str());
+
+ // internal mini webserver enabled?
+ if (mio__data->webserver_path) {
+ char request_path_copy[1024] = "";
+ snprintf(request_path_copy, sizeof(request_path_copy), "%s", request_path.c_str());
+ request_path_copy[sizeof(request_path_copy)-1] = 0; // make sure the string is terminated
+ std::string request_basename = ::basename(request_path_copy);
+ if (request_basename == "/" ||request_basename == "") {
+ request_basename = "index.html";
+ }
+ log_debug2(ZONE, LOGT_IO, "GET request processing for file %s", request_basename.c_str());
+
+ // check that the file is not a directory
+ std::string filename = std::string(mio__data->webserver_path) + "/" + request_basename;
+ struct stat stat_buf;
+ int stat_ret = ::stat(filename.c_str(), &stat_buf);
+ if (stat_ret == 0 && S_ISREG(stat_buf.st_mode)) {
+ // try to open file
+ std::ifstream file(filename.c_str(), std::ifstream::binary);
+ if (file.is_open()) {
+ // get the file size
+ file.seekg(0, std::ios::end);
+ std::streampos file_size = file.tellg();
+ file.seekg(0, std::ios::beg);
+
+ if (file_size >= 1024*1024) {
+ log_error(NULL, "mini-webserver tried to return %s (size: %i B) which is bigger than 1 MiB. Not able to handle that big files", filename.c_str(), static_cast<int>(file_size));
+
+ std::string message("Request entity too large\r\n");
+
+ std::ostringstream http_result;
+ http_result << (request_protocol == "" || request_protocol == "HTTP/1.0" ? "HTTP/1.0" : "HTTP/1.1") << " 413 Request entity too large\r\n";
+ http_result << "Server: " PACKAGE " " VERSION "\r\n";
+ http_result << "Connection: close\r\n";
+ http_result << "Content-Length: " << message.length() << "\r\n";
+ http_result << "Content-Type: text/plain; charset=utf-8\r\n";
+ http_result << "\r\n";
+ http_result << message;
+
+ mio_write(m, NULL, http_result.str().c_str(), http_result.str().length());
+ mio_close(m);
+ } else {
+ if (file_size >= 1024*100) {
+ log_warn(NULL, "Warning: mini-webserver is returning %s (size: %i B). You should not use jabberd to handle big files!", filename.c_str(), static_cast<int>(file_size));
+ }
+
+ char *result_buffer = new char[file_size];
+
+ file.read(result_buffer, file_size);
+
+ std::ostringstream http_result;
+ http_result << (request_protocol == "" || request_protocol == "HTTP/1.0" ? "HTTP/1.0" : "HTTP/1.1") << " 200 OK\r\n";
+ http_result << "Server: " PACKAGE " " VERSION "\r\n";
+ http_result << "Connection: close\r\n";
+ http_result << "Content-Length: " << file_size << "\r\n";
+ http_result << "Content-Type: text/html\r\n";
+ http_result << "\r\n";
+ http_result << std::string(result_buffer, file_size);
+
+ delete[] result_buffer;
+
+ mio_write(m, NULL, http_result.str().c_str(), http_result.str().length());
+ mio_close(m);
+ }
+
+ // close the file
+ file.close();
+
+ // we handled the request
+ return;
+ }
+ }
+ }
+
+ // no document returned, send a bounce
+ std::ostringstream http_result;
+ http_result << (request_protocol == "" || request_protocol == "HTTP/1.0" ? "HTTP/1.0" : "HTTP/1.1") << " 301 Moved permanently\r\n";
+ http_result << "Server: " PACKAGE " " VERSION "\r\n";
+ http_result << "Connection: close\r\n";
+ // bounce to a configured host?
+ if (mio__data->bounce_uri) {
+ http_result << "Location: " << mio__data->bounce_uri << "\r\n";
+ } else {
+ http_result << "Location: " HTTP_BOUNCE_URI "\r\n";
+ }
+ http_result << "\r\n";
- /* Bounce HTTP-GET-Requests to the configured host */
- if(*buf == 'G' && mio__data->bounce_uri != NULL) {
- mio_write(m, NULL, "HTTP/1.1 301 Moved permanently\r\nServer: " PACKAGE " " VERSION "\r\nConnection: close\r\nLocation: ", -1);
- mio_write(m, NULL, mio__data->bounce_uri, -1);
- mio_write(m, NULL, "\r\n\r\n", -1);
+ mio_write(m, NULL, http_result.str().c_str(), http_result.str().length());
mio_close(m);
+
+ // we handled the request now
return;
}
}
More information about the dev
mailing list