コード例 #1
0
ファイル: wsgi_handlers.c プロジェクト: StephenPierce/uwsgi
ssize_t uwsgi_python_hook_simple_input_readline(struct wsgi_request *wsgi_req, char *readline, size_t max_size) {
	ssize_t rlen = 0;
	UWSGI_RELEASE_GIL;
        if (uwsgi_waitfd(wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
                UWSGI_GET_GIL
		return 0;
        }
コード例 #2
0
ファイル: io.c プロジェクト: tinyserver/uwsgi
// like uwsgi_pipe but with fixed size
ssize_t uwsgi_pipe_sized(int src, int dst, size_t required, int timeout) {
	char buf[8192];
	size_t written = 0;
	ssize_t len;

	while (written < required) {
		int ret = uwsgi_waitfd(src, timeout);
		if (ret > 0) {
			len = read(src, buf, UMIN(8192, required - written));
			if (len == 0) {
				return written;
			}
			else if (len < 0) {
				uwsgi_error("read()");
				return -1;
			}

			size_t remains = len;
			while (remains > 0) {
				int ret = uwsgi_waitfd_write(dst, timeout);
				if (ret > 0) {
					len = write(dst, buf, remains);
					if (len > 0) {
						remains -= len;
						written += len;
					}
					else if (len == 0) {
						return written;
					}
					else {
						uwsgi_error("write()");
						return -1;
					}
				}
				else if (ret == 0) {
					goto timeout;
				}
				else {
					return -1;
				}
			}
		}
		else if (ret == 0) {
			goto timeout;
		}
		else {
			return -1;
		}
	}

	return written;
timeout:
	uwsgi_log("timeout while piping from %d to %d !!!\n", src, dst);
	return -1;
}
コード例 #3
0
ファイル: io.c プロジェクト: tinyserver/uwsgi
int uwsgi_read_nb(int fd, char *buf, size_t remains, int timeout) {
	char *ptr = buf;
        while(remains > 0) {
                int ret = uwsgi_waitfd(fd, timeout);
                if (ret > 0) {
                        ssize_t len = read(fd, ptr, remains);
                        if (len <= 0) {
                                return -1;
                        }
                        remains -=len;
                        ptr +=len;
                        continue;
                }
                return -1;
        }

        return 0;
}
コード例 #4
0
ファイル: io.c プロジェクト: tinyserver/uwsgi
int uwsgi_read_uh(int fd, struct uwsgi_header *uh, int timeout) {
	char *ptr = (char *) uh;
	size_t remains = 4;
	while(remains > 0) {
		int ret = uwsgi_waitfd(fd, timeout);
		if (ret > 0) {
			ssize_t len = read(fd, ptr, remains);
			if (len <= 0) {
				return -1;
			}
			remains -=len;
			ptr +=len;
			continue;
		}
		return -1;
	}

	return 0;
}
コード例 #5
0
PyObject *uwsgi_Input_getline(uwsgi_Input *self) {
	size_t i;
	ssize_t rlen;
	struct wsgi_request *wsgi_req = self->wsgi_req;
	PyObject *res;

	char *ptr = self->readline;

	if (uwsgi.post_buffering > 0) {
		ptr = wsgi_req->post_buffering_buf;
		self->readline_size = wsgi_req->post_cl;
		if (!self->readline_pos) {
			self->pos += self->readline_size;
		}
	}

	if (self->readline_pos > 0 || uwsgi.post_buffering) {
		for(i=self->readline_pos;i<self->readline_size;i++) {
			if (ptr[i] == '\n') {
				res = PyString_FromStringAndSize(ptr+self->readline_pos, (i-self->readline_pos)+1);
				self->readline_pos = i+1;
				if (self->readline_pos >= self->readline_size) self->readline_pos = 0;
				return res;
			}
		}
		res = PyString_FromStringAndSize(ptr + self->readline_pos, self->readline_size - self->readline_pos);
		self->readline_pos = 0;
		return res;
	}


	UWSGI_RELEASE_GIL;
	if (uwsgi_waitfd(wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
                UWSGI_GET_GIL
                return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data");
        }
コード例 #6
0
ファイル: python_plugin.c プロジェクト: dpetzold/uwsgi
void uwsgi_python_harakiri(int wid) {

	if (up.tracebacker) {

        	char buf[8192];
		char *address = uwsgi_concat2(up.tracebacker, uwsgi_num2str(wid));

        	int fd = uwsgi_connect(address, -1, 0);
        	for (;;) {
                	int ret = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
                	if (ret <= 0) {
				break;
                	}
                	ssize_t len = read(fd, buf, 8192);
                	if (len <= 0) {
				break;
                	}
                	uwsgi_log("%.*s", (int) len, buf);
        	}

		free(address);
	}

}
コード例 #7
0
ファイル: router_fcgi.c プロジェクト: Variousss/uwsgi
static int uwsgi_routing_func_fcgi(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
	struct uwsgi_buffer *ub = NULL, *headers = NULL;
	int ret = UWSGI_ROUTE_BREAK;
	int inbody = 0;

	// mark a route request
        wsgi_req->via = UWSGI_VIA_ROUTE;

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

	struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
	if (!ub_addr) return UWSGI_ROUTE_BREAK;

	// convert the wsgi_request to an fcgi request
	ub = uwsgi_to_fastcgi(wsgi_req, ur->custom ? FCGI_AUTHORIZER : FCGI_RESPONDER);

	if (!ub) {
		uwsgi_log("unable to generate fcgi request for %s\n", ub_addr->buf);
		uwsgi_buffer_destroy(ub_addr);
                return UWSGI_ROUTE_BREAK;
	}

	int fd = 0;

	fd = fcgi_send(wsgi_req, ub_addr->buf, ub, uwsgi.socket_timeout);
	uwsgi_buffer_destroy(ub);
	ub = NULL;

	if (fd == -1) {
		uwsgi_log("error routing request to fcgi server %s\n", ub_addr->buf);
		goto end;
	}

	headers = uwsgi_buffer_new(uwsgi.page_size);
	char buf[8192];
	char *ptr = buf;//, *rptr = NULL;
	ssize_t left = 0, n = 0, p = 0;
	int oversized = 0, done = 0;


	for (;;) {
                int r = uwsgi_waitfd(fd, uwsgi.socket_timeout);
                if (r <= 0) goto end;

		ssize_t rlen = 0;
		/* Amount left in buffer is not a full record header, so we
		 * need to fudge the next read to append to the current buffer. */
		if ((sizeof(buf) - (ptr - buf) - left) < 8) {
			memmove(buf, ptr, left);
			ptr = buf;
		}

		if ((!done || !left) && (sizeof(buf) - (ptr - buf) - left) > 0) {
			rlen = read(fd, ptr + left, sizeof(buf) - (ptr - buf) - left);

			if (rlen < 0)
				break;
			if (rlen == 0)
				done = 1;
		}

		if (done && !left) {
			uwsgi_log("[fastcgi] %s: truncated response\n", ub_addr->buf);
			goto end;
		}

		if (oversized) { /* n more bytes left in stdout record */
			if (uwsgi_response_write_body_do(wsgi_req, (char *) ptr, n > rlen ? rlen : n))
				goto end;

			if (n > rlen) {
				n -= rlen;
				ptr = buf;
				left = 0;
				continue;
			} else if (n == rlen) {
				oversized = 0;
				left = 0;
				ptr = buf;
				continue;
			} else {
				ptr += n;
				left = rlen - n;
				oversized = 0;
				continue;
			}
		} else {
			left += rlen;
		}

		while (left >= 8 && !oversized) {
			if (p) {
				if (left >= p) {
					left -= p;
					ptr += p;
					p = 0;
					continue;
				}
			}

			if (ptr[0] != 1) { /* version */
				uwsgi_log("[fastcgi] %s: unexpected protocol version %u\n", ub_addr->buf, (unsigned int) ptr[0]);
				goto end;
			}
			if (ptr[2] != 0 || ptr[3] != 1) { /* reqid */
				uwsgi_log("[fastcgi] %s: unexpected request id %d\n", ub_addr->buf, (int) ptr[3]);
				goto end;
			}
			n = (int)((unsigned char *)ptr)[4] << 8 | (int)((unsigned char *)ptr)[5];
			p = (int)((unsigned char *)ptr)[6];

			int type = ptr[1];
			ptr += 8;
			left -= 8;
			switch (type) {
			case FCGI_END_REQUEST:
				break;

			case FCGI_STDERR:
				uwsgi_log("[fastcgi] %s: stderr: %*s\n", ub_addr->buf, (int) (n > left ? left : n), ptr);
				if ((n + p) > left) {
					uwsgi_log("[fastcgi] %s: short record, (%d + %d) < %d\n", ub_addr->buf, (int) n, (int) p, (int) left);
					goto end;
				}
				ptr += (n + p);
				left -= (n + p);
				break;

			case FCGI_STDOUT:
				if (n == 0)
					goto end;

				if (!inbody) {
					ssize_t now = n < left ? n : left;
					if (uwsgi_buffer_append(headers, (char *) ptr, now))
						goto end;

					// check if we have a full HTTP response
					if (uwsgi_is_full_http(headers)) {
						inbody = 1;
						if (ur->custom && http_status_code(headers->buf, headers->pos) == 200) {
							ret = UWSGI_ROUTE_NEXT;
							/* XXX - add Variable headers */
							goto end;
						} else {
							uwsgi_blob_to_response(wsgi_req, headers->buf, headers->pos);
						}
						uwsgi_buffer_destroy(headers);
						headers = NULL;
					} else {
						/* we can't buffer > sizeof(buf) of headers - shouldn't be
						 * needed anyway. */
						if (n > left) {
							uwsgi_log("[fastcgi] %s: headers too long (%d)\n", ub_addr->buf, (int) n);
							goto end;
						}
					}

					ptr += now;
					left -= now;
					n -= now;
				}

				if (n) {
					ssize_t nleft = n > left ? left : n; /* min(left in buffer, record size) */
					if (uwsgi_response_write_body_do(wsgi_req, (char *) ptr, nleft))
						goto end;
					n -= nleft;
					left -= nleft;
					ptr += nleft;

					if (n > left) { /* more data in this record */
						oversized = 1;
						left = 0;
						ptr = buf;
						continue;
					}
				}

				break;

			default:
				uwsgi_log("[fastcgi] %s: unknown record type %d\n", ub_addr->buf, (int) ptr[1]);
				goto end;
			}
		}

		if (left == 0)
			ptr = buf;
	}

end:
	if (fd) close(fd);
	if (ub) uwsgi_buffer_destroy(ub);
	if (ub_addr) uwsgi_buffer_destroy(ub_addr);
	if (headers) uwsgi_buffer_destroy(headers);
	return ret;
}
コード例 #8
0
ファイル: io.c プロジェクト: tinyserver/uwsgi
/*
	extremely complex function for reading resources (files, url...)
	need a lot of refactoring...
*/
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {

	int fd;
	struct stat sb;
	char *buffer = NULL;
	char byte;
	ssize_t len;
	char *uri, *colon;
	char *domain;
	char *ip;
	int body = 0;
	char *magic_buf;

	// stdin ?
	if (!strcmp(url, "-")) {
		buffer = uwsgi_read_fd(0, size, add_zero);
	}
	// fd ?
	else if (!strncmp("fd://", url, 5)) {
		fd = atoi(url + 5);
		buffer = uwsgi_read_fd(fd, size, add_zero);
	}
	// exec ?
	else if (!strncmp("exec://", url, 5)) {
		int cpipe[2];
		if (pipe(cpipe)) {
			uwsgi_error("pipe()");
			exit(1);
		}
		uwsgi_run_command(url + 7, NULL, cpipe[1]);
		buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
		close(cpipe[0]);
		close(cpipe[1]);
	}
	// http url ?
	else if (!strncmp("http://", url, 7)) {
		domain = url + 7;
		uri = strchr(domain, '/');
		if (!uri) {
			uwsgi_log("invalid http url\n");
			exit(1);
		}
		uri[0] = 0;
		uwsgi_log("domain: %s\n", domain);

		colon = uwsgi_get_last_char(domain, ':');

		if (colon) {
			colon[0] = 0;
		}


		ip = uwsgi_resolve_ip(domain);
		if (!ip) {
			uwsgi_log("unable to resolve address %s\n", domain);
			exit(1);
		}

		if (colon) {
			colon[0] = ':';
			ip = uwsgi_concat2(ip, colon);
		}
		else {
			ip = uwsgi_concat2(ip, ":80");
		}

		fd = uwsgi_connect(ip, 0, 0);

		if (fd < 0) {
			exit(1);
		}

		free(ip);

		uri[0] = '/';

		len = write(fd, "GET ", 4);
		len = write(fd, uri, strlen(uri));
		len = write(fd, " HTTP/1.0\r\n", 11);
		len = write(fd, "Host: ", 6);

		uri[0] = 0;
		len = write(fd, domain, strlen(domain));
		uri[0] = '/';

		len = write(fd, "\r\nUser-Agent: uWSGI on ", 23);
		len = write(fd, uwsgi.hostname, uwsgi.hostname_len);
		len = write(fd, "\r\n\r\n", 4);

		int http_status_code_ptr = 0;

		while (read(fd, &byte, 1) == 1) {
			if (byte == '\r' && body == 0) {
				body = 1;
			}
			else if (byte == '\n' && body == 1) {
				body = 2;
			}
			else if (byte == '\r' && body == 2) {
				body = 3;
			}
			else if (byte == '\n' && body == 3) {
				body = 4;
			}
			else if (body == 4) {
				*size = *size + 1;
				char *tmp = realloc(buffer, *size);
				if (!tmp) {
					uwsgi_error("uwsgi_open_and_read()/realloc()");
					exit(1);
				}
				buffer = tmp;
				buffer[*size - 1] = byte;
			}
			else {
				body = 0;
				http_status_code_ptr++;
				if (http_status_code_ptr == 10) {
					if (byte != '2') {
						uwsgi_log("Not usable HTTP response: %cxx\n", byte);
						if (uwsgi.has_emperor) {
							exit(UWSGI_EXILE_CODE);
						}
						else {
							exit(1);
						}
					}
				}
			}
		}

		close(fd);

		if (add_zero) {
			*size = *size + 1;
			char *tmp = realloc(buffer, *size);
			if (!tmp) {
				uwsgi_error("uwsgi_open_and_read()/realloc()");
				exit(1);
			}
			buffer = tmp;
			buffer[*size - 1] = 0;
		}

	}
	else if (!strncmp("emperor://", url, 10)) {
		if (uwsgi.emperor_fd_config < 0) {
			uwsgi_log("this is not a vassal instance\n");
			exit(1);
		}
		ssize_t rlen;
		*size = 0;
		struct uwsgi_header uh;
		size_t remains = 4;
		char *ptr = (char *) &uh;
		while(remains) {
			int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
			if (ret <= 0) {
				uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
				exit(1);
			}
			rlen = read(uwsgi.emperor_fd_config, ptr, remains);
			if (rlen <= 0) {
				uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
				exit(1);
			}
			ptr+=rlen;
			remains-=rlen;
		}

		remains = uh.pktsize;
		if (!remains) {
			uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
			exit(1);
		}

		buffer = uwsgi_calloc(remains + add_zero);
		ptr = buffer;
		while (remains) {
			int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
                        if (ret <= 0) {
                                uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
                                exit(1);
                        }
			rlen = read(uwsgi.emperor_fd_config, ptr, remains);
			if (rlen <= 0) {
                                uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
                                exit(1);
                        }
                        ptr+=rlen;
                        remains-=rlen;
		}

		*size = uh.pktsize + add_zero;
	}
#ifdef UWSGI_EMBED_CONFIG
	else if (url[0] == 0) {
		*size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG;
		if (add_zero) {
			*size += 1;
		}
		buffer = uwsgi_malloc(*size);
		memset(buffer, 0, *size);
		memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG);
	}
#endif
	else if (!strncmp("data://", url, 7)) {
		fd = open(uwsgi.binary_path, O_RDONLY);
		if (fd < 0) {
			uwsgi_error_open(uwsgi.binary_path);
			exit(1);
		}
		int slot = atoi(url + 7);
		if (slot < 0) {
			uwsgi_log("invalid binary data slot requested\n");
			exit(1);
		}
		uwsgi_log("requesting binary data slot %d\n", slot);
		off_t fo = lseek(fd, 0, SEEK_END);
		if (fo < 0) {
			uwsgi_error("lseek()");
			uwsgi_log("invalid binary data slot requested\n");
			exit(1);
		}
		int i = 0;
		uint64_t datasize = 0;
		for (i = 0; i <= slot; i++) {
			fo = lseek(fd, -9, SEEK_CUR);
			if (fo < 0) {
				uwsgi_error("lseek()");
				uwsgi_log("invalid binary data slot requested\n");
				exit(1);
			}
			ssize_t len = read(fd, &datasize, 8);
			if (len != 8) {
				uwsgi_error("read()");
				uwsgi_log("invalid binary data slot requested\n");
				exit(1);
			}
			if (datasize == 0) {
				uwsgi_log("0 size binary data !!!\n");
				exit(1);
			}
			fo = lseek(fd, -(datasize + 9), SEEK_CUR);
			if (fo < 0) {
				uwsgi_error("lseek()");
				uwsgi_log("invalid binary data slot requested\n");
				exit(1);
			}

			if (i == slot) {
				*size = datasize;
				if (add_zero) {
					*size += 1;
				}
				buffer = uwsgi_malloc(*size);
				memset(buffer, 0, *size);
				len = read(fd, buffer, datasize);
				if (len != (ssize_t) datasize) {
					uwsgi_error("read()");
					uwsgi_log("invalid binary data slot requested\n");
					exit(1);
				}
			}
		}
	}
	else if (!strncmp("sym://", url, 6)) {
		char *symbol = uwsgi_concat3("_binary_", url + 6, "_start");
		void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
		if (!sym_start_ptr) {
			uwsgi_log("unable to find symbol %s\n", symbol);
			exit(1);
		}
		free(symbol);
		symbol = uwsgi_concat3("_binary_", url + 6, "_end");
		void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
		if (!sym_end_ptr) {
			uwsgi_log("unable to find symbol %s\n", symbol);
			exit(1);
		}
		free(symbol);

		*size = sym_end_ptr - sym_start_ptr;
		if (add_zero) {
			*size += 1;
		}
		buffer = uwsgi_malloc(*size);
		memset(buffer, 0, *size);
		memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);

	}
#ifdef UWSGI_ELF
	else if (!strncmp("section://", url, 10)) {
		size_t s_len = 0;
		buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len);
		if (!buffer) {
			uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
			exit(1);
		}
		*size = s_len;
		if (add_zero)
			*size += 1;
	}
#endif
	// fallback to file
	else {
		fd = open(url, O_RDONLY);
		if (fd < 0) {
			uwsgi_error_open(url);
			exit(1);
		}

		if (fstat(fd, &sb)) {
			uwsgi_error("fstat()");
			exit(1);
		}

		if (S_ISFIFO(sb.st_mode)) {
			buffer = uwsgi_read_fd(fd, size, add_zero);
			close(fd);
			goto end;
		}

		buffer = uwsgi_malloc(sb.st_size + add_zero);

		len = read(fd, buffer, sb.st_size);
		if (len != sb.st_size) {
			uwsgi_error("read()");
			exit(1);
		}

		close(fd);

		*size = sb.st_size + add_zero;

		if (add_zero)
			buffer[sb.st_size] = 0;
	}

end:

	if (magic_table) {

		magic_buf = magic_sub(buffer, *size, size, magic_table);
		free(buffer);
		return magic_buf;
	}

	return buffer;
}