/*
 * Returns a message to the client ; the connection is shut down for read,
 * and the request is cleared so that no server connection can be initiated.
 * The buffer is marked for read shutdown on the other side to protect the
 * message, and the buffer write is enabled. The message is contained in a
 * "chunk". If it is null, then an empty message is used. The reply buffer does
 * not need to be empty before this, and its contents will not be overwritten.
 * The primary goal of this function is to return error messages to a client.
 */
void stream_int_retnclose(struct stream_interface *si, const struct chunk *msg)
{
	buffer_auto_read(si->ib);
	buffer_abort(si->ib);
	buffer_auto_close(si->ib);
	buffer_erase(si->ib);
	if (likely(msg && msg->len))
		buffer_write(si->ob, msg->str, msg->len);

	si->ob->wex = tick_add_ifset(now_ms, si->ob->wto);
	buffer_auto_read(si->ob);
	buffer_auto_close(si->ob);
	buffer_shutr_now(si->ob);
}
Example #2
0
/* This analyser tries to fetch a line from the request buffer which looks like :
 *
 *   "PROXY" <SP> PROTO <SP> SRC3 <SP> DST3 <SP> SRC4 <SP> <DST4> "\r\n"
 *
 * There must be exactly one space between each field. Fields are :
 *  - PROTO : layer 4 protocol, which must be "TCP4" or "TCP6".
 *  - SRC3  : layer 3 (eg: IP) source address in standard text form
 *  - DST3  : layer 3 (eg: IP) destination address in standard text form
 *  - SRC4  : layer 4 (eg: TCP port) source address in standard text form
 *  - DST4  : layer 4 (eg: TCP port) destination address in standard text form
 *
 * This line MUST be at the beginning of the buffer and MUST NOT wrap.
 *
 * Once the data is fetched, the values are set in the session's field and data
 * are removed from the buffer. The function returns zero if it needs to wait
 * for more data (max: timeout_client), or 1 if it has finished and removed itself.
 */
int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_bit)
{
	char *line = req->data;
	char *end = req->data + req->l;
	int len;

	DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
		now_ms, __FUNCTION__,
		s,
		req,
		req->rex, req->wex,
		req->flags,
		req->l,
		req->analysers);

	if (req->flags & (BF_READ_ERROR|BF_READ_TIMEOUT))
		goto fail;

	len = MIN(req->l, 6);
	if (!len)
		goto missing;

	/* Decode a possible proxy request, fail early if it does not match */
	if (strncmp(line, "PROXY ", len) != 0)
		goto fail;

	line += 6;
	if (req->l < 18) /* shortest possible line */
		goto missing;

	if (!memcmp(line, "TCP4 ", 5) != 0) {
		u32 src3, dst3, sport, dport;

		line += 5;

		src3 = inetaddr_host_lim_ret(line, end, &line);
		if (line == end)
			goto missing;
		if (*line++ != ' ')
			goto fail;

		dst3 = inetaddr_host_lim_ret(line, end, &line);
		if (line == end)
			goto missing;
		if (*line++ != ' ')
			goto fail;

		sport = read_uint((const char **)&line, end);
		if (line == end)
			goto missing;
		if (*line++ != ' ')
			goto fail;

		dport = read_uint((const char **)&line, end);
		if (line > end - 2)
			goto missing;
		if (*line++ != '\r')
			goto fail;
		if (*line++ != '\n')
			goto fail;

		/* update the session's addresses and mark them set */
		((struct sockaddr_in *)&s->si[0].addr.from)->sin_family      = AF_INET;
		((struct sockaddr_in *)&s->si[0].addr.from)->sin_addr.s_addr = htonl(src3);
		((struct sockaddr_in *)&s->si[0].addr.from)->sin_port        = htons(sport);

		((struct sockaddr_in *)&s->si[0].addr.to)->sin_family      = AF_INET;
		((struct sockaddr_in *)&s->si[0].addr.to)->sin_addr.s_addr = htonl(dst3);
		((struct sockaddr_in *)&s->si[0].addr.to)->sin_port        = htons(dport);
		s->flags |= SN_FRT_ADDR_SET;

	}
	else if (!memcmp(line, "TCP6 ", 5) != 0) {
		u32 sport, dport;
		char *src_s;
		char *dst_s, *sport_s, *dport_s;
		struct in6_addr src3, dst3;

		line+=5;

		src_s = line;
		dst_s = sport_s = dport_s = NULL;
		while (1) {
			if (line > end - 2) {
				goto missing;
			}
			else if (*line == '\r') {
				*line = 0;
				line++;
				if (*line++ != '\n')
					goto fail;
				break;
			}

			if (*line == ' ') {
				*line = 0;
				if (!dst_s)
					dst_s = line+1;
				else if (!sport_s)
					sport_s = line+1;
				else if (!dport_s)
					dport_s = line+1;
			}
			line++;
		}

		if (!dst_s || !sport_s || !dport_s)
			goto fail;

		sport = read_uint((const char **)&sport_s,dport_s-1);
		if ( *sport_s != 0 )
			goto fail;

		dport = read_uint((const char **)&dport_s,line-2);
		if ( *dport_s != 0 )
			goto fail;

		if (inet_pton(AF_INET6, src_s, (void *)&src3) != 1)
			goto fail;

		if (inet_pton(AF_INET6, dst_s, (void *)&dst3) != 1)
			goto fail;

		/* update the session's addresses and mark them set */
		((struct sockaddr_in6 *)&s->si[0].addr.from)->sin6_family      = AF_INET6;
		memcpy(&((struct sockaddr_in6 *)&s->si[0].addr.from)->sin6_addr, &src3, sizeof(struct in6_addr));
		((struct sockaddr_in6 *)&s->si[0].addr.from)->sin6_port        = htons(sport);

		((struct sockaddr_in6 *)&s->si[0].addr.to)->sin6_family      = AF_INET6;
		memcpy(&((struct sockaddr_in6 *)&s->si[0].addr.to)->sin6_addr, &dst3, sizeof(struct in6_addr));
		((struct sockaddr_in6 *)&s->si[0].addr.to)->sin6_port        = htons(dport);
		s->flags |= SN_FRT_ADDR_SET;
	}
	else {
		goto fail;
	}

	/* remove the PROXY line from the request */
	len = line - req->data;
	buffer_replace2(req, req->data, line, NULL, 0);
	req->total -= len; /* don't count the header line */

	req->analysers &= ~an_bit;
	return 1;

 missing:
	if (!(req->flags & (BF_SHUTR|BF_FULL))) {
		buffer_dont_connect(s->req);
		return 0;
	}
	/* missing data and buffer is either full or shutdown => fail */

 fail:
	buffer_abort(req);
	buffer_abort(s->rep);
	req->analysers = 0;

	s->fe->fe_counters.failed_req++;
	if (s->listener->counters)
		s->listener->counters->failed_req++;

	if (!(s->flags & SN_ERR_MASK))
		s->flags |= SN_ERR_PRXCOND;
	if (!(s->flags & SN_FINST_MASK))
		s->flags |= SN_FINST_R;
	return 0;
}
Example #3
0
int bbdocument_add(char subname[],char documenturi[],char documenttype[],char document[],const int dokument_size,unsigned int lastmodified,char *acl_allow, char *acl_denied,const char title[], char doctype[], char *attributes, container *attrkeys) {

	struct ReposetoryHeaderFormat ReposetoryHeader;

	int htmlbuffersize = 0;//((dokument_size *2) +512);	//+512 da vi skal ha med div meta data, som html kode
	char *htmlbuffer = NULL;// = malloc(htmlbuffersize);
	char *imagebuffer;
	char *documenttype_real;
	size_t imageSize;
	unsigned int DocIDForExistTest;
	unsigned int lastmodifiedForExistTest;
	struct hashtable *metahash = NULL;
	buffer *documentbuffer;

	memset(&ReposetoryHeader,0,sizeof(ReposetoryHeader));

	printf("bbdocument_add: \"%s\"\n",documenturi);

	printf("bbdocument_add: Attributes = \"%s\" (", attributes);
	if (attrkeys!=NULL) printf("+)\n");
	else printf(" )\n");


	//tester at det ikke finnes først. Hvis det finnes hånterer vi det. Eventuelt også lagre  den nye versjonen hvis det er forandret.
	if (uriindex_get(documenturi,&DocIDForExistTest,&lastmodifiedForExistTest,subname)) {

		if (lastmodifiedForExistTest == lastmodified) {
			printf("bbdocument_add: Uri \"%s\" all redy exist with DocID \"%u\" and time \"%u\"\n",documenturi,DocIDForExistTest,lastmodifiedForExistTest);
			return 1;
		}
		//hvis url er kjent, men oppdater rebruker vi den.
		ReposetoryHeader.DocID = DocIDForExistTest;
	}
	else {
		//hvis vi ikke har DocID har vi et system som trenger å få opprettet det. For eks bb eller bdisk.
		ReposetoryHeader.DocID = rGeneraeADocID(subname);

		#ifdef DEBUG
			printf("Dident have a known DocID for document. Did generet on. DOcID is now %u\n",ReposetoryHeader.DocID);
		#endif

	}

	// hvis vi har en "text applicatino" enkoding, som ikke er en vanlig tekst fil, men tekst som kommer fra 
	// en apllikasjon behandler vi det som text.
	//if (strcmp(documenttype,"tapp") == 0) {
	//	documenttype_real = strdup("text");
	//}
	//else 
	if (documenttype[0] == '\0') {
		if ((documenttype_real = sfindductype(documenturi)) == NULL) {
			printf("Will use .none as documenttype because I can't decide format. File name isent dos type (8.3): %s\n", documenturi);
			documenttype_real = strdup("none");
			
		}
	}
	else {
		documenttype_real = malloc(strlen(documenttype)+1);
		strcpy(documenttype_real,documenttype);
	}



	//hvis vi ikke her med noen egen doctype så bruker vi den vi har fått via documenttype
	if (doctype[0] == '\0') {
		//vi trenger ikke å ha \0 på slutten her
		strncpy(ReposetoryHeader.doctype,documenttype_real,sizeof(ReposetoryHeader.doctype));
	}
	else {
		//vi trenger ikke å ha \0 på slutten her
		strncpy(ReposetoryHeader.doctype,doctype,sizeof(ReposetoryHeader.doctype));
	}

	documentbuffer = buffer_init(0);
	if (!bbdocument_convert(documenttype_real,document,dokument_size,documentbuffer,title,subname,documenturi, lastmodified,acl_allow, acl_denied, &metahash)) {

		printf("can't run bbdocument_convert\n");
		//lager en tom html buffer
		//Setter titelen som subjekt. Hva hvis vi ikke har title?
		htmlbuffersize = strlen(html_text_tempelate) + strlen(title) + 1;
		htmlbuffer = malloc(htmlbuffersize);
		snprintf(htmlbuffer, htmlbuffersize, html_text_tempelate,title,"");
		htmlbuffersize = strlen(htmlbuffer);
		printf("useing title \"%s\" as title\n",title);
		printf("htmlbuffersize %i\n",htmlbuffersize);
		free(buffer_abort(documentbuffer));
	} else {
		htmlbuffersize = buffer_length(documentbuffer);
		htmlbuffer = buffer_exit(documentbuffer);
	}

	buffer *attrbuffer = buffer_init(-1);
	bprintf(attrbuffer, "%s,", attributes);

	if (metahash) {
		struct hashtable_itr *itr;

		if (hashtable_count(metahash) > 0) {
			itr = hashtable_iterator(metahash);
			do {
				char *key, *value;

				key = hashtable_iterator_key(itr);
				value = hashtable_iterator_value(itr);

				printf("%s: Key: %s Value: %s\n", documenttype_real, key, value);

				if (strcmp(key, "lastmodified") == 0) {
					lastmodified = atol(value);
					continue;
				}

				bprintf(attrbuffer, "%s=%s,", key, value);
			} while (hashtable_iterator_advance(itr));

			free(itr);
		}
		hashtable_destroy(metahash, 1);
	}
	char *all_attributes = buffer_exit(attrbuffer);



	//prøver å lag et bilde
	//if ( (imagebuffer = generate_thumbnail( document, dokument_size, &imageSize )) == NULL ) {
	if (!bbdocument_makethumb(documenttype_real,document,dokument_size,&imagebuffer,&imageSize)) {
		printf("can't generate image\n");
		ReposetoryHeader.imageSize = 0;
		imagebuffer = NULL;
	}
	else {
		debug("generated image\n");
		ReposetoryHeader.imageSize = imageSize;
	}


	ReposetoryHeader.clientVersion = 2.14;

	//runarb:  8 juli 2008: tar bort bruken av ReposetoryHeader's url
	//runarb: 11 juli 2008: kan ikke gjøre dette, da vi kopierer den inn i DocumentIndex fra ReposetoryHeader 
	strncpy(ReposetoryHeader.url,documenturi,sizeof(ReposetoryHeader.url));
		

	ReposetoryHeader.response = 200;
	strcpy(ReposetoryHeader.content_type,"htm");

	ReposetoryHeader.acl_allowSize = strlen(acl_allow);
#ifdef IIACL
	ReposetoryHeader.acl_deniedSize = strlen(acl_denied);
#endif
	ReposetoryHeader.time = lastmodified;

	ReposetoryHeader.storageTime = 0; //setes automatisk av rApendPostcompress

#ifdef DEBUG
	printf("ACL was allow \"%s\", %i bytes, denied \"%s\", %i bytes\nsubname %s\n",acl_allow,ReposetoryHeader.acl_allowSize,acl_allow,ReposetoryHeader.acl_allowSize,subname);
#endif

	ReposetoryHeader.urllen = strlen(documenturi);
	ReposetoryHeader.attributeslen = strlen(all_attributes);
	rApendPostcompress(&ReposetoryHeader, htmlbuffer, imagebuffer, subname, acl_allow, acl_denied, NULL, documenturi, all_attributes, attrkeys, htmlbuffersize);

#ifdef DEBUG	
	printf("legger til DocID \"%u\", time \"%u\"\n",ReposetoryHeader.DocID,lastmodified);
	printf("htmlSize %u, imageSize %ho\n",ReposetoryHeader.htmlSize2,ReposetoryHeader.imageSize);
	printf("html: -%s-\n",htmlbuffer);
#endif

	uriindex_add(documenturi,ReposetoryHeader.DocID,lastmodified,subname);

	free(all_attributes);
	free(htmlbuffer);
	free(documenttype_real);

	if (imagebuffer != NULL) {
		free(imagebuffer);
	}

	return 1;
}