int uwsgi_read_whole_true_nb(int fd, char *buf, size_t remains, int timeout) { char *ptr = buf; while(remains > 0) { ssize_t len = uwsgi_read_true_nb(fd, ptr, remains, timeout); if (len <= 0) return -1; ptr += len; remains -= len; } return 0; }
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 uwsgi_cgi_parse(struct wsgi_request *wsgi_req, int fd, char *buf, size_t blen) { size_t i; size_t header_size = 0; int status_sent = 0; size_t remains = blen; char *ptr = buf; size_t len = 0; while(remains > 0) { ssize_t rlen = uwsgi_read_true_nb(fd, ptr, remains, uc.timeout); if (rlen < 0) { if (!errno) return 1; return -1; } // timed out if (rlen == 0) return -1; remains -= rlen; len += rlen; ptr += rlen; // Search for Status/Location headers if (!status_sent) { status_sent = uwsgi_cgi_check_status(wsgi_req, buf, len); if (status_sent < 0) return -1; // need more data ? if (status_sent == 0) continue; } // send headers char *key = buf; char *value = NULL; for(i=0;i<len;i++) { // end of a line if (buf[i] == '\n') { // end of headers if (key == NULL) { i++; goto send_body; } // invalid header else if (value == NULL) { return -1; } header_size = (buf+i) - key; // security check if (buf+i > buf) { if ((buf[i-1]) == '\r') { header_size--; } } #ifdef UWSGI_DEBUG uwsgi_log("found CGI header: %.*s\n", header_size, key); #endif // Ignore "Status: NNN" header if (header_size >= 11) { if (!strncasecmp("Status: ", key, 8)) { key = NULL; value = NULL; continue; } } uwsgi_response_add_header(wsgi_req, NULL, 0, key, header_size); key = NULL; value = NULL; } else if (buf[i] == ':') { value = buf+i; } else if (buf[i] != '\r') { if (key == NULL) { key = buf + i; } } } } return -1; send_body: if (len-i > 0) { uwsgi_response_write_body_do(wsgi_req, buf+i, len-i); } return 0; }