static int uwsgi_routing_func_rpc_blob(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; // optimization if (!wsgi_req->headers_sent) { if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {free(response) ; goto end;} if (uwsgi_response_add_connection_close(wsgi_req)) {free(response) ; goto end;} } uwsgi_response_write_body_do(wsgi_req, response, size); free(response); end: for(i=0;i<ur->custom;i++) { if (ubs[i] != NULL) { uwsgi_buffer_destroy(ubs[i]); } } return ret; }
static int uwsgi_hook_rpc(char *arg) { int ret = -1; size_t i, argc = 0; char **rargv = uwsgi_split_quoted(arg, strlen(arg), " \t", &argc); if (!argc) goto end; if (argc > 256) goto destroy; char *argv[256]; uint16_t argvs[256]; char *node = NULL; char *func = rargv[0]; char *at = strchr(func, '@'); if (at) { *at = 0; node = at + 1; } for(i=0;i<(argc-1);i++) { size_t a_len = strlen(rargv[i+1]); if (a_len > 0xffff) goto destroy; argv[i] = rargv[i+1] ; argvs[i] = a_len; } uint64_t size = 0; // response must be always freed char *response = uwsgi_do_rpc(node, func, argc-1, argv, argvs, &size); if (response) { if (at) *at = '@'; uwsgi_log("[rpc result from \"%s\"] %.*s\n", rargv[0], size, response); free(response); ret = 0; } destroy: for(i=0;i<argc;i++) { free(rargv[i]); } end: free(rargv); return ret; }
JNIEXPORT jobject JNICALL uwsgi_jvm_api_rpc(JNIEnv *env, jclass c, jobject j_args) { char *argv[256]; uint16_t argvs[256]; jobject argvj[256]; uint64_t size = 0; size_t args = uwsgi_jvm_array_len(j_args); if (args < 2) return NULL; jobject server = uwsgi_jvm_array_get(j_args, 0); jobject func = uwsgi_jvm_array_get(j_args, 1); size_t i; for(i=0;i<(args-2);i++) { jobject j_arg = uwsgi_jvm_array_get(j_args, i + 2); argvs[i] = uwsgi_jvm_strlen(j_arg); argv[i] = uwsgi_jvm_str2c(j_arg); // need this value to unref later argvj[i] = j_arg; } char *c_server = uwsgi_jvm_str2c(server); char *c_func = uwsgi_jvm_str2c(func); char *response = uwsgi_do_rpc(c_server, c_func, args-2, argv, argvs, &size); uwsgi_jvm_release_chars(func, c_func); uwsgi_jvm_release_chars(server, c_server); uwsgi_jvm_local_unref(server); uwsgi_jvm_local_unref(func); for(i=0;i<(args-2);i++) { uwsgi_jvm_release_chars(argvj[i], argv[i]); uwsgi_jvm_local_unref(argvj[i]); } if (response) { jobject o = uwsgi_jvm_str(response, size); free(response); return o; } return NULL; }
// "next" || "continue" || "break(.*)" || "goon" || "goto .+" static int uwsgi_routing_func_rpc_ret(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_CONTINUE; if (!uwsgi_strncmp(response, size, "next", 4 )) { ret = UWSGI_ROUTE_NEXT; } else if (!uwsgi_strncmp(response, size, "continue", 8 )) { ret = UWSGI_ROUTE_CONTINUE; } else if (!uwsgi_starts_with(response, size, "break", 5 )) { ret = UWSGI_ROUTE_BREAK; if (size > 6) { if (uwsgi_response_prepare_headers(wsgi_req, response+6, size-6)) goto end0; if (uwsgi_response_add_connection_close(wsgi_req)) goto end0; if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) goto end0; // no need to check for return value uwsgi_response_write_headers_do(wsgi_req); } } else if (!uwsgi_starts_with(response, size, "goto ", 5)) { ret = UWSGI_ROUTE_BREAK; if (size > 5) { // find the label struct uwsgi_route *routes = uwsgi.routes; while(routes) { if (!routes->label) goto next; if (!uwsgi_strncmp(routes->label, routes->label_len, response+5, size-5)) { ret = UWSGI_ROUTE_NEXT; wsgi_req->route_goto = routes->pos; goto found; } next: routes = routes->next; } goto end0; found: if (wsgi_req->route_goto <= wsgi_req->route_pc) { wsgi_req->route_goto = 0; uwsgi_log("[uwsgi-route] ERROR \"goto\" instruction can only jump forward (check your label !!!)\n"); ret = UWSGI_ROUTE_BREAK; } } } end0: free(response); end: for(i=0;i<ur->custom;i++) { if (ubs[i] != NULL) { uwsgi_buffer_destroy(ubs[i]); } } return ret; }