socklen_t socket_to_in_addr6(char *socket_name, char *port, int portn, struct sockaddr_in6 * sin_addr) { memset(sin_addr, 0, sizeof(struct sockaddr_in6)); sin_addr->sin6_family = AF_INET6; if (port) { *port = 0; sin_addr->sin6_port = htons(atoi(port + 1)); } else { sin_addr->sin6_port = htons(portn); } if (!strcmp(socket_name, "[::]")) { sin_addr->sin6_addr = in6addr_any; } else { char *sanitized_sn = uwsgi_concat2n(socket_name + 1, strlen(socket_name + 1) - 1, "", 0); char *resolved = uwsgi_resolve_ip(sanitized_sn); if (resolved) { inet_pton(AF_INET6, resolved, sin_addr->sin6_addr.s6_addr); } else { inet_pton(AF_INET6, sanitized_sn, sin_addr->sin6_addr.s6_addr); } free(sanitized_sn); } if (port) { *port = ':'; } return sizeof(struct sockaddr_in6); }
socklen_t socket_to_in_addr(char *socket_name, char *port, int portn, struct sockaddr_in *sin_addr) { memset(sin_addr, 0, sizeof(struct sockaddr_in)); sin_addr->sin_family = AF_INET; if (port) { *port = 0; sin_addr->sin_port = htons(atoi(port + 1)); } else { sin_addr->sin_port = htons(portn); } if (socket_name[0] == 0) { sin_addr->sin_addr.s_addr = INADDR_ANY; } else { char *resolved = uwsgi_resolve_ip(socket_name); if (resolved) { sin_addr->sin_addr.s_addr = inet_addr(resolved); } else { sin_addr->sin_addr.s_addr = inet_addr(socket_name); } } if (port) { *port = ':'; } return sizeof(struct sockaddr_in); }
int erlang_init() { char *host; struct sockaddr_in sin; socklen_t slen = sizeof(struct sockaddr_in); char *ip = NULL; char *nodename; struct in_addr addr; uerl.lock = uwsgi_lock_init("erlang"); if (uerl.name) { host = strchr(uerl.name, '@'); if (!host) { if (ei_connect_init(&uerl.cnode, uerl.name, uerl.cookie, 0) < 0) { uwsgi_log("unable to initialize erlang connection\n"); exit(1); } } else { nodename = uwsgi_concat2n(uerl.name, host-uerl.name, "",0); ip = uwsgi_resolve_ip(host+1); if (ip) { #ifdef UWSGI_DEBUG uwsgi_log("ip: %s\n", ip); #endif addr.s_addr = inet_addr(ip); if (ei_connect_xinit(&uerl.cnode, host+1, nodename, uerl.name, &addr, uerl.cookie, 0) < 0) { uwsgi_log("unable to initialize erlang connection\n"); exit(1); } } else { if (ei_connect_init(&uerl.cnode, nodename, uerl.cookie, 0) < 0) { uwsgi_log("unable to initialize erlang connection\n"); exit(1); } } free(nodename); } if (ip) { uerl.fd = bind_to_tcp(ip, uwsgi.listen_queue, NULL); } else { uerl.fd = bind_to_tcp("", uwsgi.listen_queue, NULL); } if (uerl.fd < 0) { exit(1); } if (getsockname(uerl.fd, (struct sockaddr *) &sin, &slen)) { uwsgi_error("getsockname()"); exit(1); } if (ei_publish(&uerl.cnode, ntohs(sin.sin_port)) < 0) { uwsgi_log( "*** unable to subscribe with EPMD ***\n"); exit(1); } uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port)); if (register_gateway("uWSGI erlang c-node", erlang_loop, NULL) == NULL) { uwsgi_log("unable to register the erlang gateway\n"); exit(1); } } return 0; }
/* extremely complex function for reading resources (files, url...) need a lot of refactoring... */ char *uwsgi_open_and_read(char *url, size_t *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; // stdin ? if (!strcmp(url, "-")) { buffer = uwsgi_read_fd(0, size, add_zero); } // fd ? else if (!strncmp("fd://", url, 5)) { fd = atoi(url + 5); buffer = uwsgi_read_fd(fd, size, add_zero); } // exec ? else if (!strncmp("exec://", url, 5)) { int cpipe[2]; if (pipe(cpipe)) { uwsgi_error("pipe()"); exit(1); } uwsgi_run_command(url + 7, NULL, cpipe[1]); buffer = uwsgi_read_fd(cpipe[0], size, add_zero); close(cpipe[0]); close(cpipe[1]); } // http url ? else 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); } free(ip); 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\nUser-Agent: uWSGI on ", 23); len = write(fd, uwsgi.hostname, uwsgi.hostname_len); len = write(fd, "\r\n\r\n", 4); int http_status_code_ptr = 0; 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; char *tmp = realloc(buffer, *size); if (!tmp) { uwsgi_error("uwsgi_open_and_read()/realloc()"); exit(1); } buffer = tmp; buffer[*size - 1] = byte; } else { body = 0; http_status_code_ptr++; if (http_status_code_ptr == 10) { if (byte != '2') { uwsgi_log("Not usable HTTP response: %cxx\n", byte); if (uwsgi.has_emperor) { exit(UWSGI_EXILE_CODE); } else { exit(1); } } } } } close(fd); if (add_zero) { *size = *size + 1; char *tmp = realloc(buffer, *size); if (!tmp) { uwsgi_error("uwsgi_open_and_read()/realloc()"); exit(1); } buffer = tmp; buffer[*size - 1] = 0; } } else if (!strncmp("emperor://", url, 10)) { if (uwsgi.emperor_fd_config < 0) { uwsgi_log("this is not a vassal instance\n"); exit(1); } ssize_t rlen; *size = 0; struct uwsgi_header uh; size_t remains = 4; char *ptr = (char *) &uh; while(remains) { int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5); if (ret <= 0) { uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url); exit(1); } rlen = read(uwsgi.emperor_fd_config, ptr, remains); if (rlen <= 0) { uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url); exit(1); } ptr+=rlen; remains-=rlen; } remains = uh.pktsize; if (!remains) { uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url); exit(1); } buffer = uwsgi_calloc(remains + add_zero); ptr = buffer; while (remains) { int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5); if (ret <= 0) { uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url); exit(1); } rlen = read(uwsgi.emperor_fd_config, ptr, remains); if (rlen <= 0) { uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url); exit(1); } ptr+=rlen; remains-=rlen; } *size = uh.pktsize + add_zero; } #ifdef UWSGI_EMBED_CONFIG else if (url[0] == 0) { *size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG; if (add_zero) { *size += 1; } buffer = uwsgi_malloc(*size); memset(buffer, 0, *size); memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG); } #endif else if (!strncmp("data://", url, 7)) { fd = open(uwsgi.binary_path, O_RDONLY); if (fd < 0) { uwsgi_error_open(uwsgi.binary_path); exit(1); } int slot = atoi(url + 7); if (slot < 0) { uwsgi_log("invalid binary data slot requested\n"); exit(1); } uwsgi_log("requesting binary data slot %d\n", slot); off_t fo = lseek(fd, 0, SEEK_END); if (fo < 0) { uwsgi_error("lseek()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } int i = 0; uint64_t datasize = 0; for (i = 0; i <= slot; i++) { fo = lseek(fd, -9, SEEK_CUR); if (fo < 0) { uwsgi_error("lseek()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } ssize_t len = read(fd, &datasize, 8); if (len != 8) { uwsgi_error("read()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } if (datasize == 0) { uwsgi_log("0 size binary data !!!\n"); exit(1); } fo = lseek(fd, -(datasize + 9), SEEK_CUR); if (fo < 0) { uwsgi_error("lseek()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } if (i == slot) { *size = datasize; if (add_zero) { *size += 1; } buffer = uwsgi_malloc(*size); memset(buffer, 0, *size); len = read(fd, buffer, datasize); if (len != (ssize_t) datasize) { uwsgi_error("read()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } } } } else if (!strncmp("sym://", url, 6)) { char *symbol = uwsgi_concat3("_binary_", url + 6, "_start"); void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol); if (!sym_start_ptr) { uwsgi_log("unable to find symbol %s\n", symbol); exit(1); } free(symbol); symbol = uwsgi_concat3("_binary_", url + 6, "_end"); void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol); if (!sym_end_ptr) { uwsgi_log("unable to find symbol %s\n", symbol); exit(1); } free(symbol); *size = sym_end_ptr - sym_start_ptr; if (add_zero) { *size += 1; } buffer = uwsgi_malloc(*size); memset(buffer, 0, *size); memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr); } #ifdef UWSGI_ELF else if (!strncmp("section://", url, 10)) { size_t s_len = 0; buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len); if (!buffer) { uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path); exit(1); } *size = s_len; if (add_zero) *size += 1; } #endif // 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); } if (S_ISFIFO(sb.st_mode)) { buffer = uwsgi_read_fd(fd, size, add_zero); close(fd); goto end; } buffer = uwsgi_malloc(sb.st_size + add_zero); 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; } end: if (magic_table) { magic_buf = magic_sub(buffer, *size, size, magic_table); free(buffer); return magic_buf; } return buffer; }
// create the logpipe void create_logpipe(void) { #if defined(SOCK_SEQPACKET) && defined(__linux__) if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) { #else if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) { #endif uwsgi_error("socketpair()\n"); exit(1); } uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[0]); uwsgi_socket_nb(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); } } if (dup2(1, 2) < 0) { uwsgi_error("dup2()"); exit(1); } } #ifdef UWSGI_ZEROMQ // the zeromq logger ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *ul, char *message, size_t len) { if (!ul->configured) { if (!ul->arg) { uwsgi_log_safe("invalid zeromq syntax\n"); exit(1); } void *ctx = uwsgi_zeromq_init(); ul->data = zmq_socket(ctx, ZMQ_PUSH); if (ul->data == NULL) { uwsgi_error_safe("zmq_socket()"); exit(1); } if (zmq_connect(ul->data, ul->arg) < 0) { uwsgi_error_safe("zmq_connect()"); exit(1); } ul->configured = 1; } zmq_msg_t msg; if (zmq_msg_init_size(&msg, len) == 0) { memcpy(zmq_msg_data(&msg), message, len); #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0) zmq_sendmsg(ul->data, &msg, 0); #else zmq_send(ul->data, &msg, 0); #endif zmq_msg_close(&msg); } return 0; } #endif // log to the specified file or udp address 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)); char *resolved = uwsgi_resolve_ip(logfile); if (resolved) { udp_addr.sin_addr.s_addr = inet_addr(resolved); } else { 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 if (uwsgi.log_truncate) { fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP); } else { fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP); } if (fd < 0) { uwsgi_error_open(logfile); exit(1); } uwsgi.logfile = logfile; if (uwsgi.chmod_logfile_value) { if (chmod(uwsgi.logfile, uwsgi.chmod_logfile_value)) { uwsgi_error("chmod()"); } } #ifdef UWSGI_UDP } #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); } }