#include "uwsgi.h" extern struct uwsgi_server uwsgi; #ifdef __BIG_ENDIAN__ uint16_t uwsgi_swap16(uint16_t x) { return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8); } uint32_t uwsgi_swap32(uint32_t x) { x = ( (x<<8) & 0xFF00FF00 ) | ( (x>>8) & 0x00FF00FF ); return (x>>16) | (x<<16); } // thanks to ffmpeg project for this idea :P uint64_t uwsgi_swap64(uint64_t x) { union { uint64_t ll; uint32_t l[2]; } w, r; w.ll = x; r.l[0] = uwsgi_swap32(w.l[1]); r.l[1] = uwsgi_swap32(w.l[0]); return r.ll; } #endif int check_hex(char *str, int len) { int i; for(i=0;i '9') && (str[i] < 'a' && str[i] > 'f') && (str[i] < 'A' && str[i] > 'F') ) { return 0; } } return 1; } void inc_harakiri(int sec) { if (uwsgi.master_process) { uwsgi.workers[uwsgi.mywid].harakiri += sec; } else { alarm(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] + sec); } } void set_harakiri(int sec) { if (uwsgi.master_process) { if (sec == 0) { uwsgi.workers[uwsgi.mywid].harakiri = 0; } else { uwsgi.workers[uwsgi.mywid].harakiri = time(NULL) + sec; } } else { alarm(sec); } } void daemonize(char *logfile) { pid_t pid; int fdin; pid = fork(); if (pid < 0) { uwsgi_error("fork()"); exit(1); } if (pid != 0) { exit(0); } if (setsid() < 0) { uwsgi_error("setsid()"); exit(1); } /* refork... */ pid = fork(); if (pid < 0) { uwsgi_error("fork()"); exit(1); } if (pid != 0) { exit(0); } umask(0); /*if (chdir("/") != 0) { uwsgi_error("chdir()"); exit(1); } */ fdin = open("/dev/null", O_RDWR); if (fdin < 0) { uwsgi_error_open("/dev/null"); exit(1); } /* stdin */ if (dup2(fdin, 0) < 0) { uwsgi_error("dup2()"); exit(1); } logto(logfile); } void logto(char *logfile) { int fd; #ifdef UWSGI_UDP char *udp_port; struct sockaddr_in udp_addr; udp_port = strchr(logfile, ':'); if (udp_port) { udp_port[0] = 0; if ( !udp_port[1] || !logfile[0] ) { uwsgi_log("invalid udp address\n"); exit(1); } fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { uwsgi_error("socket()"); exit(1); } memset(&udp_addr, 0, sizeof(struct sockaddr_in)); udp_addr.sin_family = AF_INET; udp_addr.sin_port = htons(atoi(udp_port+1)); udp_addr.sin_addr.s_addr = inet_addr(logfile); if (connect(fd, (const struct sockaddr *) &udp_addr, sizeof(struct sockaddr_in)) < 0) { uwsgi_error("connect()"); exit(1); } } else { #endif fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { uwsgi_error_open(logfile); exit(1); } #ifdef UWSGI_UDP uwsgi.logfile = logfile; } #endif /* stdout */ if (fd != 1) { if (dup2(fd, 1) < 0) { uwsgi_error("dup2()"); exit(1); } close(fd); } /* stderr */ if (dup2(1, 2) < 0) { uwsgi_error("dup2()"); exit(1); } } void log_syslog(char *syslog_opts) { if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) { uwsgi_error("socketpair()\n"); exit(1); } uwsgi_log("log pipe %d %d\n", uwsgi.shared->worker_log_pipe[0], uwsgi.shared->worker_log_pipe[1]); if (uwsgi.shared->worker_log_pipe[1] != 1) { if (dup2(uwsgi.shared->worker_log_pipe[1], 1) < 0) { uwsgi_error("dup2()"); exit(1); } } uwsgi_log("opening syslog\n"); if (dup2(1, 2) < 0) { uwsgi_error("dup2()"); exit(1); } openlog("uwsgi", 0, LOG_DAEMON ); } char *uwsgi_get_cwd() { int newsize = 256; char *cwd; cwd = uwsgi_malloc(newsize); if (getcwd(cwd, newsize) == NULL) { newsize = errno; uwsgi_log("need a bigger buffer (%d bytes) for getcwd(). doing reallocation.\n", newsize); free(cwd); cwd = uwsgi_malloc(newsize); if (getcwd(cwd, newsize) == NULL) { uwsgi_error("getcwd()"); exit(1); } } return cwd; } void internal_server_error(int fd, char *message) { if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) { uwsgi.wsgi_req->headers_size = write(fd, "HTTP/1.1 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 63); } else { uwsgi.wsgi_req->headers_size = write(fd, "Status: 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 62); } uwsgi.wsgi_req->header_cnt = 2; uwsgi.wsgi_req->response_size = write(fd, "

uWSGI Error

", 20); uwsgi.wsgi_req->response_size += write(fd, message, strlen(message)); } void uwsgi_as_root() { #ifdef __linux__ char *cgroup_taskfile; int i; FILE *cgroup; char *cgroup_opt; #endif if (!getuid()) { if (!uwsgi.master_as_root) { uwsgi_log("uWSGI running as root, you can use --uid/--gid/--chroot options\n"); } #ifdef __linux__ if (uwsgi.cgroup) { if (mkdir(uwsgi.cgroup, S_IRWXU | S_IROTH | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { uwsgi_log("using Linux cgroup %s\n", uwsgi.cgroup); } else { uwsgi_log("created Linux cgroup %s\n", uwsgi.cgroup); } cgroup_taskfile = uwsgi_concat2(uwsgi.cgroup, "/tasks"); cgroup = fopen(cgroup_taskfile, "w"); if (!cgroup) { uwsgi_error_open(cgroup_taskfile); exit(1); } if (fprintf(cgroup, "%d\n", (int) getpid()) < 0) { uwsgi_log( "could not set cgroup\n"); exit(1); } fclose(cgroup); free(cgroup_taskfile); for(i=0;ioptions[UWSGI_OPTION_MEMORY_DEBUG]) { uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n"); } #endif } if (uwsgi.gidname) { struct group *ugroup = getgrnam(uwsgi.gidname); if (ugroup) { uwsgi.gid = ugroup->gr_gid; } else { uwsgi_log("group %s not found.\n", uwsgi.gidname); exit(1); } } if (uwsgi.uidname) { struct passwd *upasswd = getpwnam(uwsgi.uidname); if (upasswd) { uwsgi.uid = upasswd->pw_uid; } else { uwsgi_log("user %s not found.\n", uwsgi.uidname); exit(1); } } if (uwsgi.gid) { if (!uwsgi.master_as_root) uwsgi_log("setgid() to %d\n", uwsgi.gid); if (setgid(uwsgi.gid)) { uwsgi_error("setgid()"); exit(1); } } if (uwsgi.uid) { if (!uwsgi.master_as_root) uwsgi_log("setuid() to %d\n", uwsgi.uid); if (setuid(uwsgi.uid)) { uwsgi_error("setuid()"); exit(1); } } if (!getuid()) { uwsgi_log(" *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n"); } } else { if (uwsgi.chroot && !uwsgi.is_a_reload) { uwsgi_log("cannot chroot() as non-root user\n"); exit(1); } if (uwsgi.gid && getgid() != uwsgi.gid) { uwsgi_log("cannot setgid() as non-root user\n"); exit(1); } if (uwsgi.uid && getuid() != uwsgi.uid) { uwsgi_log("cannot setuid() as non-root user\n"); exit(1); } } } void uwsgi_close_request(struct wsgi_request *wsgi_req) { int waitpid_status; int tmp_id; gettimeofday(&wsgi_req->end_of_request, NULL); uwsgi.workers[uwsgi.mywid].running_time += (double) (((double) (wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec) - (double) (wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec)) / (double) 1000.0); // get memory usage if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) get_memusage(); // close the connection with the webserver if (!wsgi_req->fd_closed) { // NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST close(wsgi_req->poll.fd); } uwsgi.workers[0].requests++; uwsgi.workers[uwsgi.mywid].requests++; // after_request hook if (uwsgi.p[wsgi_req->uh.modifier1]->after_request) uwsgi.p[wsgi_req->uh.modifier1]->after_request(wsgi_req); // leave harakiri mode if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) { set_harakiri(0); } // defunct process reaper if (uwsgi.shared->options[UWSGI_OPTION_REAPER] == 1 || uwsgi.grunt) { while( waitpid(WAIT_ANY, &waitpid_status, WNOHANG) > 0); } // reset request tmp_id = wsgi_req->async_id; memset(wsgi_req, 0, sizeof(struct wsgi_request)); wsgi_req->async_id = tmp_id; if (uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].requests >= uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS]) { goodbye_cruel_world(); } } void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id) { wsgi_req->poll.events = POLLIN; wsgi_req->app_id = uwsgi.default_app; wsgi_req->async_id = async_id; #ifdef UWSGI_SENDFILE wsgi_req->sendfile_fd = -1; #endif wsgi_req->hvec = uwsgi.async_hvec[wsgi_req->async_id]; wsgi_req->buffer = uwsgi.async_buf[wsgi_req->async_id]; #ifdef UWSGI_ROUTING wsgi_req->ovector = uwsgi.async_ovector[wsgi_req->async_id]; #endif if (uwsgi.post_buffering > 0) { wsgi_req->post_buffering_buf = uwsgi.async_post_buf[wsgi_req->async_id]; } } int wsgi_req_simple_recv(struct wsgi_request *wsgi_req) { UWSGI_SET_IN_REQUEST; gettimeofday(&wsgi_req->start_of_request, NULL); if (!uwsgi_parse_response(&wsgi_req->poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, wsgi_req->buffer)) { return -1; } // enter harakiri mode if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) { set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]); } return 0; } int wsgi_req_recv(struct wsgi_request *wsgi_req) { UWSGI_SET_IN_REQUEST; gettimeofday(&wsgi_req->start_of_request, NULL); if (!uwsgi_parse_response(&wsgi_req->poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, wsgi_req->buffer)) { return -1; } // enter harakiri mode if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) { set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]); } wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req); return 0; } int wsgi_req_simple_accept(struct wsgi_request *wsgi_req, int fd) { wsgi_req->poll.fd = accept(fd, (struct sockaddr *) &wsgi_req->c_addr, (socklen_t *) &wsgi_req->c_len); if (wsgi_req->poll.fd < 0) { uwsgi_error("accept()"); return -1; } if (uwsgi.close_on_exec) { fcntl(wsgi_req->poll.fd, F_SETFD, FD_CLOEXEC); } return 0; } int wsgi_req_accept(struct wsgi_request *wsgi_req) { int i; int ret; char uwsgi_signal; polling: ret = poll(uwsgi.sockets_poll, uwsgi.sockets_cnt+uwsgi.master_process, -1); if (ret < 0) { uwsgi_error("poll()"); return -1; } if (uwsgi.master_process && uwsgi.sockets_poll[uwsgi.sockets_cnt].revents) { if (read(uwsgi.sockets_poll[uwsgi.sockets_cnt].fd, &uwsgi_signal, 1) <= 0) { if (uwsgi.no_orphans) { uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid); end_me(0); } } else { uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid); if (uwsgi_signal_handler(uwsgi_signal)) { uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid); } } } for(i=0;ipoll.fd = accept(uwsgi.sockets_poll[i].fd, (struct sockaddr *) &wsgi_req->c_addr, (socklen_t *) &wsgi_req->c_len); if (wsgi_req->poll.fd < 0) { if (errno == EWOULDBLOCK) goto polling; uwsgi_error("accept()"); return -1; } // in Linux, new sockets do not inherit attributes #ifndef __linux__ /* re-set blocking socket */ int arg = uwsgi.sockets[i].arg ; arg &= (~O_NONBLOCK); if (fcntl(wsgi_req->poll.fd, F_SETFL, arg) < 0) { uwsgi_error("fcntl()"); return -1; } #endif if (uwsgi.close_on_exec) { fcntl(wsgi_req->poll.fd, F_SETFD, FD_CLOEXEC); } return 0; } } return -1; } void sanitize_args() { if (uwsgi.async > 1) { uwsgi.cores = uwsgi.async; } if (uwsgi.threads > 1) { uwsgi.has_threads = 1; uwsgi.cores = uwsgi.threads; } if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) { if (!uwsgi.post_buffering) { uwsgi_log(" *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** \n"); } } #ifdef UWSGI_HTTP if (uwsgi.http && !uwsgi.http_only) { uwsgi.vacuum = 1; } #endif } void env_to_arg(char *src, char *dst) { int i; int val = 0; for(i=0;i< (int) strlen(src);i++) { if (src[i] == '=') { val = 1; } if (val) { dst[i] = src[i]; } else { dst[i] = tolower( (int) src[i]); if (dst[i] == '_') { dst[i] = '-'; } } } dst[strlen(src)] = 0; } void parse_sys_envs(char **envs) { char **uenvs = envs; char *earg, *eq_pos; while(*uenvs) { if (!strncmp(*uenvs, "UWSGI_", 6) && strncmp(*uenvs, "UWSGI_RELOADS=",14)) { earg = uwsgi_malloc(strlen(*uenvs+6)+1); env_to_arg(*uenvs+6, earg); eq_pos = strchr(earg, '='); if (!eq_pos) { break; } eq_pos[0] = 0; add_exported_option(earg, eq_pos+1, 0); } uenvs++; } } //use this instead of fprintf to avoid buffering mess with udp logging void uwsgi_log(const char *fmt, ...) { va_list ap; char logpkt[4096]; int rlen = 0; struct timeval tv; char sftime[64]; time_t now; if (uwsgi.logdate) { if (uwsgi.log_strftime) { now = time(NULL); rlen = strftime( sftime, 64, uwsgi.log_strftime, localtime(&now)); memcpy( logpkt, sftime, rlen); memcpy( logpkt + rlen, " - ", 3); rlen += 3; } else { gettimeofday(&tv, NULL); memcpy( logpkt, ctime( (const time_t *) &tv.tv_sec), 24); memcpy( logpkt + 24, " - ", 3); rlen = 24 + 3; } } va_start (ap, fmt); rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap ); va_end(ap); // do not check for errors rlen = write(2, logpkt, rlen); } void uwsgi_log_verbose(const char *fmt, ...) { va_list ap; char logpkt[4096]; int rlen = 0; struct timeval tv; gettimeofday(&tv, NULL); memcpy( logpkt, ctime( (const time_t *) &tv.tv_sec), 24); memcpy( logpkt + 24, " - ", 3); rlen = 24 + 3; va_start (ap, fmt); rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap ); va_end(ap); // do not check for errors rlen = write(2, logpkt, rlen); } inline int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) { if (slen != dlen) return 1; return memcmp(src, dst, dlen); } inline int uwsgi_startswith(char *src, char *what, int wlen) { int i; for(i=0;i0) { item = va_arg( s, char *); if (item == NULL) { break; } len += va_arg( s, int); j--; } va_end( s ); buf = uwsgi_malloc(len); memset( buf, 0, len); j = c; len = 0; va_start( s, c); while(j>0) { item = va_arg( s, char *); if (item == NULL) { break; } tlen = va_arg( s, int); memcpy(buf + len, item, tlen); len += tlen; j--; } va_end( s ); return buf; } char *uwsgi_concat2(char *one, char *two) { char *buf; size_t len = strlen(one) + strlen(two) + 1; buf = uwsgi_malloc(len); buf[len-1] = 0; memcpy( buf, one, strlen(one)); memcpy( buf + strlen(one) , two, strlen(two)); return buf; } char *uwsgi_concat4(char *one, char *two, char *three, char *four) { char *buf; size_t len = strlen(one) + strlen(two) + strlen(three) + strlen(four) + 1; buf = uwsgi_malloc(len); buf[len-1] = 0; memcpy( buf, one, strlen(one)); memcpy( buf + strlen(one) , two, strlen(two)); memcpy( buf + strlen(one) + strlen(two) , three, strlen(three)); memcpy( buf + strlen(one) + strlen(two) + strlen(three) , four, strlen(four)); return buf; } char *uwsgi_concat3(char *one, char *two, char *three) { char *buf; size_t len = strlen(one) + strlen(two) + strlen(three) + 1; buf = uwsgi_malloc(len); buf[len-1] = 0; memcpy( buf, one, strlen(one)); memcpy( buf + strlen(one) , two, strlen(two)); memcpy( buf + strlen(one) + strlen(two) , three, strlen(three)); return buf; } char *uwsgi_concat2n(char *one, int s1, char *two, int s2) { char *buf; size_t len = s1 + s2 + 1; buf = uwsgi_malloc(len); buf[len-1] = 0; memcpy( buf, one, s1); memcpy( buf + s1, two, s2); return buf; } char *uwsgi_concat2nn(char *one, int s1, char *two, int s2, int *len) { char *buf; *len = s1 + s2 + 1; buf = uwsgi_malloc(*len); buf[*len-1] = 0; memcpy( buf, one, s1); memcpy( buf + s1, two, s2); return buf; } char *uwsgi_concat3n(char *one, int s1, char *two, int s2, char *three, int s3) { char *buf; size_t len = s1 + s2 + s3 + 1; buf = uwsgi_malloc(len); buf[len-1] = 0; memcpy( buf, one, s1); memcpy( buf + s1, two, s2); memcpy( buf + s1 + s2, three, s3); return buf; } char *uwsgi_concat4n(char *one, int s1, char *two, int s2, char *three, int s3, char *four, int s4) { char *buf; size_t len = s1 + s2 + s3 + s4 + 1; buf = uwsgi_malloc(len); buf[len-1] = 0; memcpy( buf, one, s1); memcpy( buf + s1, two, s2); memcpy( buf + s1 + s2, three, s3); memcpy( buf + s1 + s2 + s3, four, s4); return buf; } char *uwsgi_concat(int c, ... ) { va_list s; char *item; size_t len = 1; int j = c; char *buf; va_start( s, c); while(j>0) { item = va_arg( s, char *); if (item == NULL) { break; } len += (int) strlen(item); j--; } va_end( s ); buf = uwsgi_malloc(len); memset( buf, 0, len); j = c; len = 0; va_start( s, c); while(j>0) { item = va_arg( s, char *); if (item == NULL) { break; } memcpy(buf + len, item, strlen(item)); len += strlen(item); j--; } va_end( s ); return buf; } char *uwsgi_strncopy(char *s, int len) { char *buf; buf = uwsgi_malloc(len + 1); buf[len] = 0; memcpy(buf, s, len); return buf; } int uwsgi_get_app_id(char *script_name, int script_name_len, int modifier1) { int i; for(i=0;iname) break; count++; lopt++; } return count; } int uwsgi_read_whole_body_in_mem(struct wsgi_request *wsgi_req, char *buf) { size_t post_remains = wsgi_req->post_cl; int ret; ssize_t len; char *ptr = buf; while(post_remains) { if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) { inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); } ret = uwsgi_waitfd(wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); if (ret < 0) { return 0; } if (!ret) { uwsgi_log("buffering POST data timedout !!!\n"); return 0; } len = read(wsgi_req->poll.fd, ptr, post_remains); if (len <= 0) { uwsgi_error("read()"); return 0; } ptr += len; post_remains -= len; } return 1; } int uwsgi_read_whole_body(struct wsgi_request *wsgi_req, char *buf, size_t len) { size_t post_remains = wsgi_req->post_cl; ssize_t post_chunk; int ret,i; int upload_progress_fd = -1; char *upload_progress_filename = NULL; const char *x_progress_id = "X-Progress-ID="; char *xpi_ptr = (char *) x_progress_id ; wsgi_req->async_post = tmpfile(); if (!wsgi_req->async_post) { uwsgi_error("tmpfile()"); return 0; } if (uwsgi.upload_progress) { // first check for X-Progress-ID size // separator + 'X-Progress-ID' + '=' + uuid if (wsgi_req->uri_len > 51) { for(i=0;iuri_len;i++) { if (wsgi_req->uri[i] == xpi_ptr[0]) { if (xpi_ptr[0] == '=') { if (wsgi_req->uri+i+36 <= wsgi_req->uri+wsgi_req->uri_len) { upload_progress_filename = wsgi_req->uri+i+1 ; } break; } xpi_ptr++; } else { xpi_ptr = (char *) x_progress_id ; } } // now check for valid uuid (from spec available at http://en.wikipedia.org/wiki/Universally_unique_identifier) if (upload_progress_filename) { uwsgi_log("upload progress uuid = %.*s\n", 36, upload_progress_filename); if (!check_hex(upload_progress_filename, 8)) goto cycle; if (upload_progress_filename[8] != '-') goto cycle; if (!check_hex(upload_progress_filename+9, 4)) goto cycle; if (upload_progress_filename[13] != '-') goto cycle; if (!check_hex(upload_progress_filename+14, 4)) goto cycle; if (upload_progress_filename[18] != '-') goto cycle; if (!check_hex(upload_progress_filename+19, 4)) goto cycle; if (upload_progress_filename[23] != '-') goto cycle; if (!check_hex(upload_progress_filename+24, 12)) goto cycle; upload_progress_filename = uwsgi_concat4n(uwsgi.upload_progress, strlen(uwsgi.upload_progress), "/",1,upload_progress_filename, 36, ".js", 3); // here we use O_EXCL to avoid eventual application bug in uuid generation/using upload_progress_fd = open(upload_progress_filename, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP); if (upload_progress_fd < 0) { uwsgi_error_open(upload_progress_filename); free(upload_progress_filename); } } } } cycle: if (upload_progress_filename && upload_progress_fd == -1) { uwsgi_log("invalid X-Progress-ID value: must be a UUID\n"); } // manage buffered data and upload progress while(post_remains > 0) { if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) { inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); } ret = poll(&wsgi_req->poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] * 1000); if (ret < 0) { uwsgi_error("poll()"); goto end; } if (!ret) { uwsgi_log("buffering POST data timedout !!!\n"); goto end; } if (post_remains > len) { post_chunk = read(wsgi_req->poll.fd, buf, len); } else { post_chunk = read(wsgi_req->poll.fd, buf, post_remains); } if (post_chunk < 0) { uwsgi_error("read()"); goto end; } if (!fwrite(buf, post_chunk, 1, wsgi_req->async_post)) { uwsgi_error("fwrite()"); goto end; } if (upload_progress_fd > -1) { //write json data to the upload progress file if (lseek(upload_progress_fd, 0, SEEK_SET)) { uwsgi_error("lseek()"); goto end; } // resue buf for json buffer ret = snprintf(buf, len, "{ \"state\" : \"uploading\", \"received\" : %d, \"size\" : %d }\r\n", (int) (wsgi_req->post_cl - post_remains), (int) wsgi_req->post_cl); if (ret < 0) { uwsgi_log("unable to write JSON data in upload progress file %s\n", upload_progress_filename); goto end; } if (write(upload_progress_fd, buf, ret) < 0) { uwsgi_error("write()"); goto end; } if (fsync(upload_progress_fd)) { uwsgi_error("fsync()"); } } post_remains -= post_chunk; } rewind(wsgi_req->async_post); if (upload_progress_fd > -1) { close(upload_progress_fd); if (unlink(upload_progress_filename)) { uwsgi_error("unlink()"); } free(upload_progress_filename); } return 1; end: if (upload_progress_fd > -1) { close(upload_progress_fd); if (unlink(upload_progress_filename)) { uwsgi_error("unlink()"); } free(upload_progress_filename); } return 0; } void add_exported_option(char *key, char *value, int configured) { if (!uwsgi.exported_opts) { uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt*)); } else { uwsgi.exported_opts = realloc(uwsgi.exported_opts, sizeof(struct uwsgi_opt*) * (uwsgi.exported_opts_cnt+1)); if (!uwsgi.exported_opts) { uwsgi_error("realloc()"); exit(1); } } uwsgi.exported_opts[uwsgi.exported_opts_cnt] = uwsgi_malloc(sizeof(struct uwsgi_opt)); uwsgi.exported_opts[uwsgi.exported_opts_cnt]->key = key; uwsgi.exported_opts[uwsgi.exported_opts_cnt]->value = value; uwsgi.exported_opts[uwsgi.exported_opts_cnt]->configured = configured; uwsgi.exported_opts_cnt++; } int uwsgi_waitfd(int fd, int timeout) { int ret; struct pollfd upoll[1]; char oob ; ssize_t rlen; if (!timeout) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]; timeout = timeout*1000; if (timeout < 0) timeout = -1; upoll[0].fd = fd; upoll[0].events = POLLIN | POLLPRI; upoll[0].revents = 0; ret = poll(upoll, 1, timeout); if (ret < 0) { uwsgi_error("poll()"); } else if (ret > 0) { if (upoll[0].revents & POLLIN) { return ret; } if (upoll[0].revents & POLLPRI) { uwsgi_log("DETECTED PRI DATA\n"); rlen = recv(fd, &oob, 1, MSG_OOB); uwsgi_log("RECEIVE OOB DATA %d !!!\n", rlen); if (rlen < 0) { return -1; } return 0; } } return ret; } inline void *uwsgi_malloc(size_t size) { char *ptr = malloc(size); if (ptr == NULL) { uwsgi_error("malloc()"); exit(1); } return ptr; } char *uwsgi_cheap_string(char *buf, int len) { int i; char *cheap_buf = buf-1; for(i=0;ih_addr_list || he->h_addrtype != AF_INET) { return NULL; } return inet_ntoa( *( struct in_addr*) he->h_addr_list[0]); } char *uwsgi_open_and_read(char *url, int *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; // http url ? 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); } 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\n\r\n", 4); 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; buffer = realloc(buffer, *size); if (!buffer) { uwsgi_error("realloc()"); exit(1); } buffer[*size-1] = byte; } else { body = 0; } } close(fd); if (add_zero) { *size = *size + 1; buffer = realloc(buffer, *size); buffer[*size] = 0; } } // 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); } buffer = malloc(sb.st_size+add_zero); if (!buffer) { uwsgi_error("malloc()"); exit(1); } 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; } if (magic_table) { magic_buf = magic_sub(buffer, *size, size, magic_table); free(buffer); return magic_buf; } return buffer; } char *magic_sub(char *buffer, int len, int *size, char *magic_table[]) { int i; size_t magic_len = 0; char *magic_buf = uwsgi_malloc(len); char *magic_ptr = magic_buf; char *old_magic_buf; for(i=0;idaemons_cnt < MAX_DAEMONS) { d = &uwsgi.shared->daemons[uwsgi.shared->daemons_cnt]; memcpy(d->command, command, UMIN(strlen(command), 0xff-1)); d->registered = 0; d->status = 0; uwsgi.shared->daemons_cnt++; ret = 0; uwsgi_log("registered daemon %s\n", command); } uwsgi_unlock(uwsgi.daemon_table_lock); return ret; } void spawn_daemon(struct uwsgi_daemon *ud) { int i; char *argv[64]; char *a; int cnt = 1; if (socketpair(AF_UNIX, SOCK_STREAM, 0, ud->pipe)) { uwsgi_error("socketpair()"); return; } pid_t pid = fork(); if (pid < 0) { uwsgi_error("fork()"); return; } if (pid > 0) { close(ud->pipe[1]); ud->pid = pid; ud->status = 1; if (ud->respawns == 0) { ud->born = time(NULL); } ud->respawns++; ud->last_spawn = time(NULL); } else { // close uwsgi sockets for(i=0;ipipe[0]); // stdin will become the pipe if (ud->pipe[1] != 0) { if (dup2(ud->pipe[1], 0)) { uwsgi_error("dup2()"); exit(1); } } #ifdef __linux__ if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) { uwsgi_error("prctl()"); } #endif memcpy(ud->tmp_command, ud->command, 0xff); a = strtok(ud->tmp_command, " "); if (a) { argv[0] = a; while (a != NULL) { a = strtok(NULL, " "); if (a) { argv[cnt] = a; cnt++; } } } else { argv[0] = ud->tmp_command; } argv[cnt] = NULL; if (execvp(argv[0], argv)) { uwsgi_error("execvp()"); } // never here; exit(1); } return; } char *uwsgi_num2str(int num) { char *str = uwsgi_malloc(11); snprintf(str, 11, "%d", num); return str; } int is_unix(char *socket_name, int len) { int i; for(i=0;ikey, key)) { return uwsgi.exported_opts[i]->value; } } return NULL; } char *uwsgi_get_optname_by_index(int index) { struct option *aopt; struct option *lopt = uwsgi.long_options; while ( (aopt = lopt) ) { if (!aopt->name) break; if (aopt->val == index) { return (char *) aopt->name; } lopt++; } return NULL; } int uwsgi_list_has_num(char *list, int num) { char *list2 = uwsgi_concat2(list, ""); char *p = strtok(list2, ","); while (p != NULL) { if (atoi(p) == num) { free(list2); return 1; } p = strtok(NULL, ","); } free(list2); return 0; } int uwsgi_list_has_str(char *list, char *str) { char *list2 = uwsgi_concat2(list+1, ""); char *p = strtok(list2, " "); while (p != NULL) { if (!strcasecmp(p, str)) { free(list2); return 1; } p = strtok(NULL, " "); } free(list2); return 0; }