The 1.3.24 patch is in Bugzilla, id #8882, but I thought I'd post it here
for completeness.
The patch adds a new RewriteMap type:
RewriteMap MapName tcp:host:port
Since several child processes can connect to a multi-threaded rewrite
engine at once, RewriteLock is not required, and requests to the rewrite
engine are not serialised resulting in increased performance over the
current stdin/stdout implementation.
Cheers,
JT
--
+------------------------------------+------------------------------------+
| James Tait | ICQ# 17834893 |
| MUD programmer and Linux advocate | http://www.wyrddreams.demon.co.uk/ |
+------------------------------------+------------------------------------+
________________________________________________________________________
This email has been scanned for all viruses by the MessageLabs SkyScan
service. For more information on a proactive anti-virus service working
around the clock, around the globe, visit http://www.messagelabs.com
________________________________________________________________________
--- src/modules/standard/mod_rewrite.c Sat Mar 16 23:44:20 2002
+++ /home/jtait/src/apache_1.3.24/src/modules/standard/mod_rewrite.c Wed May 8
+15:18:36 2002
@@ -507,6 +507,11 @@
a2+4, NULL);
}
}
+ else if (strncmp(a2, "tcp:", 4) == 0) {
+ new->type = MAPTYPE_TCP;
+ new->datafile = a2+4;
+ new->checkfile = NULL;
+ }
else {
new->type = MAPTYPE_TXT;
new->datafile = a2;
@@ -2751,6 +2756,17 @@
return NULL;
#endif
}
+ else if (s->type == MAPTYPE_TCP) {
+ if ((value = lookup_map_tcp(r, s->datafile, key)) != NULL) {
+ rewritelog(r, 5, "map lookup OK: map=%s(%s) key=%s -> val=%s",
+ s->name, s->datafile, key, value);
+ return value;
+ }
+ else {
+ rewritelog(r, 5, "map lookup FAILED: map=%s(%s), key=%s",
+ s->name, s->datafile, key);
+ }
+ }
else if (s->type == MAPTYPE_PRG) {
if ((value =
lookup_map_program(r, s->fpin, s->fpout, key)) != NULL) {
@@ -2945,6 +2961,126 @@
}
}
+static char *lookup_map_tcp(request_rec *r, const char *hoststr, char *key)
+{
+ char buf[LONG_STRING_LEN];
+ char c;
+ int i, sock;
+
+ /* create a socket connection to the external program */
+ sock = make_socket_connection(r, hoststr);
+ if (sock == -1) {
+ return NULL;
+ }
+
+ ap_hard_timeout("Send external rewrite request", r);
+ /* write out the request key */
+ i = send(sock, key, strlen(key), 0);
+ if (i != strlen(key)) {
+ ap_kill_timeout(r);
+ return NULL;
+ }
+ ap_reset_timeout(r);
+
+ i = send(sock, "\n", 1, 0);
+ if (i != 1) {
+ ap_kill_timeout(r);
+ return NULL;
+ }
+ ap_kill_timeout(r);
+
+ /* read in the response value */
+ ap_hard_timeout("Receive external rewrite response", r);
+ i = 0;
+ while (recv(sock, &c, 1, 0) == 1 && (i < LONG_STRING_LEN - 1)) {
+ if (c == '\n') {
+ break;
+ }
+ buf[i++] = c;
+ }
+ buf[i] = '\0';
+ ap_pclosesocket(r->pool, sock);
+ ap_kill_timeout(r);
+
+ if (strcasecmp(buf, "NULL") == 0) {
+ return NULL;
+ }
+ else {
+ return ap_pstrdup(r->pool, buf);
+ }
+}
+
+static int make_socket_connection(request_rec *r, const char *hoststr)
+{
+ struct hostent *server_hp;
+ struct sockaddr_in addr;
+ int i, sock, port;
+ char *host;
+ char *portstr;
+
+ memset(&addr, '\0', sizeof(addr));
+ addr.sin_family = AF_INET;
+
+ host = ap_pstrdup(r->pool, hoststr);
+ rewritelog(r, 5, "Extracting port from string: [%s]", host);
+
+ port = 0;
+ portstr = strchr(host, ':');
+ if (portstr != NULL) {
+ *(portstr++) = '\0';
+ rewritelog(r, 5, "Port found: [%s]", portstr);
+ if (ap_isdigit(*portstr)) {
+ port = atoi(portstr);
+ }
+ }
+
+ addr.sin_port = htons(port);
+
+ for (i = 0; host[i] != '\0'; i++) {
+ if(!ap_isdigit(host[i]) && host[i] != '.') {
+ break;
+ }
+ }
+ if (host[i] == '\0') {
+ rewritelog(r, 3, "External rewrite host IP: %s:%d", host, port);
+ addr.sin_addr.s_addr = inet_addr(host);
+ }
+ else {
+ rewritelog(r, 3, "External rewrite hostname: %s:%d", host, port);
+ server_hp = gethostbyname(host);
+ if (host == NULL) {
+ addr.sin_addr.s_addr = 0;
+ }
+ else {
+ addr.sin_addr.s_addr = ((struct in_addr
+*)server_hp->h_addr_list[0])->s_addr;
+ }
+ }
+
+ sock = ap_psocket(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "Unable to create socket");
+ return -1;
+ }
+
+ ap_hard_timeout("External rewriter connect", r);
+ do {
+ i = connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
+#if defined(WIN32) || defined(NETWARE)
+ if (i == SOCKET_ERROR) {
+ errno = WSAGetLastError();
+ }
+#endif /* WIN32 */
+ } while (i == -1 && errno == EINTR);
+ if (i == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Unable to connect to external rewriter on %s:%d",
+ inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+ sock = -1;
+ }
+ ap_kill_timeout(r);
+ return sock;
+}
+
static char *lookup_map_internal(request_rec *r,
char *(*func)(request_rec *, char *),
char *key)
--- src/modules/standard/mod_rewrite.h Wed Mar 13 21:05:34 2002
+++ /home/jtait/src/apache_1.3.24/src/modules/standard/mod_rewrite.h Wed May 8
+15:00:22 2002
@@ -220,6 +220,7 @@
#define MAPTYPE_PRG 1<<2
#define MAPTYPE_INT 1<<3
#define MAPTYPE_RND 1<<4
+#define MAPTYPE_TCP 1<<5
#define ENGINE_DISABLED 1<<0
#define ENGINE_ENABLED 1<<1
@@ -441,6 +442,8 @@
#endif
static char *lookup_map_program(request_rec *r, int fpin,
int fpout, char *key);
+static char *lookup_map_tcp(request_rec *r, const char *hoststr, char *key);
+static int make_socket_connection(request_rec *r, const char *hoststr);
static char *lookup_map_internal(request_rec *r,
char *(*func)(request_rec *r, char *key),
char *key);
--- modules/mappers/mod_rewrite.h Fri Apr 5 21:01:20 2002
+++ /home/jtait/src/httpd-2.0.36/modules/mappers/mod_rewrite.h Tue May 21 10:24:39
+2002
@@ -198,6 +198,7 @@
#define MAPTYPE_PRG 1<<2
#define MAPTYPE_INT 1<<3
#define MAPTYPE_RND 1<<4
+#define MAPTYPE_TCP 1<<5
#define ENGINE_DISABLED 1<<0
#define ENGINE_ENABLED 1<<1
@@ -425,6 +426,8 @@
#endif
static char *lookup_map_program(request_rec *r, apr_file_t *fpin,
apr_file_t *fpout, char *key);
+static char *lookup_map_tcp(request_rec *r, const char *hoststr, char *key);
+static apr_socket_t *make_socket_connection(request_rec *r, const char *hoststr);
static char *lookup_map_internal(request_rec *r,
char *(*func)(request_rec *r, char *key),
char *key);
--- modules/mappers/mod_rewrite.c Mon Apr 22 11:27:01 2002
+++ /home/jtait/src/httpd-2.0.36/modules/mappers/mod_rewrite.c Tue May 21 17:08:59
+2002
@@ -454,6 +454,11 @@
newmap->datafile = a2+4;
newmap->checkfile = a2+4;
}
+ else if (strncmp(a2, "tcp:", 4) == 0) {
+ newmap->type = MAPTYPE_TCP;
+ newmap->datafile = a2+4;
+ newmap->checkfile = NULL;
+ }
else if (strncmp(a2, "int:", 4) == 0) {
newmap->type = MAPTYPE_INT;
newmap->datafile = NULL;
@@ -2780,6 +2785,18 @@
s->name, key);
}
}
+ else if (s->type == MAPTYPE_TCP) {
+ if ((value =
+ lookup_map_tcp(r, s->datafile, key)) != NULL) {
+ rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s",
+ s->name, key, value);
+ return value;
+ }
+ else {
+ rewritelog(r, 5, "map lookup FAILED: map=%s key=%s",
+ s->name, key);
+ }
+ }
else if (s->type == MAPTYPE_INT) {
if ((value = lookup_map_internal(r, s->func, key)) != NULL) {
rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s",
@@ -2982,6 +2999,100 @@
}
}
+static char *lookup_map_tcp(request_rec *r, const char *hoststr, char *key)
+{
+ char buf[LONG_STRING_LEN];
+ char c;
+ int i;
+ apr_socket_t *sock;
+ apr_status_t status;
+ apr_size_t len;
+
+ /* create a socket connection to the external program */
+ sock = make_socket_connection(r, hoststr);
+ if (sock == NULL) {
+ return NULL;
+ }
+
+ len = strlen(key);
+
+ /* write out the request key */
+ if ((status = apr_send(sock, key, &len)) != APR_SUCCESS || len != strlen(key)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, "Unable to write out rewrite
+request");
+ apr_socket_close(sock);
+ return NULL;
+ }
+ len = 1;
+ if ((status = apr_send(sock, "\n", &len)) != APR_SUCCESS || len != 1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, "Premature termination of
+rewrite request");
+ apr_socket_close(sock);
+ return NULL;
+ }
+
+ /* read in the response value */
+ i = 0;
+ len = 1;
+ while ((status = apr_recv(sock, &c, &len)) == APR_SUCCESS && len == 1 && (i <
+LONG_STRING_LEN - 1)) {
+ if (c == '\n') {
+ break;
+ }
+ buf[i++] = c;
+ }
+ if (status != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, "Premature end of rewrite
+response");
+ apr_snprintf(buf, sizeof(buf), "NULL");
+ }
+ else {
+ buf[i] = '\0';
+ }
+ apr_socket_close(sock);
+
+ if (strcasecmp(buf, "NULL") == 0) {
+ return NULL;
+ }
+ else {
+ return apr_pstrdup(r->pool, buf);
+ }
+}
+
+static apr_socket_t *make_socket_connection(request_rec *r, const char *hoststr)
+{
+ apr_uri_t uri;
+ apr_status_t status;
+ apr_socket_t *sock;
+ apr_sockaddr_t *addr;
+
+ if ((status = apr_uri_parse_hostinfo(r->pool, hoststr, &uri)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, "Unable to parse hostname:
+%s", hoststr);
+ return NULL;
+ }
+
+ if ((status = apr_socket_create(&sock, APR_INET, SOCK_STREAM, r->pool)) !=
+APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, "Unable to create socket");
+ return NULL;
+ }
+
+ if ((status = apr_setsocketopt(sock, APR_SO_TIMEOUT, (int)(r->server->timeout *
+APR_USEC_PER_SEC))) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, "Unable to set socket
+timeout");
+ apr_socket_close(sock);
+ return NULL;
+ }
+
+ if((status = apr_sockaddr_info_get(&addr, uri.hostname, APR_UNSPEC, uri.port, 0,
+r->pool)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, "Unable to resolve host
+details");
+ apr_socket_close(sock);
+ return NULL;
+ }
+
+ if ((status = apr_connect(sock, addr)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+ "Unable to connect to external rewriter on :");
+ apr_socket_close(sock);
+ return NULL;
+ }
+ return sock;
+}
+
static char *lookup_map_internal(request_rec *r,
char *(*func)(request_rec *, char *),
char *key)