예제 #1
0
파일: writer.c 프로젝트: JuanS/uwsgi
/*
	simplified write to client
	(generally used as fallback)
*/
int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {

	wsgi_req->write_pos = 0;

	for(;;) {
                int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
                if (ret < 0) {
                        if (!uwsgi.ignore_write_errors) {
                                uwsgi_error("uwsgi_simple_write()");
                        }
                        wsgi_req->write_errors++;
                        return -1;
                }
                if (ret == UWSGI_OK) {
                        break;
                }
                ret = uwsgi_wait_write_req(wsgi_req);
                if (ret < 0) { wsgi_req->write_errors++; return -1;}
                if (ret == 0) {
                        uwsgi_log("uwsgi_simple_write() TIMEOUT !!!\n");
                        wsgi_req->write_errors++;
                        return -1;
                }
        }
        return 0;
}
예제 #2
0
파일: writer.c 프로젝트: thrashaholic/uwsgi
// this is the function called by all request plugins to send chunks to the client
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {

	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 sendbody;
                if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
		wsgi_req->write_errors++;
                return -1;
	}

sendbody:

	if (len == 0) return UWSGI_OK;

	for(;;) {
		int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
		if (ret < 0) {
			if (!uwsgi.ignore_write_errors) {
				uwsgi_error("uwsgi_response_write_body_do()");
			}
			wsgi_req->write_errors++;
			return -1;
		}
		if (ret == UWSGI_OK) {
			break;
		}
		ret = uwsgi_wait_write_req(wsgi_req);			
		if (ret < 0) { wsgi_req->write_errors++; return -1;}
                if (ret == 0) {
                        uwsgi_log("uwsgi_response_write_body_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;

	// now we need to check if the chunk must be stored
	if (wsgi_req->cache_it) {
		if (!wsgi_req->cached_response) {
			wsgi_req->cached_response = uwsgi_buffer_new(len);
		}
		// if we are unable to append the buffer, we just stop caching it
		if (uwsgi_buffer_append(wsgi_req->cached_response, buf, len)) {
			uwsgi_buffer_destroy(wsgi_req->cache_it);
			wsgi_req->cache_it = NULL;
		}
	}

	return UWSGI_OK;	
}
예제 #3
0
파일: writer.c 프로젝트: toofishes/uwsgi
// this is the function called by all request plugins to send chunks to the client
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {

	if (wsgi_req->write_errors) return -1;

	// do not commit headers until a response_buffer is available
	if (!wsgi_req->response_buffer && !wsgi_req->headers_sent) {
		int ret = uwsgi_response_write_headers_do(wsgi_req);
                if (ret == UWSGI_OK) goto sendbody;
                if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
		wsgi_req->write_errors++;
                return -1;
	}

sendbody:

	if (len == 0) return UWSGI_OK;
	
	if (wsgi_req->response_buffer) {
		if (uwsgi_buffer_append(wsgi_req->response_buffer, buf, len)) {
			wsgi_req->write_errors++;
			return -1;
		}
		return UWSGI_OK;
	}

	for(;;) {
		int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
		if (ret < 0) {
			if (!uwsgi.ignore_write_errors) {
				uwsgi_error("uwsgi_response_write_body_do()");
			}
			wsgi_req->write_errors++;
			return -1;
		}
		if (ret == UWSGI_OK) {
			break;
		}
		ret = uwsgi_wait_write_req(wsgi_req);			
		if (ret < 0) { wsgi_req->write_errors++; return -1;}
                if (ret == 0) {
                        uwsgi_log("uwsgi_response_write_body_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;

	return UWSGI_OK;	
}
예제 #4
0
파일: writer.c 프로젝트: thrashaholic/uwsgi
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
	if (wsgi_req->headers_sent || !wsgi_req->headers || wsgi_req->response_size || wsgi_req->write_errors) {
		return UWSGI_OK;
	}

	struct uwsgi_string_list *ah = uwsgi.additional_headers;
	while(ah) {
		if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
                ah = ah->next;
        }

        ah = wsgi_req->additional_headers;
        while(ah) {
		if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
                ah = ah->next;
        }


	if (wsgi_req->socket->proto_fix_headers(wsgi_req)) { wsgi_req->write_errors++ ; return -1;}

	for(;;) {
                int ret = wsgi_req->socket->proto_write_headers(wsgi_req, wsgi_req->headers->buf, wsgi_req->headers->pos);
                if (ret < 0) {
                        if (!uwsgi.ignore_write_errors) {
                                uwsgi_error("uwsgi_response_write_headers_do()");
                        }
			wsgi_req->write_errors++;
                        return -1;
                }
                if (ret == UWSGI_OK) {
                        break;
                }
                ret = uwsgi_wait_write_req(wsgi_req);
                if (ret < 0) { wsgi_req->write_errors++; return -1;}
                if (ret == 0) {
			uwsgi_log("uwsgi_response_write_headers_do() TIMEOUT !!!\n");
			wsgi_req->write_errors++;
			return -1;
		}
        }

        wsgi_req->headers_size += wsgi_req->write_pos;
	// reset for the next write
        wsgi_req->write_pos = 0;
	wsgi_req->headers_sent = 1;

        return UWSGI_OK;
}
예제 #5
0
파일: writer.c 프로젝트: thrashaholic/uwsgi
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;
}
예제 #6
0
파일: writer.c 프로젝트: JuanS/uwsgi
// this is the function called by all request plugins to send chunks to the client
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {

	if (wsgi_req->write_errors) return -1;
	if (wsgi_req->ignore_body) return UWSGI_OK;

	// if the transformation chain returns 1, we are in buffering mode
	if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
		int t_ret = uwsgi_apply_transformations(wsgi_req, buf, len);
		if (t_ret == 0) {
			buf = wsgi_req->transformed_chunk;
			len = wsgi_req->transformed_chunk_len;
			// reset transformation
			wsgi_req->transformed_chunk = NULL;
			wsgi_req->transformed_chunk_len = 0;
			goto write;
		}
		if (t_ret == 1) {
			return UWSGI_OK;
		}
		wsgi_req->write_errors++;
		return -1;
	}

write:
	// send headers if not already sent
	if (!wsgi_req->headers_sent) {
		int ret = uwsgi_response_write_headers_do(wsgi_req);
                if (ret == UWSGI_OK) goto sendbody;
                if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
		wsgi_req->write_errors++;
                return -1;
	}

sendbody:

	if (len == 0) return UWSGI_OK;
	
	for(;;) {
		int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
		if (ret < 0) {
			if (!uwsgi.ignore_write_errors) {
				uwsgi_error("uwsgi_response_write_body_do()");
			}
			wsgi_req->write_errors++;
			return -1;
		}
		if (ret == UWSGI_OK) {
			break;
		}
		ret = uwsgi_wait_write_req(wsgi_req);			
		if (ret < 0) { wsgi_req->write_errors++; return -1;}
                if (ret == 0) {
                        uwsgi_log("uwsgi_response_write_body_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;

	return UWSGI_OK;	
}