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)

Reply via email to