Example #1
0
void
urnStart(request_t * r, StoreEntry * e)
{
    LOCAL_ARRAY(char, urlres, 4096);
    request_t *urlres_r = NULL;
    const char *t;
    char *host;
    UrnState *urnState;
    StoreEntry *urlres_e;
    ErrorState *err;
    debug(52, 3) ("urnStart: '%s'\n", storeUrl(e));
    CBDATA_INIT_TYPE(UrnState);
    urnState = cbdataAlloc(UrnState);
    urnState->entry = e;
    urnState->request = requestLink(r);
    storeLockObject(urnState->entry);
    if (strncasecmp(strBuf(r->urlpath), "menu.", 5) == 0) {
	char *new_path = xstrdup(strBuf(r->urlpath) + 5);
	urnState->flags.force_menu = 1;
	stringReset(&r->urlpath, new_path);
	xfree(new_path);
    }
    if ((t = strChr(r->urlpath, ':')) != NULL) {
	strSet(r->urlpath, t, '\0');
	host = xstrdup(strBuf(r->urlpath));
	strSet(r->urlpath, t, ':');
    } else {
	host = xstrdup(strBuf(r->urlpath));
    }
    snprintf(urlres, 4096, "http://%s/uri-res/N2L?urn:%s", host, strBuf(r->urlpath));
    safe_free(host);
    urlres_r = urlParse(METHOD_GET, urlres);
    if (urlres_r == NULL) {
	debug(52, 3) ("urnStart: Bad uri-res URL %s\n", urlres);
	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
	err->url = xstrdup(urlres);
	errorAppendEntry(e, err);
	return;
    }
    httpHeaderPutStr(&urlres_r->header, HDR_ACCEPT, "text/plain");
    if ((urlres_e = storeGetPublic(urlres, METHOD_GET)) == NULL) {
	urlres_e = storeCreateEntry(urlres, urlres, null_request_flags, METHOD_GET);
	urnState->sc = storeClientListAdd(urlres_e, urnState);
	fwdStart(-1, urlres_e, urlres_r);
    } else {
	storeLockObject(urlres_e);
	urnState->sc = storeClientListAdd(urlres_e, urnState);
    }
    urnState->urlres_e = urlres_e;
    urnState->urlres_r = requestLink(urlres_r);
    storeClientCopy(urnState->sc, urlres_e,
	0,
	0,
	4096,
	memAllocate(MEM_4K_BUF),
	urnHandleReply,
	urnState);
}
Example #2
0
static void
icapProcessHttpReplyHeader(IcapStateData * icap, const char *buf, int size)
{
    if (NULL == icap->httpState) {
	icap->httpState = cbdataAlloc(HttpStateData);
	icap->httpState->request = requestLink(icap->request);
	icap->httpState->orig_request = requestLink(icap->request);
	icap->httpState->entry = icap->respmod.entry;
	storeLockObject(icap->httpState->entry);	/* lock it */
    }
    httpProcessReplyHeader(icap->httpState, buf, size);
    if (2 == icap->httpState->reply_hdr_state)
	EBIT_CLR(icap->httpState->entry->flags, ENTRY_FWD_HDR_WAIT);
}
Example #3
0
static void
asnCacheStart(int as)
{
    LOCAL_ARRAY(char, asres, 4096);
    StoreEntry *e;
    request_t *req;
    ASState *asState;
    method_t *method_get;
    method_get = urlMethodGetKnownByCode(METHOD_GET);
    asState = cbdataAlloc(ASState);
    debug(53, 3) ("asnCacheStart: AS %d\n", as);
    snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as);
    asState->as_number = as;
    req = urlParse(method_get, asres);
    assert(NULL != req);
    asState->request = requestLink(req);
    if ((e = storeGetPublic(asres, method_get)) == NULL) {
	e = storeCreateEntry(asres, null_request_flags, method_get);
	asState->sc = storeClientRegister(e, asState);
	fwdStart(-1, e, asState->request);
    } else {
	storeLockObject(e);
	asState->sc = storeClientRegister(e, asState);
    }
    asState->entry = e;
    asState->seen = 0;
    asState->offset = 0;
    storeClientRef(asState->sc,
	e,
	asState->seen,
	asState->offset,
	SM_PAGE_SIZE,
	asHandleReply,
	asState);
}
Example #4
0
/* starts swap out sequence for the digest */
static void
storeDigestRewriteStart(void *datanotused)
{
    request_flags flags;
    char *url;
    StoreEntry *e;

    assert(store_digest);
    /* prevent overlapping if rewrite schedule is too tight */
    if (sd_state.rewrite_lock) {
	debug(71, 1) ("storeDigestRewriteStart: overlap detected, consider increasing rewrite period\n");
	return;
    }
    debug(71, 2) ("storeDigestRewriteStart: start rewrite #%d\n", sd_state.rewrite_count + 1);
    /* make new store entry */
    url = internalStoreUri("/squid-internal-periodic/", StoreDigestFileName);
    flags = null_request_flags;
    flags.cachable = 1;
    e = storeCreateEntry(url, flags, METHOD_GET);
    assert(e);
    sd_state.rewrite_lock = cbdataAlloc(generic_cbdata);
    sd_state.rewrite_lock->data = e;
    debug(71, 3) ("storeDigestRewriteStart: url: %s key: %s\n", url, storeKeyText(e->hash.key));
    e->mem_obj->request = requestLink(urlParse(METHOD_GET, url));
    /* wait for rebuild (if any) to finish */
    if (sd_state.rebuild_lock) {
	debug(71, 2) ("storeDigestRewriteStart: waiting for rebuild to finish.\n");
	return;
    }
    storeDigestRewriteResume();
}
Example #5
0
void
peerSelect(request_t * request,
		   StoreEntry * entry,
		   PSC * callback,
		   void *callback_data)
{
	ps_state *psstate;
	if (entry)
		debug(44, 3) ("peerSelect: %s\n", storeUrl(entry));
	else
		debug(44, 3) ("peerSelect: %s\n", RequestMethods[request->method].str);
	psstate = cbdataAlloc(ps_state);
	psstate->request = requestLink(request);
	psstate->entry = entry;
	psstate->callback = callback;
	psstate->callback_data = callback_data;
	psstate->direct = DIRECT_UNKNOWN;
#if USE_CACHE_DIGESTS
	request->hier.peer_select_start = current_time;
#endif
	if (psstate->entry)
		storeLockObject(psstate->entry);
	cbdataLock(callback_data);
	peerSelectFoo(psstate);
}
Example #6
0
int
errorMapStart(const errormap * map, request_t * client_req, HttpReply * reply, const char *aclname, ERRMAPCB * callback, void *callback_data)
{
    char squid_error[100];
    int len = 0;
    const char *errorUrl;
    ErrorMapState *state;
    const char *tmp;
    http_status status;
    request_t *req;
    HttpHeaderPos hdrpos;
    HttpHeaderEntry *hdr;

    if (!client_req || !reply)
	return 0;

    status = reply->sline.status;

    tmp = httpHeaderGetStr(&reply->header, HDR_X_SQUID_ERROR);
    squid_error[0] = '\0';
    if (tmp) {
	xstrncpy(squid_error, tmp, sizeof(squid_error));
	len = strcspn(squid_error, " ");
    }
    squid_error[len] = '\0';
    errorUrl = getErrorMap(map, status, squid_error, aclname);
    if (!errorUrl)
	return 0;
    req = urlParse(urlMethodGetKnownByCode(METHOD_GET), (char *) errorUrl);
    if (!req) {
	debug(0, 0) ("errorMapStart: Invalid error URL '%s'\n", errorUrl);
	return 0;
    }
    req->urlgroup = xstrdup("error");

    state = cbdataAlloc(ErrorMapState);
    state->req = requestLink(req);
    state->e = storeCreateEntry(errorUrl, req->flags, req->method);
    state->sc = storeClientRegister(state->e, state);
    state->callback = callback;
    state->callback_data = callback_data;
    cbdataLock(callback_data);

    hdrpos = HttpHeaderInitPos;
    while ((hdr = httpHeaderGetEntry(&client_req->header, &hdrpos)) != NULL) {
	if (CBIT_TEST(client_headers, hdr->id))
	    httpHeaderAddClone(&req->header, hdr);
    }
    hdrpos = HttpHeaderInitPos;
    while ((hdr = httpHeaderGetEntry(&reply->header, &hdrpos)) != NULL) {
	if (CBIT_TEST(server_headers, hdr->id))
	    httpHeaderAddClone(&req->header, hdr);
    }
    httpHeaderPutInt(&req->header, HDR_X_ERROR_STATUS, (int) reply->sline.status);
    httpHeaderPutStr(&req->header, HDR_X_REQUEST_URI, urlCanonical(client_req));

    fwdStart(-1, state->e, req);
    storeClientRef(state->sc, state->e, 0, 0, SM_PAGE_SIZE, errorMapFetchHeaders, state);
    return 1;
}
Example #7
0
void
netdbExchangeStart(void *data)
{
#if USE_ICMP
    peer *p = data;
    char *uri;
    netdbExchangeState *ex;
    method_t *method_get;
    CBDATA_INIT_TYPE(netdbExchangeState);
    ex = cbdataAlloc(netdbExchangeState);
    cbdataLock(p);
    ex->p = p;
    uri = internalRemoteUri(p->host, p->http_port, "/squid-internal-dynamic/", "netdb");
    debug(38, 3) ("netdbExchangeStart: Requesting '%s'\n", uri);
    assert(NULL != uri);
    method_get = urlMethodGetKnownByCode(METHOD_GET);
    ex->r = urlParse(method_get, uri);
    if (NULL == ex->r) {
        debug(38, 1) ("netdbExchangeStart: Bad URI %s\n", uri);
        return;
    }
    requestLink(ex->r);
    assert(NULL != ex->r);
    httpBuildVersion(&ex->r->http_ver, 1, 0);
    ex->e = storeCreateEntry(uri, null_request_flags, method_get);
    assert(NULL != ex->e);
    ex->sc = storeClientRegister(ex->e, ex);
    storeClientRef(ex->sc, ex->e, ex->seen, ex->used, SM_PAGE_SIZE,
                   netdbExchangeHandleReply, ex);
    ex->r->flags.loopdetect = 1;	/* cheat! -- force direct */
    if (p->login)
        xstrncpy(ex->r->login, p->login, MAX_LOGIN_SZ);
    fwdStart(-1, ex->e, ex->r);
#endif
}
Example #8
0
static void
mimeLoadIconFile(const char *icon)
{
    int fd;
    int n;
    request_flags flags;
    struct stat sb;
    StoreEntry *e;
    LOCAL_ARRAY(char, path, MAXPATHLEN);
    LOCAL_ARRAY(char, url, MAX_URL);
    char *buf;
    const char *type = mimeGetContentType(icon);
    HttpReply *reply;
    if (type == NULL)
	fatal("Unknown icon format while reading mime.conf\n");
    buf = internalLocalUri("/squid-internal-static/icons/", icon);
    xstrncpy(url, buf, MAX_URL);
    if (storeGetPublic(url, METHOD_GET))
	return;
    snprintf(path, MAXPATHLEN, "%s/%s", Config.icons.directory, icon);
    fd = file_open(path, O_RDONLY);
    if (fd < 0) {
	debug(25, 0) ("mimeLoadIconFile: %s: %s\n", path, xstrerror());
	return;
    }
    if (fstat(fd, &sb) < 0) {
	debug(50, 0) ("mimeLoadIconFile: FD %d: fstat: %s\n", fd, xstrerror());
	return;
    }
    flags = null_request_flags;
    flags.cachable = 1;
    e = storeCreateEntry(url,
	url,
	flags,
	METHOD_GET);
    assert(e != NULL);
    storeSetPublicKey(e);
    storeBuffer(e);
    e->mem_obj->request = requestLink(urlParse(METHOD_GET, url));
    httpReplyReset(reply = e->mem_obj->reply);
    httpReplySetHeaders(reply, 1.0, HTTP_OK, NULL,
	type, (int) sb.st_size, sb.st_mtime, -1);
    reply->cache_control = httpHdrCcCreate();
    httpHdrCcSetMaxAge(reply->cache_control, 86400);
    httpHeaderPutCc(&reply->header, reply->cache_control);
    httpReplySwapOut(reply, e);
    reply->hdr_sz = e->mem_obj->inmem_hi;	/* yuk */
    /* read the file into the buffer and append it to store */
    buf = memAllocate(MEM_4K_BUF);
    while ((n = read(fd, buf, 4096)) > 0)
	storeAppend(e, buf, n);
    file_close(fd);
    EBIT_SET(e->flags, ENTRY_SPECIAL);
    storeBufferFlush(e);
    storeComplete(e);
    storeTimestampsSet(e);
    debug(25, 3) ("Loaded icon %s\n", url);
    storeUnlockObject(e);
    memFree(buf, MEM_4K_BUF);
}
Example #9
0
static void
peerCountMcastPeersStart(void *data)
{
    peer *p = data;
    ps_state *psstate;
    StoreEntry *fake;
    MemObject *mem;
    icp_common_t *query;
    int reqnum;
    method_t *method_get;
    LOCAL_ARRAY(char, url, MAX_URL);
    assert(p->type == PEER_MULTICAST);
    method_get = urlMethodGetKnownByCode(METHOD_GET);
    p->mcast.flags.count_event_pending = 0;
    snprintf(url, MAX_URL, "http://%s/", inet_ntoa(p->in_addr.sin_addr));
    fake = storeCreateEntry(url, null_request_flags, method_get);
    psstate = cbdataAlloc(ps_state);
    psstate->request = requestLink(urlParse(method_get, url));
    psstate->entry = fake;
    psstate->callback = NULL;
    psstate->callback_data = p;
    cbdataLock(psstate->callback_data);
    psstate->ping.start = current_time;
    mem = fake->mem_obj;
    mem->request = requestLink(psstate->request);
    mem->start_ping = current_time;
    mem->ping_reply_callback = peerCountHandleIcpReply;
    mem->ircb_data = psstate;
    mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
    p->mcast.id = mem->id;
    reqnum = icpSetCacheKey(fake->hash.key);
    query = icpCreateMessage(ICP_QUERY, 0, url, reqnum, 0);
    icpUdpSend(theOutIcpConnection,
	&p->in_addr,
	query,
	LOG_ICP_QUERY,
	0);
    fake->ping_status = PING_WAITING;
    eventAdd("peerCountMcastPeersDone",
	peerCountMcastPeersDone,
	psstate,
	Config.Timeout.mcast_icp_query / 1000.0, 1);
    p->mcast.flags.counting = 1;
    peerCountMcastPeersSchedule(p, MCAST_COUNT_RATE);
}
Example #10
0
/*
 * copied from httpReadReply()
 *
 * by the time this is called, the ICAP headers have already
 * been read.
 */
void
icapReadReply(int fd, void *data)
{
    IcapStateData *icap = data;
    StoreEntry *entry = icap->respmod.entry;
    const request_t *request = icap->request;
    int len;
    debug(81, 5) ("icapReadReply: FD %d: icap %p.\n", fd, data);
    if (icap->flags.no_content && !icap->flags.http_server_eof) {	//AI

	return;
    }
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	comm_close(fd);
	return;
    }
    errno = 0;
    statCounter.syscalls.sock.reads++;
    len = memBufRead(fd, &icap->chunk_buf);
    debug(81, 5) ("icapReadReply: FD %d: len %d.\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
	kb_incr(&statCounter.icap.all.kbytes_in, len);
	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
	if (icap->chunk_buf.size < icap->chunk_buf.capacity) {
	    *(icap->chunk_buf.buf + icap->chunk_buf.size) = '\0';
	    debug(81, 9) ("{%s}\n", icap->chunk_buf.buf);
	}
    }
    if (len <= 0) {
	debug(81, 2) ("icapReadReply: FD %d: read failure: %s.\n",
	    fd, xstrerror());
	if (ignoreErrno(errno)) {
	    debug(81, 2) ("icapReadReply: FD %d: ignored errno\n", fd);
	    commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0);
	} else if (entry->mem_obj->inmem_hi == 0) {
	    ErrorState *err;
	    debug(81, 2) ("icapReadReply: FD %d: generating error page\n", fd);
	    err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	    err->request = requestLink((request_t *) request);
	    err->xerrno = errno;
	    errorAppendEntry(entry, err);
	    comm_close(fd);
	} else {
	    debug(81, 2) ("icapReadReply: FD %d: just calling comm_close()\n",
		fd);
	    comm_close(fd);
	}
	return;
    }
    if (icapReadReply2(icap) < 0)
	comm_close(fd);
}
Example #11
0
static inline void modify_request(clientHttpRequest * http)
{
	debug(97, 3)("modify_request: start, uri=[%s]\n", http->uri);
	request_t* old_request = http->request;
	request_t* new_request = urlParse(old_request->method, http->uri);
	safe_free(http->uri);

	if (new_request)
	{
		safe_free(http->uri);
		http->uri = xstrdup(urlCanonical(new_request));
		if(!http->log_uri)
			http->log_uri = xstrdup(urlCanonicalClean(old_request));
		new_request->http_ver = old_request->http_ver;
		httpHeaderAppend(&new_request->header, &old_request->header);
		new_request->client_addr = old_request->client_addr;
		new_request->client_port = old_request->client_port;
#if FOLLOW_X_FORWARDED_FOR
		new_request->indirect_client_addr = old_request->indirect_client_addr;
#endif /* FOLLOW_X_FORWARDED_FOR */
		new_request->my_addr = old_request->my_addr;
		new_request->my_port = old_request->my_port;
		new_request->flags = old_request->flags;
		new_request->flags.redirected = 1;
		if (old_request->auth_user_request)
		{
			new_request->auth_user_request = old_request->auth_user_request;
			authenticateAuthUserRequestLock(new_request->auth_user_request);
		}
		if (old_request->body_reader)
		{
			new_request->body_reader = old_request->body_reader;
			new_request->body_reader_data = old_request->body_reader_data;
			old_request->body_reader = NULL;
			old_request->body_reader_data = NULL;
		}
		new_request->content_length = old_request->content_length;
		if (strBuf(old_request->extacl_log))
			new_request->extacl_log = stringDup(&old_request->extacl_log);
		if (old_request->extacl_user)
			new_request->extacl_user = xstrdup(old_request->extacl_user);
		if (old_request->extacl_passwd)
			new_request->extacl_passwd = xstrdup(old_request->extacl_passwd);
		if(old_request->cc_request_private_data)
		{
			new_request->cc_request_private_data = old_request->cc_request_private_data;
			old_request->cc_request_private_data = NULL;
		}
		requestUnlink(old_request);
		http->request = requestLink(new_request);
	}
}
Example #12
0
/*
 * Function:  errorCon
 *
 * Abstract:  This function creates a ErrorState object.
 */
ErrorState *
errorCon(err_type type, http_status status, request_t * request)
{
    ErrorState *err;
    err = cbdataAlloc(ErrorState);
    err->page_id = type;	/* has to be reset manually if needed */
    err->type = type;
    err->http_status = status;
    if (request != NULL) {
	err->request = requestLink(request);
	err->src_addr = request->client_addr;
    }
    return err;
}
Example #13
0
static void
sslConnectDone(int fdnotused, int status, void *data)
{
    SslStateData *sslState = data;
    request_t *request = sslState->request;
    ErrorState *err = NULL;
    if (status == COMM_ERR_DNS) {
	debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host);
	err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND);
	err->request = requestLink(request);
	err->dnsserver_msg = xstrdup(dns_error_message);
	err->callback = sslErrorComplete;
	err->callback_data = sslState;
	errorSend(sslState->client.fd, err);
    } else if (status != COMM_OK) {
	err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
	err->xerrno = errno;
	err->host = xstrdup(sslState->host);
	err->port = sslState->port;
	err->request = requestLink(request);
	err->callback = sslErrorComplete;
	err->callback_data = sslState;
	errorSend(sslState->client.fd, err);
    } else {
	if (sslState->servers->peer)
	    sslProxyConnected(sslState->server.fd, sslState);
	else
	    sslConnected(sslState->server.fd, sslState);
	commSetTimeout(sslState->server.fd,
	    Config.Timeout.read,
	    sslTimeout,
	    sslState);
#if DELAY_POOLS
	commSetDefer(sslState->server.fd, sslDeferServerRead, sslState);
#endif
    }
}
Example #14
0
static void
sslPeerSelectComplete(FwdServer * fs, void *data)
{
    SslStateData *sslState = data;
    request_t *request = sslState->request;
    peer *g = NULL;
    if (fs == NULL) {
	ErrorState *err;
	err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE);
	err->request = requestLink(sslState->request);
	err->callback = sslErrorComplete;
	err->callback_data = sslState;
	errorSend(sslState->client.fd, err);
	return;
    }
    sslState->servers = fs;
    sslState->host = fs->peer ? fs->peer->host : request->host;
    if (fs->peer == NULL) {
	sslState->port = request->port;
    } else if (fs->peer->http_port != 0) {
	sslState->port = fs->peer->http_port;
    } else if ((g = peerFindByName(fs->peer->host))) {
	sslState->port = g->http_port;
    } else {
	sslState->port = CACHE_HTTP_PORT;
    }
    if (fs->peer) {
	sslState->request->peer_login = fs->peer->login;
	sslState->request->flags.proxying = 1;
    } else {
	sslState->request->flags.proxying = 0;
    }
#if DELAY_POOLS
    /* no point using the delayIsNoDelay stuff since ssl is nice and simple */
    if (g && g->options.no_delay && sslState->delay_id) {
	delayUnregisterDelayIdPtr(&sslState->delay_id);
	sslState->delay_id = 0;
    }
#endif
    hierarchyNote(&sslState->request->hier,
	fs->peer ? fs->code : DIRECT,
	sslState->host);
    commConnectStart(sslState->server.fd,
	sslState->host,
	sslState->port,
	sslConnectDone,
	sslState);
}
Example #15
0
static request_t *
modifyRequestUrlstoreUrl(const char *url)
{
    request_t *new_request = NULL;
    new_request = urlParse(METHOD_GET, (char*)url);
    char *new_storeurl = xstrdup((const char *)url);
    char* str = strchr(new_storeurl, '?');
    if (str) {
        debug(207, 3)("modify_request_url_storeurl rid_question: storeurl=[%s] have question\n", new_storeurl);
        *str = '\0';
    }
    
    new_request->store_url = xstrdup((const char *)new_storeurl); 
    
    debug(207, 3)("after modifyRequestUrlstoreUrl url=%s,storeurl=%s,uri=%s\n",urlCanonical(new_request),new_request->store_url,strBuf(new_request->urlpath));
    return requestLink(new_request);
}
Example #16
0
void
icapConnectOver(int fd, int status, void *data)
{
    ErrorState *err;
    IcapStateData *icap = data;
    debug(81, 3) ("icapConnectOver: FD %d, status=%d\n", fd, status);
    icap->flags.connect_pending = 0;
    if (status < 0) {
	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->xerrno = errno;
	err->request = requestLink(icap->request);
	errorAppendEntry(icap->respmod.entry, err);
	comm_close(fd);
	debug(81, 3) ("icapConnectOver: status < 0, unreachable=1\n");
	icapOptSetUnreachable(icap->current_service);
	return;
    }
    commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
}
Example #17
0
static void
peerMonitorRequest(void *data)
{
	PeerMonitor *pm = data;
	char *url;
	request_t *req;

	if (!cbdataValid(pm->peer))
	{
		cbdataFree(pm);
		return;
	}
	url = pm->peer->monitor.url;
	if (!url)
	{
		cbdataFree(pm);
		return;
	}
	req = urlParse(METHOD_GET, url);
	if (!req)
	{
		debug(DBG, 1) ("peerMonitorRequest: Failed to parse URL '%s' for cache_peer %s\n", url, pm->peer->name);
		cbdataFree(pm);
		return;
	}
	pm->last_probe = squid_curtime;
	pm->running.timeout_set = 1;
	eventAdd(pm->name, peerMonitorTimeout, pm, (double) (pm->peer->monitor.timeout ? pm->peer->monitor.timeout : pm->peer->monitor.interval), 0);

	httpHeaderPutStr(&req->header, HDR_ACCEPT, "*/*");
	httpHeaderPutStr(&req->header, HDR_USER_AGENT, full_appname_string);
	if (pm->peer->login)
		xstrncpy(req->login, pm->peer->login, MAX_LOGIN_SZ);
	pm->running.req = requestLink(req);
	pm->running.e = storeCreateEntry(url, req->flags, req->method);
	pm->running.sc = storeClientRegister(pm->running.e, pm);
	pm->running.buf = memAllocate(MEM_4K_BUF);
	fwdStartPeer(pm->peer, pm->running.e, pm->running.req);
	storeClientCopy(pm->running.sc, pm->running.e, 0, 0, 4096, pm->running.buf, peerMonitorFetchReplyHeaders, pm);
	return;
}
Example #18
0
static void
authenticateNegotiateAuthenticateUser(auth_user_request_t * auth_user_request, request_t * request, ConnStateData * conn, http_hdr_type type)
{
    const char *proxy_auth, *blob;
    auth_user_t *auth_user;
    negotiate_request_t *negotiate_request;

    auth_user = auth_user_request->auth_user;
    assert(auth_user);
    assert(auth_user->auth_type == AUTH_NEGOTIATE);
    assert(auth_user->scheme_data != NULL);
    assert(auth_user_request->scheme_data != NULL);
    negotiate_request = auth_user_request->scheme_data;
    /* Check that we are in the client side, where we can generate
     * auth challenges */
    if (!conn) {
	negotiate_request->auth_state = AUTHENTICATE_STATE_FAILED;
	debug(29, 1) ("authenticateNegotiateAuthenticateUser: attempt to perform authentication without a connection!\n");
	return;
    }
    if (negotiate_request->waiting) {
	debug(29, 1) ("authenticateNegotiateAuthenticateUser: waiting for helper reply!\n");
	return;
    }
    if (negotiate_request->server_blob) {
	debug(29, 2) ("authenticateNegotiateAuthenticateUser: need to challenge client '%s'!\n", negotiate_request->server_blob);
	return;
    }
    /* get header */
    proxy_auth = httpHeaderGetStr(&request->header, type);
    blob = proxy_auth;
    while (xisspace(*blob) && *blob)
	blob++;
    while (!xisspace(*blob) && *blob)
	blob++;
    while (xisspace(*blob) && *blob)
	blob++;

    switch (negotiate_request->auth_state) {
    case AUTHENTICATE_STATE_NONE:
	/* we've received a negotiate request. pass to a helper */
	debug(29, 9) ("authenticateNegotiateAuthenticateUser: auth state negotiate none. %s\n", proxy_auth);
	negotiate_request->auth_state = AUTHENTICATE_STATE_INITIAL;
	safe_free(negotiate_request->client_blob);
	negotiate_request->client_blob = xstrdup(blob);
	conn->auth_type = AUTH_NEGOTIATE;
	conn->auth_user_request = auth_user_request;
	negotiate_request->conn = conn;
	/* and lock for the connection duration */
	debug(29, 9) ("authenticateNegotiateAuthenticateUser: Locking auth_user from the connection.\n");
	authenticateAuthUserRequestLock(auth_user_request);
	negotiate_request->request = requestLink(request);
	return;
	break;
    case AUTHENTICATE_STATE_INITIAL:
	debug(29, 1) ("authenticateNegotiateAuthenticateUser: need to ask helper!\n");
	return;
	break;
    case AUTHENTICATE_STATE_NEGOTIATE:
	/* we should have received a blob from the clien. pass it to the same 
	 * helper process */
	debug(29, 9) ("authenticateNegotiateAuthenticateUser: auth state challenge with header %s.\n", proxy_auth);
	/* do a cache lookup here. If it matches it's a successful negotiate 
	 * challenge - release the helper and use the existing auth_user 
	 * details. */
	safe_free(negotiate_request->client_blob);
	negotiate_request->client_blob = xstrdup(blob);
	if (negotiate_request->request)
	    requestUnlink(negotiate_request->request);
	negotiate_request->request = requestLink(request);
	return;
	break;
    case AUTHENTICATE_STATE_DONE:
	fatal("authenticateNegotiateAuthenticateUser: unexpect auth state DONE! Report a bug to the squid developers.\n");
	break;
    case AUTHENTICATE_STATE_FAILED:
	/* we've failed somewhere in authentication */
	debug(29, 9) ("authenticateNegotiateAuthenticateUser: auth state negotiate failed. %s\n", proxy_auth);
	return;
    }
    return;
}
Example #19
0
/* ask store for a digest */
static void
peerDigestRequest(PeerDigest * pd)
{
    peer *p = pd->peer;
    StoreEntry *e, *old_e;
    char *url;
    const cache_key *key;
    request_t *req;
    DigestFetchState *fetch = NULL;

    pd->req_result = NULL;
    pd->flags.requested = 1;

    /* compute future request components */
    if (p->digest_url)
	url = xstrdup(p->digest_url);
    else
	url = internalRemoteUri(p->host, p->http_port,
	    "/squid-internal-periodic/", StoreDigestFileName);

    key = storeKeyPublic(url, METHOD_GET);
    debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key));
    req = urlParse(METHOD_GET, url);
    assert(req);

    /* add custom headers */
    assert(!req->header.len);
    httpHeaderPutStr(&req->header, HDR_ACCEPT, StoreDigestMimeStr);
    httpHeaderPutStr(&req->header, HDR_ACCEPT, "text/html");
    if (p->login)
	xstrncpy(req->login, p->login, MAX_LOGIN_SZ);
    /* create fetch state structure */
    fetch = memAllocate(MEM_DIGEST_FETCH_STATE);
    cbdataAdd(fetch, memFree, MEM_DIGEST_FETCH_STATE);
    fetch->request = requestLink(req);
    fetch->pd = pd;
    fetch->offset = 0;

    /* update timestamps */
    fetch->start_time = squid_curtime;
    pd->times.requested = squid_curtime;
    pd_last_req_time = squid_curtime;

    req->flags.cachable = 1;
    /* the rest is based on clientProcessExpired() */
    req->flags.refresh = 1;
    old_e = fetch->old_entry = storeGet(key);
    if (old_e) {
	debug(72, 5) ("peerDigestRequest: found old entry\n");
	storeLockObject(old_e);
	storeCreateMemObject(old_e, url, url);
	storeClientListAdd(old_e, fetch);
    }
    e = fetch->entry = storeCreateEntry(url, url, req->flags, req->method);
    assert(EBIT_TEST(e->flags, KEY_PRIVATE));
    storeClientListAdd(e, fetch);
    /* set lastmod to trigger IMS request if possible */
    if (old_e)
	e->lastmod = old_e->lastmod;

    /* push towards peer cache */
    debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n");
    fwdStart(-1, e, req);
    cbdataLock(fetch);
    cbdataLock(fetch->pd);
    storeClientCopy(e, 0, 0, 4096, memAllocate(MEM_4K_BUF),
	peerDigestFetchReply, fetch);
}
Example #20
0
void
sslStart(int fd, const char *url, request_t * request, size_t * size_ptr)
{
    /* Create state structure. */
    SslStateData *sslState = NULL;
    int sock;
    ErrorState *err = NULL;
    debug(26, 3) ("sslStart: '%s %s'\n",
	RequestMethodStr[request->method], url);
    Counter.server.all.requests++;
    Counter.server.other.requests++;
    /* Create socket. */
    sock = comm_open(SOCK_STREAM,
	0,
	Config.Addrs.tcp_outgoing,
	0,
	COMM_NONBLOCKING,
	url);
    if (sock == COMM_ERROR) {
	debug(26, 4) ("sslStart: Failed because we're out of sockets.\n");
	err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->xerrno = errno;
	err->request = requestLink(request);
	errorSend(fd, err);
	return;
    }
    sslState = xcalloc(1, sizeof(SslStateData));
    cbdataAdd(sslState, cbdataXfree, 0);
#if DELAY_POOLS
    sslState->delay_id = delayClient(request);
    delayRegisterDelayIdPtr(&sslState->delay_id);
#endif
    sslState->url = xstrdup(url);
    sslState->request = requestLink(request);
    sslState->size_ptr = size_ptr;
    sslState->client.fd = fd;
    sslState->server.fd = sock;
    sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
    sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
    comm_add_close_handler(sslState->server.fd,
	sslServerClosed,
	sslState);
    comm_add_close_handler(sslState->client.fd,
	sslClientClosed,
	sslState);
    commSetTimeout(sslState->client.fd,
	Config.Timeout.lifetime,
	sslTimeout,
	sslState);
    commSetTimeout(sslState->server.fd,
	Config.Timeout.connect,
	sslTimeout,
	sslState);
    peerSelect(request,
	NULL,
	sslPeerSelectComplete,
	sslState);
    /*
     * Disable the client read handler until peer selection is complete
     * Take control away from client_side.c.
     */
    commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0);
}
Example #21
0
static void
icapRespModReadReply(int fd, void *data)
{
    IcapStateData *icap = data;
    int version_major, version_minor;
    const char *str_status;
    int x;
    int status = 0;
    int isIcap = 0;
    int directResponse = 0;
    ErrorState *err;
    const char *start;
    const char *end;

    debug(81, 5) ("icapRespModReadReply: FD %d data = %p\n", fd, data);
    statCounter.syscalls.sock.reads++;

    x = icapReadHeader(fd, icap, &isIcap);
    if (x < 0) {
	/* Did not find a proper ICAP response */
	debug(81, 3) ("ICAP : Error path!\n");
	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->request = requestLink(icap->request);
	err->xerrno = errno;
	errorAppendEntry(icap->respmod.entry, err);
	comm_close(fd);
	return;
    }
    if (x == 0) {
	/*
	 * Waiting for more headers.  Schedule new read hander, but
	 * don't reset timeout.
	 */
	commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
	return;
    }
    /*
     * Parse the ICAP header
     */
    assert(icap->icap_hdr.size);
    debug(81, 3) ("Parse icap header : <%s>\n", icap->icap_hdr.buf);
    if ((status =
	    icapParseStatusLine(icap->icap_hdr.buf, icap->icap_hdr.size,
		&version_major, &version_minor, &str_status)) < 0) {
	debug(81, 1) ("BAD ICAP status line <%s>\n", icap->icap_hdr.buf);
	/* is this correct in case of ICAP protocol error? */
	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->request = requestLink(icap->request);
	err->xerrno = errno;
	errorAppendEntry(icap->respmod.entry, err);
	comm_close(fd);
	return;
    };
    /*  OK here we have responce. Lets stop filling the 
     *  icap->respmod.resp_copy buffer ....
     */
    icap->flags.copy_response = 0;

    icapSetKeepAlive(icap, icap->icap_hdr.buf);
#if ICAP_PREVIEW
    if (icap->flags.wait_for_preview_reply) {
	if (100 == status) {
	    debug(81, 5) ("icapRespModReadReply: 100 Continue received\n");
	    icap->flags.wait_for_preview_reply = 0;
	    /* if http_server_eof
	     * call again icapSendRespMod to handle data that
	     * was received while waiting for this ICAP response
	     * else let http to call icapSendRespMod when new data arrived
	     */
	    if (icap->flags.http_server_eof)
		icapSendRespMod(icap, NULL, 0, 0);
	    /*
	     * reset the header to send the rest of the preview
	     */
	    if (!memBufIsNull(&icap->icap_hdr))
		memBufReset(&icap->icap_hdr);

	    /*We do n't need it any more .......*/
	    if (!memBufIsNull(&icap->respmod.resp_copy))
		 memBufClean(&icap->respmod.resp_copy);

	    return;
	}
	if (204 == status) {
	    debug(81,
		5) ("icapRespModReadReply: 204 No modification received\n");
	    icap->flags.wait_for_preview_reply = 0;
	}
    }
#endif /*ICAP_PREVIEW */

#if SUPPORT_ICAP_204 || ICAP_PREVIEW
    if (204 == status) {
	debug(81, 3) ("got 204 status from ICAP server\n");
	debug(81, 3) ("setting icap->flags.no_content\n");
	icap->flags.no_content = 1;
	/*
	 * copy the response already written to the ICAP server
	 */
	debug(81, 3) ("copying %d bytes from resp_copy to chunk_buf\n",
	    icap->respmod.resp_copy.size);
	memBufAppend(&icap->chunk_buf,
	    icap->respmod.resp_copy.buf, icap->respmod.resp_copy.size);
	icap->respmod.resp_copy.size = 0;
	if (icapReadReply2(icap) < 0)
	    comm_close(fd);
	/*
	 * XXX ideally want to clean icap->respmod.resp_copy here
	 * XXX ideally want to "close" ICAP server connection here
	 * OK do it....
	 */
	if (!memBufIsNull(&icap->respmod.resp_copy))
	     memBufClean(&icap->respmod.resp_copy);
	return;
    }
#endif
    if (200 != status) {
	debug(81, 1) ("Unsupported status '%d' from ICAP server\n", status);
	/* Did not find a proper ICAP response */
	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->request = requestLink(icap->request);
	err->xerrno = errno;
	errorAppendEntry(icap->respmod.entry, err);
	comm_close(fd);
	return;
    }
    if (icapFindHeader(icap->icap_hdr.buf, "Encapsulated:", &start, &end)) {
	icapParseEncapsulated(icap, start, end);
    } else {
	debug(81,
	    1)
	    ("WARNING: icapRespModReadReply() did not find 'Encapsulated' header\n");
    }
    if (icap->enc.res_hdr > -1)
	directResponse = 1;
    else if (icap->enc.res_body > -1)
	directResponse = 1;
    else
	directResponse = 0;

    /*
     * "directResponse" is the normal case here.  If we don't have
     * a response header or body, it is an error.
     */
    if (!directResponse) {
	/* Did not find a proper ICAP response */
	debug(81, 3) ("ICAP : Error path!\n");
	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->request = requestLink(icap->request);
	err->xerrno = errno;
	errorAppendEntry(icap->respmod.entry, err);
	comm_close(fd);
	return;
    }
    /* got the reply, no need to come here again */
    icap->flags.wait_for_reply = 0;
    icap->flags.got_reply = 1;
    /* Next, gobble any data before the HTTP response starts */
    if (icap->enc.res_hdr > -1)
	icap->bytes_to_gobble = icap->enc.res_hdr;
    commSetSelect(fd, COMM_SELECT_READ, icapRespModGobble, icap, 0);
}
Example #22
0
static void
icapSendRespModDone(int fd, char *bufnotused, size_t size, int errflag,
    void *data)
{
    IcapStateData *icap = data;
    ErrorState *err;

    icap->flags.write_pending = 0;
    debug(81, 5) ("icapSendRespModDone: FD %d: size %d: errflag %d.\n",
	fd, size, errflag);
    if (size > 0) {
	fd_bytes(fd, size, FD_WRITE);
	kb_incr(&statCounter.icap.all.kbytes_out, size);
    }
    if (errflag == COMM_ERR_CLOSING)
	return;
    if (errflag) {
	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->xerrno = errno;
	if (cbdataValid(icap))
	    err->request = requestLink(icap->request);
	storeEntryReset(icap->respmod.entry);
	errorAppendEntry(icap->respmod.entry, err);
	comm_close(fd);
	return;
    }
    if (EBIT_TEST(icap->respmod.entry->flags, ENTRY_ABORTED)) {
        debug(81, 3) ("icapSendRespModDone: Entry Aborded\n");	
	comm_close(fd);
	return;
    }
    if (icap->flags.send_zero_chunk) {
	debug(81,
	    3) ("icapSendRespModDone: I'm supposed to send zero chunk now\n");
	icap->flags.send_zero_chunk = 0;
	icapSendRespMod(icap, NULL, 0, 1);
	return;
    }
    if (icap->flags.wait_for_preview_reply || icap->flags.wait_for_reply) {
	/* Schedule reading the ICAP response */
	debug(81,
	    3)
	    ("icapSendRespModDone: FD %d: commSetSelect on read icapRespModReadReply.\n",
	    fd);
	commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
#if 1
	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
#else
	if (icap->flags.wait_for_preview_reply || icap->flags.http_server_eof) {
	    /*
	     * Set the read timeout only after all data has been sent
	     * or we are waiting for a preview response
	     * If the ICAP server does not return any data till all data
	     * has been sent, we are likely to hit the timeout for large
	     * HTTP bodies
	     */
	    commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
	}
#endif
    }
}
Example #23
0
/* wait for full http headers to be received then parse them */
static void
peerDigestFetchReply(void *data, char *buf, ssize_t size)
{
    DigestFetchState *fetch = data;
    PeerDigest *pd = fetch->pd;
    size_t hdr_size;
    assert(pd && buf);
    assert(!fetch->offset);

    if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestFetchReply"))
	return;

    if ((hdr_size = headersEnd(buf, size))) {
	http_status status;
	HttpReply *reply = fetch->entry->mem_obj->reply;
	assert(reply);
	httpReplyParse(reply, buf, hdr_size);
	status = reply->sline.status;
	debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %d (%+d)\n",
	    strBuf(pd->host), status,
	    reply->expires, reply->expires - squid_curtime);

	/* this "if" is based on clientHandleIMSReply() */
	if (status == HTTP_NOT_MODIFIED) {
	    request_t *r = NULL;
	    /* our old entry is fine */
	    assert(fetch->old_entry);
	    if (!fetch->old_entry->mem_obj->request)
		fetch->old_entry->mem_obj->request = r =
		    requestLink(fetch->entry->mem_obj->request);
	    assert(fetch->old_entry->mem_obj->request);
	    httpReplyUpdateOnNotModified(fetch->old_entry->mem_obj->reply, reply);
	    storeTimestampsSet(fetch->old_entry);
	    /* get rid of 304 reply */
	    storeUnregister(fetch->entry, fetch);
	    storeUnlockObject(fetch->entry);
	    fetch->entry = fetch->old_entry;
	    fetch->old_entry = NULL;
	    /* preserve request -- we need its size to update counters */
	    /* requestUnlink(r); */
	    /* fetch->entry->mem_obj->request = NULL; */
	} else if (status == HTTP_OK) {
	    /* get rid of old entry if any */
	    if (fetch->old_entry) {
		debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n");
		storeUnregister(fetch->old_entry, fetch);
		storeReleaseRequest(fetch->old_entry);
		storeUnlockObject(fetch->old_entry);
		fetch->old_entry = NULL;
	    }
	} else {
	    /* some kind of a bug */
	    peerDigestFetchAbort(fetch, buf, httpStatusLineReason(&reply->sline));
	    return;
	}
	/* must have a ready-to-use store entry if we got here */
	/* can we stay with the old in-memory digest? */
	if (status == HTTP_NOT_MODIFIED && fetch->pd->cd)
	    peerDigestFetchStop(fetch, buf, "Not modified");
	else
	    storeClientCopy(fetch->entry,	/* have to swap in */
		0, 0, SM_PAGE_SIZE, buf, peerDigestSwapInHeaders, fetch);
    } else {
	/* need more data, do we have space? */
	if (size >= SM_PAGE_SIZE)
	    peerDigestFetchAbort(fetch, buf, "reply header too big");
	else
	    storeClientCopy(fetch->entry, size, 0, SM_PAGE_SIZE, buf,
		peerDigestFetchReply, fetch);
    }
}
Example #24
0
static int
icapReadReply2(IcapStateData * icap)
{
    StoreEntry *entry = icap->respmod.entry;
    const request_t *request = icap->request;
    debug(81, 3) ("icapReadReply2\n");
    if (icap->chunk_buf.size == 0 && entry->mem_obj->inmem_hi == 0) {
	ErrorState *err;
	err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
	err->xerrno = errno;
	err->request = requestLink((request_t *) request);
	errorAppendEntry(entry, err);
	icap->flags.http_server_eof = 1;
	return -1;
    }
    if (icap->chunk_buf.size == 0) {
	/* Retrieval done. */
	if (icapHttpReplyHdrState(icap) < 2)
	    icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf,
		icap->chunk_buf.size);
	icap->flags.http_server_eof = 1;
	icapReadReply3(icap);
	return 0;
    }
    if (icapHttpReplyHdrState(icap) == 0) {
	int expect = icapExpectedHttpReplyHdrSize(icap);
	int so_far = icap->http_header_bytes_read_so_far;
	int needed = expect - so_far;
	debug(81, 3) ("expect=%d\n", expect);
	debug(81, 3) ("so_far=%d\n", so_far);
	debug(81, 3) ("needed=%d\n", needed);
	assert(needed < 0 || needed >= 0);
	if (0 > expect) {
	    icapProcessHttpReplyHeader(icap,
		icap->chunk_buf.buf, icap->chunk_buf.size);
	} else if (0 == expect) {
	    /*
	     * this icap reply doesn't give us new HTTP headers
	     * so we must copy them from our copy
	     */
	    debug(81, 1) ("WARNING: untested code at %s:%d\n", __FILE__,
		__LINE__);
	    if(icap->respmod.req_hdr_copy.size){/*For HTTP 0.9 we do not have headers*/
		 storeAppend(entry,
			     icap->respmod.req_hdr_copy.buf,
			     icap->respmod.req_hdr_copy.size);
	    }
	    icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf,
				       icap->chunk_buf.size);
	    assert(icapHttpReplyHdrState(icap) == 2);
	    icap->chunk_size = 0;/*we are ready to read chunks of data now....*/
	} else if (needed) {
	    icapProcessHttpReplyHeader(icap,
		icap->chunk_buf.buf, icap->chunk_buf.size);
	    if (icap->chunk_buf.size >= needed) {
		storeAppend(entry, icap->chunk_buf.buf, needed);
		so_far += needed;
		xmemmove(icap->chunk_buf.buf,
		    icap->chunk_buf.buf + needed,
		    icap->chunk_buf.size - needed);
		icap->chunk_buf.size -= needed;
		assert(icapHttpReplyHdrState(icap) == 2);
		icap->chunk_size = 0;
	    } else {
		/*
		 * We don't have the full HTTP reply headers yet, so keep
		 * the partial reply buffered in 'chunk_buf' and wait
		 * for more.
		 */
                debug(81,3)("We don't have full Http headers.Schedule a new read\n");
  		commSetSelect(icap->icap_fd, COMM_SELECT_READ, icapReadReply, icap, 0);
	    }
	}
	icap->http_header_bytes_read_so_far = so_far;
    }
    debug(81, 3) ("%s:%d: icap->chunk_buf.size=%d\n", __FILE__, __LINE__,
	(int) icap->chunk_buf.size);
    debug(81, 3) ("%s:%d: flags.no_content=%d\n", __FILE__, __LINE__,
	icap->flags.no_content);
    if (icap->flags.no_content) {
	/* data from http.c is not chunked */
	if (!EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	    debug(81, 3) ("copying %d bytes from chunk_buf to entry\n",
		icap->chunk_buf.size);
	    storeAppend(entry, icap->chunk_buf.buf, icap->chunk_buf.size);
	    icap->chunk_buf.size = 0;
	}
    } else if (2 == icapHttpReplyHdrState(icap)) {
	if (icap->chunk_buf.size)
	    icapParseChunkedBody(icap, (STRCB *) storeAppend, entry);
    }
    icapReadReply3(icap);
    return 0;
}
Example #25
0
static void
urnHandleReply(void *data, char *buf, ssize_t size)
{
    UrnState *urnState = data;
    StoreEntry *e = urnState->entry;
    StoreEntry *urlres_e = urnState->urlres_e;
    char *s = NULL;
    size_t k;
    HttpReply *rep;
    url_entry *urls;
    url_entry *u;
    url_entry *min_u;
    MemBuf mb;
    ErrorState *err;
    int i;
    int urlcnt = 0;
    http_version_t version;

    debug(52, 3) ("urnHandleReply: Called with size=%d.\n", (int) size);
    if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) {
	memFree(buf, MEM_4K_BUF);
	return;
    }
    if (size == 0) {
	memFree(buf, MEM_4K_BUF);
	return;
    } else if (size < 0) {
	memFree(buf, MEM_4K_BUF);
	return;
    }
    if (urlres_e->store_status == STORE_PENDING && size < SM_PAGE_SIZE) {
	storeClientCopy(urnState->sc, urlres_e,
	    size,
	    0,
	    SM_PAGE_SIZE,
	    buf,
	    urnHandleReply,
	    urnState);
	return;
    }
    /* we know its STORE_OK */
    k = headersEnd(buf, size);
    if (0 == k) {
	debug(52, 1) ("urnHandleReply: didn't find end-of-headers for %s\n",
	    storeUrl(e));
	return;
    }
    s = buf + k;
    assert(urlres_e->mem_obj->reply);
    httpReplyParse(urlres_e->mem_obj->reply, buf, k);
    debug(52, 3) ("mem->reply exists, code=%d.\n",
	urlres_e->mem_obj->reply->sline.status);
    if (urlres_e->mem_obj->reply->sline.status != HTTP_OK) {
	debug(52, 3) ("urnHandleReply: failed.\n");
	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
	err->request = requestLink(urnState->request);
	err->url = xstrdup(storeUrl(e));
	errorAppendEntry(e, err);
	return;
    }
    while (xisspace(*s))
	s++;
    urls = urnParseReply(s, urnState->request->method);
    for (i = 0; NULL != urls[i].url; i++)
	urlcnt++;
    debug(53, 3) ("urnFindMinRtt: Counted %d URLs\n", i);
    if (urls == NULL) {		/* unkown URN error */
	debug(52, 3) ("urnTranslateDone: unknown URN %s\n", storeUrl(e));
	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
	err->request = requestLink(urnState->request);
	err->url = xstrdup(storeUrl(e));
	errorAppendEntry(e, err);
	return;
    }
    min_u = urnFindMinRtt(urls, urnState->request->method, NULL);
    qsort(urls, urlcnt, sizeof(*urls), url_entry_sort);
    storeBuffer(e);
    memBufDefInit(&mb);
    memBufPrintf(&mb,
	"<TITLE>Select URL for %s</TITLE>\n"
	"<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n"
	"<H2>Select URL for %s</H2>\n"
	"<TABLE BORDER=\"0\" WIDTH=\"100%%\">\n", storeUrl(e), storeUrl(e));
    for (i = 0; i < urlcnt; i++) {
	u = &urls[i];
	debug(52, 3) ("URL {%s}\n", u->url);
	memBufPrintf(&mb,
	    "<TR><TD><A HREF=\"%s\">%s</A></TD>", u->url, u->url);
	if (urls[i].rtt > 0)
	    memBufPrintf(&mb,
		"<TD align=\"right\">%4d <it>ms</it></TD>", u->rtt);
	else
	    memBufPrintf(&mb, "<TD align=\"right\">Unknown</TD>");
	memBufPrintf(&mb,
	    "<TD>%s</TD></TR>\n", u->flags.cached ? "    [cached]" : " ");
    }
    memBufPrintf(&mb,
	"</TABLE>"
	"<HR noshade size=\"1px\">\n"
	"<ADDRESS>\n"
	"Generated by %s@%s\n"
	"</ADDRESS>\n",
	full_appname_string, getMyHostname());
    rep = e->mem_obj->reply;
    httpReplyReset(rep);
    httpBuildVersion(&version, 1, 0);
    httpReplySetHeaders(rep, version, HTTP_MOVED_TEMPORARILY, NULL,
	"text/html", mb.size, 0, squid_curtime);
    if (urnState->flags.force_menu) {
	debug(51, 3) ("urnHandleReply: forcing menu\n");
    } else if (min_u) {
	httpHeaderPutStr(&rep->header, HDR_LOCATION, min_u->url);
    }
    httpBodySet(&rep->body, &mb);
    httpReplySwapOut(rep, e);
    storeComplete(e);
    memFree(buf, MEM_4K_BUF);
    for (i = 0; i < urlcnt; i++) {
	safe_free(urls[i].url);
	safe_free(urls[i].host);
    }
    safe_free(urls);
    /* mb was absorbed in httpBodySet call, so we must not clean it */
    storeUnregister(urnState->sc, urlres_e, urnState);
    storeUnlockObject(urlres_e);
    storeUnlockObject(urnState->entry);
    requestUnlink(urnState->request);
    requestUnlink(urnState->urlres_r);
    cbdataFree(urnState);
}
Example #26
0
void
storeUpdate(StoreEntry * entry, request_t * request)
{
    StoreUpdateState *state;
    request_flags flags = null_request_flags;
    const char *vary;

    if (!request)
	request = entry->mem_obj->request;

    if (EBIT_TEST(entry->flags, KEY_PRIVATE))
	return;			/* Nothing to do here... */

    if (!Config.onoff.update_headers)
	return;			/* Disabled */

    CBDATA_INIT_TYPE_FREECB(StoreUpdateState, free_StoreUpdateState);

    if (entry->mem_obj)
	entry->mem_obj->refresh_timestamp = 0;
    state = cbdataAlloc(StoreUpdateState);
    state->oldentry = entry;
    storeLockObject(state->oldentry);
    flags.cachable = 1;
    state->newentry = storeCreateEntry(storeUrl(entry), flags, entry->mem_obj->method);
    storeRegisterAbort(state->newentry, storeUpdateAbort, state);
    state->sc = storeClientRegister(state->oldentry, state);
    state->offset = entry->mem_obj->reply->hdr_sz;
    storeBuffer(state->newentry);
    httpReplySwapOut(httpReplyClone(entry->mem_obj->reply), state->newentry);
    state->newentry->timestamp = entry->timestamp;
    state->newentry->lastref = entry->lastref;
    state->newentry->expires = entry->expires;
    state->newentry->lastmod = entry->lastmod;
    state->newentry->refcount = entry->refcount;
    if (request) {
	state->newentry->mem_obj->request = requestLink(request);
	vary = httpMakeVaryMark(request, state->newentry->mem_obj->reply);
	if (vary) {
	    state->newentry->mem_obj->vary_headers = xstrdup(vary);
	    if (strBuf(request->vary_encoding))
		state->newentry->mem_obj->vary_encoding = xstrdup(strBuf(request->vary_encoding));
	}
    } else {
	if (entry->mem_obj->vary_headers)
	    state->newentry->mem_obj->vary_headers = xstrdup(entry->mem_obj->vary_headers);
	if (entry->mem_obj->vary_encoding)
	    state->newentry->mem_obj->vary_encoding = xstrdup(entry->mem_obj->vary_encoding);
    }
    storeSetPublicKey(state->newentry);
    storeBufferFlush(state->newentry);
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	/*
	 * the above storeBufferFlush() call could ABORT this entry,
	 * in that case, there's nothing for us to do.
	 */
	debug(20, 1) ("storeUpdate: Aborted on write\n");
	return;
    }
    storeClientCopy(state->sc, state->oldentry, state->offset, state->offset, sizeof(state->buf), state->buf, storeUpdateCopy, state);
    return;
}
Example #27
0
IcapStateData *
icapRespModStart(icap_service_t type, request_t * request, StoreEntry * entry,
    http_state_flags http_flags)
{
    IcapStateData *icap = NULL;
    CNCB *theCallback = NULL;
    icap_service *service = NULL;

    debug(81, 3) ("icapRespModStart: type=%d\n", (int) type);
    assert(type >= 0 && type < ICAP_SERVICE_MAX);

    service = icapService(type, request);
    if (!service) {
	debug(81, 3) ("icapRespModStart: no service found\n");
	return NULL;		/* no service found */
    }
    if (service->unreachable) {
	if (service->bypass) {
	    debug(81,
		5)
		("icapRespModStart: BYPASS because service unreachable: %s\n",
		service->uri);
	    return NULL;
	} else {
	    debug(81,
		5)
		("icapRespModStart: ERROR  because service unreachable: %s\n",
		service->uri);
	    return (IcapStateData *) - 1;
	}
    }
    switch (type) {
	/* TODO: When we support more than ICAP_SERVICE_RESPMOD_PRECACHE, we needs to change
	 * this switch, because callbacks isn't keep */
    case ICAP_SERVICE_RESPMOD_PRECACHE:
	theCallback = icapConnectOver;
	break;
    default:
	fatalf("icapRespModStart: unsupported service type '%s'\n",
	    icap_service_type_str[type]);
	break;
    }

    icap = icapAllocate();
    if (!icap) {
	debug(81, 3) ("icapRespModStart: icapAllocate() failed\n");
	return NULL;
    }
    icap->request = requestLink(request);
    icap->respmod.entry = entry;
    if (entry)
	storeLockObject(entry);
    icap->http_flags = http_flags;
    memBufDefInit(&icap->respmod.buffer);
    memBufDefInit(&icap->chunk_buf);

    icap->current_service = service;
    icap->preview_size = service->preview;

    /* 
     * Don't create socket to the icap server now, but only for the first
     * packet receive from the http server. This will resolve all timeout
     * between the web server and icap server.
     */
    debug(81, 3) ("icapRespModStart: setting connect_requested to 0\n");
    icap->flags.connect_requested = 0;

    /*
     * make a copy the HTTP response that we send to the ICAP server in
     * case it turns out to be a 204
     */
#ifdef SUPPORT_ICAP_204
    icap->flags.copy_response = 1;
#elif ICAP_PREVIEW
    if(preview_size < 0 || !Config.icapcfg.preview_enable)
	 icap->flags.copy_response = 0;
    else
	 icap->flags.copy_response = 1;
#else
    icap->flags.copy_response = 0;
#endif
    
    statCounter.icap.all.requests++;
    debug(81, 3) ("icapRespModStart: returning %p\n", icap);
    return icap;
}
Example #28
0
/* wait for full http headers to be received */
static void
peerDigestFetchReply(void *data, mem_node_ref nr, ssize_t size)
{
    const char *buf = nr.node->data + nr.offset;
    DigestFetchState *fetch = data;
    PeerDigest *pd = fetch->pd;
    http_status status;
    HttpReply *reply;
    assert(pd && buf);
    assert(!fetch->offset);
    assert(size <= nr.node->len - nr.offset);

    if (peerDigestFetchedEnough(fetch, size, "peerDigestFetchReply"))
	goto finish;

    reply = fetch->entry->mem_obj->reply;
    assert(reply);
    status = reply->sline.status;
    debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %ld (%+d)\n",
	strBuf(pd->host), status,
	(long int) reply->expires, (int) (reply->expires - squid_curtime));

    /* this "if" is based on clientHandleIMSReply() */
    if (status == HTTP_NOT_MODIFIED) {
	request_t *r = NULL;
	/* our old entry is fine */
	assert(fetch->old_entry);
	if (!fetch->old_entry->mem_obj->request)
	    fetch->old_entry->mem_obj->request = r =
		requestLink(fetch->entry->mem_obj->request);
	assert(fetch->old_entry->mem_obj->request);
	httpReplyUpdateOnNotModified(fetch->old_entry->mem_obj->reply, reply);
	storeTimestampsSet(fetch->old_entry);
	/* get rid of 304 reply */
	storeClientUnregister(fetch->sc, fetch->entry, fetch);
	storeUnlockObject(fetch->entry);
	/* And prepare to swap in old entry if needed */
	fetch->entry = fetch->old_entry;
	fetch->old_entry = NULL;
	fetch->sc = fetch->old_sc;
	fetch->old_sc = NULL;
	/* preserve request -- we need its size to update counters */
	/* requestUnlink(r); */
	/* fetch->entry->mem_obj->request = NULL; */
    } else if (status == HTTP_OK) {
	/* get rid of old entry if any */
	if (fetch->old_entry) {
	    debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n");
	    storeClientUnregister(fetch->old_sc, fetch->old_entry, fetch);
	    storeReleaseRequest(fetch->old_entry);
	    storeUnlockObject(fetch->old_entry);
	    fetch->old_entry = NULL;
	}
    } else {
	/* some kind of a bug */
	peerDigestFetchAbort(fetch, httpStatusLineReason(&reply->sline));
	goto finish;
    }
    /* must have a ready-to-use store entry if we got here */
    /* can we stay with the old in-memory digest? */
    if (status == HTTP_NOT_MODIFIED && fetch->pd->cd)
	peerDigestFetchStop(fetch, "Not modified");
    else
	storeClientRef(fetch->sc, fetch->entry,		/* have to swap in */
	    0, 0, SM_PAGE_SIZE, peerDigestSwapInHeaders, fetch);
  finish:
    stmemNodeUnref(&nr);
}