Re: squid3 comments

From: Tsantilas Christos <chtsanti@dont-contact.us>
Date: Wed, 28 Feb 2007 21:06:03 +0200

Tsantilas Christos wrote:
>
>
> As an example of such changes I am attaching the rewritten
> parseHttpRequest, prepareTransparentURL and prepareAcceleratedURL
>
Sorry to all
 the code I send in previous mail will not compile. I am sending it
again. Needs some more testing to be sure that it is OK....

int
internalCheckn(const char *urlpath,int size)
{
    if(size<16)
        return 0;
    return (0 == strncmp(urlpath, "/squid-internal-", 16));
}

char *memstr(char *s,const char *pattern,int s_len){
    int i,k;
    int p_len=strlen(pattern);
    for(i=0;i<=s_len-p_len;i++){
      k=0;
      while(k<p_len){
          if(s[i+k] != pattern[k])
             break;
          k++;
      }
      if(k==p_len)
           return s+i;
    }
    return NULL;
}

static void
prepareAcceleratedURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, char *url, int url_size, const char *req_hdr)
{
    int vhost = conn->port->vhost;
    int vport = conn->port->vport;
    int uri_sz = 0, tmpsz = 0;
    char *host,*s;

    http->flags.accel = 1;

    /* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */

    if (url_size >= 15 && strncasecmp(url, "cache_object://", 15) == 0)
        return; /* already in good shape */

    if (*url != '/') {
        if (conn->port->vhost)
            return; /* already in good shape */

        /* else we need to ignore the host name */
        s = NULL;
        s = memstr(url, "//", url_size);
        if(s)
            url_size -= ((s-url) + 2);
        url = s + 2;

#if SHOULD_REJECT_UNKNOWN_URLS

        if (!url)
            return parseHttpRequestAbort(conn, "error:invalid-request");

#endif

        if (url){
            s=(char *)memchr(url,'/',url_size);
            if(s)
                url_size -= s-url;
            url=s;
        }

        if (!url){
            url = (char *) "/";
            url_size = 1;
        }
    }

    if (internalCheckn(url,url_size)) {
        /* prepend our name & port */
        s = (char *)xcalloc(url_size+1,1);
        memcpy(s,url,url_size);
        s[url_size]='\0';
        http->uri = xstrdup(internalLocalUri(NULL, s));
        xfree(s);
        return;
    }

    if (vhost && (host = mime_get_header(req_hdr, "Host")) != NULL) {
        uri_sz = url_size + 32 + Config.appendDomainLen +
                     strlen(host);
        http->uri = (char *)xcalloc(uri_sz, 1);
        tmpsz = snprintf(http->uri, uri_sz, "%s://%s",
                 conn->port->protocol, host);
    } else if (conn->port->defaultsite) {
        uri_sz = url_size + 32 + Config.appendDomainLen +
                     strlen(conn->port->defaultsite);
        http->uri = (char *)xcalloc(uri_sz, 1);
        tmpsz = snprintf(http->uri, uri_sz, "%s://%s",
                 conn->port->protocol, conn->port->defaultsite);
    } else if (vport == -1) {
        /* Put the local socket IP address as the hostname. */
        uri_sz = url_size + 32 + Config.appendDomainLen;
        http->uri = (char *)xcalloc(uri_sz, 1);
        tmpsz = snprintf(http->uri, uri_sz, "%s://%s:%d",
                 http->getConn()->port->protocol,
                 inet_ntoa(http->getConn()->me.sin_addr),
                 ntohs(http->getConn()->me.sin_port));
    } else if (vport > 0) {
        /* Put the local socket IP address as the hostname, but static port */
        uri_sz = url_size + 32 + Config.appendDomainLen;
        http->uri = (char *)xcalloc(uri_sz, 1);
        tmpsz = snprintf(http->uri, uri_sz, "%s://%s:%d",
                 http->getConn()->port->protocol,
                 inet_ntoa(http->getConn()->me.sin_addr),
                 vport);
    }
    else
         return;

    /*OK Append the url at the end of uri and we are OK....*/
    uri_sz -= tmpsz;
    url_size = XMIN(uri_sz - 1, url_size);
    memcpy(http->uri+tmpsz, url , url_size);
    http->uri[tmpsz+url_size] = '\0';
    debug(33, 5) ("ACCEL VHOST REWRITE: '%s'\n", http->uri);
}

static void
prepareTransparentURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, char *url, int url_size, const char *req_hdr)
{
    char *host;
    int uri_sz = 0, tmpsz = 0;
    http->flags.transparent = 1;

    if (*url != '/')
        return; /* already in good shape */

    /* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */
    if ((host = mime_get_header(req_hdr, "Host")) != NULL) {
        uri_sz = url_size + 32 + Config.appendDomainLen +
             strlen(host);
        http->uri = (char *)xcalloc(uri_sz, 1);
        tmpsz = snprintf(http->uri, uri_sz, "%s://%s",
                             conn->port->protocol, host);
    } else {
        /* Put the local socket IP address as the hostname. */
        uri_sz = url_size + 32 + Config.appendDomainLen;
        http->uri = (char *)xcalloc(uri_sz, 1);
        tmpsz = snprintf(http->uri, uri_sz, "%s://%s:%d",
                            http->getConn()->port->protocol,
                            inet_ntoa(http->getConn()->me.sin_addr),
                            ntohs(http->getConn()->me.sin_port));
    }
    uri_sz -= tmpsz;
    url_size = XMIN(uri_sz - 1, url_size);
    memcpy(http->uri+tmpsz, url , url_size);
    http->uri[tmpsz+url_size] = '\0';
    debug(33, 5) ("TRANSPARENT HOST REWRITE: '%s'\n", http->uri);
}

/*
 * parseHttpRequest()
 *
 * Returns
 * NULL on incomplete requests
 * a ClientSocketContext structure on success or failure.
 * Sets result->flags.parsed_ok to 0 if failed to parse the request.
 * Sets result->flags.parsed_ok to 1 if we have a good request.
 */
static ClientSocketContext *
parseHttpRequest(ConnStateData::Pointer & conn, HttpParser *hp, method_t * method_p, HttpVersion *http_ver)
{
    char *url = NULL;
    int url_size = 0;
    char *req_hdr = NULL;
    char *end;
    size_t req_sz;
    ClientHttpRequest *http;
    ClientSocketContext *result;
    StoreIOBuffer tempBuffer;
    int r;

    /* pre-set these values to make aborting simpler */
    *method_p = METHOD_NONE;

    /* Attempt to parse the first line; this'll define the method, url, version and header begin */
    r = HttpParserParseReqLine(hp);
    if (r == 0) {
        debug(33, 5) ("Incomplete request, waiting for end of request line\n");
    return NULL;
    }
    if (r == -1) {
        return parseHttpRequestAbort(conn, "error:invalid-request");
    }
    /* Request line is valid here .. */
    *http_ver = HttpVersion(hp->v_maj, hp->v_min);

    /* This call scans the entire request, not just the headers */
    if (hp->v_maj > 0) {
        if ((req_sz = headersEnd(hp->buf, hp->bufsiz)) == 0) {
            debug(33, 5) ("Incomplete request, waiting for end of headers\n");
            return NULL;
        }
    } else {
        debug(33, 3) ("parseHttpRequest: Missing HTTP identifier\n");
        req_sz = HttpParserReqSz(hp);
    }

    /* We know the whole request is in hp->buf now */

    assert(req_sz <= (size_t) hp->bufsiz);
    /* Will the following be true with HTTP/0.9 requests? probably not .. */
    /* So the rest of the code will need to deal with '0'-byte headers (ie, none, so don't try parsing em) */
    assert(req_sz > 0);
    hp->hdr_end = req_sz - 1;
    hp->hdr_start = hp->req_end + 1;

    /* Enforce max_request_size */
    if (req_sz >= Config.maxRequestHeaderSize) {
        debug(33, 5) ("parseHttpRequest: Too large request\n");
        return parseHttpRequestAbort(conn, "error:request-too-large");
    }

    /* Set method_p */
    *method_p = HttpRequestMethod(&hp->buf[hp->m_start], &hp->buf[hp->m_end]);
    if (*method_p == METHOD_NONE) {
    /* XXX need a way to say "this many character length string" */
        debug(33, 1) ("clientParseRequestMethod: Unsupported method in request '%s'\n", hp->buf);
    /* XXX where's the method set for this error? */
        return parseHttpRequestAbort(conn, "error:unsupported-request-method");
    }

    /*
     * Process headers after request line
     * TODO: Use httpRequestParse here.
     */
    /* XXX this code should be modified to take a const char * later! */
    req_hdr = (char *) hp->buf + hp->req_end + 1;
    debug(33, 3) ("parseHttpRequest: req_hdr = {%s}\n", req_hdr);
    end = (char *) hp->buf + hp->hdr_end;
    debug(33, 3) ("parseHttpRequest: end = {%s}\n", end);

    if (strstr(req_hdr, "\r\r\n")) {
        debug(33, 1) ("WARNING: suspicious HTTP request contains double CR\n");
        return parseHttpRequestAbort(conn, "error:double-CR");
    }

    debug(33, 3) ("parseHttpRequest: prefix_sz = %d, req_line_sz = %d\n",
                  (int) HttpParserRequestLen(hp), HttpParserReqSz(hp));

    /* Ok, all headers are received */
    http = new ClientHttpRequest(conn);

    http->req_sz = HttpParserRequestLen(hp);
    result = ClientSocketContextNew(http);
    tempBuffer.data = result->reqbuf;
    tempBuffer.length = HTTP_REQBUF_SZ;

    ClientStreamData newServer = new clientReplyContext(http);
    ClientStreamData newClient = result;
    clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
                     clientReplyStatus, newServer, clientSocketRecipient,
                     clientSocketDetach, newClient, tempBuffer);

    debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n",
                  (hp->buf) + hp->hdr_start);

    url = (char *)(hp->buf + hp->u_start);
    url_size = hp->u_end - hp->u_start + 1;

#if THIS_VIOLATES_HTTP_SPECS_ON_URL_TRANSFORMATION
/*url is not \0 terminated. this code if realy needed must rewritten*/
    if ((t = strchr(url, '#'))) /* remove HTML anchors */
        *t = '\0';

#endif

    /* Rewrite the URL in transparent or accelerator mode */
    if (conn->transparent()) {
        prepareTransparentURL(conn, http, url, url_size, req_hdr);
    } else if (conn->port->accel) {
         prepareAcceleratedURL(conn, http, url, url_size, req_hdr);
    } else if (internalCheckn(url, url_size)) {
        /* prepend our name & port */
        char *s = (char *)xmalloc(url_size + 16);
        memcpy(s, url, url_size);
        s[url_size] = '\0';
        http->uri = xstrdup(internalLocalUri(NULL, s));
        http->flags.accel = 1;
        xfree(s);
    }

    if (!http->uri) {
        /* No special rewrites have been applied above, use the
         * requested url. may be rewritten later, so make extra room */
        int u_sz = url_size + Config.appendDomainLen + 5;
        http->uri = (char *)xcalloc(u_sz, 1);
        memcpy(http->uri, url, url_size);
        http->uri[url_size]='\0';
    }

    setLogUri(http, http->uri);
    debug(33, 5) ("parseHttpRequest: Complete request received\n");
    result->flags.parsed_ok = 1;
    return result;
}
Received on Wed Feb 28 2007 - 12:04:38 MST

This archive was generated by hypermail pre-2.1.9 : Thu Mar 01 2007 - 12:00:02 MST