Ejemplo n.º 1
0
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {

	int can_close = 1;

	if (fd == wsgi_req->sendfile_fd) can_close = 0;

	if (wsgi_req->write_errors) return -1;

	if (!wsgi_req->headers_sent) {
		int ret = uwsgi_response_write_headers_do(wsgi_req);
		if (ret == UWSGI_OK) goto sendfile;
		if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
		wsgi_req->write_errors++;
		if (can_close) close(fd);
		return -1;
	}

sendfile:

	if (len == 0) {
		struct stat st;
		if (fstat(fd, &st)) {
			uwsgi_error("fstat()");
			wsgi_req->write_errors++;
			if (can_close) close(fd);
			return -1;
		}
		if (pos >= (size_t)st.st_size) return UWSGI_OK;
		len = st.st_size;
	}

	if (wsgi_req->socket->can_offload) {
		// of we cannot close the socket (before the app will close it later)
		// let's dup it
		if (!can_close) {
			int tmp_fd = dup(fd);
			if (tmp_fd < 0) {
				uwsgi_error("uwsgi_response_sendfile_do()/dup()");
				wsgi_req->write_errors++;
				return -1;
			}
			fd = tmp_fd;
			can_close = 1;
		}
       		if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, len)) {
                	wsgi_req->via = UWSGI_VIA_OFFLOAD;
			wsgi_req->response_size += len;
                        return 0;
                }
		wsgi_req->write_errors++;
		if (can_close) close(fd);
		return -1;
	}


        wsgi_req->via = UWSGI_VIA_SENDFILE;

        for(;;) {
                int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
                if (ret < 0) {
                        if (!uwsgi.ignore_write_errors) {
                                uwsgi_error("uwsgi_response_sendfile_do()");
                        }
			wsgi_req->write_errors++;
			if (can_close) close(fd);
                        return -1;
                }
                if (ret == UWSGI_OK) {
                        break;
                }
                ret = uwsgi_wait_write_req(wsgi_req);
                if (ret < 0) {
			wsgi_req->write_errors++;
			if (can_close) close(fd);
			return -1;
		}
		if (ret == 0) {
                        uwsgi_log("uwsgi_response_sendfile_do() TIMEOUT !!!\n");
                        wsgi_req->write_errors++;
                        return -1;
                }	
        }

        wsgi_req->response_size += wsgi_req->write_pos;
	// reset for the next write
        wsgi_req->write_pos = 0;
	// close the file descriptor
	if (can_close) close(fd);
        return UWSGI_OK;
}
Ejemplo n.º 2
0
int uwsgi_routing_func_fastfile(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {

        struct stat st;
        int ret = UWSGI_ROUTE_BREAK;

        struct uwsgi_router_file_conf *urfc = (struct uwsgi_router_file_conf *) ur->data2;

        char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
        uint16_t *subject_len = (uint16_t *)  (((char *)(wsgi_req))+ur->subject_len);

        struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->filename, urfc->filename_len);
        if (!ub) return UWSGI_ROUTE_BREAK;

        int fd = open(ub->buf, O_RDONLY);
        if (fd < 0) {
                if (ur->custom)
                        ret = UWSGI_ROUTE_NEXT;
                goto end;
        }

        if (fstat(fd, &st)) {
                goto end2;
        }

        struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
        if (!ub_s) goto end2;

        // static file - don't update avg_rt after request
        wsgi_req->do_not_account_avg_rt = 1;

	if (urfc->no_headers) {
                uwsgi_buffer_destroy(ub_s);
		goto send;
	}

        if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
                uwsgi_buffer_destroy(ub_s);
                goto end2;
        }
        uwsgi_buffer_destroy(ub_s);
        if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end2;
        if (urfc->mime) {
                size_t mime_type_len = 0;
                char *mime_type = uwsgi_get_mime_type(ub->buf, ub->pos, &mime_type_len);
                if (mime_type) {
                        if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end2;
                }
                else {
                        if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
                }
        }
        else {
                if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
        }

send:

	if (!wsgi_req->headers_sent) {
                if (uwsgi_response_write_headers_do(wsgi_req)) goto end2;
        }

	if (wsgi_req->socket->can_offload) {
		if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, st.st_size)) {
                        wsgi_req->via = UWSGI_VIA_OFFLOAD;
                        wsgi_req->response_size += st.st_size;
                	// the fd will be closed by the offload engine
			goto end;
		}
	}

        if (!uwsgi_simple_sendfile(wsgi_req, fd, 0, st.st_size)) {
                wsgi_req->via = UWSGI_VIA_SENDFILE;
                wsgi_req->response_size += st.st_size;
        }

end2:
        close(fd);
end:
        uwsgi_buffer_destroy(ub);
        return ret;
}