Example #1
0
void websrv_output(struct websrv_context *web, void *data, size_t length)
{
	data_blob_append(web, &web->output.content, data, length);
	EVENT_FD_NOT_READABLE(web->conn->event.fde);
	EVENT_FD_WRITEABLE(web->conn->event.fde);
	web->output.output_pending = true;
}
/*
  destroy a pending request
*/
static int nbt_name_request_destructor(struct nbt_name_request *req)
{	
	if (req->state == NBT_REQUEST_SEND) {
		DLIST_REMOVE(req->nbtsock->send_queue, req);
	}
	if (req->state == NBT_REQUEST_WAIT) {
		req->nbtsock->num_pending--;
	}
	if (req->name_trn_id != 0 && !req->is_reply) {
		idr_remove(req->nbtsock->idr, req->name_trn_id);
		req->name_trn_id = 0;
	}
	if (req->te) {
		req->te = NULL;
	}
	if (req->nbtsock->send_queue == NULL) {
		EVENT_FD_NOT_WRITEABLE(req->nbtsock->fde);
	}
	if (req->nbtsock->num_pending == 0 && 
	    req->nbtsock->incoming.handler == NULL) {
		EVENT_FD_NOT_READABLE(req->nbtsock->fde);
	}

	/* once this has been called for this req, don't call again */
	talloc_set_destructor(req, NULL);

	return 0;
}
Example #3
0
/*
  called when a web connection becomes readable
*/
static void websrv_recv(struct stream_connection *conn, uint16_t flags)
{
	struct web_server_data *wdata;
	struct websrv_context *web = talloc_get_type(conn->private_data,
						     struct websrv_context);
	NTSTATUS status;
	uint8_t buf[1024];
	size_t nread;
	uint8_t *p;
	DATA_BLOB b;

	/* not the most efficient http parser ever, but good enough for us */
	status = socket_recv(conn->socket, buf, sizeof(buf), &nread);
	if (NT_STATUS_IS_ERR(status)) goto failed;
	if (!NT_STATUS_IS_OK(status)) return;

	if (!data_blob_append(web, &web->input.partial, buf, nread))
		goto failed;

	/* parse any lines that are available */
	b = web->input.partial;
	while (!web->input.end_of_headers &&
	       (p=(uint8_t *)memchr(b.data, '\n', b.length))) {
		const char *line = (const char *)b.data;
		*p = 0;
		if (p != b.data && p[-1] == '\r') {
			p[-1] = 0;
		}
		status = http_parse_header(web, line);
		if (!NT_STATUS_IS_OK(status)) return;
		b.length -= (p - b.data) + 1;
		b.data = p+1;
	}

	/* keep any remaining bytes in web->input.partial */
	if (b.length == 0) {
		b.data = NULL;
	}
	b = data_blob_talloc(web, b.data, b.length);
	data_blob_free(&web->input.partial);
	web->input.partial = b;

	/* we finish when we have both the full headers (terminated by
	   a blank line) and any post data, as indicated by the
	   content_length */
	if (web->input.end_of_headers &&
	    web->input.partial.length >= web->input.content_length) {
		if (web->input.partial.length > web->input.content_length) {
			web->input.partial.data[web->input.content_length] = 0;
		}
		EVENT_FD_NOT_READABLE(web->conn->event.fde);

		/* the reference/unlink code here is quite subtle. It
		 is needed because the rendering of the web-pages, and
		 in particular the esp/ejs backend, is semi-async.  So
		 we could well end up in the connection timeout code
		 while inside http_process_input(), but we must not
		 destroy the stack variables being used by that
		 rendering process when we handle the timeout. */
		if (!talloc_reference(web->task, web)) goto failed;
		wdata = talloc_get_type(web->task->private_data, struct web_server_data);
		if (wdata == NULL) goto failed;
		wdata->http_process_input(wdata, web);
		talloc_unlink(web->task, web);
	}
	return;

failed:
	stream_terminate_connection(conn, "websrv_recv: failed");
}