int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffer *ub, size_t remains, int timeout) { int fd = uwsgi_connect(addr, 0, 1); if (fd < 0) { return -1; } int ret = uwsgi.wait_write_hook(fd, timeout); if (ret <= 0) { goto end; } // send the request (+ remaining data) if (ub) { if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) { goto end; } } // send the body while(remains > 0) { ssize_t rlen = 0; char *buf = uwsgi_request_body_read(wsgi_req, 8192, &rlen); if (!buf) { goto end; } if (buf == uwsgi.empty) break; // write data to the node if (uwsgi_write_true_nb(fd, buf, rlen, timeout)) { goto end; } remains -= rlen; } // read the response for(;;) { char buf[8192]; ssize_t rlen = uwsgi_read_true_nb(fd, buf, 8192, timeout); if (rlen > 0) { if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) { break; } continue; } break; } close(fd); return 0; end: close(fd); return -1; }
int uwsgi_wstcp(struct wsgi_request *wsgi_req) { if (uwsgi_parse_vars(wsgi_req)) return -1; // handshake the websocket connection if (uwsgi_websocket_handshake(wsgi_req, NULL, 0, NULL, 0, NULL, 0)) return -1; // async connect to the tcp server int fd = uwsgi_connect("127.0.0.1:9090", 0, 1); if (fd < 0) return -1; // wait for connection int ret = uwsgi.wait_write_hook(fd, 30); if (ret <= 0) { close(fd); return -1; } // ok we are connected, enter the main loop for(;;) { int ready_fd = -1; // wait for both websockets and tcp int ret = uwsgi.wait_read2_hook(wsgi_req->fd, fd, 30, &ready_fd); if (ret <= 0) break; // websocket message if (ready_fd == wsgi_req->fd) { // read websocket message struct uwsgi_buffer *ub = uwsgi_websocket_recv_nb(wsgi_req); if (!ub) break; // send to tcp if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, 30)) break; } // packet from tcp else if (ready_fd == fd) { char buf[8192]; // read from the tcp socket ssize_t rlen = uwsgi_read_true_nb(fd, buf, 8192, 30); if (rlen <= 0) break; // send to the websocket if (uwsgi_websocket_send_binary(wsgi_req, buf, rlen)) break; } } // end of the session close(fd); return UWSGI_OK; }
static int fcgi_send(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffer *ub, int timeout) { int fd = uwsgi_connect(addr, 0, 1); if (fd < 0) return -1; int ret = uwsgi.wait_write_hook(fd, timeout); if (ret <= 0) goto error; if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto error; return fd; error: close(fd); return -1; }
static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t docroot_len, char *full_path, char *helper, char *path_info, char *script_name, int is_a_file, int discard_base) { int cgi_pipe[2]; int post_pipe[2]; int nargs = 0; int waitpid_status; int i; char **argv; char *command = full_path; if (is_a_file) { command = docroot; } if (pipe(cgi_pipe)) { uwsgi_error("uwsgi_cgi_run()/pipe()"); return UWSGI_OK; } if (pipe(post_pipe)) { close(cgi_pipe[0]); close(cgi_pipe[1]); uwsgi_error("uwsgi_cgi_run()/pipe()"); return UWSGI_OK; } pid_t cgi_pid = fork(); if (cgi_pid < 0) { uwsgi_error("uwsgi_cgi_run()/fork()"); close(cgi_pipe[0]); close(cgi_pipe[1]); close(post_pipe[0]); close(post_pipe[1]); return UWSGI_OK; } if (cgi_pid > 0) { close(cgi_pipe[1]); close(post_pipe[0]); uwsgi_socket_nb(cgi_pipe[0]); uwsgi_socket_nb(post_pipe[1]); // ok start sending post data... size_t remains = wsgi_req->post_cl; while(remains > 0) { ssize_t rlen = 0; char *buf = uwsgi_request_body_read(wsgi_req, 8192, &rlen); if (!buf) { goto clear2; } if (buf == uwsgi.empty) break; // write data to the node if (uwsgi_write_true_nb(post_pipe[1], buf, rlen, uc.timeout)) { goto clear2; } remains -= rlen; } // wait for data char *buf = uwsgi_malloc(uc.buffer_size); int completed = uwsgi_cgi_parse(wsgi_req, cgi_pipe[0], buf, uc.buffer_size); if (completed < 0) { uwsgi_log("invalid CGI response !!!\n"); kill_on_error goto clear; }
static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){ // this is the buffer for the memcached response char buf[MEMCACHED_BUFSIZE]; size_t i; char last_char = 0; struct uwsgi_router_memcached_conf *urmc = (struct uwsgi_router_memcached_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_key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->key, urmc->key_len); if (!ub_key) return UWSGI_ROUTE_BREAK; int fd = uwsgi_connect(urmc->addr, 0, 1); if (fd < 0) { uwsgi_buffer_destroy(ub_key) ; goto end; } // wait for connection; int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); if (ret <= 0) { uwsgi_buffer_destroy(ub_key) ; close(fd); goto end; } // build the request and send it char *cmd = uwsgi_concat3n("get ", 4, ub_key->buf, ub_key->pos, "\r\n", 2); if (uwsgi_write_true_nb(fd, cmd, 6+ub_key->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) { uwsgi_buffer_destroy(ub_key); free(cmd); close(fd); goto end; } uwsgi_buffer_destroy(ub_key); free(cmd); // ok, start reading the response... // first we need to get a full line; size_t found = 0; size_t pos = 0; for(;;) { ssize_t len = read(fd, buf + pos, MEMCACHED_BUFSIZE - pos); if (len > 0) { pos += len; goto read; } if (len < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait; } close(fd); goto end; wait: ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); // when we have a chunk try to read the first line if (ret > 0) { len = read(fd, buf + pos, MEMCACHED_BUFSIZE - pos); if (len > 0) { pos += len; goto read; } } close(fd); goto end; read: for(i=0;i<pos;i++) { if (last_char == '\r' && buf[i] == '\n') { found = i-1; break; } last_char = buf[i]; } if (found) break; } // ok parse the first line size_t response_size = memcached_firstline_parse(buf, found); if (response_size == 0) { close(fd); goto end; } if (urmc->type_num == 1) { if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) { close(fd); goto end; } if (uwsgi_response_add_content_type(wsgi_req, urmc->content_type, urmc->content_type_len)) { close(fd); goto end; } if (uwsgi_response_add_content_length(wsgi_req, response_size)) { close(fd); goto end; } } size_t remains = pos-(found+2); if (remains >= response_size) { uwsgi_response_write_body_do(wsgi_req, buf+found+2, response_size); close(fd); goto end; } // send what we have if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) { close(fd); goto end; } // and now start reading til the output is consumed response_size -= remains; while(response_size > 0) { ssize_t len = read(fd, buf, UMIN(MEMCACHED_BUFSIZE, response_size)); if (len > 0) goto write; if (len < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2; } goto error; wait2: ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); if (ret > 0) { len = read(fd, buf, UMIN(MEMCACHED_BUFSIZE, response_size)); if (len > 0) goto write; } goto error; write: if (uwsgi_response_write_body_do(wsgi_req, buf, len)) { goto error; } response_size -= len; } close(fd); return UWSGI_ROUTE_BREAK; error: close(fd); end: if (ur->custom) return UWSGI_ROUTE_NEXT; return UWSGI_ROUTE_BREAK; }