static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { int ret = -1; // this is the list of args char *argv[UMAX8]; // this is the size of each argument uint16_t argvs[UMAX8]; // this is a placeholder for tmp uwsgi_buffers struct uwsgi_buffer *ubs[UMAX8]; char **r_argv = (char **) ur->data2; uint16_t *r_argvs = (uint16_t *) ur->data3; char **subject = (char **) (((char *)(wsgi_req))+ur->subject); uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len); uint64_t i; for(i=0;i<ur->custom;i++) { ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]); if (!ubs[i]) goto end; argv[i] = ubs[i]->buf; argvs[i] = ubs[i]->pos; } // ok we now need to check it it is a local call or a remote one char *func = uwsgi_str(ur->data); char *remote = NULL; char *at = strchr(func, '@'); if (at) { *at = 0; remote = at+1; } uint16_t size; char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size); free(func); if (!response) goto end; ret = UWSGI_ROUTE_NEXT; if (size == 0) goto end; ret = uwsgi_blob_to_response(wsgi_req, response, size); free(response); if (ret == 0) { ret = UWSGI_ROUTE_BREAK; } end: for(i=0;i<ur->custom;i++) { if (ubs[i] != NULL) { uwsgi_buffer_destroy(ubs[i]); } } return ret; }
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; }